77 Commits

Author SHA1 Message Date
9e5a5970a3 Improved PIBlockingDeque constructors
- resolve creation from constant (see test construct_from_constant_is_max_size_eq_capacity)
- add tests for constructors
2020-08-11 12:30:28 +03:00
46d93c6c9f Improved PIBlockingDeque behaviour and unit tests for put, offer, take methods
- Methods put, offer, take begins working with move and copy semantics
- Mocking queue condition variables with GMock in Unit tests
- Rewrite part of unit tests
2020-08-07 19:12:09 +03:00
662a2fc464 Refactor PIBlockingDequeue 2020-08-07 10:10:05 +03:00
194389ef6d Refactor templates & submit doc 2020-08-06 13:23:49 +03:00
3cfdda7365 PIThreadPoolExecutor & PIBlockingDequeue improvements
- add support move & copy semantic
- introduce submit method for executor with future result
2020-08-05 22:59:33 +03:00
3ec1ecfb5b refactor concurrent module code 2020-08-04 16:39:08 +03:00
be51728570 Merge remote-tracking branch 'origin/master' into concurrent 2020-08-03 17:48:36 +03:00
41e54e5859 Merge pip2 2020-08-03 17:47:19 +03:00
9cd108cf20 tests binary dir fix 2020-08-03 11:10:27 +03:00
22208fbf51 tests binary dir fix 2020-08-03 11:10:05 +03:00
badaa01deb Merge remote-tracking branch 'origin/master' into concurrent
# Conflicts:
#	lib/main/thread/pithreadpoolexecutor.cpp
#	lib/main/thread/pithreadpoolexecutor.h
#	tests/concurrent/ExecutorIntegrationTest.cpp
#	tests/concurrent/ExecutorUnitTest.cpp
#	tests/concurrent/testutil.h
2020-08-03 10:18:52 +03:00
e8a066abcd doc 2020-08-03 09:04:50 +03:00
427e7411c1 move most old PIMap iterators to new
Documentation of PIVector, PIMap and PIMapIterator
2020-08-03 01:43:23 +03:00
df457a1602 rename "iterate" 2020-08-02 19:18:28 +03:00
1dfcaf4952 Merge branch 'master' of https://git.shs.tools/SHS/pip 2020-08-02 15:57:27 +03:00
b468a6d581 PIMapIterator
small PIString optimize
general PIChunkStream pack optimization
2020-08-02 15:57:21 +03:00
b68e8f7a65 Merge picloud branch 2020-08-02 14:00:46 +03:00
1fb5356825 move picompress.h 2020-08-01 23:34:23 +03:00
01f7b15818 remove " " 2020-08-01 23:27:10 +03:00
284971fe8d Merge branch 'master' of https://git.shs.tools/SHS/pip 2020-08-01 23:24:16 +03:00
edacac54f9 PIByteArray rvalue, some fixes 2020-08-01 23:24:08 +03:00
0821742e45 missed exports 2020-08-01 23:18:02 +03:00
2d317a9959 missed exports 2020-08-01 22:42:11 +03:00
7486866c17 CMakeLists.txt fix 2020-08-01 22:34:20 +03:00
c7ac4fa551 Refactored CMakeLists.txt
* new pip_module() macro
 * fixed exports
 * automatic gather all exports and pass them to Doxygen and PICodeParser
2020-08-01 21:29:32 +03:00
21111b3e67 move tests to separate dir
create macro "pip_test()" for easily add new tests
2020-07-31 15:47:08 +03:00
e728b30e5e PIString hard optimization 2020-07-31 14:12:47 +03:00
1d5c979607 fix bug in move constructor 2020-07-31 00:00:26 +03:00
79e17b48b8 rvalue functions for containers 2020-07-30 22:26:05 +03:00
a12e63e569 PIStringList move operator fix 2020-07-30 20:41:38 +03:00
52062e6ccd move operators works 2020-07-30 20:30:24 +03:00
557f2a4d0d replace piForeach* to for(:)
another c++11 try ...
2020-07-30 20:08:33 +03:00
2ffc457566 merged concurrent to main library
removed PIConditionLock, use PIMutex instead
2020-07-30 18:50:42 +03:00
4dd59132d5 LUA lib status, some fixes 2020-07-30 16:17:45 +03:00
48692a4724 remove remote_console 2020-07-30 00:20:19 +03:00
4de3a052f1 time to merge v2 to master 2020-07-29 01:30:46 +03:00
b153673974 CMakeLists.txt 2020-07-27 17:54:07 +03:00
abbbce1380 Merge branch 'pip_2' of https://git.shs.tools/SHS/pip into pip_2 2020-07-25 13:13:58 +03:00
e82831377a CMakeLists.txt 2020-07-25 13:13:53 +03:00
9bd87dcc63 поправил PIP_CONCURRENT_TEST 2020-07-24 14:42:49 +03:00
cdbc401616 fixed FindPIP with Lua 2020-07-24 14:04:19 +03:00
e63aab40f6 fix FindPIP.cmake 2020-07-24 12:14:00 +03:00
422dad847e Merge remote-tracking branch 'remotes/origin/lua' into pip_2 2020-07-23 17:15:36 +03:00
6f58388d8d PILuaProgram 2020-07-22 23:00:31 +03:00
16bbcddf50 PIP Lua Module 2020-07-22 22:20:54 +03:00
b018ea9e07 PIString test for Lua 2020-07-22 21:22:20 +03:00
94c09e1131 test lua support 2020-07-22 21:11:33 +03:00
14f0c192d8 Merge branch 'master' of https://git.shs.tools/SHS/pip into pip_2 2020-07-22 12:15:22 +03:00
20c58f5423 fix cmake for tests 2020-07-20 18:22:55 +03:00
8efd2cf447 Rewrite executor to template & come back executor unit tests 2020-07-17 18:36:28 +03:00
b772928dc1 #15 убрать PIP_CXX11_SUPPORT 2020-07-17 11:51:30 +03:00
33a6382f4d NO_COPY_CLASS c++11 2020-07-17 11:46:21 +03:00
1a3096c48b PIMutex typedef std::mutex, patch PIMutexLocker, replace volatile by atomic 2020-07-17 11:32:04 +03:00
6f5c864e9f PIMutex as std::mutex 2020-07-17 11:14:11 +03:00
ea624a5111 pip_test clear 2020-07-16 13:58:55 +03:00
c642702265 fix main.cpp 2020-07-16 13:44:15 +03:00
478f0a7fd3 arch 32 piswap fixes 2020-07-16 13:41:29 +03:00
1045b274fb fix test main.cpp 2020-07-16 12:52:44 +03:00
5fd429cca6 version 2020-07-16 12:51:34 +03:00
ffd1af904d Merge branch 'master' of https://git.shs.tools/SHS/pip 2020-07-16 12:48:26 +03:00
32f16fdb64 optimize piSwap and c++11 improvments 2020-07-16 12:48:20 +03:00
2f57945c34 Merge pull request 'Added additional poll method without timeout' (#12) from concurrent into master 2020-07-16 12:06:16 +03:00
5df43a45f2 Added additional poll method without timeout 2020-07-16 11:59:47 +03:00
835e6c7773 code clean 2020-07-10 16:57:02 +03:00
614370096c Merge pull request 'Fixed tests and improve multithread sync' (#9) from atomic into master 2020-07-08 15:36:36 +03:00
6cb1040b56 version 2020-07-08 15:27:36 +03:00
6feb628a94 Fixed tests and improve multithread sync 2020-07-07 17:29:59 +03:00
101164902a Merge branch 'master' into picloud 2020-06-28 09:09:59 +03:00
2dfbbf80b7 clean, fix FindPIP.cmake 2020-06-28 01:03:29 +03:00
42925122cb version 1.22.0
source tree changed
detached PIConsole and PIScreen* in "pip_console" library
2020-06-28 00:18:24 +03:00
5de62b1c83 FindPIP patch 2020-06-26 09:51:05 +03:00
d3ffc19610 Merge commit '02ac4020d3f7a948c87dd0349db093934c0aed3c' into picloud 2020-06-18 19:09:21 +03:00
02ac4020d3 api fixes, PIStreamPacker potential fixes 2020-06-18 17:14:33 +03:00
4910631ce8 PIObject::scopeList() fix
DeployMacros supports for "$<>" files
2020-06-17 16:49:02 +03:00
3f7f67e198 picloud start develop 2020-06-15 11:09:34 +03:00
f662a92380 Merge branch 'master' of https://git.shs.tools/SHS/pip 2020-06-10 15:36:41 +03:00
5f8f8e0050 remove pifixedpoint.h 2020-06-10 15:36:36 +03:00
286 changed files with 32583 additions and 26075 deletions

View File

@@ -1,737 +1,689 @@
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 1) set(_PIP_MAJOR 1)
set(_PIP_MINOR 20) set(_PIP_MINOR 99)
set(_PIP_REVISION 0) set(_PIP_REVISION 3)
set(_PIP_SUFFIX alpha) set(_PIP_SUFFIX _prebeta)
set(_PIP_COMPANY SHS) set(_PIP_COMPANY SHS)
set(_PIP_DOMAIN org.SHS) set(_PIP_DOMAIN org.SHS)
if ("x${CMAKE_MODULE_PATH}" STREQUAL "x") if ("x${CMAKE_MODULE_PATH}" STREQUAL "x")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
endif() endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
set(PIP_BUILD 1) set(PIP_BUILD 1)
include(CheckFunctionExists) include(CheckFunctionExists)
include(DeployMacros) include(GenerateExportHeader)
include(PIPMacros) include(DeployMacros)
if(NOT DEFINED BUILD_NUMBER) include(PIPMacros)
set(BUILD_NUMBER 9999) if(NOT DEFINED BUILD_NUMBER)
endif() set(BUILD_NUMBER 9999)
if("x${BUILD_NUMBER}" STREQUAL "x") endif()
set(BUILD_NUMBER 0) if("x${BUILD_NUMBER}" STREQUAL "x")
endif() set(BUILD_NUMBER 0)
endif()
set(_ICU_DEFAULT OFF)
if((NOT DEFINED WIN32) AND (NOT DEFINED ANDROID_PLATFORM) AND (NOT DEFINED APPLE)) set(_ICU_DEFAULT OFF)
set(_ICU_DEFAULT ON) if((NOT DEFINED WIN32) AND (NOT DEFINED ANDROID_PLATFORM) AND (NOT DEFINED APPLE))
endif() set(_ICU_DEFAULT ON)
endif()
# Options
option(ICU "ICU support for convert codepages" ${_ICU_DEFAULT}) # Options
option(STD_IOSTREAM "Building with std iostream operators support" OFF) option(ICU "ICU support for convert codepages" ${_ICU_DEFAULT})
option(INTROSPECTION "Build with introspection" OFF) option(STD_IOSTREAM "Building with std iostream operators support" OFF)
option(LIB "System install" ON) option(INTROSPECTION "Build with introspection" OFF)
option(STATIC_LIB OFF) option(LIB "System install" ON)
option(TESTS "Build tests and perform their before install step" OFF) option(STATIC_LIB OFF)
set(PIP_UTILS 1) option(TESTS "Build tests and perform their before install step" OFF)
if(LIBPROJECT) set(PIP_UTILS 1)
set(PIP_UTILS ${UTILS}) if(LIBPROJECT)
endif() set(PIP_UTILS ${UTILS})
set(CMAKE_CXX_STANDARD 11) endif()
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_STANDARD 11)
# Basic
macro(gather_src DIR CPP H H_P)
set(CS) # Basic
set(HS) set(PIP_MODULES)
set(PHS) set(LIBS_MAIN)
file(GLOB CS "${DIR}/*.cpp") set(LIBS_STATUS)
file(GLOB HS "${DIR}/*.h") set(HDRS)
file(GLOB PHS "${DIR}/*_p.h") set(PHDRS)
list(REMOVE_ITEM HS "${PHS}") set(HDR_DIRS)
list(APPEND ${CPP} ${CS}) set(PIP_UTILS_LIST)
list(APPEND ${H} ${HS}) set(PIP_TESTS_LIST)
list(APPEND ${H_P} ${PHS}) set(PIP_EXPORTS)
endmacro()
set(PIP_SRC_MODULES "console;crypt;compress;usb;fftw;opencl;io_utils;cloud;lua")
set(PIP_SRC_MAIN "src_main") foreach(_m ${PIP_SRC_MODULES})
set(PIP_SRC_CRYPT "src_crypt") set(PIP_MSG_${_m} "no")
set(PIP_SRC_COMPRESS "src_compress") endforeach()
set(PIP_SRC_USB "src_usb")
set(PIP_SRC_FFTW "src_fftw") macro(pip_module NAME LIBS LABEL INCLUDES MSG)
set(PIP_SRC_OPENCL "src_opencl") set(CPPS)
set(PIP_SRC_IO_UTILS "src_io_utils") set(HS)
set(PIP_SRC_CONCURRENT "src_concurrent") set(PHS)
set(PIP_SRC_CLOUD "src_cloud") set(CRES)
set(PIP_SRC_DIRS "src_main" "src_crypt" "src_compress" "src_usb" "src_fftw" "src_opencl" "src_io_utils" "src_concurrent" "src_cloud") file(GLOB_RECURSE CPPS "lib/${NAME}/*.cpp")
set(PIP_LIBS_TARGETS pip) file(GLOB_RECURSE HS "lib/${NAME}/*.h")
set(LIBS_MAIN) file(GLOB_RECURSE PHS "lib/${NAME}/*_p.h")
set(LIBS_STATUS) file(GLOB_RECURSE RES "lib/${NAME}/*conf.h")
set(HDRS) list(REMOVE_ITEM HS "${PHS}")
set(PHDRS) list(APPEND HDRS ${HS})
list(APPEND PHDRS ${PHS})
if (TESTS)
set(PIP_SRC_CONCURRENT_TEST "src_concurrent/test") set(_target "pip_${NAME}")
endif() set(_libs "${LIBS}")
if ("${NAME}" STREQUAL "main")
if (DEFINED ENV{QNX_HOST} OR PIP_FREERTOS) set(_target "pip")
set(STATIC_LIB ON) else()
endif() list(APPEND _libs "pip")
endif()
if(STATIC_LIB) string(TOUPPER "${_target}" DEF_NAME)
set(PIP_LIB_TYPE STATIC)
add_definitions(-DPIP_STATIC_DEFINE) set(PIP_MSG_${NAME} "yes${MSG}")
#message(STATUS "Building PIP static library") import_version(${_target} PIP)
else() set_deploy_property(${_target} ${PIP_LIB_TYPE}
set(PIP_LIB_TYPE SHARED) LABEL "${LABEL}"
#message(STATUS "Building PIP shared library") FULLNAME "${_PIP_DOMAIN}.${_target}"
endif() COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(${_target} _RC)
# Version
set_version(PIP set(LINK_LIBS)
MAJOR "${_PIP_MAJOR}" foreach (_l ${_libs})
MINOR "${_PIP_MINOR}" if (${${_l}_FOUND})
REVISION "${_PIP_REVISION}" list(APPEND LINK_LIBS ${${_l}_LIBRARIES})
BUILD "${BUILD_NUMBER}" else()
SUFFIX "${_PIP_SUFFIX}" list(APPEND LINK_LIBS ${_l})
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/piversion.h") endif()
set_deploy_property(pip ${PIP_LIB_TYPE} endforeach()
LABEL "PIP main library"
FULLNAME "${_PIP_DOMAIN}.pip" if (NOT "${RES}" STREQUAL "")
COMPANY "${_PIP_COMPANY}" pip_resources(CRES "${RES}")
INFO "Platform-Independent Primitives") endif()
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h") add_definitions(-D${DEF_NAME})
file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h") add_library(${_target} ${PIP_LIB_TYPE} ${CPPS} ${CRES} ${_RC})
endif() if (NOT "${RES}" STREQUAL "")
list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/piversion.h") add_dependencies(${_target} pip_rc)
message(STATUS "Building PIP version ${PIP_VERSION} (${PIP_LIB_TYPE})") endif()
if (NOT "${INCLUDES}" STREQUAL "")
target_include_directories(${_target} PRIVATE ${INCLUDES})
if(MINGW) endif()
find_package(MinGW REQUIRED) generate_export_header(${_target})
list(APPEND CMAKE_LIBRARY_PATH ${MINGW_LIB}) list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/${_target}_export.h")
else() list(APPEND PIP_EXPORTS "${DEF_NAME}_EXPORT")
if(APPLE) target_link_libraries(${_target} ${LINK_LIBS})
if(CMAKE_CROSSCOMPILING) list(APPEND PIP_MODULES ${_target})
set(CMAKE_INSTALL_NAME_DIR "@rpath") if (NOT "${LIBS}" STREQUAL "")
else() list(APPEND LIBS_STATUS ${LIBS})
include_directories(/usr/local/include) endif()
link_directories(/usr/local/lib) endmacro()
endif()
set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/lib;@loader_path/../lib") macro(pip_find_lib NAME)
set(CMAKE_MACOSX_RPATH 1) find_library(${NAME}_LIBRARIES ${NAME} ${ARGN})
else() set(${NAME}_FOUND FALSE)
set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib") if(${NAME}_LIBRARIES)
endif() set(${NAME}_FOUND TRUE)
endif() endif()
if(LIB) endmacro()
if(WIN32)
if(MINGW) if (DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) set(STATIC_LIB ON)
endif() endif()
else()
if (DEFINED ANDROID_PLATFORM) if(STATIC_LIB)
set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr) set(PIP_LIB_TYPE STATIC)
else() set(PIP_LIB_TYPE_MSG "Static")
if(CMAKE_CROSSCOMPILING) add_definitions(-DPIP_STATIC_DEFINE)
set(CMAKE_INSTALL_PREFIX ${CMAKE_STAGING_PREFIX}) else()
else() set(PIP_LIB_TYPE SHARED)
set(CMAKE_INSTALL_PREFIX ${INSTALL_PREFIX}/usr/local) set(PIP_LIB_TYPE_MSG "Shared")
endif() endif()
endif()
endif()
endif() # Version
set_version(PIP
if (NOT DEFINED PIP_CMG) MAJOR "${_PIP_MAJOR}"
if (CMAKE_CROSSCOMPILING OR (DEFINED ANDROID_PLATFORM)) MINOR "${_PIP_MINOR}"
set(PIP_CMG "pip_cmg") REVISION "${_PIP_REVISION}"
set(PIP_RC "pip_rc") BUILD "${BUILD_NUMBER}"
set(PIP_DEPLOY_TOOL "deploy_tool") SUFFIX "${_PIP_SUFFIX}"
else() OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/piversion.h")
set(PIP_CMG "${CMAKE_CURRENT_BINARY_DIR}/utils/code_model_generator/pip_cmg") if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h")
set(PIP_RC "${CMAKE_CURRENT_BINARY_DIR}/utils/resources_compiler/pip_rc") file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h")
set(PIP_DEPLOY_TOOL "${CMAKE_CURRENT_BINARY_DIR}/utils/deploy_tool/deploy_tool") endif()
endif() list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/piversion.h")
endif()
if(MINGW)
find_package(MinGW REQUIRED)
# Compiler list(APPEND CMAKE_LIBRARY_PATH ${MINGW_LIB})
get_filename_component(C_COMPILER "${CMAKE_C_COMPILER}" NAME) else()
#message("${C_COMPILER}") if(APPLE)
if(CMAKE_CROSSCOMPILING)
set(CMAKE_INSTALL_NAME_DIR "@rpath")
# Sources else()
include_directories(/usr/local/include)
# Main lib link_directories(/usr/local/lib)
set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io_devices" "io_utils" "console" "math" "code" "geo" "resources" "opencl" "crypt" "introspection" "concurrent" "cloud") endif()
include_directories("${PIP_SRC_MAIN}") set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/lib;@loader_path/../lib")
set(PIP_MAIN_FOLDERS) set(CMAKE_MACOSX_RPATH 1)
foreach(F ${PIP_FOLDERS}) else()
list(APPEND PIP_MAIN_FOLDERS "\"${PROJECT_SOURCE_DIR}/${PIP_SRC_MAIN}/${F}\"") set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib")
include_directories("${PIP_SRC_MAIN}/${F}") endif()
gather_src("${PIP_SRC_MAIN}/${F}" CPP_LIB_MAIN HDRS PHDRS) endif()
endforeach(F) if(LIB)
# Crypt lib if(WIN32)
gather_src("${PIP_SRC_CRYPT}" CPP_LIB_CRYPT HDRS PHDRS) if(MINGW)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
# Compress lib endif()
gather_src("${PIP_SRC_COMPRESS}" CPP_LIB_COMPRESS HDRS PHDRS) else()
if (DEFINED ANDROID_PLATFORM)
# USB lib set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr)
gather_src("${PIP_SRC_USB}" CPP_LIB_USB HDRS PHDRS) else()
if(CMAKE_CROSSCOMPILING)
# FFTW lib set(CMAKE_INSTALL_PREFIX ${CMAKE_STAGING_PREFIX})
gather_src("${PIP_SRC_FFTW}" CPP_LIB_FFTW HDRS PHDRS) else()
set(CMAKE_INSTALL_PREFIX ${INSTALL_PREFIX}/usr/local)
# OpenCL lib endif()
gather_src("${PIP_SRC_OPENCL}" CPP_LIB_OPENCL HDRS PHDRS) endif()
endif()
# IO Utils lib endif()
gather_src("${PIP_SRC_IO_UTILS}" CPP_LIB_IO_UTILS HDRS PHDRS)
if (NOT DEFINED PIP_CMG)
# Concurrent lib if (CMAKE_CROSSCOMPILING OR (DEFINED ANDROID_PLATFORM))
gather_src("${PIP_SRC_CONCURRENT}" CPP_LIB_CONCURRENT HDRS PHDRS) set(PIP_CMG "pip_cmg")
set(PIP_RC "pip_rc")
gather_src("${PIP_SRC_CONCURRENT_TEST}" CPP_CONCURRENT_TEST HDRS PHDRS) set(PIP_DEPLOY_TOOL "deploy_tool")
else()
# Cloud lib set(PIP_CMG "${CMAKE_CURRENT_BINARY_DIR}/utils/code_model_generator/pip_cmg")
gather_src("${PIP_SRC_CLOUD}" CPP_LIB_CLOUD HDRS PHDRS) set(PIP_RC "${CMAKE_CURRENT_BINARY_DIR}/utils/resources_compiler/pip_rc")
set(PIP_DEPLOY_TOOL "${CMAKE_CURRENT_BINARY_DIR}/utils/deploy_tool/deploy_tool")
if(PIP_FREERTOS) endif()
add_definitions(-DPIP_FREERTOS) endif()
set(ICU OFF)
set(LIB OFF)
endif() # Compiler
get_filename_component(C_COMPILER "${CMAKE_C_COMPILER}" NAME)
# Check Bessel functions
set(CMAKE_REQUIRED_INCLUDES math.h)
set(CMAKE_REQUIRED_LIBRARIES m) # Main lib
CHECK_FUNCTION_EXISTS(j0 PIP_MATH_J0) file(GLOB PIP_FOLDERS LIST_DIRECTORIES TRUE "${CMAKE_CURRENT_SOURCE_DIR}/lib/main/*")
CHECK_FUNCTION_EXISTS(j1 PIP_MATH_J1) list(APPEND PIP_FOLDERS "${CMAKE_CURRENT_SOURCE_DIR}/lib/main")
CHECK_FUNCTION_EXISTS(jn PIP_MATH_JN) set(PIP_MAIN_FOLDERS)
CHECK_FUNCTION_EXISTS(y0 PIP_MATH_Y0) foreach(F ${PIP_FOLDERS})
CHECK_FUNCTION_EXISTS(y1 PIP_MATH_Y1) if (IS_DIRECTORY "${F}")
CHECK_FUNCTION_EXISTS(yn PIP_MATH_YN) list(APPEND PIP_MAIN_FOLDERS "${F}")
if(PIP_MATH_J0) include_directories("${F}")
add_definitions(-DPIP_MATH_J0) endif()
endif() endforeach(F)
if(PIP_MATH_J1) if (DEFINED LIBPROJECT)
add_definitions(-DPIP_MATH_J1) set(PIP_MAIN_FOLDERS "${PIP_MAIN_FOLDERS}" PARENT_SCOPE)
endif() endif()
if(PIP_MATH_JN)
add_definitions(-DPIP_MATH_JN) if (TESTS)
endif() set(PIP_ROOT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
if(PIP_MATH_Y0) add_subdirectory(tests)
add_definitions(-DPIP_MATH_Y0) endif()
endif()
if(PIP_MATH_Y1) if(PIP_FREERTOS)
add_definitions(-DPIP_MATH_Y1) add_definitions(-DPIP_FREERTOS)
endif() set(ICU OFF)
if(PIP_MATH_YN) set(LIB OFF)
add_definitions(-DPIP_MATH_YN) endif()
endif()
# Check Bessel functions
set(CMAKE_REQUIRED_INCLUDES math.h)
# Check if RT timers exists set(CMAKE_REQUIRED_LIBRARIES m)
set(CMAKE_REQUIRED_INCLUDES time.h) CHECK_FUNCTION_EXISTS(j0 PIP_MATH_J0)
set(CMAKE_REQUIRED_LIBRARIES ) CHECK_FUNCTION_EXISTS(j1 PIP_MATH_J1)
if((NOT DEFINED ENV{QNX_HOST}) AND (NOT APPLE) AND (NOT WIN32) AND (NOT DEFINED ANDROID_PLATFORM) AND (NOT PIP_FREERTOS)) CHECK_FUNCTION_EXISTS(jn PIP_MATH_JN)
list(APPEND LIBS_MAIN rt) CHECK_FUNCTION_EXISTS(y0 PIP_MATH_Y0)
set(CMAKE_REQUIRED_LIBRARIES rt) CHECK_FUNCTION_EXISTS(y1 PIP_MATH_Y1)
endif() CHECK_FUNCTION_EXISTS(yn PIP_MATH_YN)
CHECK_FUNCTION_EXISTS(timer_create PIP_TIMER_RT_0) if(PIP_MATH_J0)
CHECK_FUNCTION_EXISTS(timer_settime PIP_TIMER_RT_1) add_definitions(-DPIP_MATH_J0)
CHECK_FUNCTION_EXISTS(timer_delete PIP_TIMER_RT_2) endif()
if(PIP_MATH_J1)
add_definitions(-DPIP_MATH_J1)
# Check if build debug version endif()
if (CMAKE_BUILD_TYPE MATCHES Debug) if(PIP_MATH_JN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall") add_definitions(-DPIP_MATH_JN)
add_definitions(-DPIP_DEBUG) endif()
message(STATUS "Building PIP debug version") if(PIP_MATH_Y0)
else() add_definitions(-DPIP_MATH_Y0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall") endif()
message(STATUS "Building PIP release version") if(PIP_MATH_Y1)
endif() add_definitions(-DPIP_MATH_Y1)
endif()
if (TESTS) if(PIP_MATH_YN)
include(DownloadGTest) add_definitions(-DPIP_MATH_YN)
set(CONCURRENT_TESTS 1) #"Enable tests for concurrent library" endif()
else()
set(CONCURRENT_TESTS 0)
endif() # Check if RT timers exists
set(CMAKE_REQUIRED_INCLUDES time.h)
# Check if std::iostream operators support set(CMAKE_REQUIRED_LIBRARIES )
if(STD_IOSTREAM) if((NOT DEFINED ENV{QNX_HOST}) AND (NOT APPLE) AND (NOT WIN32) AND (NOT DEFINED ANDROID_PLATFORM) AND (NOT PIP_FREERTOS))
add_definitions(-DPIP_STD_IOSTREAM) list(APPEND LIBS_MAIN rt)
message(STATUS "Building PIP with std iostream operators support") set(CMAKE_REQUIRED_LIBRARIES rt)
else() endif()
message(STATUS "Building PIP without std iostream operators support") CHECK_FUNCTION_EXISTS(timer_create PIP_TIMER_RT_0)
endif() CHECK_FUNCTION_EXISTS(timer_settime PIP_TIMER_RT_1)
CHECK_FUNCTION_EXISTS(timer_delete PIP_TIMER_RT_2)
# Check if ICU used for PIString and PIChar
if(ICU) # Check if build debug version
message(STATUS "Building PIP with ICU") if (CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-DPIP_ICU) set(PIP_BUILD_TYPE "Debug")
list(APPEND LIBS_MAIN icuuc) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall")
else() add_definitions(-DPIP_DEBUG)
message(STATUS "Building PIP without ICU") else()
endif() set(PIP_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
endif()
# Check if PIP should be built with introspection
set(_PIP_DEFS "")
set(_PIP_DEFS_FILE "${CMAKE_CURRENT_BINARY_DIR}/pip_defs.h") # Check if std::iostream operators support
if(INTROSPECTION) set(PIP_STD_IOSTREAM "no")
message(STATUS "Building PIP with introspection") if(STD_IOSTREAM)
message(STATUS "Warning: Introspection reduces the performance!") set(PIP_STD_IOSTREAM "yes")
add_definitions(-DPIP_INTROSPECTION) add_definitions(-DPIP_STD_IOSTREAM)
set(_PIP_DEFS "PIP_INTROSPECTION") endif()
else()
message(STATUS "Building PIP without introspection")
endif() # Check if ICU used for PIString and PIChar
if ((NOT DEFINED _PIP_SAVED_DEFS) OR (NOT "x${_PIP_SAVED_DEFS}" STREQUAL "x${_PIP_DEFS}")) set(PIP_ICU "no")
set(_PIP_SAVED_DEFS "${_PIP_DEFS}" CACHE STRING "pip_defs" FORCE) if(ICU)
file(WRITE ${_PIP_DEFS_FILE} "// This file was generated by PIP CMake, don`t edit it!\n") set(PIP_ICU "yes")
if (NOT "x${_PIP_DEFS}" STREQUAL "x") add_definitions(-DPIP_ICU)
file(APPEND ${_PIP_DEFS_FILE} "#ifndef ${_PIP_DEFS}\n# define ${_PIP_DEFS}\n#endif\n") list(APPEND LIBS_MAIN icuuc)
endif() endif()
endif()
list(APPEND HDRS ${_PIP_DEFS_FILE})
#message("${_PIP_DEFS_CHANGED}") # Check if PIP should be built with introspection
set(_PIP_DEFS "")
set(_PIP_DEFS_FILE "${CMAKE_CURRENT_BINARY_DIR}/pip_defs.h")
# Check if RT timers exists set(PIP_INTROSPECTION "no")
if(PIP_TIMER_RT_0 AND PIP_TIMER_RT_1 AND PIP_TIMER_RT_2) if(INTROSPECTION)
add_definitions(-DPIP_TIMER_RT) set(PIP_INTROSPECTION "yes")
message(STATUS "Building PIP with timers: Thread, ThreadRT, Pool") add_definitions(-DPIP_INTROSPECTION)
else() set(_PIP_DEFS "PIP_INTROSPECTION")
message(STATUS "Building PIP with timers: Thread, Pool") endif()
endif() if ((NOT DEFINED _PIP_SAVED_DEFS) OR (NOT "x${_PIP_SAVED_DEFS}" STREQUAL "x${_PIP_DEFS}"))
set(_PIP_SAVED_DEFS "${_PIP_DEFS}" CACHE STRING "pip_defs" FORCE)
file(WRITE ${_PIP_DEFS_FILE} "// This file was generated by PIP CMake, don`t edit it!\n")
if (NOT "x${_PIP_DEFS}" STREQUAL "x")
# Add main library file(APPEND ${_PIP_DEFS_FILE} "#ifndef ${_PIP_DEFS}\n# define ${_PIP_DEFS}\n#endif\n")
if(APPLE) endif()
add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) endif()
endif() list(APPEND HDRS ${_PIP_DEFS_FILE})
if ((NOT DEFINED LIBPROJECT) AND (DEFINED ANDROID_PLATFORM)) #message("${_PIP_DEFS_CHANGED}")
include_directories(${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include)
#message("${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include")
#message("${ANDROID_NDK}/sysroot/usr/include") # Check if RT timers exists
endif() if(PIP_TIMER_RT_0 AND PIP_TIMER_RT_1 AND PIP_TIMER_RT_2)
if(NOT PIP_FREERTOS) set(PIP_TIMERS "Thread, ThreadRT, Pool")
if(WIN32) add_definitions(-DPIP_TIMER_RT)
if(${C_COMPILER} STREQUAL "cl.exe") else()
else() set(PIP_TIMERS "Thread, Pool")
list(APPEND LIBS_MAIN ws2_32 iphlpapi psapi cfgmgr32 setupapi) endif()
endif()
else()
list(APPEND LIBS_MAIN dl)
if(DEFINED ENV{QNX_HOST}) # Add main library
list(APPEND LIBS_MAIN socket) if(APPLE)
else() add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
if (NOT DEFINED ANDROID_PLATFORM) endif()
list(APPEND LIBS_MAIN pthread util) if ((NOT DEFINED LIBPROJECT) AND (DEFINED ANDROID_PLATFORM))
endif() include_directories(${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include)
endif() #message("${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include")
endif() #message("${ANDROID_NDK}/sysroot/usr/include")
endif() endif()
set(PIP_LIBS) if(NOT PIP_FREERTOS)
if(PIP_FREERTOS) if(WIN32)
set(PIP_LIBS ${LIBS_MAIN}) if(${C_COMPILER} STREQUAL "cl.exe")
else() else()
foreach(LIB_ ${LIBS_MAIN}) list(APPEND LIBS_MAIN ws2_32 iphlpapi psapi cfgmgr32 setupapi)
find_library(${LIB_}_FOUND ${LIB_}) endif()
if(${LIB_}_FOUND) else()
list(APPEND CMAKE_REQUIRED_LIBRARIES ${${LIB_}_FOUND}) list(APPEND LIBS_MAIN dl)
list(APPEND PIP_LIBS ${${LIB_}_FOUND}) if(DEFINED ENV{QNX_HOST})
endif() list(APPEND LIBS_MAIN socket)
endforeach() else()
endif() if (NOT DEFINED ANDROID_PLATFORM)
list(APPEND LIBS_STATUS ${LIBS_MAIN}) list(APPEND LIBS_MAIN pthread util)
import_version(pip PIP) endif()
if(WIN32) endif()
make_rc(pip _RC) endif()
add_definitions(-DPSAPI_VERSION=1) endif()
add_library(pip ${PIP_LIB_TYPE} ${CPP_LIB_MAIN} ${HDRS} ${PHDRS} ${_RC}) set(PIP_LIBS)
if(${C_COMPILER} STREQUAL "cl.exe") if(PIP_FREERTOS)
set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0") set(PIP_LIBS ${LIBS_MAIN})
endif() else()
else() foreach(LIB_ ${LIBS_MAIN})
set(${CMAKE_CXX_FLAGS} "${CMAKE_CXX_FLAGS} -fPIC") pip_find_lib(${LIB_})
if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS) endforeach()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32") endif()
else() import_version(pip PIP)
endif() if(WIN32)
add_library(pip ${PIP_LIB_TYPE} ${CPP_LIB_MAIN}) add_definitions(-DPSAPI_VERSION=1)
endif() if(${C_COMPILER} STREQUAL "cl.exe")
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0")
include(GenerateExportHeader) endif()
generate_export_header(pip) else()
list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/pip_export.h") set(${CMAKE_CXX_FLAGS} "${CMAKE_CXX_FLAGS} -fPIC")
target_link_libraries(pip ${PIP_LIBS}) if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32")
if (NOT CROSSTOOLS) endif()
if (NOT PIP_FREERTOS) endif()
# Check if USB is supported set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}")
find_library(usb_FOUND usb SHARED)
if(usb_FOUND)
message(STATUS "Building PIP with USB support") pip_module(main "${LIBS_MAIN}" "PIP main library" "" "")
import_version(pip_usb pip)
set_deploy_property(pip_usb ${PIP_LIB_TYPE}
LABEL "PIP usb support" if (NOT CROSSTOOLS)
FULLNAME "${_PIP_DOMAIN}.pip_usb" if (NOT PIP_FREERTOS)
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_usb _RC) pip_module(console "" "PIP console support" "" "")
add_definitions(-DPIP_USB)
add_library(pip_usb ${PIP_LIB_TYPE} ${CPP_LIB_USB} ${_RC})
target_link_libraries(pip_usb pip ${usb_FOUND}) pip_find_lib(usb)
list(APPEND LIBS_STATUS usb) if(usb_FOUND)
list(APPEND PIP_LIBS_TARGETS pip_usb) pip_module(usb "usb" "PIP usb support" "" "")
else() endif()
message(STATUS "Building PIP without USB support")
endif()
pip_find_lib(zlib NAMES z zlib)
if(zlib_FOUND)
# Check if PIP support cryptographic encryption/decryption using sodium library pip_module(compress "zlib" "PIP compression support" "" "")
find_library(sodium_FOUND sodium) endif()
if(sodium_FOUND)
message(STATUS "Building PIP with crypt support")
import_version(pip_crypt pip) pip_find_lib(sodium)
set_deploy_property(pip_crypt ${PIP_LIB_TYPE} if(sodium_FOUND)
LABEL "PIP crypt support" pip_module(crypt "sodium" "PIP crypt support" "" "")
FULLNAME "${_PIP_DOMAIN}.pip_crypt" pip_module(cloud "pip_crypt" "PIP cloud support" "" "")
COMPANY "${_PIP_COMPANY}" endif()
INFO "Platform-Independent Primitives")
make_rc(pip_crypt _RC)
add_definitions(-DPIP_CRYPT) # Check if PIP support fftw3 for PIFFT using in math module
add_library(pip_crypt ${PIP_LIB_TYPE} ${CPP_LIB_CRYPT} ${_RC}) set(FFTW_LIB_NAME fftw3)
target_link_libraries(pip_crypt pip ${sodium_FOUND}) set(FFTW_LIB_SUFFIXES "" "f" "l" "q")
list(APPEND LIBS_STATUS sodium) set(FFTW_LIB_SUFFIXES2 "" "-3")
list(APPEND PIP_LIBS_TARGETS pip_crypt) set(FFTW_LIBS)
else() set(FFTW_ABS_LIBS)
message(STATUS "Building PIP without crypt support") set(CMAKE_REQUIRED_INCLUDES fftw3.h)
endif() foreach(FFTW_S_ IN LISTS FFTW_LIB_SUFFIXES)
set(FFTW_BREAK false)
foreach(FFTW_S2_ IN LISTS FFTW_LIB_SUFFIXES2)
# Check if PIP support compress/decompress using zlib library if(NOT FFTW_BREAK)
find_library(zlib_FOUND NAMES z zlib) set(FFTW_CLN "${FFTW_LIB_NAME}${FFTW_S_}${FFTW_S2_}")
if(zlib_FOUND) set(FFTW_CLNT "${FFTW_LIB_NAME}${FFTW_S_}_threads${FFTW_S2_}")
message(STATUS "Building PIP with zlib compress support") find_library(${FFTW_CLN}_LIBRARIES ${FFTW_CLN})
import_version(pip_compress pip) find_library(${FFTW_CLNT}_LIBRARIES ${FFTW_CLNT})
set_deploy_property(pip_compress ${PIP_LIB_TYPE} set(${FFTW_CLN}_FOUND FALSE)
LABEL "PIP compression support" set(${FFTW_CLNT}_FOUND FALSE)
FULLNAME "${_PIP_DOMAIN}.pip_compress" if(${FFTW_CLN}_LIBRARIES)
COMPANY "${_PIP_COMPANY}" set(${FFTW_CLN}_FOUND TRUE)
INFO "Platform-Independent Primitives") list(APPEND FFTW_LIBS "${FFTW_CLN}")
make_rc(pip_compress _RC) list(APPEND FFTW_ABS_LIBS "${${FFTW_CLN}_LIBRARIES}")
add_definitions(-DPIP_COMPRESS) set(${FFTW_CLN}_CTS "${FFTW_CLN}")
add_library(pip_compress ${PIP_LIB_TYPE} ${CPP_LIB_COMPRESS} ${_RC}) if(${FFTW_CLNT}_FLIBRARIES)
target_link_libraries(pip_compress pip ${zlib_FOUND}) set(${FFTW_CLNT}_FOUND TRUE)
list(APPEND LIBS_STATUS zlib) list(APPEND FFTW_LIBS "${FFTW_CLNT}")
list(APPEND PIP_LIBS_TARGETS pip_compress) list(APPEND FFTW_ABS_LIBS "${${FFTW_CLNT}_LIBRARIES}")
else() list(APPEND ${FFTW_CLN}_CTS "${FFTW_CLNT}")
message(STATUS "Building PIP without compress support") endif()
endif() set(CMAKE_REQUIRED_LIBRARIES ${${FFTW_CLN}_CTS})
CHECK_FUNCTION_EXISTS(fftw${FFTW_S_}_make_planner_thread_safe ${FFTW_CLN}_TSFE)
add_definitions(-DPIP_FFTW${FFTW_S_})
# Check if PIP support fftw3 for PIFFT using in math module if(${FFTW_CLN}_TSFE)
set(FFTW_LIB_NAME fftw3) add_definitions(-DPIP_FFTW${FFTW_S_}_THREADSAFE)
set(FFTW_LIB_SUFFIXES "" "f" "l" "q") else()
set(FFTW_LIB_SUFFIXES2 "" "-3") message(STATUS "Warning: PIFFTW${FFTW_S_}::preparePlan was not threadsafe")
set(FFTW_LIBS) endif()
set(FFTW_ABS_LIBS) endif()
set(PIP_FFTW_FOUND) endif()
set(CMAKE_REQUIRED_INCLUDES fftw3.h) endforeach()
foreach(FFTW_S_ IN LISTS FFTW_LIB_SUFFIXES) endforeach()
set(FFTW_BREAK false) if(FFTW_LIBS)
foreach(FFTW_S2_ IN LISTS FFTW_LIB_SUFFIXES2) pip_module(fftw "${FFTW_LIBS}" "PIP FFTW support" "" "")
if(NOT FFTW_BREAK) endif()
set(FFTW_CLN "${FFTW_LIB_NAME}${FFTW_S_}${FFTW_S2_}")
set(FFTW_CLNT "${FFTW_LIB_NAME}${FFTW_S_}_threads${FFTW_S2_}")
find_library(${FFTW_CLN}_FOUND ${FFTW_CLN}) find_package(OpenCL QUIET) #OpenCL_VERSION_STRING
find_library(${FFTW_CLNT}_FOUND ${FFTW_CLNT}) if(OpenCL_FOUND)
if(${FFTW_CLN}_FOUND) set(_opencl_lib OpenCL::OpenCL)
list(APPEND FFTW_LIBS "${FFTW_CLN}") if(${CMAKE_VERSION} VERSION_LESS "3.7.0")
list(APPEND FFTW_ABS_LIBS "${${FFTW_CLN}_FOUND}") target_link_libraries(_opencl_lib OpenCL)
#message(STATUS "PIFFTW found ${FFTW_CLN} = ${${FFTW_CLN}_FOUND}") endif()
set(${FFTW_CLN}_CTS "${FFTW_CLN}") pip_module(opencl "${_opencl_lib}" "PIP OpenCL support" "" " (${OpenCL_VERSION_STRING})")
if(${FFTW_CLNT}_FOUND) endif()
list(APPEND FFTW_LIBS "${FFTW_CLNT}")
list(APPEND FFTW_ABS_LIBS "${${FFTW_CLNT}_FOUND}")
list(APPEND ${FFTW_CLN}_CTS "${FFTW_CLNT}") if(sodium_FOUND)
endif() pip_module(io_utils "pip_crypt" "PIP I/O support" "" " (+crypt)")
set(CMAKE_REQUIRED_LIBRARIES ${${FFTW_CLN}_CTS}) else()
CHECK_FUNCTION_EXISTS(fftw${FFTW_S_}_make_planner_thread_safe ${FFTW_CLN}_TSFE) pip_module(io_utils "" "PIP I/O support" "" "")
add_definitions(-DPIP_FFTW${FFTW_S_}) endif()
set(PIP_FFTW_FOUND true)
if(${FFTW_CLN}_TSFE)
add_definitions(-DPIP_FFTW${FFTW_S_}_THREADSAFE) # Check Lua support
else() if(MINGW)
message(STATUS "Warning: PIFFTW${FFTW_S_}::preparePlan was not threadsafe") set(LUA_INCLUDE_DIR ${MINGW_INCLUDE})
endif() endif()
#message(STATUS "${FFTW_CLN} -> ${${FFTW_CLN}_TSFE}") find_package(Lua QUIET)
endif() if (LUA_FOUND)
endif() pip_module(lua "LUA" "PIP Lua support" "${LUA_INCLUDE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/lib/lua/3rd" " (${LUA_VERSION_STRING})")
endforeach() list(APPEND HDR_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/lib/lua/3rd/LuaBridge")
endforeach() endif()
if(FFTW_LIBS)
message(STATUS "Building PIP with fftw3 support: ${FFTW_LIBS}")
import_version(pip_fftw pip) # Test program
set_deploy_property(pip_fftw ${PIP_LIB_TYPE} if(PIP_UTILS)
LABEL "PIP FFTW support" add_executable(pip_test "main.cpp")
FULLNAME "${_PIP_DOMAIN}.pip_fftw" target_link_libraries(pip_test pip)
COMPANY "${_PIP_COMPANY}" if (LUA_FOUND)
INFO "Platform-Independent Primitives") target_link_libraries(pip_test pip_lua ${LUA_LIBRARIES})
make_rc(pip_fftw _RC) endif()
add_library(pip_fftw ${PIP_LIB_TYPE} ${CPP_LIB_FFTW} ${_RC}) endif()
target_link_libraries(pip_fftw pip ${FFTW_ABS_LIBS})
list(APPEND LIBS_STATUS ${FFTW_LIBS}) else()
list(APPEND PIP_LIBS_TARGETS pip_fftw)
else() set(PIP_MSG_crypt "yes")
message(STATUS "Building PIP without fftw3 support") set(PIP_MSG_compress "yes")
endif() set(PIP_MODULES pip)
add_definitions(-DPIP_CRYPT)
add_library(pip_crypt ${PIP_LIB_TYPE} ${CPP_LIB_CRYPT})
# Check if PIP support OpenCL target_link_libraries(pip_crypt pip)
find_package(OpenCL QUIET) list(APPEND PIP_MODULES pip_crypt)
if(OpenCL_FOUND) set(IO_UTILS_LIBS pip)
message(STATUS "Building PIP with OpenCL support") add_library(pip_io_utils ${PIP_LIB_TYPE} ${CPP_LIB_IO_UTILS})
import_version(pip_opencl pip) list(APPEND IO_UTILS_LIBS pip_crypt)
set_deploy_property(pip_opencl ${PIP_LIB_TYPE} target_link_libraries(pip_io_utils ${IO_UTILS_LIBS})
LABEL "PIP OpenCL support" list(APPEND PIP_MODULES pip_io_utils)
FULLNAME "${_PIP_DOMAIN}.pip_opencl" add_definitions(-DPIP_COMPRESS)
COMPANY "${_PIP_COMPANY}" add_library(pip_compress ${PIP_LIB_TYPE} ${CPP_LIB_COMPRESS})
INFO "Platform-Independent Primitives") target_link_libraries(pip_compress pip)
make_rc(pip_opencl _RC) list(APPEND PIP_MODULES pip_compress)
if(APPLE)
include_directories(${OpenCL_INCLUDE_DIRS}/Headers) endif()
else() endif()
include_directories(${OpenCL_INCLUDE_DIRS})
endif() string(REPLACE ";" "," PIP_EXPORTS_STR "${PIP_EXPORTS}")
add_definitions(-DPIP_OPENCL) target_compile_definitions(pip PRIVATE "PICODE_DEFINES=\"${PIP_EXPORTS_STR}\"")
pip_resources(CL_RES "src_opencl/resources.conf")
add_library(pip_opencl ${PIP_LIB_TYPE} ${CPP_LIB_OPENCL} ${CL_RES} ${_RC}) # Install
add_dependencies(pip_opencl pip_rc) # Check if system or local install will be used (to system install use "-DLIB=" argument of cmake)
if(${CMAKE_VERSION} VERSION_LESS "3.7.0") if(LIB)
target_link_libraries(pip_opencl pip OpenCL) if(WIN32)
else() if(MINGW)
target_link_libraries(pip_opencl pip OpenCL::OpenCL) if (NOT CROSSTOOLS)
endif() install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE}/pip)
list(APPEND LIBS_STATUS OpenCL) install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE}/pip)
list(APPEND PIP_LIBS_TARGETS pip_opencl) if(HDR_DIRS)
set(OpenCL_FOUND ${OpenCL_LIBRARIES}) install(DIRECTORY ${HDR_DIRS} DESTINATION ${MINGW_INCLUDE}/pip)
else() endif()
message(STATUS "Building PIP without OpenCL support") install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION ${MINGW_LIB})
endif() endif()
install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION ${MINGW_BIN})
find_library(STDLIB "stdc++-6" PATHS ${MINGW_BIN} NO_DEFAULT_PATH)
# Check if PIP IO Utils library supports crypt find_library(STDLIB "stdc++-6")
set(IO_UTILS_LIBS pip) #message("${STDLIB}")
import_version(pip_io_utils pip) if (STDLIB)
set_deploy_property(pip_io_utils ${PIP_LIB_TYPE} file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/code_model_generator")
LABEL "PIP I/O utilites" file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/resources_compiler")
FULLNAME "${_PIP_DOMAIN}.pip_io_utils" file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/deploy_tool")
COMPANY "${_PIP_COMPANY}" endif()
INFO "Platform-Independent Primitives") else()
make_rc(pip_io_utils _RC) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pip_export.h DESTINATION include)
add_library(pip_io_utils ${PIP_LIB_TYPE} ${CPP_LIB_IO_UTILS} ${_RC}) endif()
if(sodium_FOUND) else()
message(STATUS "Building PIP IO Utils library with crypt support") if (NOT CROSSTOOLS)
list(APPEND IO_UTILS_LIBS pip_crypt) install(FILES ${HDRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip)
else() if(HDR_DIRS)
message(STATUS "Building PIP IO Utils library without crypt support, attention!") install(DIRECTORY ${HDR_DIRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip)
endif() endif()
target_link_libraries(pip_io_utils ${IO_UTILS_LIBS}) endif()
list(APPEND PIP_LIBS_TARGETS pip_io_utils) install(TARGETS ${PIP_MODULES} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in" "cmake/android_debug.keystore")
# Concurrent module install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
set(CONCURRENT_LIBS pip) else()
import_version(pip_concurrent pip) if(NOT PIP_FREERTOS)
set_deploy_property(pip_concurrent ${PIP_LIB_TYPE} if(WIN32)
LABEL "PIP concurrent support" install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION bin)
FULLNAME "${_PIP_DOMAIN}.pip_concurrent" install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION lib)
COMPANY "${_PIP_COMPANY}" else()
INFO "Platform-Independent Primitives") install(TARGETS ${PIP_MODULES} DESTINATION lib)
make_rc(pip_concurrent _RC) endif()
add_library(pip_concurrent ${PIP_LIB_TYPE} ${CPP_LIB_CONCURRENT} ${_RC}) install(FILES ${HDRS} DESTINATION include/pip)
target_link_libraries(pip_concurrent ${CONCURRENT_LIBS}) if(HDR_DIRS)
set_property(TARGET pip_concurrent PROPERTY CXX_STANDARD 11) install(DIRECTORY ${HDR_DIRS} DESTINATION include/pip)
list(APPEND PIP_LIBS_TARGETS pip_concurrent) endif()
endif()
# Enable build tests for concurrent module endif()
if(CONCURRENT_TESTS)
add_executable(pip_concurrent_test ${CPP_CONCURRENT_TEST}) if(NOT PIP_FREERTOS)
target_link_libraries(pip_concurrent_test gtest_main gmock_main pip_concurrent)
add_test(NAME pip_concurrent_test COMMAND tests) # Auxiliary
add_custom_target(pip_concurrent_test_perform ALL COMMAND pip_concurrent_test) if (NOT CROSSTOOLS)
endif() add_subdirectory("utils/piterminal")
endif()
# Build cloud library if crypt enabled # Utils
if(sodium_FOUND) add_subdirectory("utils/code_model_generator")
message(STATUS "Building PICloud support") add_subdirectory("utils/resources_compiler")
import_version(pip_cloud pip) add_subdirectory("utils/deploy_tool")
set_deploy_property(pip_cloud ${PIP_LIB_TYPE} if(PIP_UTILS AND (NOT CROSSTOOLS))
LABEL "PIP cloud transport support" add_subdirectory("utils/system_test")
FULLNAME "${_PIP_DOMAIN}.pip_cloud" add_subdirectory("utils/udp_file_transfer")
COMPANY "${_PIP_COMPANY}" if(sodium_FOUND)
INFO "Platform-Independent Primitives") add_subdirectory("utils/system_daemon")
make_rc(pip_cloud _RC) add_subdirectory("utils/crypt_tool")
add_definitions(-DPIP_CLOUD) add_subdirectory("utils/cloud_dispatcher")
add_library(pip_cloud ${PIP_LIB_TYPE} ${CPP_LIB_CLOUD} ${_RC}) endif()
target_link_libraries(pip_cloud pip pip_crypt) endif()
list(APPEND PIP_LIBS_TARGETS pip_cloud)
endif() endif()
# Test program # Libraries messages
if(PIP_UTILS) if(DEFINED LIBPROJECT)
add_executable(pip_test "main.cpp") set(PIP_MODULES ${PIP_MODULES} PARENT_SCOPE)
target_link_libraries(pip_test pip) list(APPEND _ALL_TARGETS ${PIP_MODULES})
endif() set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
else()
#
message(STATUS "Building PIP with crypt support") # Build Documentation
add_definitions(-DPIP_CRYPT) #
add_library(pip_crypt ${PIP_LIB_TYPE} ${CPP_LIB_CRYPT}) if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
target_link_libraries(pip_crypt pip) include(PIPDocumentation)
list(APPEND PIP_LIBS_TARGETS pip_crypt) find_package(Doxygen)
set(IO_UTILS_LIBS pip) if(DOXYGEN_FOUND)
add_library(pip_io_utils ${PIP_LIB_TYPE} ${CPP_LIB_IO_UTILS}) set(DOXY_PROJECT_NUMBER "${PIP_VERSION}")
message(STATUS "Building PIP IO Utils library with crypt support") set(DOXY_QHP_CUST_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
list(APPEND IO_UTILS_LIBS pip_crypt) set(DOXY_QHP_SECT_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
target_link_libraries(pip_io_utils ${IO_UTILS_LIBS}) set(DOXY_EXAMPLE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/examples\"")
list(APPEND PIP_LIBS_TARGETS pip_io_utils) set(DOXY_IMAGE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/images\"")
message(STATUS "Building PIP with zlib compress support") set(DOXY_EXCLUDE "\"${CMAKE_CURRENT_SOURCE_DIR}/lib/lua/3rd\"")
add_definitions(-DPIP_COMPRESS) if(DOXYGEN_DOT_EXECUTABLE)
add_library(pip_compress ${PIP_LIB_TYPE} ${CPP_LIB_COMPRESS}) string(REPLACE "\\" "" _DOT_PATH "${DOXYGEN_DOT_PATH}")
target_link_libraries(pip_compress pip) set(DOXY_DOT_PATH "\"${_DOT_PATH}\"")
list(APPEND PIP_LIBS_TARGETS pip_compress) set(DOXY_MSCGEN_PATH "\"${_DOT_PATH}\"")
set(DOXY_DIA_PATH "\"${_DOT_PATH}\"")
endif() endif()
endif() set(DOXY_INPUT)
foreach(F ${PIP_MAIN_FOLDERS})
# Install list(APPEND DOXY_INPUT "\"${F}\"")
# Check if system or local install will be used (to system install use "-DLIB=" argument of cmake) endforeach(F)
if(LIB) string(REPLACE ";" " " DOXY_INPUT "\"${CMAKE_CURRENT_SOURCE_DIR}/lib\"")
if(WIN32) string(REPLACE ";" " " DOXY_INCLUDE_PATH "${DOXY_INPUT}")
if(MINGW) string(REPLACE ";" " " DOXY_DEFINES "${PIP_EXPORTS};DOXYGEN;PIOBJECT;PIOBJECT_SUBCLASS")
if (NOT CROSSTOOLS) add_documentation(doc doc/Doxyfile.in)
install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE}/pip) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html DESTINATION ../share/doc/pip COMPONENT doc EXCLUDE_FROM_ALL OPTIONAL)
install(TARGETS ${PIP_LIBS_TARGETS} ARCHIVE DESTINATION ${MINGW_LIB}) endif()
endif() endif()
install(TARGETS ${PIP_LIBS_TARGETS} RUNTIME DESTINATION ${MINGW_BIN})
find_library(STDLIB "stdc++-6" PATHS ${MINGW_BIN} NO_DEFAULT_PATH)
find_library(STDLIB "stdc++-6")
#message("${STDLIB}") list(REMOVE_ITEM LIBS_STATUS ${PIP_MODULES})
if (STDLIB) message("----------PIP----------")
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/code_model_generator") message(" Version: ${PIP_VERSION} ")
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/resources_compiler") message(" Linkage: ${PIP_LIB_TYPE_MSG}")
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/deploy_tool") message(" Type : ${PIP_BUILD_TYPE}")
endif() if(LIB)
else() message(" Install: \"${CMAKE_INSTALL_PREFIX}\"")
#message("${CMAKE_CURRENT_BINARY_DIR}/pip_export.h") else()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pip_export.h DESTINATION include) if(NOT PIP_FREERTOS)
endif() message(" Install: local \"bin\", \"lib\" and \"include\"")
else() endif()
if (NOT CROSSTOOLS) endif()
install(FILES ${HDRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip) message("")
endif() message(" Options:")
install(TARGETS ${PIP_LIBS_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) message(" std::iostream: ${PIP_STD_IOSTREAM}")
endif() message(" ICU strings : ${PIP_ICU}")
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"") message(" Timer types : ${PIP_TIMERS}")
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in" "cmake/android_debug.keystore") message(" Introspection: ${PIP_INTROSPECTION}")
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules) if(INTROSPECTION)
else() message(STATUS " Warning: Introspection reduces the performance!")
if(NOT PIP_FREERTOS) endif()
if(WIN32) message("")
install(TARGETS ${PIP_LIBS_TARGETS} RUNTIME DESTINATION bin) message(" Modules:")
install(TARGETS ${PIP_LIBS_TARGETS} ARCHIVE DESTINATION lib) foreach(_m ${PIP_SRC_MODULES})
else() message(" ${_m}: ${PIP_MSG_${_m}}")
install(TARGETS ${PIP_LIBS_TARGETS} DESTINATION lib) endforeach()
endif() message("")
install(FILES ${HDRS} DESTINATION include/pip) if (PIP_TESTS_LIST)
message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"") message(" Tests:")
endif() foreach(_test ${PIP_TESTS_LIST})
endif() message(" * ${_test}")
endforeach()
if(NOT PIP_FREERTOS) else()
message(" Tests: skip (tests off)")
# Auxiliary endif()
if (NOT CROSSTOOLS) message("")
add_subdirectory("${PIP_SRC_MAIN}/auxiliary/piterminal") message(" Utilites:")
endif() foreach(_util ${PIP_UTILS_LIST})
message(" * ${_util}")
# Utils endforeach()
add_subdirectory("utils/code_model_generator") if(NOT PIP_FREERTOS)
add_subdirectory("utils/resources_compiler") message("")
add_subdirectory("utils/deploy_tool") message(" Using libraries:")
if(PIP_UTILS AND (NOT CROSSTOOLS)) foreach(LIB_ ${LIBS_STATUS})
add_subdirectory("utils/system_test") if (NOT TARGET ${LIB_})
add_subdirectory("utils/remote_console") if(${LIB_}_FOUND)
add_subdirectory("utils/udp_file_transfer") message(" ${LIB_} -> ${${LIB_}_LIBRARIES}")
if(sodium_FOUND) else()
add_subdirectory("utils/system_daemon") message(" ${LIB_} not found, may fail")
add_subdirectory("utils/crypt_tool") endif()
add_subdirectory("utils/cloud_dispatcher") endif()
endif() endforeach()
endif() endif()
message("-----------------------")
endif()
# Libraries messages
message(STATUS "Building PIP modules: ${PIP_LIBS_TARGETS}")
if(DEFINED LIBPROJECT)
set(PIP_LIBS_TARGETS ${PIP_LIBS_TARGETS} PARENT_SCOPE)
list(APPEND _ALL_TARGETS ${PIP_LIBS_TARGETS})
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
if(NOT PIP_FREERTOS)
foreach(LIB_ ${LIBS_STATUS})
message(STATUS "Library ${LIB_} -> " ${${LIB_}_FOUND})
if(NOT ${LIB_}_FOUND)
message(WARNING "Library ${LIB_} not found, please install it")
endif()
endforeach()
endif()
#
# Build Documentation
#
if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
include(PIPDocumentation)
find_package(Doxygen)
if(DOXYGEN_FOUND)
set(DOXY_PROJECT_NUMBER "${PIP_VERSION}")
set(DOXY_QHP_CUST_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
set(DOXY_QHP_SECT_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
set(DOXY_EXAMPLE_PATH "\"${PROJECT_SOURCE_DIR}/doc/examples\"")
set(DOXY_IMAGE_PATH "\"${PROJECT_SOURCE_DIR}/doc/images\"")
if(DOXYGEN_DOT_EXECUTABLE)
string(REPLACE "\\" "" _DOT_PATH "${DOXYGEN_DOT_PATH}")
set(DOXY_DOT_PATH "\"${_DOT_PATH}\"")
set(DOXY_MSCGEN_PATH "\"${_DOT_PATH}\"")
set(DOXY_DIA_PATH "\"${_DOT_PATH}\"")
endif()
set(DOXY_INPUT)
foreach(F ${PIP_SRC_DIRS})
list(APPEND DOXY_INPUT "\"${PROJECT_SOURCE_DIR}/${F}\"")
endforeach(F)
string(REPLACE ";" " " DOXY_INPUT "${DOXY_INPUT}")
string(REPLACE ";" " " DOXY_INCLUDE_PATH "${PIP_MAIN_FOLDERS}")
add_documentation(doc Doxyfile.in)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html DESTINATION ../share/doc/pip COMPONENT doc EXCLUDE_FROM_ALL OPTIONAL)
endif()
endif()

24
clean
View File

@@ -1,24 +0,0 @@
#! /bin/sh
VERBOSE=1 make clean
rm -rvf ./CMakeFiles
rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core
cd utils/system_test
VERBOSE=1 make clean
rm -rvf ./CMakeFiles
rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core
cd ../../
cd utils/system_daemon
VERBOSE=1 make clean
rm -rvf ./CMakeFiles
rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core
cd ../../
cd utils/remote_console
VERBOSE=1 make clean
rm -rvf ./CMakeFiles
rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core
cd ../../
cd utils/code_model_generator
VERBOSE=1 make clean
rm -rvf ./CMakeFiles
rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core
cd ../../

View File

@@ -1,34 +0,0 @@
#make clean
del /q /f /s CMakeFiles
rmdir /q /s CMakeFiles
del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core
cd utils\system_test
del /q /f /s CMakeFiles
rmdir /q /s CMakeFiles
del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core
cd ..
cd ..
cd utils\remote_console
del /q /f /s CMakeFiles
rmdir /q /s CMakeFiles
del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core
cd ..
cd ..
cd utils\code_model_generator
del /q /f /s CMakeFiles
rmdir /q /s CMakeFiles
del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core
cd ..
cd ..
cd utils\system_daemon
del /q /f /s CMakeFiles
rmdir /q /s CMakeFiles
del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core
cd ..
cd ..
cd utils\udp_file_transfer
del /q /f /s CMakeFiles
rmdir /q /s CMakeFiles
del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core
cd ..
cd ..

View File

@@ -383,7 +383,14 @@ endmacro()
macro(__add_file_or_dir _DIR_VAR _FILE_VAR _PATH _RELPATH) macro(__add_file_or_dir _DIR_VAR _FILE_VAR _PATH _RELPATH)
set(_p) set(_p)
set(_abs 0)
if (IS_ABSOLUTE "${_PATH}") if (IS_ABSOLUTE "${_PATH}")
set(_abs 1)
endif()
if ("${_PATH}" MATCHES "^\$<")
set(_abs 1)
endif()
if (_abs)
set(_p "${_PATH}") set(_p "${_PATH}")
else() else()
set(_p "${_RELPATH}/${_PATH}") set(_p "${_RELPATH}/${_PATH}")

View File

@@ -3,12 +3,14 @@
Also create imported targets: Also create imported targets:
* PIP - main library * PIP - main library
* PIP::USB * PIP::USB
* PIP::Console
* PIP::Crypt * PIP::Crypt
* PIP::FFTW
* PIP::Compress * PIP::Compress
* PIP::FFTW
* PIP::OpenCL
* PIP::IOUtils * PIP::IOUtils
* PIP::Concurrent
* PIP::Cloud * PIP::Cloud
* PIP::Lua
These targets include directories and depends on These targets include directories and depends on
main library main library
@@ -58,12 +60,14 @@ set(_pip_suffix "")
find_library(PIP_LIBRARY pip${_pip_suffix} HINTS ${_PIP_LIBDIR}) find_library(PIP_LIBRARY pip${_pip_suffix} HINTS ${_PIP_LIBDIR})
find_library(PIP_USB_LIBRARY pip_usb${_pip_suffix} HINTS ${_PIP_LIBDIR}) find_library(PIP_USB_LIBRARY pip_usb${_pip_suffix} HINTS ${_PIP_LIBDIR})
find_library(PIP_CONSOLE_LIBRARY pip_console${_pip_suffix} HINTS ${_PIP_LIBDIR})
find_library(PIP_CRYPT_LIBRARY pip_crypt${_pip_suffix} HINTS ${_PIP_LIBDIR}) find_library(PIP_CRYPT_LIBRARY pip_crypt${_pip_suffix} HINTS ${_PIP_LIBDIR})
find_library(PIP_FFTW_LIBRARY pip_fftw${_pip_suffix} HINTS ${_PIP_LIBDIR}) find_library(PIP_FFTW_LIBRARY pip_fftw${_pip_suffix} HINTS ${_PIP_LIBDIR})
find_library(PIP_COMPRESS_LIBRARY pip_compress${_pip_suffix} HINTS ${_PIP_LIBDIR}) find_library(PIP_COMPRESS_LIBRARY pip_compress${_pip_suffix} HINTS ${_PIP_LIBDIR})
find_library(PIP_OPENCL_LIBRARY pip_opencl${_pip_suffix} HINTS ${_PIP_LIBDIR})
find_library(PIP_IO_UTILS_LIBRARY pip_io_utils${_pip_suffix} HINTS ${_PIP_LIBDIR}) find_library(PIP_IO_UTILS_LIBRARY pip_io_utils${_pip_suffix} HINTS ${_PIP_LIBDIR})
find_library(PIP_CONCURRENT_LIBRARY pip_concurrent${_pip_suffix} HINTS ${_PIP_LIBDIR})
find_library(PIP_CLOUD_LIBRARY pip_cloud HINTS${_pip_suffix} ${_PIP_LIBDIR}) find_library(PIP_CLOUD_LIBRARY pip_cloud HINTS${_pip_suffix} ${_PIP_LIBDIR})
find_library(PIP_LUA_LIBRARY pip_lua HINTS${_pip_suffix} ${_PIP_LIBDIR})
find_file(PIP_H_INCLUDE "pip.h" HINTS ${_PIP_INCDIR} $ENV{SMSDK_DIR}/include/pip) find_file(PIP_H_INCLUDE "pip.h" HINTS ${_PIP_INCDIR} $ENV{SMSDK_DIR}/include/pip)
get_filename_component(PIP_INCLUDES ${PIP_H_INCLUDE} PATH) get_filename_component(PIP_INCLUDES ${PIP_H_INCLUDE} PATH)
set(__ext "") set(__ext "")
@@ -92,6 +96,19 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
list(APPEND PIP_LIBRARY ${_PIP_ADD_LIBS_}) list(APPEND PIP_LIBRARY ${_PIP_ADD_LIBS_})
endif() endif()
endif() endif()
if(PIP_LUA_LIBRARY)
if (NOT LUA_FOUND)
if(MINGW)
set(LUA_INCLUDE_DIR ${MINGW_INCLUDE})
set(_prev_clp "${CMAKE_LIBRARY_PATH}")
set(CMAKE_LIBRARY_PATH "${MINGW_LIB}")
endif()
find_package(Lua QUIET)
if(MINGW)
set(CMAKE_LIBRARY_PATH "${_prev_clp}")
endif()
endif()
endif()
if(NOT PIP_VERSION) if(NOT PIP_VERSION)
include(CheckSymbolExists) include(CheckSymbolExists)
@@ -115,14 +132,16 @@ 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!")
endif() endif()
set(__modules "USB;Crypt;FFTW;Compress;IOUtils;Concurrent;Cloud") set(__modules "USB;Crypt;Console;FFTW;Compress;IOUtils;Cloud;Lua")
set(__module_USB "${PIP_USB_LIBRARY}" ) set(__module_USB "${PIP_USB_LIBRARY}" )
set(__module_Console "${PIP_CONSOLE_LIBRARY}" )
set(__module_Crypt "${PIP_CRYPT_LIBRARY}" ) set(__module_Crypt "${PIP_CRYPT_LIBRARY}" )
set(__module_FFTW "${PIP_FFTW_LIBRARY}" ) set(__module_FFTW "${PIP_FFTW_LIBRARY}" )
set(__module_Compress "${PIP_COMPRESS_LIBRARY}" ) set(__module_Compress "${PIP_COMPRESS_LIBRARY}" )
set(__module_OpenCL "${PIP_OPENCL_LIBRARY}" )
set(__module_IOUtils "${PIP_IO_UTILS_LIBRARY}" ) set(__module_IOUtils "${PIP_IO_UTILS_LIBRARY}" )
set(__module_Concurrent "${PIP_CONCURRENT_LIBRARY}")
set(__module_Cloud "${PIP_CLOUD_LIBRARY}" ) set(__module_Cloud "${PIP_CLOUD_LIBRARY}" )
set(__module_Lua "${PIP_LUA_LIBRARY}" )
if((NOT TARGET PIP) AND PIP_LIBRARY) if((NOT TARGET PIP) AND PIP_LIBRARY)
add_library(PIP UNKNOWN IMPORTED) add_library(PIP UNKNOWN IMPORTED)
set_target_properties(PIP PROPERTIES set_target_properties(PIP PROPERTIES
@@ -138,8 +157,15 @@ foreach (_m ${__modules})
INTERFACE_LINK_LIBRARIES "PIP") INTERFACE_LINK_LIBRARIES "PIP")
endif() endif()
endforeach() endforeach()
set_target_properties(PIP::IOUtils PROPERTIES INTERFACE_LINK_LIBRARIES "PIP::Crypt") if(__module_IOUtils AND __module_Crypt)
set_target_properties(PIP::Cloud PROPERTIES INTERFACE_LINK_LIBRARIES "PIP::IOUtils") set_target_properties(PIP::IOUtils PROPERTIES INTERFACE_LINK_LIBRARIES "PIP::Crypt")
endif()
if(__module_Cloud AND __module_IOUtils)
set_target_properties(PIP::Cloud PROPERTIES INTERFACE_LINK_LIBRARIES "PIP::IOUtils")
endif()
if(__module_Lua)
set_target_properties(PIP::Lua PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}" INTERFACE_LINK_LIBRARIES "PIP;${LUA_LIBRARIES}")
endif()
include(PIPMacros) include(PIPMacros)

View File

@@ -1,27 +1,6 @@
macro(CONFIGURE_DOXYGEN_FILE DOXYGEN_CONFIG_FILE FILE_NAME_SUFFIX)
if(EXISTS ${PROJECT_SOURCE_DIR}/${DOXYGEN_CONFIG_FILE})
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doxyfile-${FILE_NAME_SUFFIX}")
file(READ ${PROJECT_SOURCE_DIR}/${DOXYGEN_CONFIG_FILE} DOXYFILE_CONTENTS)
string(REPLACE "\\\n" " " DOXYFILE_CONTENTS "${DOXYFILE_CONTENTS}")
string(REPLACE "\n" ";" DOXYFILE_LINES "${DOXYFILE_CONTENTS}")
foreach(LINE IN LISTS DOXYFILE_LINES)
if(LINE STRGREATER "")
string(REGEX MATCH "^[a-zA-Z]([^ ])+" DOXY_PARAM ${LINE})
if(DEFINED DOXY_${DOXY_PARAM})
STRING(REGEX REPLACE "=([^\n])+" "= ${DOXY_${DOXY_PARAM}}" LINE ${LINE})
endif(DEFINED DOXY_${DOXY_PARAM})
endif()
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doxyfile-${FILE_NAME_SUFFIX} "${LINE}\n")
endforeach()
else()
MESSAGE(SEND_ERROR "Doxygen configuration file '${DOXYGEN_CONFIG_FILE}' not found, can`t generate documentation")
endif()
endmacro(CONFIGURE_DOXYGEN_FILE)
macro(ADD_DOCUMENTATION TARGET DOXYGEN_CONFIG_FILE) macro(ADD_DOCUMENTATION TARGET DOXYGEN_CONFIG_FILE)
if(DOXYGEN_FOUND) if(DOXYGEN_FOUND)
configure_doxygen_file(${DOXYGEN_CONFIG_FILE} ${TARGET}) configure_file("${PROJECT_SOURCE_DIR}/${DOXYGEN_CONFIG_FILE}" "${CMAKE_CURRENT_BINARY_DIR}/doxyfile-${TARGET}")
add_custom_target("genereate.${TARGET}" COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxyfile-${TARGET}) add_custom_target("genereate.${TARGET}" COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxyfile-${TARGET})
add_custom_target("${TARGET}" COMMAND ${CMAKE_COMMAND} -D COMPONENT=doc -P cmake_install.cmake) add_custom_target("${TARGET}" COMMAND ${CMAKE_COMMAND} -D COMPONENT=doc -P cmake_install.cmake)
add_dependencies("${TARGET}" "genereate.${TARGET}") add_dependencies("${TARGET}" "genereate.${TARGET}")

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = PIP
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = 1.8.0 PROJECT_NUMBER = ${DOXY_PROJECT_NUMBER}
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a
@@ -816,13 +816,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = src_main \ INPUT = ${DOXY_INPUT}
src_crypt \
src_fftw \
src_io_utils \
src_compress \
src_opencl \
src_usb
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -895,7 +889,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is # Note that relative paths are relative to the directory from which doxygen is
# run. # run.
EXCLUDE = EXCLUDE = ${DOXY_EXCLUDE}
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded # directories that are symbolic links (a Unix file system feature) are excluded
@@ -928,7 +922,7 @@ EXCLUDE_SYMBOLS =
# that contain example code fragments that are included (see the \include # that contain example code fragments that are included (see the \include
# command). # command).
EXAMPLE_PATH = doc/examples EXAMPLE_PATH = ${DOXY_EXAMPLE_PATH}
# If the value of the EXAMPLE_PATH tag contains directories, you can use the # If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
@@ -948,7 +942,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the # that contain images that are to be included in the documentation (see the
# \image command). # \image command).
IMAGE_PATH = doc/images IMAGE_PATH = ${DOXY_IMAGE_PATH}
# The INPUT_FILTER tag can be used to specify a program that doxygen should # The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program # invoke to filter for each input file. Doxygen will invoke the filter program
@@ -1459,14 +1453,14 @@ QHP_CUST_FILTER_NAME = PIP
# filters). # filters).
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS = PIP QHP_CUST_FILTER_ATTRS = ${DOXY_QHP_CUST_FILTER_ATTRS}
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see: # project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS = PIP QHP_SECT_FILTER_ATTRS = ${DOXY_QHP_SECT_FILTER_ATTRS}
# The QHG_LOCATION tag can be used to specify the location of Qt's # The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
@@ -2152,15 +2146,7 @@ SEARCH_INCLUDES = YES
# preprocessor. # preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES. # This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH = src_main/code \ INCLUDE_PATH = ${DOXY_INCLUDE_PATH}
src_main/containers \
src_main/core \
src_main/math \
src_main/system \
src_main/thread \
src_main/console \
src_main/io_devices \
src_main/io_utils
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the # patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -2178,8 +2164,8 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator. # recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = DOXYGEN \ PREDEFINED = ${DOXY_DEFINES}
PIP_EXPORT
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The # tag can be used to specify a list of macro names that should be expanded. The
@@ -2272,14 +2258,14 @@ CLASS_DIAGRAMS = YES
# the mscgen tool resides. If left empty the tool is assumed to be found in the # the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path. # default search path.
MSCGEN_PATH = "C:/Program Files/doxygen/graphviz/bin" MSCGEN_PATH = ${DOXY_MSCGEN_PATH}
# You can include diagrams made with dia in doxygen documentation. Doxygen will # You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The # then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides. # DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path. # If left empty dia is assumed to be found in the default search path.
DIA_PATH = "C:/Program Files/doxygen/graphviz/bin" DIA_PATH = ${DOXY_DIA_PATH}
# If set to YES the inheritance and collaboration graphs will hide inheritance # If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class. # and usage relations if the target is undocumented or is not a class.
@@ -2472,7 +2458,7 @@ INTERACTIVE_SVG = NO
# found. If left blank, it is assumed the dot tool can be found in the path. # found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
DOT_PATH = "C:/Program Files/doxygen/graphviz/bin" DOT_PATH = ${DOXY_DOT_PATH}
# The DOTFILE_DIRS tag can be used to specify one or more directories that # The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile # contain dot files that are included in the documentation (see the \dotfile

View File

@@ -1,20 +1,20 @@
set(COMPONENT_SRCS "main.cpp") set(COMPONENT_SRCS "main.cpp")
set(COMPONENT_ADD_INCLUDEDIRS "pip/src_main") set(COMPONENT_ADD_INCLUDEDIRS "pip/lib/main")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/auxiliary") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/auxiliary")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/code") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/code")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/console") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/console")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/containers") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/containers")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/core") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/core")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/crypt") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/crypt")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/geo") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/geo")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/io_devices") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/io_devices")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/io_utils") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/io_utils")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/math") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/math")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/opencl") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/opencl")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/resources") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/resources")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/system") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/system")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/thread") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/thread")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/introspection") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/introspection")
set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spiffs) set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spiffs)
register_component() register_component()
set(PIP_FREERTOS ON) set(PIP_FREERTOS ON)

View File

@@ -23,3 +23,18 @@
PICloudClient::PICloudClient() { PICloudClient::PICloudClient() {
} }
PICloudClient::~PICloudClient() {
}
bool PICloudClient::openDevice() {
}
bool PICloudClient::closeDevice() {
}

View File

@@ -1,645 +1,645 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console output/input Console output/input
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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 "piscreen.h" #include "piscreen.h"
#include "piincludes_p.h" #include "piincludes_p.h"
#ifndef WINDOWS #ifndef WINDOWS
# include <sys/ioctl.h> # include <sys/ioctl.h>
# include <fcntl.h> # include <fcntl.h>
# include <termios.h> # include <termios.h>
#else #else
# include <wincon.h> # include <wincon.h>
# ifndef COMMON_LVB_UNDERSCORE # ifndef COMMON_LVB_UNDERSCORE
# define COMMON_LVB_UNDERSCORE 0x8000 # define COMMON_LVB_UNDERSCORE 0x8000
# endif # endif
#endif #endif
using namespace PIScreenTypes; using namespace PIScreenTypes;
PRIVATE_DEFINITION_START(PIScreen::SystemConsole) PRIVATE_DEFINITION_START(PIScreen::SystemConsole)
#ifdef WINDOWS #ifdef WINDOWS
void * hOut; void * hOut;
CONSOLE_SCREEN_BUFFER_INFO sbi, csbi; CONSOLE_SCREEN_BUFFER_INFO sbi, csbi;
CONSOLE_CURSOR_INFO curinfo; CONSOLE_CURSOR_INFO curinfo;
COORD ccoord, ulcoord, bs, bc; COORD ccoord, ulcoord, bs, bc;
SMALL_RECT srect; SMALL_RECT srect;
WORD dattr; WORD dattr;
DWORD smode, written; DWORD smode, written;
PIVector<CHAR_INFO> chars; PIVector<CHAR_INFO> chars;
#endif #endif
PRIVATE_DEFINITION_END(PIScreen::SystemConsole) 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;
int w, h; int w, h;
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->ulcoord.X = 0; PRIVATE->ulcoord.X = 0;
PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE); PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
PRIVATE->dattr = PRIVATE->sbi.wAttributes; PRIVATE->dattr = PRIVATE->sbi.wAttributes;
w = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left; w = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left;
h = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top; h = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top;
PRIVATE->ulcoord.Y = PRIVATE->sbi.srWindow.Top; PRIVATE->ulcoord.Y = PRIVATE->sbi.srWindow.Top;
GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode); GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode);
GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
# ifdef FREERTOS # ifdef FREERTOS
w = 80; w = 80;
h = 24; h = 24;
# else # else
winsize ws; winsize ws;
ioctl(0, TIOCGWINSZ, &ws); ioctl(0, TIOCGWINSZ, &ws);
w = ws.ws_col; w = ws.ws_col;
h = ws.ws_row; h = ws.ws_row;
# endif # endif
#endif #endif
resize(w, h); resize(w, h);
} }
PIScreen::SystemConsole::~SystemConsole() { PIScreen::SystemConsole::~SystemConsole() {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode); SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr); SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
#endif #endif
} }
void PIScreen::SystemConsole::begin() { 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);
PRIVATE->bc.X = 0; PRIVATE->bc.X = 0;
PRIVATE->bc.Y = 0; PRIVATE->bc.Y = 0;
#endif #endif
clear(); clear();
hideCursor(); hideCursor();
} }
void PIScreen::SystemConsole::end() { void PIScreen::SystemConsole::end() {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr); SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
#else #else
printf("\e[0m"); printf("\e[0m");
#endif #endif
moveTo(0, height); moveTo(0, height);
showCursor(); showCursor();
} }
void PIScreen::SystemConsole::prepare() { void PIScreen::SystemConsole::prepare() {
int w, h; int w, h;
#ifdef WINDOWS #ifdef WINDOWS
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi);
w = PRIVATE->csbi.srWindow.Right - PRIVATE->csbi.srWindow.Left + 1; w = PRIVATE->csbi.srWindow.Right - PRIVATE->csbi.srWindow.Left + 1;
h = PRIVATE->csbi.srWindow.Bottom - PRIVATE->csbi.srWindow.Top + 1; h = PRIVATE->csbi.srWindow.Bottom - PRIVATE->csbi.srWindow.Top + 1;
#else #else
# ifdef FREERTOS # ifdef FREERTOS
w = 80; w = 80;
h = 24; h = 24;
# else # else
winsize ws; winsize ws;
ioctl(0, TIOCGWINSZ, &ws); ioctl(0, TIOCGWINSZ, &ws);
w = ws.ws_col; w = ws.ws_col;
h = ws.ws_row; h = ws.ws_row;
# endif # endif
#endif #endif
resize(w, h); resize(w, h);
} }
void PIScreen::SystemConsole::clear() { void PIScreen::SystemConsole::clear() {
for (int i = 0; i < cells.size_s(); ++i) for (int i = 0; i < cells.size_s(); ++i)
cells[i].fill(Cell()); cells[i].fill(Cell());
} }
void PIScreen::SystemConsole::resize(int w, int h) { void PIScreen::SystemConsole::resize(int w, int h) {
if (w == pwidth && h == pheight) return; if (w == pwidth && h == pheight) return;
width = piMaxi(w, 0); width = piMaxi(w, 0);
height = piMaxi(h, 0); height = piMaxi(h, 0);
pwidth = width; pwidth = width;
pheight = height; pheight = height;
cells.resize(height); cells.resize(height);
pcells.resize(height); pcells.resize(height);
for (int i = 0; i < height; ++i) { for (int i = 0; i < height; ++i) {
cells[i].resize(width); cells[i].resize(width);
pcells[i].resize(width, Cell(0)); pcells[i].resize(width, Cell(0));
} }
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->sbi.srWindow = PRIVATE->csbi.srWindow; PRIVATE->sbi.srWindow = PRIVATE->csbi.srWindow;
PRIVATE->chars.resize(width * height); PRIVATE->chars.resize(width * height);
#endif #endif
for (int i = 0; i < pcells.size_s(); ++i) for (int i = 0; i < pcells.size_s(); ++i)
pcells[i].fill(Cell()); pcells[i].fill(Cell());
clear(); clear();
clearScreen(); clearScreen();
} }
void PIScreen::SystemConsole::print() { void PIScreen::SystemConsole::print() {
if (mouse_x >= 0 && mouse_x < width && mouse_y >= 0 && mouse_y < height) { if (mouse_x >= 0 && mouse_x < width && mouse_y >= 0 && mouse_y < height) {
///cells[mouse_y][mouse_x].format.flags ^= Inverse; ///cells[mouse_y][mouse_x].format.flags ^= Inverse;
} }
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->srect = PRIVATE->sbi.srWindow; PRIVATE->srect = PRIVATE->sbi.srWindow;
int dx0 = -1, dx1 = -1, dy0 = -1, dy1 = -1; int dx0 = -1, dx1 = -1, dy0 = -1, dy1 = -1;
for (int j = 0; j < height; ++j) { for (int j = 0; j < height; ++j) {
PIVector<Cell> & ccv(cells[j]); PIVector<Cell> & ccv(cells[j]);
PIVector<Cell> & pcv(pcells[j]); PIVector<Cell> & pcv(pcells[j]);
for (int i = 0; i < width; ++i) for (int i = 0; i < width; ++i)
if (ccv[i] != pcv[i]) { if (ccv[i] != pcv[i]) {
if (dx0 < 0) { if (dx0 < 0) {
dx0 = dx1 = i; dx0 = dx1 = i;
dy0 = dy1 = j; dy0 = dy1 = j;
} else { } else {
dx0 = piMini(dx0, i); dx0 = piMini(dx0, i);
dx1 = piMaxi(dx1, i); dx1 = piMaxi(dx1, i);
dy0 = piMini(dy0, j); dy0 = piMini(dy0, j);
dy1 = piMaxi(dy1, j); dy1 = piMaxi(dy1, j);
} }
} }
} }
if (dx0 < 0) return; if (dx0 < 0) return;
int dw = dx1 - dx0 + 1, dh = dy1 - dy0 + 1; int dw = dx1 - dx0 + 1, dh = dy1 - dy0 + 1;
for (int i = 0; i < dw; ++i) for (int i = 0; i < dw; ++i)
for (int j = 0; j < dh; ++j) { for (int j = 0; j < dh; ++j) {
int k = j * dw + i; int k = j * dw + i;
Cell & c(cells[j + dy0][i + dx0]); Cell & c(cells[j + dy0][i + dx0]);
PRIVATE->chars[k].Char.UnicodeChar = 0; PRIVATE->chars[k].Char.UnicodeChar = 0;
PRIVATE->chars[k].Char.AsciiChar = c.symbol.toConsole1Byte(); PRIVATE->chars[k].Char.AsciiChar = c.symbol.toConsole1Byte();
PRIVATE->chars[k].Attributes = attributes(c); PRIVATE->chars[k].Attributes = attributes(c);
} }
//piCout << "draw" << dw << dh; //piCout << "draw" << dw << dh;
PRIVATE->bs.X = dw; PRIVATE->bs.X = dw;
PRIVATE->bs.Y = dh; PRIVATE->bs.Y = dh;
PRIVATE->srect.Left += dx0; PRIVATE->srect.Left += dx0;
PRIVATE->srect.Top += dy0; PRIVATE->srect.Top += dy0;
PRIVATE->srect.Right -= width - dx1 - 1; PRIVATE->srect.Right -= width - dx1 - 1;
PRIVATE->srect.Bottom -= height - dy1 - 1; PRIVATE->srect.Bottom -= height - dy1 - 1;
WriteConsoleOutput(PRIVATE->hOut, PRIVATE->chars.data(), PRIVATE->bs, PRIVATE->bc, &PRIVATE->srect); WriteConsoleOutput(PRIVATE->hOut, PRIVATE->chars.data(), PRIVATE->bs, PRIVATE->bc, &PRIVATE->srect);
#else #else
PIString s; PIString s;
int si = 0, sj = 0; int si = 0, sj = 0;
CellFormat prf(0xFFFF); CellFormat prf(0xFFFF);
for (int j = 0; j < height; ++j) { for (int j = 0; j < height; ++j) {
PIVector<Cell> & ccv(cells[j]); PIVector<Cell> & ccv(cells[j]);
PIVector<Cell> & pcv(pcells[j]); PIVector<Cell> & pcv(pcells[j]);
for (int i = 0; i < width; ++i) { for (int i = 0; i < width; ++i) {
Cell & cc(ccv[i]); Cell & cc(ccv[i]);
Cell & pc(pcv[i]); Cell & pc(pcv[i]);
if (cc != pc) { if (cc != pc) {
if (s.isEmpty()) { if (s.isEmpty()) {
si = i; si = i;
sj = j; sj = j;
} }
if (prf != cc.format) { if (prf != cc.format) {
prf = cc.format; prf = cc.format;
s += formatString(cc); s += formatString(cc);
} }
s += cc.symbol; s += cc.symbol;
} else { } else {
if (!s.isEmpty()) { if (!s.isEmpty()) {
moveTo(si, sj); moveTo(si, sj);
printf("%s", s.data()); printf("%s", s.data());
s.clear(); s.clear();
} }
} }
} }
if (!s.isEmpty()) { if (!s.isEmpty()) {
moveTo(si, sj); moveTo(si, sj);
printf("%s", s.data()); printf("%s", s.data());
s.clear(); s.clear();
} }
} }
printf("\e[0m"); printf("\e[0m");
fflush(0); fflush(0);
#endif #endif
pcells = cells; pcells = cells;
} }
#ifdef WINDOWS #ifdef WINDOWS
#define FOREGROUND_MASK (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) #define FOREGROUND_MASK (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
#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) attr |= FOREGROUND_INTENSITY; if (c.format.flags & Bold) attr |= FOREGROUND_INTENSITY;
else attr &= ~FOREGROUND_INTENSITY; else attr &= ~FOREGROUND_INTENSITY;
if (c.format.flags & Underline) attr |= COMMON_LVB_UNDERSCORE; if (c.format.flags & Underline) attr |= COMMON_LVB_UNDERSCORE;
else 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;
case Green: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_GREEN; break; case Green: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_GREEN; break;
case Blue: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_BLUE; break; case Blue: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_BLUE; break;
case Cyan: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE; break; case Cyan: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
case Magenta: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED | FOREGROUND_BLUE; break; case Magenta: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED | FOREGROUND_BLUE; break;
case Yellow: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED | FOREGROUND_GREEN; break; case Yellow: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED | FOREGROUND_GREEN; break;
case White: attr = attr | FOREGROUND_MASK; break; case White: attr = attr | FOREGROUND_MASK; break;
} }
switch (c.format.color_back) { switch (c.format.color_back) {
case Black: attr = (attr & ~BACKGROUND_MASK); break; case Black: attr = (attr & ~BACKGROUND_MASK); break;
case Red: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED; break; case Red: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED; break;
case Green: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_GREEN; break; case Green: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_GREEN; break;
case Blue: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_BLUE; break; case Blue: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_BLUE; break;
case Cyan: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE; break; case Cyan: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE; break;
case Magenta: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED | BACKGROUND_BLUE; break; case Magenta: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED | BACKGROUND_BLUE; break;
case Yellow: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED | BACKGROUND_GREEN; break; case Yellow: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED | BACKGROUND_GREEN; break;
case White: attr = attr | BACKGROUND_MASK; break; case White: attr = attr | BACKGROUND_MASK; break;
} }
if ((c.format.flags & Inverse) == Inverse) { if ((c.format.flags & Inverse) == Inverse) {
uchar f = attr & 0xFF; uchar f = attr & 0xFF;
attr &= 0xFFFFFF00; attr &= 0xFFFFFF00;
f = (f << 4) | (f >> 4); f = (f << 4) | (f >> 4);
attr |= f; attr |= f;
} }
return attr; return attr;
} }
#undef FOREGROUND_MASK #undef FOREGROUND_MASK
#undef BACKGROUND_MASK #undef BACKGROUND_MASK
void PIScreen::SystemConsole::getWinCurCoord() { void PIScreen::SystemConsole::getWinCurCoord() {
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi);
PRIVATE->ccoord = PRIVATE->csbi.dwCursorPosition; PRIVATE->ccoord = PRIVATE->csbi.dwCursorPosition;
} }
void PIScreen::SystemConsole::clearLine() { void PIScreen::SystemConsole::clearLine() {
getWinCurCoord(); getWinCurCoord();
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
} }
void PIScreen::SystemConsole::newLine() { void PIScreen::SystemConsole::newLine() {
getWinCurCoord(); getWinCurCoord();
PRIVATE->ccoord.X = 0; PRIVATE->ccoord.Y++; PRIVATE->ccoord.X = 0; PRIVATE->ccoord.Y++;
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
} }
#else // WINDOWS #else // WINDOWS
PIString PIScreen::SystemConsole::formatString(const PIScreenTypes::Cell & c) { PIString PIScreen::SystemConsole::formatString(const PIScreenTypes::Cell & c) {
PIString ts("\e[0"); PIString ts("\e[0");
switch (c.format.color_char) { switch (c.format.color_char) {
case Black: ts += ";30"; break; case Black: ts += ";30"; break;
case Red: ts += ";31"; break; case Red: ts += ";31"; break;
case Green: ts += ";32"; break; case Green: ts += ";32"; break;
case Blue: ts += ";34"; break; case Blue: ts += ";34"; break;
case Cyan: ts += ";36"; break; case Cyan: ts += ";36"; break;
case Magenta: ts += ";35"; break; case Magenta: ts += ";35"; break;
case Yellow: ts += ";33"; break; case Yellow: ts += ";33"; break;
case White: ts += ";37"; break; case White: ts += ";37"; break;
} }
switch (c.format.color_back) { switch (c.format.color_back) {
case Black: ts += ";40"; break; case Black: ts += ";40"; break;
case Red: ts += ";41"; break; case Red: ts += ";41"; break;
case Green: ts += ";42"; break; case Green: ts += ";42"; break;
case Blue: ts += ";44"; break; case Blue: ts += ";44"; break;
case Cyan: ts += ";46"; break; case Cyan: ts += ";46"; break;
case Magenta: ts += ";45"; break; case Magenta: ts += ";45"; break;
case Yellow: ts += ";43"; break; case Yellow: ts += ";43"; break;
case White: ts += ";47"; break; case White: ts += ";47"; break;
} }
if ((c.format.flags & Bold) == Bold) ts += ";1"; if ((c.format.flags & Bold) == Bold) ts += ";1";
if ((c.format.flags & Underline) == Underline) ts += ";4"; if ((c.format.flags & Underline) == Underline) ts += ";4";
if ((c.format.flags & Blink) == Blink) ts += ";5"; if ((c.format.flags & Blink) == Blink) ts += ";5";
if ((c.format.flags & Inverse) == Inverse) ts += ";7"; if ((c.format.flags & Inverse) == Inverse) ts += ";7";
return ts + "m"; return ts + "m";
} }
#endif // WINDOWS #endif // WINDOWS
void PIScreen::SystemConsole::toUpperLeft() { void PIScreen::SystemConsole::toUpperLeft() {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ulcoord); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ulcoord);
#else #else
printf("\e[H"); printf("\e[H");
#endif #endif
} }
void PIScreen::SystemConsole::moveTo(int x, int y) { void PIScreen::SystemConsole::moveTo(int x, int y) {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->ccoord.X = x; PRIVATE->ccoord.X = x;
PRIVATE->ccoord.Y = PRIVATE->ulcoord.Y + y; PRIVATE->ccoord.Y = PRIVATE->ulcoord.Y + y;
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
#else #else
printf("\e[%d;%dH", y + 1, x + 1); printf("\e[%d;%dH", y + 1, x + 1);
#endif #endif
} }
void PIScreen::SystemConsole::clearScreen() { void PIScreen::SystemConsole::clearScreen() {
#ifdef WINDOWS #ifdef WINDOWS
toUpperLeft(); toUpperLeft();
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written); FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written);
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written); FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written);
#else #else
printf("\e[0m\e[H\e[J"); printf("\e[0m\e[H\e[J");
#endif #endif
} }
void PIScreen::SystemConsole::clearScreenLower() { void PIScreen::SystemConsole::clearScreenLower() {
#ifdef WINDOWS #ifdef WINDOWS
getWinCurCoord(); getWinCurCoord();
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, 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); 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
} }
void PIScreen::SystemConsole::hideCursor() { void PIScreen::SystemConsole::hideCursor() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->curinfo.bVisible = false; PRIVATE->curinfo.bVisible = false;
SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
printf("\e[?25l"); printf("\e[?25l");
#endif #endif
} }
void PIScreen::SystemConsole::showCursor() { void PIScreen::SystemConsole::showCursor() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->curinfo.bVisible = true; PRIVATE->curinfo.bVisible = true;
SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
printf("\e[?25h"); printf("\e[?25h");
#endif #endif
} }
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");
setPriority(piLow); setPriority(piLow);
needLockRun(true); needLockRun(true);
mouse_ = false; mouse_ = false;
ret_func = slot; ret_func = slot;
tile_focus = tile_dialog = 0; 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);
CONNECTU(listener, mouseEvent, this, mouse_event); CONNECTU(listener, mouseEvent, this, mouse_event);
CONNECTU(listener, wheelEvent, this, wheel_event); CONNECTU(listener, wheelEvent, this, wheel_event);
if (startNow) start(); if (startNow) start();
} }
PIScreen::~PIScreen() { PIScreen::~PIScreen() {
if (isRunning()) if (isRunning())
stop(); stop();
PIThread::waitForFinish(10); PIThread::waitForFinish(10);
listener->waitForFinish(10); listener->waitForFinish(10);
delete listener; delete listener;
} }
void PIScreen::setMouseEnabled(bool on) { void PIScreen::setMouseEnabled(bool on) {
mouse_ = on; mouse_ = on;
console.mouse_x = console.mouse_y = -1; console.mouse_x = console.mouse_y = -1;
} }
void PIScreen::key_event(PIKbdListener::KeyEvent key) { void PIScreen::key_event(PIKbdListener::KeyEvent key) {
/** DEBUG /** DEBUG
if (ret_func != 0) ret_func(key, t); if (ret_func != 0) ret_func(key, t);
keyPressed(key, t); keyPressed(key, t);
return; return;
*/ */
PIScreenTile * rtile = rootTile(); PIScreenTile * rtile = rootTile();
if (tile_dialog) if (tile_dialog)
rtile = 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)) if (tile_focus->keyEvent(key))
return; return;
} }
} }
if (ret_func != 0) ret_func(key, data_); if (ret_func != 0) ret_func(key, data_);
keyPressed(key, data_); keyPressed(key, data_);
} }
PIVector<PIScreenTile * > PIScreen::prepareMouse(PIKbdListener::MouseEvent * e) { PIVector<PIScreenTile * > PIScreen::prepareMouse(PIKbdListener::MouseEvent * e) {
PIVector<PIScreenTile * > ret; PIVector<PIScreenTile * > ret;
if (!mouse_ || !e) return ret; if (!mouse_ || !e) return ret;
console.mouse_x = e->x; console.mouse_x = e->x;
console.mouse_y = e->y; console.mouse_y = e->y;
PIVector<PIScreenTile * > tl = tilesUnderMouse(e->x, e->y); PIVector<PIScreenTile * > tl = tilesUnderMouse(e->x, e->y);
bool ff = false; bool ff = false;
piForeachR (PIScreenTile * t, tl) { piForeachR (PIScreenTile * t, tl) {
if (!ff) { if (!ff) {
if (t->focus_flags[FocusOnMouse] && (e->action == PIKbdListener::MouseButtonPress)) { if (t->focus_flags[FocusOnMouse] && (e->action == PIKbdListener::MouseButtonPress)) {
t->setFocus(); t->setFocus();
ff = true; ff = true;
} }
if (t->focus_flags[FocusOnWheel] && (e->action == PIKbdListener::MouseWheel)) { if (t->focus_flags[FocusOnWheel] && (e->action == PIKbdListener::MouseWheel)) {
t->setFocus(); t->setFocus();
ff = true; ff = true;
} }
} }
} }
return tl; return tl;
} }
PIVector<PIScreenTile * > PIScreen::tilesUnderMouse(int x, int y) { PIVector<PIScreenTile * > PIScreen::tilesUnderMouse(int x, int y) {
PIVector<PIScreenTile * > ret; PIVector<PIScreenTile * > ret;
if (x < 0 || x >= console.width || y < 0 || y >= console.height) return ret; if (x < 0 || x >= console.width || y < 0 || y >= console.height) return ret;
PIScreenTile * ct = tile_dialog ? tile_dialog : rootTile(); PIScreenTile * ct = tile_dialog ? tile_dialog : rootTile();
bool f = true; bool f = true;
while (ct) { while (ct) {
if (!f) ret << ct; if (!f) ret << ct;
f = false; f = false;
ct = ct->childUnderMouse(x, y); ct = ct->childUnderMouse(x, y);
} }
return ret; return ret;
} }
void PIScreen::mouse_event(PIKbdListener::MouseEvent me) { void PIScreen::mouse_event(PIKbdListener::MouseEvent me) {
PIVector<PIScreenTile * > tl = prepareMouse(&me); PIVector<PIScreenTile * > tl = prepareMouse(&me);
if (tl.isEmpty()) return; if (tl.isEmpty()) return;
piForeachR (PIScreenTile * t, tl) piForeachR (PIScreenTile * t, tl)
if (t->mouseEvent(me)) piBreak; if (t->mouseEvent(me)) break;
} }
void PIScreen::wheel_event(PIKbdListener::WheelEvent we) { void PIScreen::wheel_event(PIKbdListener::WheelEvent we) {
PIVector<PIScreenTile * > tl = prepareMouse(&we); PIVector<PIScreenTile * > tl = prepareMouse(&we);
if (tl.isEmpty()) return; if (tl.isEmpty()) return;
piForeachR (PIScreenTile * t, tl) piForeachR (PIScreenTile * t, tl)
if (t->wheelEvent(we)) piBreak; 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]) if (t->focus_flags[CanHasFocus])
ftl << t; 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)
if (ftl[i] == tile_focus) { if (ftl[i] == tile_focus) {
ind = i; ind = i;
break; break;
} }
if (ind < 0) if (ind < 0)
tile_focus = 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) if (!tile_focus->visible)
tile_focus = 0; 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) if (tile_focus->focus_flags[NextByTab] && key.key == PIKbdListener::Tab)
next = 1; 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;
} }
if (tile_focus->focus_flags[NextByArrowsVertical]) { if (tile_focus->focus_flags[NextByArrowsVertical]) {
if (key.key == PIKbdListener::UpArrow) next = -1; if (key.key == PIKbdListener::UpArrow) next = -1;
if (key.key == PIKbdListener::DownArrow) next = 1; if (key.key == PIKbdListener::DownArrow) next = 1;
} }
} }
//piCout << ftl.size() << ind << next; //piCout << ftl.size() << ind << next;
if (next != 0) { if (next != 0) {
PIVector<PIScreenTile*> tl = rt->children(); PIVector<PIScreenTile*> tl = rt->children();
piForeach (PIScreenTile * t, tl) piForeach (PIScreenTile * t, tl)
t->has_focus = false; t->has_focus = false;
if (!ftl.isEmpty()) { if (!ftl.isEmpty()) {
ind += next; ind += next;
if (ind >= ftl.size_s()) ind = 0; if (ind >= ftl.size_s()) ind = 0;
if (ind < 0) ind = ftl.size_s() - 1; if (ind < 0) ind = ftl.size_s() - 1;
tile_focus = ftl[ind]; tile_focus = ftl[ind];
tile_focus->has_focus = true; tile_focus->has_focus = true;
} }
return true; return true;
} }
} }
return false; return false;
} }
void PIScreen::tileEventInternal(PIScreenTile * t, TileEvent e) { void PIScreen::tileEventInternal(PIScreenTile * t, TileEvent e) {
tileEvent(t, e); tileEvent(t, e);
} }
void PIScreen::tileRemovedInternal(PIScreenTile * t) { void PIScreen::tileRemovedInternal(PIScreenTile * t) {
if (tile_dialog == t) if (tile_dialog == t)
tile_dialog = 0; tile_dialog = 0;
} }
void PIScreen::tileSetFocusInternal(PIScreenTile * t) { void PIScreen::tileSetFocusInternal(PIScreenTile * t) {
PIScreenTile * rt = rootTile(); PIScreenTile * rt = rootTile();
if (tile_dialog) if (tile_dialog)
rt = 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]) if (tile_focus->focus_flags[CanHasFocus])
tile_focus->has_focus = true; tile_focus->has_focus = true;
} }
void PIScreen::setDialogTile(PIScreenTile * t) { void PIScreen::setDialogTile(PIScreenTile * t) {
tile_dialog = t; tile_dialog = t;
if (!tile_dialog) { if (!tile_dialog) {
nextFocus(&root); nextFocus(&root);
return; return;
} }
tile_dialog->setScreen(this); tile_dialog->setScreen(this);
tile_dialog->parent = 0; tile_dialog->parent = 0;
nextFocus(tile_dialog); nextFocus(tile_dialog);
} }
void PIScreen::waitForFinish() { void PIScreen::waitForFinish() {
WAIT_FOR_EXIT WAIT_FOR_EXIT
stop(); stop();
} }
void PIScreen::stop(bool clear) { void PIScreen::stop(bool clear) {
PIThread::stop(true); PIThread::stop(true);
if (clear) console.clearScreen(); if (clear) console.clearScreen();
#ifndef WINDOWS #ifndef WINDOWS
fflush(0); fflush(0);
#endif #endif
} }
void PIScreen::begin() { void PIScreen::begin() {
listener->start(); listener->start();
nextFocus(&root); nextFocus(&root);
console.begin(); console.begin();
} }
void PIScreen::run() { void PIScreen::run() {
console.prepare(); console.prepare();
root.width_ = drawer_.width = console.width; root.width_ = drawer_.width = console.width;
root.height_ = drawer_.height = console.height; root.height_ = drawer_.height = console.height;
root.layout(); root.layout();
root.drawEventInternal(&drawer_); root.drawEventInternal(&drawer_);
if (tile_dialog) { if (tile_dialog) {
int sw(0), sh(0); int sw(0), sh(0);
tile_dialog->sizeHint(sw, sh); tile_dialog->sizeHint(sw, sh);
sw = piClampi(sw, tile_dialog->minimumWidth, tile_dialog->maximumWidth); sw = piClampi(sw, tile_dialog->minimumWidth, tile_dialog->maximumWidth);
sh = piClampi(sh, tile_dialog->minimumHeight, tile_dialog->maximumHeight); sh = piClampi(sh, tile_dialog->minimumHeight, tile_dialog->maximumHeight);
tile_dialog->x_ = (console.width - sw) / 2; tile_dialog->x_ = (console.width - sw) / 2;
tile_dialog->y_ = (console.height - sh) / 2; tile_dialog->y_ = (console.height - sh) / 2;
tile_dialog->width_ = sw; tile_dialog->width_ = sw;
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, dy, dx + dw + 1, dy + dh + 1, (Color)tile_dialog->back_format.color_char, drawer_.drawFrame(dx, dy, 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); (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();
} }
void PIScreen::end() { void PIScreen::end() {
listener->stop(); listener->stop();
console.end(); console.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) if (t->name() == name)
return t; return t;
return 0; return 0;
} }

View File

@@ -1,42 +1,42 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API Tile for PIScreen with PIConsole API
Andrey Bychkov work.a.b@yandex.ru Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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 "piscreenconsole.h" #include "piscreenconsole.h"
using namespace PIScreenTypes; using namespace PIScreenTypes;
TileVars::TileVars(const PIString &n) : PIScreenTile(n) { TileVars::TileVars(const PIString &n) : PIScreenTile(n) {
alignment = Left; alignment = Left;
} }
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() {
} }

View File

@@ -1,271 +1,271 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console output/input Console output/input
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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 "piscreendrawer.h" #include "piscreendrawer.h"
// comment for use ascii instead of unicode symbols // comment for use ascii instead of unicode symbols
#define USE_UNICODE #define USE_UNICODE
using namespace PIScreenTypes; using namespace PIScreenTypes;
PIScreenDrawer::PIScreenDrawer(PIVector<PIVector<Cell> > & c): cells(c) { PIScreenDrawer::PIScreenDrawer(PIVector<PIVector<Cell> > & c): cells(c) {
arts_[LineVertical] = arts_[LineVertical] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('|'); PIChar('|');
#endif #endif
arts_[LineHorizontal] = arts_[LineHorizontal] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('-'); PIChar('-');
#endif #endif
arts_[Cross] = arts_[Cross] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[CornerTopLeft] = arts_[CornerTopLeft] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[CornerTopRight] = arts_[CornerTopRight] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[CornerBottomLeft] = arts_[CornerBottomLeft] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[CornerBottomRight] = arts_[CornerBottomRight] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[Unchecked] = arts_[Unchecked] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('O'); PIChar('O');
#endif #endif
arts_[Checked] = arts_[Checked] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('0'); PIChar('0');
#endif #endif
} }
void PIScreenDrawer::clear() { void PIScreenDrawer::clear() {
clear(cells); clear(cells);
} }
void PIScreenDrawer::drawPixel(int x, int y, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawPixel(int x, int y, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
if (x < 0 || x >= width || y < 0 || y >= height) return; if (x < 0 || x >= width || y < 0 || y >= height) return;
cells[y][x].symbol = c; cells[y][x].symbol = c;
cells[y][x].format.color_char = col_char; cells[y][x].format.color_char = col_char;
cells[y][x].format.color_back = col_back; cells[y][x].format.color_back = col_back;
cells[y][x].format.flags = flags_char; cells[y][x].format.flags = flags_char;
} }
void PIScreenDrawer::drawLine(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawLine(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char); if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
Cell cc; Cell cc;
cc.symbol = c; cc.symbol = c;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
int x = 0, y = 0; int x = 0, y = 0;
if (piAbsi(x1 - x0) >= piAbsi(y1 - y0)) { if (piAbsi(x1 - x0) >= piAbsi(y1 - y0)) {
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; y = piRound(cy); x = i; 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) if (x1 >= 0 && x1 < width && y >= 0 && y < height)
cells[y][x1] = cc; 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); y = i; x = piRound(cx); 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) if (x >= 0 && x < width && y1 >= 0 && y1 < height)
cells[y1][x] = cc; cells[y1][x] = cc;
} }
} }
void PIScreenDrawer::drawRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char); if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
Cell cc; Cell cc;
cc.symbol = c; cc.symbol = c;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
int dx = x0 < x1 ? 1 : -1; int dx = x0 < x1 ? 1 : -1;
int dy = y0 < y1 ? 1 : -1; int dy = y0 < y1 ? 1 : -1;
int xs[2] = {x0, x1}; int xs[2] = {x0, x1};
int ys[2] = {y0, y1}; int ys[2] = {y0, y1};
for (int k = 0; k < 2; ++k) { for (int k = 0; k < 2; ++k) {
int j = ys[k]; int j = ys[k];
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) if (i >= 0 && i < width)
cv[i] = cc; 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) if (i >= 0 && i < height)
cells[i][j] = cc; cells[i][j] = cc;
} }
} }
int i = x1, j = y1; int i = x1, j = y1;
if (i >= 0 && i < width && j >= 0 && j < height) if (i >= 0 && i < width && j >= 0 && j < height)
cells[j][i] = cc; cells[j][i] = cc;
} }
void PIScreenDrawer::drawFrame(int x0, int y0, int x1, int y1, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawFrame(int x0, int y0, int x1, int y1, Color col_char, Color col_back, CharFlags flags_char) {
if (x0 == x1 && y0 == y1) return; if (x0 == x1 && y0 == y1) return;
Cell cc; Cell cc;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
int dx = x0 < x1 ? 1 : -1; int dx = x0 < x1 ? 1 : -1;
int dy = y0 < y1 ? 1 : -1; int dy = y0 < y1 ? 1 : -1;
int xs[2] = {x0, x1}; int xs[2] = {x0, x1};
int ys[2] = {y0, y1}; int ys[2] = {y0, y1};
for (int k = 0; k < 2; ++k) { for (int k = 0; k < 2; ++k) {
int j = ys[k]; int j = ys[k];
if (j >= 0 && j < height) { if (j >= 0 && j < height) {
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) if (i >= 0 && i < width)
cv[i] = cc; 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) if (i >= 0 && i < height)
cells[i][j] = cc; cells[i][j] = cc;
} }
} }
int i = x0, j = y0; cc.symbol = artChar(CornerTopLeft); int i = x0, j = y0; 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; cc.symbol = artChar(CornerTopRight); i = x1, j = y0; 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; cc.symbol = artChar(CornerBottomLeft); i = x0, j = y1; 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; cc.symbol = artChar(CornerBottomRight); i = x1, j = y1; 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;
} }
void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char); if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
Cell cc; Cell cc;
cc.symbol = c; cc.symbol = c;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
int dx = x0 < x1 ? 1 : -1; int dx = x0 < x1 ? 1 : -1;
int dy = y0 < y1 ? 1 : -1; int dy = y0 < y1 ? 1 : -1;
for (int j = y0; j != y1; j += dy) for (int j = y0; j != y1; j += dy)
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) if (i >= 0 && i < width)
cv[i] = cc; cv[i] = cc;
} }
} }
void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<Cell> > & content) { void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<Cell> > & content) {
if (x0 > x1) piSwap(x0, x1); if (x0 > x1) piSwap(x0, x1);
if (y0 > y1) piSwap(y0, y1); if (y0 > y1) piSwap(y0, y1);
int w = x1 - x0; int w = x1 - x0;
int h = y1 - y0; int h = y1 - y0;
for (int j = 0; j < h; ++j) for (int j = 0; j < h; ++j)
if (j < piMini(height, content.size_s())) { if (j < piMini(height, content.size_s())) {
if ((j + y0) >= 0 && (j + y0) < height) { if ((j + y0) >= 0 && (j + y0) < height) {
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) if ((i + x0) >= 0 && (i + x0) < width)
cv[x0 + i] = contv[i]; cv[x0 + i] = contv[i];
} }
} }
} }
void PIScreenDrawer::clear(PIVector<PIVector<Cell> > & cells) { void PIScreenDrawer::clear(PIVector<PIVector<Cell> > & cells) {
for (int i = 0; i < cells.size_s(); ++i) for (int i = 0; i < cells.size_s(); ++i)
cells[i].fill(Cell()); cells[i].fill(Cell());
} }
void PIScreenDrawer::drawText(int x, int y, const PIString & s, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawText(int x, int y, const PIString & s, Color col_char, Color col_back, CharFlags flags_char) {
if (x < 0 || x >= width || y < 0 || y >= height) return; if (x < 0 || x >= width || y < 0 || y >= height) return;
PIVector<Cell> & cv(cells[y]); PIVector<Cell> & cv(cells[y]);
Cell cc; Cell cc;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
for (int i = 0; i < s.size_s(); ++i) { for (int i = 0; i < s.size_s(); ++i) {
int j = i + x; int j = i + x;
if (j >= 0 && j < width) { if (j >= 0 && j < width) {
cc.symbol = s[i]; cc.symbol = s[i];
cv[j] = cc; cv[j] = cc;
} }
} }
} }

View File

@@ -1,250 +1,250 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic PIScreen tile Basic PIScreen tile
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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 "piscreentile.h" #include "piscreentile.h"
#include "piscreendrawer.h" #include "piscreendrawer.h"
using namespace PIScreenTypes; using namespace PIScreenTypes;
PIScreenTile::PIScreenTile(const PIString & n, Direction d, SizePolicy p): PIObject(n) { PIScreenTile::PIScreenTile(const PIString & n, Direction d, SizePolicy p): PIObject(n) {
direction = d; direction = d;
size_policy = p; size_policy = p;
focus_flags = 0; focus_flags = 0;
screen = 0; screen = 0;
minimumWidth = minimumHeight = x_ = y_ = width_ = height_ = pw = ph = 0; minimumWidth = minimumHeight = x_ = y_ = width_ = height_ = pw = ph = 0;
maximumWidth = maximumHeight = 65535; maximumWidth = maximumHeight = 65535;
marginLeft = marginRight = marginTop = marginBottom = spacing = 0; marginLeft = marginRight = marginTop = marginBottom = spacing = 0;
parent = 0; parent = 0;
back_symbol = ' '; back_symbol = ' ';
visible = true; visible = true;
has_focus = false; has_focus = false;
} }
PIScreenTile::~PIScreenTile() { PIScreenTile::~PIScreenTile() {
//piCout << this << "~"; //piCout << this << "~";
if (screen) if (screen)
screen->tileRemovedInternal(this); screen->tileRemovedInternal(this);
setScreen(0); setScreen(0);
deleteChildren(); deleteChildren();
if (!parent) return; if (!parent) return;
parent->tiles.removeOne(this); parent->tiles.removeOne(this);
} }
void PIScreenTile::addTile(PIScreenTile * t) { void PIScreenTile::addTile(PIScreenTile * t) {
if (t == 0) return; if (t == 0) return;
if (tiles.contains(t)) return; if (tiles.contains(t)) return;
tiles << t; tiles << t;
t->parent = this; t->parent = this;
t->setScreen(screen); t->setScreen(screen);
} }
void PIScreenTile::takeTile(PIScreenTile * t) { void PIScreenTile::takeTile(PIScreenTile * t) {
if (!tiles.contains(t)) return; if (!tiles.contains(t)) return;
tiles.removeOne(t); tiles.removeOne(t);
t->parent = 0; t->parent = 0;
t->setScreen(0); t->setScreen(0);
} }
void PIScreenTile::removeTile(PIScreenTile * t) { void PIScreenTile::removeTile(PIScreenTile * t) {
if (!tiles.contains(t)) return; if (!tiles.contains(t)) return;
tiles.removeOne(t); tiles.removeOne(t);
t->parent = 0; t->parent = 0;
t->setScreen(0); t->setScreen(0);
delete t; delete 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) if (t->visible || !only_visible)
ret << t << t->children(only_visible); ret << t << t->children(only_visible);
return ret; return ret;
} }
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_ && if (x >= t->x_ && (x - t->x_) < t->width_ &&
y >= t->y_ && (y - t->y_) < t->height_) { y >= t->y_ && (y - t->y_) < t->height_) {
return t; return t;
} }
} }
return 0; return 0;
} }
void PIScreenTile::raiseEvent(TileEvent e) { void PIScreenTile::raiseEvent(TileEvent e) {
if (!screen) return; if (!screen) return;
screen->tileEventInternal(this, e); screen->tileEventInternal(this, e);
} }
void PIScreenTile::setScreen(PIScreenBase * s) { void PIScreenTile::setScreen(PIScreenBase * s) {
screen = s; screen = s;
piForeach (PIScreenTile * t, tiles) piForeach (PIScreenTile * t, tiles)
t->setScreen(s); t->setScreen(s);
} }
void PIScreenTile::deleteChildren() { void PIScreenTile::deleteChildren() {
piForeach (PIScreenTile * t, tiles) { piForeach (PIScreenTile * t, tiles) {
t->parent = 0; t->parent = 0;
delete t; delete t;
} }
tiles.clear(); tiles.clear();
} }
void PIScreenTile::setFocus() { void PIScreenTile::setFocus() {
if (!screen || !focus_flags[CanHasFocus]) return; if (!screen || !focus_flags[CanHasFocus]) return;
screen->tileSetFocusInternal(this); screen->tileSetFocusInternal(this);
} }
void PIScreenTile::drawEventInternal(PIScreenDrawer * d) { void PIScreenTile::drawEventInternal(PIScreenDrawer * d) {
if (!visible) { if (!visible) {
return; return;
} }
d->fillRect(x_, y_, x_ + width_, y_ + height_, back_symbol, (Color)back_format.color_char, (Color)back_format.color_back, back_format.flags); d->fillRect(x_, 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);
} }
void PIScreenTile::sizeHint(int & w, int & h) const { void PIScreenTile::sizeHint(int & w, int & h) const {
w = 0; w = 0;
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) w += sl; if (direction == Horizontal) 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);
t->sizeHint(cw, ch); t->sizeHint(cw, ch);
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; h = piMaxi(h, ch); w += cw; h = piMaxi(h, ch);
} else { } else {
h += ch; w = piMaxi(w, cw); h += ch; w = piMaxi(w, cw);
} }
} }
w += marginLeft + marginRight; w += marginLeft + marginRight;
h += marginTop + marginBottom; h += marginTop + marginBottom;
} }
void PIScreenTile::layout() { void PIScreenTile::layout() {
if (tiles.isEmpty() || !visible) return; if (tiles.isEmpty() || !visible) return;
int as(0), ts(0), ts2(0), ecnt(0), pcnt(0); int as(0), ts(0), ts2(0), ecnt(0), pcnt(0);
ts = (direction == Horizontal) ? (width_ - marginLeft - marginRight) : (height_ - marginTop - marginBottom); ts = (direction == Horizontal) ? (width_ - marginLeft - marginRight) : (height_ - marginTop - marginBottom);
ts2 = (direction != Horizontal) ? (width_ - marginLeft - marginRight) : (height_ - marginTop - marginBottom); ts2 = (direction != Horizontal) ? (width_ - marginLeft - marginRight) : (height_ - marginTop - marginBottom);
ts -= spacing * (tiles.size_s() - 1); ts -= spacing * (tiles.size_s() - 1);
PIVector<int> hints(tiles.size_s()); PIVector<int> hints(tiles.size_s());
PIVector<float> asizes(tiles.size_s()); PIVector<float> asizes(tiles.size_s());
for (int i = 0; i < tiles.size_s(); ++i) { for (int i = 0; i < tiles.size_s(); ++i) {
PIScreenTile * t(tiles[i]); PIScreenTile * t(tiles[i]);
int cw(0), ch(0), cs(0); int cw(0), ch(0), cs(0);
if (t->visible && t->needLayout()) { if (t->visible && t->needLayout()) {
t->sizeHint(cw, ch); t->sizeHint(cw, ch);
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 (t->size_policy == Expanding) ++ecnt; if (t->size_policy == Expanding) ++ecnt;
if (t->size_policy == Preferred) ++pcnt; if (t->size_policy == Preferred) ++pcnt;
cs = (direction == Horizontal) ? cw : ch; cs = (direction == Horizontal) ? cw : ch;
as += cs; as += cs;
} }
hints[i] = cs; hints[i] = cs;
asizes[i] = 0.f; asizes[i] = 0.f;
} }
if (as <= ts) { if (as <= ts) {
int acnt(0); int acnt(0);
SizePolicy pol = Fixed; SizePolicy pol = Fixed;
if (ecnt > 0) { if (ecnt > 0) {
acnt = ecnt; acnt = ecnt;
pol = Expanding; pol = Expanding;
} else if (pcnt > 0) { } else if (pcnt > 0) {
acnt = pcnt; acnt = pcnt;
pol = Preferred; pol = Preferred;
} }
if (acnt > 0) { if (acnt > 0) {
float add_a = float(ts - as), add_s = add_a / acnt, add_da(0.); float add_a = float(ts - as), add_s = add_a / acnt, add_da(0.);
asizes.fill(add_s); asizes.fill(add_s);
PISet<int> max_tl; PISet<int> max_tl;
for (int i = 0; i < tiles.size_s(); ++i) { for (int i = 0; i < tiles.size_s(); ++i) {
if (tiles[i]->size_policy == pol && tiles[i]->visible && tiles[i]->needLayout()) { if (tiles[i]->size_policy == pol && tiles[i]->visible && tiles[i]->needLayout()) {
float maxs = (direction == Horizontal) ? tiles[i]->maximumWidth : tiles[i]->maximumHeight; float maxs = (direction == Horizontal) ? tiles[i]->maximumWidth : tiles[i]->maximumHeight;
if (hints[i] + asizes[i] > maxs) { if (hints[i] + asizes[i] > maxs) {
max_tl << i; max_tl << i;
float pas = asizes[i]; float pas = asizes[i];
asizes[i] = maxs - hints[i]; asizes[i] = maxs - hints[i];
acnt--; acnt--;
if (acnt > 0) { if (acnt > 0) {
pas = (pas - asizes[i]) / acnt; pas = (pas - asizes[i]) / acnt;
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()) if (tiles[j]->size_policy == pol && tiles[j]->visible && tiles[j]->needLayout())
asizes[j] += pas; asizes[j] += pas;
} }
} }
} }
} }
} }
for (int i = 0; i < tiles.size_s(); ++i) { for (int i = 0; i < tiles.size_s(); ++i) {
if (tiles[i]->size_policy == pol && tiles[i]->visible && tiles[i]->needLayout()) { if (tiles[i]->size_policy == pol && tiles[i]->visible && tiles[i]->needLayout()) {
int a = piRound(asizes[i] + add_da); int a = piRound(asizes[i] + add_da);
add_da += asizes[i] - a; add_da += asizes[i] - a;
hints[i] += a; hints[i] += a;
} }
} }
} }
} }
int cx = x_ + marginLeft, cy = y_ + marginTop; int cx = x_ + marginLeft, cy = y_ + marginTop;
for (int i = 0; i < tiles.size_s(); ++i) { for (int i = 0; i < tiles.size_s(); ++i) {
PIScreenTile * t = tiles[i]; PIScreenTile * t = tiles[i];
if (!t->visible || !t->needLayout()) continue; if (!t->visible || !t->needLayout()) continue;
t->x_ = cx; t->x_ = cx;
t->y_ = cy; t->y_ = cy;
if (direction == Horizontal) { if (direction == Horizontal) {
t->width_ = hints[i]; t->width_ = hints[i];
t->height_ = ts2; t->height_ = ts2;
cx += hints[i] + spacing; cx += hints[i] + spacing;
} else { } else {
t->width_ = ts2; t->width_ = ts2;
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_) if (t->pw != t->width_ || t->ph != t->height_)
t->resizeEvent(t->width_, 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();
} }
} }

View File

@@ -1,714 +1,714 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Various tiles for PIScreen Various tiles for PIScreen
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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 "piscreentiles.h" #include "piscreentiles.h"
#include "piscreendrawer.h" #include "piscreendrawer.h"
using namespace PIScreenTypes; using namespace PIScreenTypes;
TileSimple::TileSimple(const PIString & n): PIScreenTile(n) { TileSimple::TileSimple(const PIString & n): PIScreenTile(n) {
alignment = Left; alignment = Left;
} }
TileSimple::TileSimple(const TileSimple::Row & r): PIScreenTile() { TileSimple::TileSimple(const TileSimple::Row & r): PIScreenTile() {
alignment = Left; alignment = Left;
content << r; content << r;
} }
void TileSimple::sizeHint(int & w, int & h) const { void TileSimple::sizeHint(int & w, int & h) const {
w = h = 0; w = h = 0;
piForeachC (Row & r, content) piForeachC (Row & r, content)
w = piMaxi(w, r.first.size_s()); w = piMaxi(w, r.first.size_s());
h = content.size_s(); h = content.size_s();
} }
void TileSimple::drawEvent(PIScreenDrawer * d) { void TileSimple::drawEvent(PIScreenDrawer * d) {
for (int i = 0; i < content.size_s(); ++i) { for (int i = 0; i < content.size_s(); ++i) {
Row & r(content[i]); Row & r(content[i]);
int rx = 0; int rx = 0;
switch (alignment) { switch (alignment) {
case Left: rx = x_; break; case Left: rx = x_; break;
case Center: rx = x_ + (width_ - r.first.size_s()) / 2; break; case Center: rx = x_ + (width_ - r.first.size_s()) / 2; break;
case Right: rx = x_ + width_ - r.first.size_s(); break; case Right: rx = x_ + width_ - r.first.size_s(); break;
}; };
d->drawText(rx, y_ + i, r.first, (Color)r.second.color_char, (Color)r.second.color_back, r.second.flags); d->drawText(rx, y_ + i, r.first, (Color)r.second.color_char, (Color)r.second.color_back, r.second.flags);
} }
} }
TileScrollBar::TileScrollBar(const PIString & n) { TileScrollBar::TileScrollBar(const PIString & n) {
direction = Vertical; direction = Vertical;
thickness = 1; thickness = 1;
minimum_ = value_ = 0; minimum_ = value_ = 0;
maximum_ = 100; maximum_ = 100;
} }
void TileScrollBar::setMinimum(int v) { void TileScrollBar::setMinimum(int v) {
minimum_ = v; minimum_ = v;
_check(); _check();
} }
void TileScrollBar::setMaximum(int v) { void TileScrollBar::setMaximum(int v) {
maximum_ = v; maximum_ = v;
_check(); _check();
} }
void TileScrollBar::setValue(int v) { void TileScrollBar::setValue(int v) {
value_ = v; value_ = v;
_check(); _check();
} }
void TileScrollBar::_check() { void TileScrollBar::_check() {
value_ = piClampi(value_, minimum_, maximum_); value_ = piClampi(value_, minimum_, maximum_);
} }
void TileScrollBar::sizeHint(int & w, int & h) const { void TileScrollBar::sizeHint(int & w, int & h) const {
w = h = 0; w = h = 0;
if (direction == Vertical) { if (direction == Vertical) {
w = thickness; w = thickness;
h = 255; h = 255;
} else { } else {
h = thickness; h = thickness;
w = 255; w = 255;
} }
} }
void TileScrollBar::drawEvent(PIScreenDrawer * d) { void TileScrollBar::drawEvent(PIScreenDrawer * d) {
line_char = d->artChar(direction == Vertical ? PIScreenDrawer::LineVertical : PIScreenDrawer::LineHorizontal); line_char = d->artChar(direction == Vertical ? PIScreenDrawer::LineVertical : PIScreenDrawer::LineHorizontal);
d->fillRect(x_, y_, x_ + width_, y_ + height_, line_char, Green); d->fillRect(x_, y_, x_ + width_, y_ + height_, line_char, Green);
if (value_ >= minimum_ && value_ <= maximum_) { if (value_ >= minimum_ && value_ <= maximum_) {
if (direction == Vertical) { if (direction == Vertical) {
int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (height_ - 1)); int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (height_ - 1));
d->drawLine(x_, y_ + c, x_ + width_ - 1, y_ + c, ' ', Green, Green); d->drawLine(x_, y_ + c, x_ + width_ - 1, y_ + c, ' ', Green, Green);
} else { } else {
int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (width_ - 1)); int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (width_ - 1));
d->drawLine(x_ + c, y_, x_ + c, y_ + height_ - 1, ' ', Green, Green); d->drawLine(x_ + c, y_, x_ + c, y_ + height_ - 1, ' ', Green, Green);
} }
} }
} }
bool TileScrollBar::mouseEvent(PIKbdListener::MouseEvent me) { bool TileScrollBar::mouseEvent(PIKbdListener::MouseEvent me) {
return true; return true;
} }
TileList::TileList(const PIString & n): PIScreenTile(n) { TileList::TileList(const PIString & n): PIScreenTile(n) {
alignment = Left; alignment = Left;
focus_flags = CanHasFocus | NextByArrowsHorizontal | NextByTab | FocusOnMouseOrWheel; focus_flags = CanHasFocus | NextByArrowsHorizontal | NextByTab | FocusOnMouseOrWheel;
lhei = offset = cur = 0; lhei = offset = cur = 0;
mouse_sel = false; mouse_sel = false;
selection_mode = NoSelection; selection_mode = NoSelection;
scroll = new TileScrollBar(); scroll = new TileScrollBar();
scroll->size_policy = Ignore; scroll->size_policy = Ignore;
addTile(scroll); addTile(scroll);
} }
void TileList::sizeHint(int & w, int & h) const { void TileList::sizeHint(int & w, int & h) const {
w = h = 0; w = h = 0;
piForeachC (Row & r, content) piForeachC (Row & r, content)
w = piMaxi(w, r.first.size_s()); w = piMaxi(w, r.first.size_s());
h = 3; h = 3;
} }
void TileList::resizeEvent(int w, int h) { void TileList::resizeEvent(int w, int h) {
scroll->x_ = x_ + width_ - 1; scroll->x_ = x_ + width_ - 1;
scroll->y_ = y_; scroll->y_ = y_;
scroll->width_ = 1; scroll->width_ = 1;
scroll->height_ = height_; scroll->height_ = height_;
} }
void TileList::drawEvent(PIScreenDrawer * d) { void TileList::drawEvent(PIScreenDrawer * d) {
lhei = height_ - 2; lhei = height_ - 2;
int is = piClampi(offset, 0, piMaxi(0, content.size_s() - 1)), ie = piClampi(offset + lhei, 0, content.size_s()); int is = piClampi(offset, 0, piMaxi(0, content.size_s() - 1)), ie = piClampi(offset + lhei, 0, content.size_s());
if (is > 0) d->drawText(x_, y_, PIString(" /\\ ").repeat(width_ / 4), Green, Default, Bold); if (is > 0) d->drawText(x_, y_, PIString(" /\\ ").repeat(width_ / 4), Green, Default, Bold);
if (ie < content.size_s()) d->drawText(x_, y_ + height_ - 1, PIString(" \\/ ").repeat(width_ / 4), Green, Default, Bold); if (ie < content.size_s()) d->drawText(x_, y_ + height_ - 1, PIString(" \\/ ").repeat(width_ / 4), Green, Default, Bold);
//piCout << is << ie << offset << lhei << content.size_s(); //piCout << is << ie << offset << lhei << content.size_s();
for (int i = is; i < ie; ++i) { for (int i = is; i < ie; ++i) {
Row & r(content[i]); Row & r(content[i]);
bool sel = i == cur && has_focus; bool sel = i == cur && has_focus;
if (sel) { if (sel) {
int cy = y_ + i - is + 1; int cy = y_ + i - is + 1;
d->drawLine(x_, cy, x_ + width_ - 2, cy, ' ', Default, Blue); d->drawLine(x_, cy, x_ + width_ - 2, cy, ' ', Default, Blue);
} }
int rx(0); int rx(0);
switch (alignment) { switch (alignment) {
case Left: rx = x_; break; case Left: rx = x_; break;
case Center: rx = x_ + (width_ - 1 - r.first.size_s()) / 2; break; case Center: rx = x_ + (width_ - 1 - r.first.size_s()) / 2; break;
case Right: rx = x_ + width_ - 1 - r.first.size_s(); break; case Right: rx = x_ + width_ - 1 - r.first.size_s(); break;
}; };
CharFlags cf = r.second.flags; CharFlags cf = r.second.flags;
Color cc = (Color)r.second.color_char; Color cc = (Color)r.second.color_char;
if (selected[i]) { if (selected[i]) {
cf |= Bold; cf |= Bold;
cc = Yellow; cc = Yellow;
} }
d->drawText(rx, y_ + i - is + 1, r.first, cc, sel ? Blue : Default, cf); d->drawText(rx, y_ + i - is + 1, r.first, cc, sel ? Blue : Default, cf);
} }
scroll->setMaximum(piMaxi(0, content.size_s() - 1)); scroll->setMaximum(piMaxi(0, content.size_s() - 1));
scroll->setValue(cur); scroll->setValue(cur);
} }
bool TileList::keyEvent(PIKbdListener::KeyEvent key) { 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: case PIKbdListener::PageUp:
cur -= lhei / 2; cur -= lhei / 2;
oo -= lhei / 2; oo -= lhei / 2;
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
cur--; cur--;
oo--; oo--;
if (key.modifiers[PIKbdListener::Ctrl]) { if (key.modifiers[PIKbdListener::Ctrl]) {
cur -= 4; cur -= 4;
oo -= 4; oo -= 4;
} }
if (cur < 0) cur = 0; if (cur < 0) cur = 0;
if (cur - offset < osp) offset += oo; if (cur - offset < osp) offset += oo;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
return true; return true;
case PIKbdListener::Space: case PIKbdListener::Space:
if (cur < 0 || cur >= content.size_s()) return true; if (cur < 0 || cur >= content.size_s()) return true;
switch (selection_mode) { switch (selection_mode) {
case NoSelection: return false; case NoSelection: return false;
case SingleSelection: case SingleSelection:
if (selected.isEmpty()) selected << cur; if (selected.isEmpty()) selected << cur;
else { else {
bool add = !selected[cur]; bool add = !selected[cur];
selected.clear(); selected.clear();
if (add) selected << cur; if (add) selected << cur;
} }
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
return true; return true;
case MultiSelection: case MultiSelection:
if (selected[cur]) selected.remove(cur); if (selected[cur]) selected.remove(cur);
else selected << cur; else selected << cur;
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
break; break;
} }
case PIKbdListener::PageDown: case PIKbdListener::PageDown:
if (key.key == PIKbdListener::PageDown) { if (key.key == PIKbdListener::PageDown) {
cur += lhei / 2; cur += lhei / 2;
oo += lhei / 2; oo += lhei / 2;
} }
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
cur++; cur++;
oo++; oo++;
if (key.modifiers[PIKbdListener::Ctrl]) { if (key.modifiers[PIKbdListener::Ctrl]) {
cur += 4; cur += 4;
oo += 4; oo += 4;
} }
if (cur >= content.size_s()) cur = content.size_s() - 1; if (cur >= content.size_s()) cur = content.size_s() - 1;
if (cur - offset >= lhei - osp) offset += oo; if (cur - offset >= lhei - osp) offset += oo;
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: case PIKbdListener::Home:
cur = offset = 0; cur = offset = 0;
return true; 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()) if (cur >= 0 && cur < content.size_s())
raiseEvent(TileEvent(RowPressed, cur)); raiseEvent(TileEvent(RowPressed, cur));
return true; return true;
case '*': case '*':
if (selection_mode == TileList::MultiSelection) { if (selection_mode == TileList::MultiSelection) {
PISet<int> nsel; PISet<int> nsel;
for (int i = 0; i < content.size_s(); ++i) for (int i = 0; i < content.size_s(); ++i)
if (!selected[i]) nsel << i; if (!selected[i]) nsel << i;
selected = nsel; selected = nsel;
} }
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
return true; return true;
case 'A': case 'A':
if (selection_mode == TileList::MultiSelection) { if (selection_mode == TileList::MultiSelection) {
selected.clear(); selected.clear();
for (int i = 0; i < content.size_s(); ++i) for (int i = 0; i < content.size_s(); ++i)
selected << i; selected << i;
} }
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
return true; return true;
} }
return PIScreenTile::keyEvent(key); return PIScreenTile::keyEvent(key);
} }
bool TileList::mouseEvent(PIKbdListener::MouseEvent me) { bool TileList::mouseEvent(PIKbdListener::MouseEvent me) {
if (me.action == PIKbdListener::MouseButtonRelease) return true; if (me.action == PIKbdListener::MouseButtonRelease) return true;
int mp = me.y - y() - 1 + offset; int mp = me.y - y() - 1 + offset;
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: case PIKbdListener::MouseButtonPress:
mouse_sel = !selected.contains(cur); mouse_sel = !selected.contains(cur);
break; break;
case PIKbdListener::MouseButtonDblClick: case PIKbdListener::MouseButtonDblClick:
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return)); keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
return true; return true;
default: break; default: break;
} }
if (me.buttons[PIKbdListener::MouseRight]) { if (me.buttons[PIKbdListener::MouseRight]) {
switch (selection_mode) { switch (selection_mode) {
case SingleSelection: case SingleSelection:
selected.clear(); selected.clear();
selected << cur; selected << cur;
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
break; break;
case MultiSelection: case MultiSelection:
if (mouse_sel) selected << cur; if (mouse_sel) selected << cur;
else selected.remove(cur); else selected.remove(cur);
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
break; break;
default: break; default: break;
} }
} }
return true; return true;
} }
bool TileList::wheelEvent(PIKbdListener::WheelEvent we) { bool TileList::wheelEvent(PIKbdListener::WheelEvent we) {
keyEvent(PIKbdListener::KeyEvent(we.direction ? PIKbdListener::PageUp : PIKbdListener::PageDown)); keyEvent(PIKbdListener::KeyEvent(we.direction ? PIKbdListener::PageUp : PIKbdListener::PageDown));
return true; return true;
} }
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;
} }
void TileButton::sizeHint(int & w, int & h) const { void TileButton::sizeHint(int & w, int & h) const {
w = text.size_s() + 2; w = text.size_s() + 2;
h = 1; h = 1;
} }
void TileButton::drawEvent(PIScreenDrawer * d) { void TileButton::drawEvent(PIScreenDrawer * d) {
Color cb = has_focus ? Blue : Cyan; Color cb = has_focus ? Blue : Cyan;
Color ct = has_focus ? White : Black; Color ct = has_focus ? White : Black;
int ff = has_focus ? Bold : 0; int ff = has_focus ? Bold : 0;
d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb); d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb);
d->drawText(x_, y_, "[", ct, Transparent, ff); d->drawText(x_, y_, "[", ct, Transparent, ff);
d->drawText(x_ + (width_ - text.size_s()) / 2, y_, text, ct, Transparent, ff); d->drawText(x_ + (width_ - text.size_s()) / 2, y_, text, ct, Transparent, ff);
d->drawText(x_ + width_ - 1, y_, "]", ct, Transparent, ff); d->drawText(x_ + width_ - 1, y_, "]", ct, Transparent, ff);
} }
bool TileButton::keyEvent(PIKbdListener::KeyEvent key) { bool TileButton::keyEvent(PIKbdListener::KeyEvent key) {
if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) { if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) {
raiseEvent(TileEvent(ButtonClicked)); raiseEvent(TileEvent(ButtonClicked));
return true; return true;
} }
return PIScreenTile::keyEvent(key); return PIScreenTile::keyEvent(key);
} }
bool TileButton::mouseEvent(PIKbdListener::MouseEvent me) { bool TileButton::mouseEvent(PIKbdListener::MouseEvent me) {
if (me.action != PIKbdListener::MouseButtonRelease) return true; if (me.action != PIKbdListener::MouseButtonRelease) return true;
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return)); keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
return true; return true;
} }
TileButtons::TileButtons(const PIString & n): PIScreenTile(n) { TileButtons::TileButtons(const PIString & n): PIScreenTile(n) {
focus_flags = CanHasFocus | NextByTab | FocusOnMouse; focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
direction = Horizontal; direction = Horizontal;
alignment = PIScreenTypes::Center; alignment = PIScreenTypes::Center;
cur = 0; cur = 0;
} }
void TileButtons::sizeHint(int & w, int & h) const { void TileButtons::sizeHint(int & w, int & h) const {
w = h = 0; w = h = 0;
if (direction == Horizontal) { if (direction == Horizontal) {
piForeachC (Button & b, content) piForeachC (Button & b, content)
w += b.first.size_s() + 4; w += b.first.size_s() + 4;
w += piMaxi(0, content.size_s() - 1) * 2; w += piMaxi(0, content.size_s() - 1) * 2;
h += 1; h += 1;
} else { } else {
piForeachC (Button & b, content) piForeachC (Button & b, content)
w = piMaxi(w, b.first.size_s() + 4); w = piMaxi(w, b.first.size_s() + 4);
h += content.size_s(); h += content.size_s();
h += piMaxi(0, content.size_s() - 1); h += piMaxi(0, content.size_s() - 1);
} }
} }
void TileButtons::drawEvent(PIScreenDrawer * d) { void TileButtons::drawEvent(PIScreenDrawer * d) {
int cx = x_, cy = y_, shw, shh; int cx = x_, cy = y_, shw, shh;
sizeHint(shw, shh); sizeHint(shw, shh);
btn_rects.resize(content.size()); btn_rects.resize(content.size());
int dx = 0; int dx = 0;
switch (alignment) { switch (alignment) {
case PIScreenTypes::Center: dx = (width_ - shw) / 2; break; case PIScreenTypes::Center: dx = (width_ - shw) / 2; break;
case PIScreenTypes::Right: dx = width_ - shw; break; case PIScreenTypes::Right: dx = width_ - shw; break;
default: break; default: break;
} }
if (direction == PIScreenTypes::Horizontal) if (direction == PIScreenTypes::Horizontal)
cx += dx; 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;
int ff = 0; int ff = 0;
if (i == cur && has_focus) { if (i == cur && has_focus) {
cb = Blue; cb = Blue;
ct = White; ct = White;
ff = Bold; ff = Bold;
} }
Button & b(content[i]); Button & b(content[i]);
int cw = b.first.size_s() + 2, xo(0); int cw = b.first.size_s() + 2, xo(0);
if (direction == Vertical) { if (direction == Vertical) {
cw = width_ - 2; cw = width_ - 2;
xo = (cw - b.first.size_s()) / 2 - 1; xo = (cw - b.first.size_s()) / 2 - 1;
} }
btn_rects[i] = Rect(cx, cy, cx + cw + 2, cy + 1); btn_rects[i] = Rect(cx, cy, cx + cw + 2, cy + 1);
d->fillRect(cx, cy, cx + cw + 2, cy + 1, ' ', Default, cb); d->fillRect(cx, cy, cx + cw + 2, cy + 1, ' ', Default, cb);
d->drawText(cx, cy, "[", ct, Transparent, ff); d->drawText(cx, cy, "[", ct, Transparent, ff);
d->drawText(cx + xo + 2, cy, b.first, ct, Transparent, ff); d->drawText(cx + xo + 2, cy, b.first, ct, Transparent, ff);
d->drawText(cx + cw + 1, cy, "]", ct, Transparent, ff); d->drawText(cx + cw + 1, cy, "]", ct, Transparent, ff);
if (direction == Horizontal) if (direction == Horizontal)
cx += b.first.size_s() + 6; cx += b.first.size_s() + 6;
else else
cy += 2; cy += 2;
} }
} }
bool TileButtons::keyEvent(PIKbdListener::KeyEvent key) { bool TileButtons::keyEvent(PIKbdListener::KeyEvent key) {
switch (key.key) { switch (key.key) {
case PIKbdListener::LeftArrow: case PIKbdListener::LeftArrow:
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
cur--; cur--;
if (cur < 0) cur = 0; if (cur < 0) cur = 0;
return true; return true;
case PIKbdListener::RightArrow: case PIKbdListener::RightArrow:
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
cur++; cur++;
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: case PIKbdListener::Return:
raiseEvent(TileEvent(ButtonSelected, cur)); raiseEvent(TileEvent(ButtonSelected, cur));
return true; return true;
}; };
return PIScreenTile::keyEvent(key); return PIScreenTile::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 && 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) { me.y >= btn_rects[i].y0 && me.y < btn_rects[i].y1) {
cur = i; cur = i;
break; break;
} }
return true; return true;
} }
if (me.action != PIKbdListener::MouseButtonRelease) return true; if (me.action != PIKbdListener::MouseButtonRelease) return true;
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return)); keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
return true; return true;
} }
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;
toggled = false; toggled = false;
} }
void TileCheck::sizeHint(int & w, int & h) const { void TileCheck::sizeHint(int & w, int & h) const {
w = text.size_s() + 4; w = text.size_s() + 4;
h = 1; h = 1;
} }
void TileCheck::drawEvent(PIScreenDrawer * d) { void TileCheck::drawEvent(PIScreenDrawer * d) {
Color cb = has_focus ? Blue : Cyan; Color cb = has_focus ? Blue : Cyan;
Color ct = has_focus ? White : Black; Color ct = has_focus ? White : Black;
int ff = has_focus ? Bold : 0; int ff = has_focus ? Bold : 0;
PIString cs("[ ]"); PIString cs("[ ]");
if (toggled) cs[1] = '*'; if (toggled) cs[1] = '*';
d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb); d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb);
d->drawText(x_, y_, cs, ct, Transparent, ff); d->drawText(x_, y_, cs, ct, Transparent, ff);
d->drawText(x_ + 4, y_, text, ct, Transparent, ff); d->drawText(x_ + 4, y_, text, ct, Transparent, ff);
} }
bool TileCheck::keyEvent(PIKbdListener::KeyEvent key) { bool TileCheck::keyEvent(PIKbdListener::KeyEvent key) {
if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) { if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) {
toggled = !toggled; toggled = !toggled;
raiseEvent(TileEvent(Toggled, toggled)); raiseEvent(TileEvent(Toggled, toggled));
return true; return true;
} }
return PIScreenTile::keyEvent(key); return PIScreenTile::keyEvent(key);
} }
bool TileCheck::mouseEvent(PIKbdListener::MouseEvent me) { bool TileCheck::mouseEvent(PIKbdListener::MouseEvent me) {
if (me.action == PIKbdListener::MouseButtonPress) { if (me.action == PIKbdListener::MouseButtonPress) {
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return)); keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
return true; return true;
} }
return false; return false;
} }
TileProgress::TileProgress(const PIString & n): PIScreenTile(n) { TileProgress::TileProgress(const PIString & n): PIScreenTile(n) {
maximum = 100.; maximum = 100.;
value = 0.; value = 0.;
suffix = " %"; suffix = " %";
} }
void TileProgress::sizeHint(int & w, int & h) const { void TileProgress::sizeHint(int & w, int & h) const {
w = 20; w = 20;
h = 1; h = 1;
} }
void TileProgress::drawEvent(PIScreenDrawer * d) { void TileProgress::drawEvent(PIScreenDrawer * d) {
int v = maximum == 0. ? 0 : piClampd(piRoundd(value / maximum * 100.), 0, 100); int v = maximum == 0. ? 0 : piClampd(piRoundd(value / maximum * 100.), 0, 100);
PIString s = prefix + PIString::fromNumber(piRoundd(value)) + suffix; PIString s = prefix + PIString::fromNumber(piRoundd(value)) + suffix;
int w = piRoundd(v / 100. * width_), sx = (width_ - s.size_s()) / 2; int w = piRoundd(v / 100. * width_), sx = (width_ - s.size_s()) / 2;
d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, Cyan); d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, Cyan);
d->fillRect(x_, y_, x_ + w, y_ + 1, ' ', Default, Blue); d->fillRect(x_, y_, x_ + w, y_ + 1, ' ', Default, Blue);
if (w < sx) if (w < sx)
d->drawText(x_ + sx, y_, s, Black, Transparent); d->drawText(x_ + sx, y_, s, Black, Transparent);
else if (w >= sx + s.size_s()) else if (w >= sx + s.size_s())
d->drawText(x_ + sx, y_, s, White, Transparent); d->drawText(x_ + sx, y_, s, White, Transparent);
else { else {
int fw = w - sx; int fw = w - sx;
d->drawText(x_ + sx, y_, s.left(fw), White, Transparent); d->drawText(x_ + sx, y_, s.left(fw), White, Transparent);
d->drawText(x_ + sx + fw, y_, s.cutLeft(fw), Black, Transparent); d->drawText(x_ + sx + fw, y_, s.cutLeft(fw), Black, Transparent);
} }
} }
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); PICout::setBufferActive(true);
} }
void TilePICout::drawEvent(PIScreenDrawer * d) { void TilePICout::drawEvent(PIScreenDrawer * d) {
PIString out = PICout::buffer(true); 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) if (content.size_s() > max_lines)
content.remove(0, 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;
} }
} }
TileList::drawEvent(d); TileList::drawEvent(d);
} }
bool TilePICout::keyEvent(PIKbdListener::KeyEvent key) { bool TilePICout::keyEvent(PIKbdListener::KeyEvent key) {
if (key.key == 'C') { if (key.key == 'C') {
content.clear(); content.clear();
cur = offset = 0; cur = offset = 0;
return true; return true;
} }
return TileList::keyEvent(key); return TileList::keyEvent(key);
} }
TileInput::TileInput(const PIString & n): PIScreenTile(n) { TileInput::TileInput(const PIString & n): PIScreenTile(n) {
focus_flags = CanHasFocus | NextByTab | FocusOnMouse; focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
back_format.color_back = White; back_format.color_back = White;
format.color_char = Black; format.color_char = Black;
format.color_back = White; format.color_back = White;
max_length = 1024; max_length = 1024;
cur = offset = 0; cur = offset = 0;
inv = false; inv = false;
} }
void TileInput::sizeHint(int & w, int & h) const { void TileInput::sizeHint(int & w, int & h) const {
w = 32; w = 32;
h = 1; h = 1;
} }
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) if (offset > 0)
d->drawText(x_, y_, "<", Green, Black, Bold); d->drawText(x_, y_, "<", Green, Black, Bold);
if (text.size_s() - offset >= width_ - 2) if (text.size_s() - offset >= width_ - 2)
d->drawText(x_ + width_ - 1, y_, ">", Green, Black, Bold); 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) {
tm_blink.reset(); tm_blink.reset();
inv = !inv; inv = !inv;
} }
if (inv) piSwap(cb, cc); if (inv) piSwap(cb, cc);
d->drawText(x_ + 1 + cur - offset, y_, text.mid(cur, 1).expandLeftTo(1, ' '), cc, cb, (CharFlags)format.flags); d->drawText(x_ + 1 + cur - offset, y_, text.mid(cur, 1).expandLeftTo(1, ' '), cc, cb, (CharFlags)format.flags);
} }
bool TileInput::keyEvent(PIKbdListener::KeyEvent key) { bool TileInput::keyEvent(PIKbdListener::KeyEvent key) {
int lwid = piMaxi(0, width_ - 2); int lwid = piMaxi(0, width_ - 2);
int oo(0), osp = piMini(3, lwid / 4); int oo(0), osp = piMini(3, lwid / 4);
lwid--; lwid--;
switch (key.key) { switch (key.key) {
case PIKbdListener::LeftArrow: case PIKbdListener::LeftArrow:
cur--; cur--;
oo--; oo--;
if (key.modifiers[PIKbdListener::Ctrl]) { if (key.modifiers[PIKbdListener::Ctrl]) {
cur -= 4; cur -= 4;
oo -= 4; oo -= 4;
} }
if (cur < 0) cur = 0; if (cur < 0) cur = 0;
if (cur - offset < osp) offset += oo; if (cur - offset < osp) offset += oo;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::RightArrow: case PIKbdListener::RightArrow:
cur++; cur++;
oo++; oo++;
if (key.modifiers[PIKbdListener::Ctrl]) { if (key.modifiers[PIKbdListener::Ctrl]) {
cur += 4; cur += 4;
oo += 4; oo += 4;
} }
if (cur > text.size_s()) cur = text.size_s(); if (cur > text.size_s()) cur = text.size_s();
if (cur - offset >= lwid - osp) offset += oo; if (cur - offset >= lwid - osp) offset += oo;
if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid; if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::Home: case PIKbdListener::Home:
cur = offset = 0; cur = offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::End: case PIKbdListener::End:
cur = text.size_s(); cur = text.size_s();
offset = text.size_s() - lwid; offset = text.size_s() - lwid;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::Backspace: case PIKbdListener::Backspace:
if (cur > text.size_s() || text.isEmpty()) if (cur > text.size_s() || text.isEmpty())
return true; 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();
if (cur - offset >= lwid - osp) offset += oo; if (cur - offset >= lwid - osp) offset += oo;
if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid; if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::Delete: case PIKbdListener::Delete:
if (cur >= text.size_s() || text.isEmpty()) if (cur >= text.size_s() || text.isEmpty())
return true; 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();
if (cur - offset < osp) offset += oo; if (cur - offset < osp) offset += oo;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
case PIKbdListener::PageUp: case PIKbdListener::PageUp:
case PIKbdListener::PageDown: case PIKbdListener::PageDown:
case PIKbdListener::Insert: case PIKbdListener::Insert:
case PIKbdListener::Return: case PIKbdListener::Return:
case PIKbdListener::Esc: case PIKbdListener::Esc:
case PIKbdListener::F1: case PIKbdListener::F1:
case PIKbdListener::F2: case PIKbdListener::F2:
case PIKbdListener::F3: case PIKbdListener::F3:
case PIKbdListener::F4: case PIKbdListener::F4:
case PIKbdListener::F5: case PIKbdListener::F5:
case PIKbdListener::F6: case PIKbdListener::F6:
case PIKbdListener::F7: case PIKbdListener::F7:
case PIKbdListener::F8: case PIKbdListener::F8:
case PIKbdListener::F9: case PIKbdListener::F9:
case PIKbdListener::F10: case PIKbdListener::F10:
case PIKbdListener::F11: case PIKbdListener::F11:
case PIKbdListener::F12: case PIKbdListener::F12:
break; break;
default: default:
PIChar tc PIChar tc
#ifdef WINDOWS #ifdef WINDOWS
= PIChar(key.key); = PIChar(key.key);
#else #else
= PIChar::fromUTF8((char *)&(key.key)); = PIChar::fromUTF8((char *)&(key.key));
#endif #endif
text.insert(cur, tc); text.insert(cur, tc);
cur++; cur++;
oo++; oo++;
if (cur - offset >= lwid - osp) offset += oo; if (cur - offset >= lwid - osp) offset += oo;
if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid; if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
} }
return PIScreenTile::keyEvent(key); return PIScreenTile::keyEvent(key);
} }
void TileInput::reserCursor() { void TileInput::reserCursor() {
tm_blink.reset(); tm_blink.reset();
inv = false; inv = false;
} }

View File

@@ -1,920 +1,920 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Virtual terminal Virtual terminal
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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 "piincludes_p.h" #include "piincludes_p.h"
#include "piterminal.h" #include "piterminal.h"
#include "pisharedmemory.h" #include "pisharedmemory.h"
#ifndef FREERTOS #ifndef FREERTOS
#ifdef WINDOWS #ifdef WINDOWS
# include <windows.h> # include <windows.h>
# include <wincon.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>
# if defined(QNX) || defined(BLACKBERRY) # if defined(QNX) || defined(BLACKBERRY)
# include <unix.h> # include <unix.h>
# else # else
# ifdef MAC_OS # ifdef MAC_OS
# include <util.h> # include <util.h>
# else # else
# include <pty.h> # include <pty.h>
# endif # endif
# endif # endif
# ifdef ANDROID # ifdef ANDROID
# if __ANDROID_API__ >= 23 # if __ANDROID_API__ >= 23
# define HAS_FORKPTY # define HAS_FORKPTY
# endif # endif
# else # else
# define HAS_FORKPTY # define HAS_FORKPTY
# endif # endif
#endif #endif
//extern PIMutex PICout::__mutex__; //extern PIMutex PICout::__mutex__;
#ifdef WINDOWS #ifdef WINDOWS
# define PIPE_BUFFER_SIZE 1024 # define PIPE_BUFFER_SIZE 1024
enum PITerminalAuxMessageType { enum PITerminalAuxMessageType {
mtKey = 1, mtKey = 1,
mtResize, mtResize,
mtScroll mtScroll
}; };
struct PITerminalAuxData { struct PITerminalAuxData {
int cursor_x; int cursor_x;
int cursor_y; int cursor_y;
int size_x; int size_x;
int size_y; int size_y;
int cells_size; int cells_size;
}; };
#else #else
# define BUFFER_SIZE 4096 # define BUFFER_SIZE 4096
enum DECType { enum DECType {
CKM = 1 CKM = 1
}; };
#endif #endif
PRIVATE_DEFINITION_START(PITerminal) PRIVATE_DEFINITION_START(PITerminal)
#ifdef WINDOWS #ifdef WINDOWS
PISharedMemory * shm; PISharedMemory * shm;
HANDLE hConBuf; HANDLE hConBuf;
STARTUPINFOA si; STARTUPINFOA si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
HANDLE pipe; HANDLE pipe;
#else #else
PIString shell; PIString shell;
PIByteArray read_buf, tmp_buf; PIByteArray read_buf, tmp_buf;
PIScreenTypes::CellFormat cur_format, line_format; PIScreenTypes::CellFormat cur_format, line_format;
int term_type; int term_type;
int fd, cur_x, cur_y; int fd, cur_x, cur_y;
int save_cur_x, save_cur_y; int save_cur_x, save_cur_y;
int win_y0, win_y1; int win_y0, win_y1;
pid_t pid; pid_t pid;
PIString esc_seq; PIString esc_seq;
bool is_esc_seq, last_read; bool is_esc_seq, last_read;
PIMap<int, bool> DEC; PIMap<int, bool> DEC;
PIVector<PIVector<PIScreenTypes::Cell> > cells_save; PIVector<PIVector<PIScreenTypes::Cell> > cells_save;
#endif #endif
PRIVATE_DEFINITION_END(PITerminal) PRIVATE_DEFINITION_END(PITerminal)
#ifdef WINDOWS #ifdef WINDOWS
int writePipe(HANDLE pipe, const PIByteArray & ba) { int writePipe(HANDLE pipe, const PIByteArray & ba) {
DWORD wrote[2]; DWORD wrote[2];
int sz = ba.size_s(); int sz = ba.size_s();
WriteFile(pipe, &sz, 4, &(wrote[0]), 0); WriteFile(pipe, &sz, 4, &(wrote[0]), 0);
WriteFile(pipe, ba.data(), ba.size_s(), &(wrote[1]), 0); WriteFile(pipe, ba.data(), ba.size_s(), &(wrote[1]), 0);
//piCout << "send" << ba.size_s(); //piCout << "send" << ba.size_s();
return int(wrote[0] + wrote[1]); return int(wrote[0] + wrote[1]);
} }
#endif #endif
PITerminal::PITerminal(): PIThread() { PITerminal::PITerminal(): PIThread() {
setName("terminal"); setName("terminal");
initPrivate(); initPrivate();
cursor_blink = false; cursor_blink = false;
cursor_x = cursor_y = 0; cursor_x = cursor_y = 0;
dsize_x = 80; dsize_x = 80;
dsize_y = 24; dsize_y = 24;
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->shm = 0; PRIVATE->shm = 0;
#endif #endif
} }
PITerminal::~PITerminal() { PITerminal::~PITerminal() {
if (isRunning()) if (isRunning())
stop(); stop();
PIThread::waitForFinish(10); PIThread::waitForFinish(10);
destroy(); destroy();
#ifdef WINDOWS #ifdef WINDOWS
if (PRIVATE->shm) delete PRIVATE->shm; if (PRIVATE->shm) delete PRIVATE->shm;
#endif #endif
} }
void PITerminal::write(const PIByteArray & d) { void PITerminal::write(const PIByteArray & d) {
#ifdef WINDOWS #ifdef WINDOWS
PIByteArray msg; PIByteArray msg;
PIVector<PIKbdListener::KeyEvent> ke; PIVector<PIKbdListener::KeyEvent> ke;
for (int i = 0; i < d.size_s(); ++i) for (int i = 0; i < d.size_s(); ++i)
ke << PIKbdListener::KeyEvent(d[i]); ke << PIKbdListener::KeyEvent(d[i]);
msg << int(mtKey) << ke; msg << int(mtKey) << ke;
writePipe(PRIVATE->pipe, msg); writePipe(PRIVATE->pipe, msg);
#else #else
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
if (PRIVATE->fd == 0) return; if (PRIVATE->fd == 0) return;
//ssize_t wrote = 0; //ssize_t wrote = 0;
//wrote = //wrote =
::write(PRIVATE->fd, d.data(), d.size_s()); ::write(PRIVATE->fd, d.data(), d.size_s());
//piCout << "wrote" << wrote << d; //piCout << "wrote" << wrote << d;
# endif # endif
#endif #endif
cursor_tm.reset(); cursor_tm.reset();
cursor_blink = true; cursor_blink = true;
} }
void PITerminal::write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m) { void PITerminal::write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m) {
PIByteArray ba; PIByteArray ba;
#ifdef WINDOWS #ifdef WINDOWS
switch (k) { switch (k) {
case PIKbdListener::Tab: ba << uchar('\t'); break; case PIKbdListener::Tab: ba << uchar('\t'); break;
case PIKbdListener::Return: ba << uchar('\r') << uchar('\n'); break; case PIKbdListener::Return: ba << uchar('\r') << uchar('\n'); break;
case PIKbdListener::Space: ba << uchar(' '); break; case PIKbdListener::Space: ba << uchar(' '); break;
default: break; default: break;
} }
//piCout << "write" << ba.size(); //piCout << "write" << ba.size();
if (!ba.isEmpty()) write(ba); if (!ba.isEmpty()) write(ba);
else { else {
PIByteArray msg; PIByteArray msg;
PIVector<PIKbdListener::KeyEvent> ke; PIVector<PIKbdListener::KeyEvent> ke;
ke << PIKbdListener::KeyEvent(k, m); ke << PIKbdListener::KeyEvent(k, m);
msg << int(mtKey) << ke; msg << int(mtKey) << ke;
writePipe(PRIVATE->pipe, msg); writePipe(PRIVATE->pipe, msg);
} }
#else #else
int term = PRIVATE->term_type; int term = PRIVATE->term_type;
int flags = 0; int flags = 0;
switch (k) { switch (k) {
case PIKbdListener::Tab: ba << uchar('\t'); break; case PIKbdListener::Tab: ba << uchar('\t'); break;
case PIKbdListener::Return: ba << uchar('\n'); break; case PIKbdListener::Return: ba << uchar('\n'); break;
case PIKbdListener::Esc: ba << uchar('\e'); break; case PIKbdListener::Esc: ba << uchar('\e'); break;
case PIKbdListener::Space: ba << uchar(' '); break; case PIKbdListener::Space: ba << uchar(' '); break;
case PIKbdListener::Backspace: ba << uchar(0x7f); break; case PIKbdListener::Backspace: ba << uchar(0x7f); break;
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
case PIKbdListener::RightArrow: case PIKbdListener::RightArrow:
case PIKbdListener::LeftArrow: if (PRIVATE->DEC.value(CKM, false)) flags = 1; case PIKbdListener::LeftArrow: 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;
case PIKbdListener::PageDown: //ba << uchar('\e') << uchar('[') << uchar('6') << uchar('~'); break; case PIKbdListener::PageDown: //ba << uchar('\e') << uchar('[') << uchar('6') << uchar('~'); break;
case PIKbdListener::Insert: //ba << uchar('\e') << uchar('[') << uchar('2') << uchar('~'); break; case PIKbdListener::Insert: //ba << uchar('\e') << uchar('[') << uchar('2') << uchar('~'); break;
case PIKbdListener::Delete: //ba << uchar('\e') << uchar('[') << uchar('3') << uchar('~'); break; case PIKbdListener::Delete: //ba << uchar('\e') << uchar('[') << uchar('3') << uchar('~'); break;
case PIKbdListener::F1: //break; case PIKbdListener::F1: //break;
case PIKbdListener::F2: //break; case PIKbdListener::F2: //break;
case PIKbdListener::F3: //break; case PIKbdListener::F3: //break;
case PIKbdListener::F4: //break; case PIKbdListener::F4: //break;
case PIKbdListener::F5: //break; case PIKbdListener::F5: //break;
case PIKbdListener::F6: //break; case PIKbdListener::F6: //break;
case PIKbdListener::F7: //break; case PIKbdListener::F7: //break;
case PIKbdListener::F8: //break; case PIKbdListener::F8: //break;
case PIKbdListener::F9: //break; case PIKbdListener::F9: //break;
case PIKbdListener::F10: //break; case PIKbdListener::F10: //break;
case PIKbdListener::F11: //break; case PIKbdListener::F11: //break;
case PIKbdListener::F12: //break; case PIKbdListener::F12: //break;
*/ */
default: { default: {
//piCout << flags; //piCout << flags;
//int mod = 0; //int mod = 0;
if (m[PIKbdListener::Shift]) m |= 1; if (m[PIKbdListener::Shift]) m |= 1;
if (m[PIKbdListener::Alt]) m |= 2; if (m[PIKbdListener::Alt]) m |= 2;
if (m[PIKbdListener::Ctrl]) m |= 4; if (m[PIKbdListener::Ctrl]) m |= 4;
for (int i = 0; ; ++i) { for (int i = 0; ; ++i) {
const PIKbdListener::EscSeq & e(PIKbdListener::esc_seq[i]); const PIKbdListener::EscSeq & e(PIKbdListener::esc_seq[i]);
if (!e.seq) break; if (!e.seq) break;
//piCout << "search" << rc[1] << esc_seq[i].seq; //piCout << "search" << rc[1] << esc_seq[i].seq;
if (e.key == k && e.mod == m) { if (e.key == k && e.mod == m) {
if (((e.vt & term) == term) || (((e.flags & flags) == flags) && (flags != 0))) { if (((e.vt & term) == term) || (((e.flags & flags) == flags) && (flags != 0))) {
//piCout << "found key" << PIString(e.seq).replaceAll("\e", "\\e"); //piCout << "found key" << PIString(e.seq).replaceAll("\e", "\\e");
PIByteArray d = ("\e" + PIString(e.seq)).toByteArray(); PIByteArray d = ("\e" + PIString(e.seq)).toByteArray();
write(d); write(d);
break; break;
} }
} }
} }
} break; } break;
} }
//piCout << "write" << ba.size(); //piCout << "write" << ba.size();
if (!ba.isEmpty()) write(ba); if (!ba.isEmpty()) write(ba);
#endif #endif
cursor_tm.reset(); cursor_tm.reset();
cursor_blink = true; cursor_blink = true;
} }
void PITerminal::write(PIKbdListener::KeyEvent ke) { void PITerminal::write(PIKbdListener::KeyEvent ke) {
if (isSpecialKey(ke.key)) write((PIKbdListener::SpecialKey)ke.key, ke.modifiers); if (isSpecialKey(ke.key)) write((PIKbdListener::SpecialKey)ke.key, ke.modifiers);
else { else {
PIByteArray ba; PIByteArray ba;
#ifdef WINDOWS #ifdef WINDOWS
ba << uchar(PIChar(ke.key).toConsole1Byte()); ba << uchar(PIChar(ke.key).toConsole1Byte());
#else #else
ba = PIString(PIChar(ke.key)).toUTF8(); ba = PIString(PIChar(ke.key)).toUTF8();
#endif #endif
write(ba); write(ba);
} }
} }
PIVector<PIVector<PIScreenTypes::Cell> > PITerminal::content() { PIVector<PIVector<PIScreenTypes::Cell> > PITerminal::content() {
readConsole(); readConsole();
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) if (cursor_y >= 0 && cursor_y < size_y)
ret[cursor_y][cursor_x].format.flags ^= PIScreenTypes::Inverse; ret[cursor_y][cursor_x].format.flags ^= PIScreenTypes::Inverse;
return ret; return ret;
} }
bool PITerminal::isSpecialKey(int k) { bool PITerminal::isSpecialKey(int k) {
switch (k) { switch (k) {
case PIKbdListener::Tab: case PIKbdListener::Tab:
case PIKbdListener::Return: case PIKbdListener::Return:
case PIKbdListener::Esc: case PIKbdListener::Esc:
case PIKbdListener::Space: case PIKbdListener::Space:
case PIKbdListener::Backspace: case PIKbdListener::Backspace:
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
case PIKbdListener::RightArrow: case PIKbdListener::RightArrow:
case PIKbdListener::LeftArrow: case PIKbdListener::LeftArrow:
case PIKbdListener::Home: case PIKbdListener::Home:
case PIKbdListener::End: case PIKbdListener::End:
case PIKbdListener::PageUp: case PIKbdListener::PageUp:
case PIKbdListener::PageDown: case PIKbdListener::PageDown:
case PIKbdListener::Insert: case PIKbdListener::Insert:
case PIKbdListener::Delete: case PIKbdListener::Delete:
case PIKbdListener::F1: case PIKbdListener::F1:
case PIKbdListener::F2: case PIKbdListener::F2:
case PIKbdListener::F3: case PIKbdListener::F3:
case PIKbdListener::F4: case PIKbdListener::F4:
case PIKbdListener::F5: case PIKbdListener::F5:
case PIKbdListener::F6: case PIKbdListener::F6:
case PIKbdListener::F7: case PIKbdListener::F7:
case PIKbdListener::F8: case PIKbdListener::F8:
case PIKbdListener::F9: case PIKbdListener::F9:
case PIKbdListener::F10: case PIKbdListener::F10:
case PIKbdListener::F11: case PIKbdListener::F11:
case PIKbdListener::F12: return true; case PIKbdListener::F12: return true;
default: return false; default: return false;
} }
return false; return false;
} }
void PITerminal::initPrivate() { void PITerminal::initPrivate() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->hConBuf = INVALID_HANDLE_VALUE; PRIVATE->hConBuf = INVALID_HANDLE_VALUE;
PRIVATE->pipe = INVALID_HANDLE_VALUE; PRIVATE->pipe = INVALID_HANDLE_VALUE;
PRIVATE->pi.hProcess = 0; PRIVATE->pi.hProcess = 0;
#else #else
PRIVATE->shell = "/bin/bash"; PRIVATE->shell = "/bin/bash";
PRIVATE->read_buf.reserve(BUFFER_SIZE); PRIVATE->read_buf.reserve(BUFFER_SIZE);
PRIVATE->read_buf.fill(0); PRIVATE->read_buf.fill(0);
PRIVATE->fd = PRIVATE->cur_x = PRIVATE->cur_y = 0; PRIVATE->fd = PRIVATE->cur_x = PRIVATE->cur_y = 0;
PRIVATE->save_cur_x = PRIVATE->save_cur_y = 0; PRIVATE->save_cur_x = PRIVATE->save_cur_y = 0;
PRIVATE->pid = 0; PRIVATE->pid = 0;
PRIVATE->term_type = 0; PRIVATE->term_type = 0;
PRIVATE->is_esc_seq = false; PRIVATE->is_esc_seq = false;
PRIVATE->last_read = true; PRIVATE->last_read = true;
PRIVATE->esc_seq.clear(); PRIVATE->esc_seq.clear();
PRIVATE->cur_format = PIScreenTypes::CellFormat(); PRIVATE->cur_format = PIScreenTypes::CellFormat();
#endif #endif
cursor_blink = cursor_visible = true; cursor_blink = cursor_visible = true;
size_x = size_y = 0; size_x = size_y = 0;
} }
void PITerminal::readConsole() { void PITerminal::readConsole() {
#ifdef WINDOWS #ifdef WINDOWS
if (!PRIVATE->shm) return; if (!PRIVATE->shm) return;
PITerminalAuxData data; PITerminalAuxData data;
PRIVATE->shm->read(&data, sizeof(data)); PRIVATE->shm->read(&data, sizeof(data));
if (data.cells_size <= 4) return; if (data.cells_size <= 4) return;
cursor_x = data.cursor_x; cursor_x = data.cursor_x;
cursor_y = data.cursor_y; cursor_y = data.cursor_y;
size_x = data.size_x; size_x = data.size_x;
size_y = data.size_y; size_y = data.size_y;
PIByteArray ba; PIByteArray ba;
ba.resize(data.cells_size); ba.resize(data.cells_size);
PRIVATE->shm->read(ba.data(), ba.size_s(), sizeof(data)); PRIVATE->shm->read(ba.data(), ba.size_s(), sizeof(data));
ba >> cells; ba >> cells;
#endif #endif
//piCout << cursor_x << cursor_y; //piCout << cursor_x << cursor_y;
} }
void PITerminal::getCursor(int & x, int & y) { void PITerminal::getCursor(int & x, int & y) {
#ifdef WINDOWS #ifdef WINDOWS
if (!PRIVATE->shm) return; if (!PRIVATE->shm) return;
int sz = 0; int sz = 0;
PRIVATE->shm->read(&sz, 4); PRIVATE->shm->read(&sz, 4);
#else #else
x = PRIVATE->cur_x; x = PRIVATE->cur_x;
y = PRIVATE->cur_y; y = PRIVATE->cur_y;
#endif #endif
} }
uchar PITerminal::invertColor(uchar c) { uchar PITerminal::invertColor(uchar c) {
switch ((PIScreenTypes::Color)c) { switch ((PIScreenTypes::Color)c) {
case PIScreenTypes::Black: return PIScreenTypes::White; case PIScreenTypes::Black: return PIScreenTypes::White;
case PIScreenTypes::Red: return PIScreenTypes::Cyan; case PIScreenTypes::Red: return PIScreenTypes::Cyan;
case PIScreenTypes::Green: return PIScreenTypes::Magenta; case PIScreenTypes::Green: return PIScreenTypes::Magenta;
case PIScreenTypes::Blue: return PIScreenTypes::Yellow; case PIScreenTypes::Blue: return PIScreenTypes::Yellow;
case PIScreenTypes::Cyan: return PIScreenTypes::Red; case PIScreenTypes::Cyan: return PIScreenTypes::Red;
case PIScreenTypes::Magenta: return PIScreenTypes::Green; case PIScreenTypes::Magenta: return PIScreenTypes::Green;
case PIScreenTypes::Yellow: return PIScreenTypes::Blue; case PIScreenTypes::Yellow: return PIScreenTypes::Blue;
case PIScreenTypes::White: return PIScreenTypes::Black; case PIScreenTypes::White: return PIScreenTypes::Black;
default: break; default: break;
} }
return PIScreenTypes::White; return PIScreenTypes::White;
} }
void PITerminal::run() { void PITerminal::run() {
getCursor(cursor_x, cursor_y); getCursor(cursor_x, cursor_y);
if (cursor_tm.elapsed_m() >= 500) { if (cursor_tm.elapsed_m() >= 500) {
cursor_tm.reset(); cursor_tm.reset();
cursor_blink = !cursor_blink; cursor_blink = !cursor_blink;
} }
#ifndef WINDOWS #ifndef WINDOWS
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
if (PRIVATE->fd == 0) return; if (PRIVATE->fd == 0) return;
PRIVATE->tmp_buf.resize(BUFFER_SIZE); PRIVATE->tmp_buf.resize(BUFFER_SIZE);
int readed = ::read(PRIVATE->fd, PRIVATE->tmp_buf.data(), BUFFER_SIZE - PRIVATE->read_buf.size_s()); int readed = ::read(PRIVATE->fd, PRIVATE->tmp_buf.data(), BUFFER_SIZE - PRIVATE->read_buf.size_s());
bool used = false; bool used = false;
if (readed > 0) { if (readed > 0) {
PRIVATE->last_read = true; PRIVATE->last_read = true;
//piCoutObj << "readed" << readed << PIString(PRIVATE->tmp_buf.resized(readed)).replaceAll("\e", "\\e"); //piCoutObj << "readed" << readed << PIString(PRIVATE->tmp_buf.resized(readed)).replaceAll("\e", "\\e");
//piCoutObj << "readed" << readed << (PRIVATE->tmp_buf.resized(readed)); //piCoutObj << "readed" << readed << (PRIVATE->tmp_buf.resized(readed));
PRIVATE->read_buf.append(PRIVATE->tmp_buf.resized(readed)); PRIVATE->read_buf.append(PRIVATE->tmp_buf.resized(readed));
for (;;) { for (;;) {
int ind = -1; int ind = -1;
for (int i = PRIVATE->read_buf.size_s() - 1; i >= 0; --i) for (int i = PRIVATE->read_buf.size_s() - 1; i >= 0; --i)
if (PRIVATE->read_buf[i] == uchar('\n') || PRIVATE->read_buf[i] == uchar('\e')) { if (PRIVATE->read_buf[i] == uchar('\n') || PRIVATE->read_buf[i] == uchar('\e')) {
ind = i; ind = i;
break; break;
} }
if (ind <= 0) break; if (ind <= 0) break;
used = true; used = true;
parseInput(PIString((const char *)PRIVATE->read_buf.data(), ind)); parseInput(PIString((const char *)PRIVATE->read_buf.data(), ind));
PRIVATE->read_buf.remove(0, ind); PRIVATE->read_buf.remove(0, ind);
} }
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) if (PRIVATE->read_buf[0] < 0x80)
parse = true; parse = true;
if (parse) { if (parse) {
parseInput(PIString(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(PRIVATE->read_buf)); parseInput(PIString(PRIVATE->read_buf));
PRIVATE->read_buf.clear(); PRIVATE->read_buf.clear();
} }
PRIVATE->last_read = false; PRIVATE->last_read = false;
# endif # endif
#endif #endif
} }
#ifndef WINDOWS #ifndef WINDOWS
void PITerminal::parseInput(const PIString & s) { void PITerminal::parseInput(const PIString & s) {
//piCoutObj << s.replaceAll("\e", "\\e"); //piCoutObj << s.replaceAll("\e", "\\e");
//printf("%s", s.data()); //printf("%s", s.data());
for (int i = 0; i < s.size_s(); ++i) { for (int i = 0; i < s.size_s(); ++i) {
if (s[i].unicode16Code() == 0) break; if (s[i].unicode16Code() == 0) break;
if (PRIVATE->is_esc_seq) { if (PRIVATE->is_esc_seq) {
if (s[i] == '\e') { if (s[i] == '\e') {
applyEscSeq(PRIVATE->esc_seq); applyEscSeq(PRIVATE->esc_seq);
PRIVATE->esc_seq.clear(); PRIVATE->esc_seq.clear();
PRIVATE->is_esc_seq = true; PRIVATE->is_esc_seq = true;
} else { } else {
PRIVATE->esc_seq += s[i]; PRIVATE->esc_seq += s[i];
if (isCompleteEscSeq(PRIVATE->esc_seq)) { if (isCompleteEscSeq(PRIVATE->esc_seq)) {
PRIVATE->is_esc_seq = false; PRIVATE->is_esc_seq = false;
applyEscSeq(PRIVATE->esc_seq); applyEscSeq(PRIVATE->esc_seq);
//piCoutObj << PRIVATE->esc_seq; //piCoutObj << PRIVATE->esc_seq;
} }
} }
} else { } else {
if (s[i] == '\e') { if (s[i] == '\e') {
PRIVATE->esc_seq.clear(); PRIVATE->esc_seq.clear();
PRIVATE->is_esc_seq = true; PRIVATE->is_esc_seq = true;
} else { } else {
if (s[i] == '\a') continue; if (s[i] == '\a') continue;
if (s[i] == '\b') { if (s[i] == '\b') {
moveCursor(-1, 0); moveCursor(-1, 0);
continue; continue;
} }
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) cells[PRIVATE->cur_y][i].format = PRIVATE->cur_format; for (int i = PRIVATE->cur_x; i < size_x; ++i) 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);
continue; continue;
} }
//piCoutObj << "char" << s[i] << s[i].unicode16Code() << "at" << PRIVATE->cur_x << PRIVATE->cur_y; //piCoutObj << "char" << s[i] << s[i].unicode16Code() << "at" << PRIVATE->cur_x << PRIVATE->cur_y;
cells[PRIVATE->cur_y][PRIVATE->cur_x].symbol = s[i]; cells[PRIVATE->cur_y][PRIVATE->cur_x].symbol = s[i];
cells[PRIVATE->cur_y][PRIVATE->cur_x].format = PRIVATE->cur_format; cells[PRIVATE->cur_y][PRIVATE->cur_x].format = PRIVATE->cur_format;
moveCursor(1, 0); moveCursor(1, 0);
} }
} }
} }
} }
bool PITerminal::isCompleteEscSeq(const PIString & es) { bool PITerminal::isCompleteEscSeq(const PIString & es) {
if (es.size_s() < 2) return false; if (es.size_s() < 2) return false;
if (es.front() == ']') { if (es.front() == ']') {
if (es.back().toAscii() == '\\' || es.back().toAscii() == '\a') return true; if (es.back().toAscii() == '\\' || es.back().toAscii() == '\a') return true;
} else { } else {
if (es.back().toAscii() >= 64 && es.back().toAscii() <= 126) return true; if (es.back().toAscii() >= 64 && es.back().toAscii() <= 126) return true;
} }
return false; return false;
} }
void PITerminal::applyEscSeq(PIString es) { void PITerminal::applyEscSeq(PIString es) {
piCoutObj << es; piCoutObj << es;
if (es.size_s() < 2) return; if (es.size_s() < 2) return;
// PIScreenTypes::Cell line_cell = PIScreenTypes::Cell(' ', PRIVATE->line_format); // PIScreenTypes::Cell line_cell = PIScreenTypes::Cell(' ', PRIVATE->line_format);
PIScreenTypes::Cell def_cell = PIScreenTypes::Cell(' ', PRIVATE->cur_format); PIScreenTypes::Cell def_cell = PIScreenTypes::Cell(' ', PRIVATE->cur_format);
if (es[1] == '?' && es.size_s() >= 2) { if (es[1] == '?' && es.size_s() >= 2) {
char a = es.takeRight(1)[0].toAscii(); char a = es.takeRight(1)[0].toAscii();
bool val = false; bool val = false;
if (a == 'l') val = false; if (a == 'l') val = false;
if (a == 'h') val = true; if (a == 'h') val = true;
int dec = es.mid(2).toInt(); int dec = es.mid(2).toInt();
piCoutObj << "DEC" << dec << val; piCoutObj << "DEC" << dec << val;
PRIVATE->DEC[dec] = val; PRIVATE->DEC[dec] = val;
switch (dec) { switch (dec) {
case 25: cursor_visible = val; break; case 25: cursor_visible = val; break;
case 1049: case 1049:
if (val) { if (val) {
PRIVATE->save_cur_x = PRIVATE->cur_x; PRIVATE->save_cur_x = PRIVATE->cur_x;
PRIVATE->save_cur_y = PRIVATE->cur_y; PRIVATE->save_cur_y = PRIVATE->cur_y;
} else { } else {
PRIVATE->cur_x = PRIVATE->save_cur_x; PRIVATE->cur_x = PRIVATE->save_cur_x;
PRIVATE->cur_y = PRIVATE->save_cur_y; PRIVATE->cur_y = PRIVATE->save_cur_y;
} }
case 1047: case 1047:
if (val) { if (val) {
PRIVATE->cells_save = cells; PRIVATE->cells_save = cells;
for (int i = 0; i < size_y; ++i) cells[i].fill(def_cell); for (int i = 0; i < size_y; ++i) cells[i].fill(def_cell);
} else { } else {
cells = PRIVATE->cells_save; cells = PRIVATE->cells_save;
} }
break; break;
} }
} }
if (es[0] == '[') { // CSI if (es[0] == '[') { // CSI
if (es.back() == 'm') { if (es.back() == 'm') {
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
if (es.isEmpty()) { if (es.isEmpty()) {
PRIVATE->cur_format = PIScreenTypes::CellFormat(); PRIVATE->cur_format = PIScreenTypes::CellFormat();
return; return;
} }
PIStringList args = es.split(";"); PIStringList args = es.split(";");
piForeachC (PIString & a, args) { piForeachC (PIString & a, args) {
int av = a.toInt(); int av = a.toInt();
switch (av) { switch (av) {
case 0: PRIVATE->cur_format = PIScreenTypes::CellFormat(); break; case 0: PRIVATE->cur_format = PIScreenTypes::CellFormat(); break;
case 1: PRIVATE->cur_format.flags |= PIScreenTypes::Bold; break; case 1: PRIVATE->cur_format.flags |= PIScreenTypes::Bold; break;
case 4: PRIVATE->cur_format.flags |= PIScreenTypes::Underline; break; case 4: PRIVATE->cur_format.flags |= PIScreenTypes::Underline; break;
case 5: PRIVATE->cur_format.flags |= PIScreenTypes::Blink; break; case 5: PRIVATE->cur_format.flags |= PIScreenTypes::Blink; break;
case 7: PRIVATE->cur_format.flags |= PIScreenTypes::Inverse; break; case 7: PRIVATE->cur_format.flags |= PIScreenTypes::Inverse; break;
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) {col = true; target = false;} if (av >= 30 && av <= 37) {col = true; target = false;}
if (av >= 40 && av <= 47) {col = true; target = true;} if (av >= 40 && av <= 47) {col = true; target = true;}
if (col) { if (col) {
int cfl = 0; int cfl = 0;
switch (cid) { switch (cid) {
case 0: cfl = PIScreenTypes::Black; break; case 0: cfl = PIScreenTypes::Black; break;
case 1: cfl = PIScreenTypes::Red; break; case 1: cfl = PIScreenTypes::Red; break;
case 2: cfl = PIScreenTypes::Green; break; case 2: cfl = PIScreenTypes::Green; break;
case 3: cfl = PIScreenTypes::Yellow; break; case 3: cfl = PIScreenTypes::Yellow; break;
case 4: cfl = PIScreenTypes::Blue; break; case 4: cfl = PIScreenTypes::Blue; break;
case 5: cfl = PIScreenTypes::Magenta; break; case 5: cfl = PIScreenTypes::Magenta; break;
case 6: cfl = PIScreenTypes::Cyan; break; case 6: cfl = PIScreenTypes::Cyan; break;
case 7: cfl = PIScreenTypes::White; break; case 7: cfl = PIScreenTypes::White; break;
} }
if (target) if (target)
PRIVATE->cur_format.color_back = cfl; PRIVATE->cur_format.color_back = cfl;
else else
PRIVATE->cur_format.color_char = cfl; PRIVATE->cur_format.color_char = cfl;
break; break;
} }
} break; } break;
} }
} }
/*if ((PRIVATE->cur_format.flags & PIScreenTypes::Inverse) == PIScreenTypes::Inverse) { /*if ((PRIVATE->cur_format.flags & PIScreenTypes::Inverse) == PIScreenTypes::Inverse) {
uchar t = PRIVATE->cur_format.color_char; uchar t = PRIVATE->cur_format.color_char;
PRIVATE->cur_format.color_char = PRIVATE->cur_format.color_back; PRIVATE->cur_format.color_char = PRIVATE->cur_format.color_back;
PRIVATE->cur_format.color_back = t; PRIVATE->cur_format.color_back = t;
}*/ }*/
} }
if (es.back() == 'r') { if (es.back() == 'r') {
piCoutObj << es; piCoutObj << es;
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
PIStringList args = es.split(";"); PIStringList args = es.split(";");
args.resize(2); args.resize(2);
int y0(0), y1(0); int y0(0), y1(0);
if (!args[0].isEmpty()) y0 = args[0].toInt() - 1; if (!args[0].isEmpty()) y0 = args[0].toInt() - 1;
if (!args[1].isEmpty()) y1 = args[1].toInt() - 1; if (!args[1].isEmpty()) y1 = args[1].toInt() - 1;
PRIVATE->win_y0 = piClamp(y0, 0, size_y - 1); PRIVATE->win_y0 = piClamp(y0, 0, size_y - 1);
PRIVATE->win_y1 = piClamp(y1, 0, size_y - 1); PRIVATE->win_y1 = piClamp(y1, 0, size_y - 1);
} }
if (es.back() == 's') { if (es.back() == 's') {
PRIVATE->save_cur_x = PRIVATE->cur_x; PRIVATE->save_cur_x = PRIVATE->cur_x;
PRIVATE->save_cur_y = PRIVATE->cur_y; PRIVATE->save_cur_y = PRIVATE->cur_y;
} }
if (es.back() == 'u') { if (es.back() == 'u') {
PRIVATE->cur_x = PRIVATE->save_cur_x; PRIVATE->cur_x = PRIVATE->save_cur_x;
PRIVATE->cur_y = PRIVATE->save_cur_y; PRIVATE->cur_y = PRIVATE->save_cur_y;
} }
if (es.back() == 'H' || es.back() == 'f' || es.back() == 'r') { if (es.back() == 'H' || es.back() == 'f' || es.back() == 'r') {
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
PIStringList args = es.split(";"); PIStringList args = es.split(";");
args.resize(2); args.resize(2);
int x(0), y(0); int x(0), y(0);
if (!args[0].isEmpty()) y = args[0].toInt() - 1; if (!args[0].isEmpty()) y = args[0].toInt() - 1;
if (!args[1].isEmpty()) x = args[1].toInt() - 1; if (!args[1].isEmpty()) x = args[1].toInt() - 1;
//piCoutObj << x << y; //piCoutObj << x << y;
PRIVATE->cur_x = piClamp(x, 0, size_x - 1); PRIVATE->cur_x = piClamp(x, 0, size_x - 1);
PRIVATE->cur_y = piClamp(y, 0, size_y - 1); PRIVATE->cur_y = piClamp(y, 0, size_y - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
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(); if (v == 0) v = 1; int v = es.toInt(); 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(); if (v == 0) v = 1; int v = es.toInt(); 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(); if (v == 0) v = 1; int v = es.toInt(); 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(); if (v == 0) v = 1; int v = es.toInt(); 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() == 'G' || es.back() == '`') { // goto column if (es.back() == 'G' || es.back() == '`') { // goto column
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); int v = es.toInt();
if (v) PRIVATE->cur_x = piClamp(v - 1, 0, size_x - 1); if (v) PRIVATE->cur_x = piClamp(v - 1, 0, size_x - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
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(); if (v == 0) v = 1; int v = es.toInt(); 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(); if (v == 0) v = 1; int v = es.toInt(); 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(); if (v == 0) v = 1; int v = es.toInt(); 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(); if (v == 0) v = 1; int v = es.toInt(); 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); i >= piClamp(PRIVATE->cur_y + v, PRIVATE->win_y0, PRIVATE->win_y1); --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 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; 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(); if (v == 0) v = 1; int v = es.toInt(); 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) cells[j][i] = def_cell; for (int i = 0; i < PRIVATE->cur_x; ++i) 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(); if (v == 0) v = 1; int v = es.toInt(); 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) 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; 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(); if (v == 0) v = 1; int v = es.toInt(); 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) 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; 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) cells[PRIVATE->cur_y][i] = def_cell; for (int i = PRIVATE->cur_x; i < size_x; ++i) 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) cells[PRIVATE->cur_y][i] = def_cell; for (int i = 0; i <= PRIVATE->cur_x; ++i) 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) cells[i].fill(def_cell); for (int i = 0; i < size_y; ++i) cells[i].fill(def_cell);
//PRIVATE->cur_x = PRIVATE->cur_y = 0; //PRIVATE->cur_x = PRIVATE->cur_y = 0;
break; break;
} }
} }
if (es.back() == 'K') { // erase in line if (es.back() == 'K') { // erase in line
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) cells[PRIVATE->cur_y][i] = def_cell; for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
break; break;
case 1: case 1:
for (int i = 0; i <= PRIVATE->cur_x; ++i) cells[PRIVATE->cur_y][i] = def_cell; for (int i = 0; i <= PRIVATE->cur_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
break; break;
case 2: case 2:
cells[PRIVATE->cur_y].fill(def_cell); cells[PRIVATE->cur_y].fill(def_cell);
break; break;
} }
} }
} }
} }
void PITerminal::moveCursor(int dx, int dy) { void PITerminal::moveCursor(int dx, int dy) {
PRIVATE->cur_x += dx; PRIVATE->cur_x += dx;
PRIVATE->cur_y += dy; PRIVATE->cur_y += dy;
if (PRIVATE->cur_x < 0) PRIVATE->cur_x = 0; if (PRIVATE->cur_x < 0) PRIVATE->cur_x = 0;
if (PRIVATE->cur_y < 0) PRIVATE->cur_y = 0; if (PRIVATE->cur_y < 0) PRIVATE->cur_y = 0;
if (PRIVATE->cur_x >= size_x) { if (PRIVATE->cur_x >= size_x) {
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
PRIVATE->cur_x = 0; PRIVATE->cur_x = 0;
PRIVATE->cur_y++; PRIVATE->cur_y++;
} }
if (PRIVATE->cur_y >= size_y) { if (PRIVATE->cur_y >= size_y) {
int scroll = piMini(PRIVATE->cur_y - size_y + 1, size_y - 1); int scroll = piMini(PRIVATE->cur_y - size_y + 1, size_y - 1);
//piCout << "scroll" << size_x << size_y << size_y - scroll - 1; //piCout << "scroll" << size_x << size_y << size_y - scroll - 1;
PRIVATE->cur_y = size_y - 1; PRIVATE->cur_y = size_y - 1;
for (int y = 0; y < size_y - scroll; ++y) for (int y = 0; y < size_y - scroll; ++y)
cells[y] = cells[y + scroll]; cells[y] = cells[y + scroll];
for (int y = size_y - scroll; y < size_y; ++y) for (int y = size_y - scroll; y < size_y; ++y)
cells[y].fill(PIScreenTypes::Cell()); cells[y].fill(PIScreenTypes::Cell());
} }
} }
int PITerminal::termType(const PIString & t) { int PITerminal::termType(const PIString & t) {
if (t == "xterm") return PIKbdListener::vt_xterm; if (t == "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
bool PITerminal::initialize() { bool PITerminal::initialize() {
destroy(); destroy();
#ifdef WINDOWS #ifdef WINDOWS
/*SECURITY_ATTRIBUTES sa; /*SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = true; sa.bInheritHandle = true;
sa.lpSecurityDescriptor = 0; sa.lpSecurityDescriptor = 0;
if (!CreatePipe(&(PRIVATE->pipe_in[0]), &(PRIVATE->pipe_in[1]), &sa, 0)) { if (!CreatePipe(&(PRIVATE->pipe_in[0]), &(PRIVATE->pipe_in[1]), &sa, 0)) {
piCoutObj << "CreatePipe error," << errorString(); piCoutObj << "CreatePipe error," << errorString();
initPrivate(); initPrivate();
return false; return false;
} }
PRIVATE->hConBuf = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, &sa, CONSOLE_TEXTMODE_BUFFER, 0); PRIVATE->hConBuf = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, &sa, CONSOLE_TEXTMODE_BUFFER, 0);
if (PRIVATE->hConBuf == INVALID_HANDLE_VALUE) { if (PRIVATE->hConBuf == INVALID_HANDLE_VALUE) {
piCoutObj << "CreateConsoleScreenBuffer error," << errorString(); piCoutObj << "CreateConsoleScreenBuffer error," << errorString();
destroy(); destroy();
return false; return false;
}*/ }*/
//CreatePipe(&(PRIVATE->pipe_out[0]), &(PRIVATE->pipe_out[1]), &sa, 0); //CreatePipe(&(PRIVATE->pipe_out[0]), &(PRIVATE->pipe_out[1]), &sa, 0);
//SetHandleInformation(PRIVATE->pipe_in[1], HANDLE_FLAG_INHERIT, 0); //SetHandleInformation(PRIVATE->pipe_in[1], HANDLE_FLAG_INHERIT, 0);
//SetHandleInformation(PRIVATE->hConBuf, HANDLE_FLAG_INHERIT, 0); //SetHandleInformation(PRIVATE->hConBuf, HANDLE_FLAG_INHERIT, 0);
//GetStartupInfoA(&PRIVATE->si); //GetStartupInfoA(&PRIVATE->si);
memset(&PRIVATE->si, 0, sizeof(PRIVATE->si)); memset(&PRIVATE->si, 0, sizeof(PRIVATE->si));
PRIVATE->si.cb = sizeof(STARTUPINFO); PRIVATE->si.cb = sizeof(STARTUPINFO);
//PRIVATE->si.dwFlags |= STARTF_USESTDHANDLES; //PRIVATE->si.dwFlags |= STARTF_USESTDHANDLES;
PRIVATE->si.dwFlags |= STARTF_USESHOWWINDOW; PRIVATE->si.dwFlags |= STARTF_USESHOWWINDOW;
PRIVATE->si.dwFlags |= STARTF_USECOUNTCHARS; PRIVATE->si.dwFlags |= STARTF_USECOUNTCHARS;
//PRIVATE->si.hStdInput = PRIVATE->pipe; //PRIVATE->si.hStdInput = PRIVATE->pipe;
//PRIVATE->si.hStdOutput = PRIVATE->hConBuf; //PRIVATE->si.hStdOutput = PRIVATE->hConBuf;
//PRIVATE->si.hStdError = PRIVATE->hConBuf; //PRIVATE->si.hStdError = PRIVATE->hConBuf;
PRIVATE->si.wShowWindow = SW_HIDE; PRIVATE->si.wShowWindow = SW_HIDE;
PRIVATE->si.dwXCountChars = 80; PRIVATE->si.dwXCountChars = 80;
PRIVATE->si.dwYCountChars = 24; PRIVATE->si.dwYCountChars = 24;
memset(&PRIVATE->pi, 0, sizeof(PRIVATE->pi)); memset(&PRIVATE->pi, 0, sizeof(PRIVATE->pi));
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, (LPSTR)cmd.dataAscii(), 0, 0, false, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, 0, 0, &PRIVATE->si, &PRIVATE->pi)) { if(!CreateProcessA(0, (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 = CreateNamedPipe((LPSTR)pname.dataAscii(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 2, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 1000, NULL); 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);
if (PRIVATE->pipe == INVALID_HANDLE_VALUE) { if (PRIVATE->pipe == INVALID_HANDLE_VALUE) {
piCoutObj << "CreateNamedPipe error," << errorString(); piCoutObj << "CreateNamedPipe error," << errorString();
destroy(); destroy();
return false; return false;
} }
PITimeMeasurer tm; PITimeMeasurer tm;
bool ok = false; bool ok = false;
while (tm.elapsed_m() < 1000) { while (tm.elapsed_m() < 1000) {
if (ConnectNamedPipe(PRIVATE->pipe, 0) == TRUE) { if (ConnectNamedPipe(PRIVATE->pipe, 0) == TRUE) {
ok = true; ok = true;
break; break;
} }
} }
if (!ok) { if (!ok) {
piCoutObj << "ConnectNamedPipe error," << errorString(); piCoutObj << "ConnectNamedPipe error," << errorString();
destroy(); destroy();
return false; return false;
} }
if (PRIVATE->shm) delete PRIVATE->shm; if (PRIVATE->shm) delete PRIVATE->shm;
PRIVATE->shm = new PISharedMemory("piterm_aux" + shmh, 1024*1024); PRIVATE->shm = new PISharedMemory("piterm_aux" + shmh, 1024*1024);
CloseHandle(PRIVATE->pi.hThread); CloseHandle(PRIVATE->pi.hThread);
resize(dsize_x, dsize_y); resize(dsize_x, dsize_y);
#else #else
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
char pty[256]; memset(pty, 0, 256); char pty[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;
PIStringList env = PIProcess::currentEnvironment(); PIStringList env = PIProcess::currentEnvironment();
piForeachC (PIString & e, env) piForeachC (PIString & e, env)
if (e.startsWith("TERM=")) { if (e.startsWith("TERM=")) {
PRIVATE->term_type = termType(e.mid(5).trim().toLowerCase()); PRIVATE->term_type = termType(e.mid(5).trim().toLowerCase());
//piCout << PRIVATE->term_type; //piCout << PRIVATE->term_type;
piBreak; break;
} }
pid_t fr = forkpty(&(PRIVATE->fd), pty, 0, &ws); pid_t fr = forkpty(&(PRIVATE->fd), pty, 0, &ws);
//piCoutObj << fr << PRIVATE->fd << pty; //piCoutObj << fr << PRIVATE->fd << pty;
if (fr == 0) { if (fr == 0) {
char ** argv = new char*[2]; char ** argv = new char*[2];
argv[0] = new char[PRIVATE->shell.lengthAscii() + 1]; argv[0] = new char[PRIVATE->shell.lengthAscii() + 1];
memcpy(argv[0], PRIVATE->shell.dataAscii(), PRIVATE->shell.lengthAscii()); memcpy(argv[0], PRIVATE->shell.dataAscii(), PRIVATE->shell.lengthAscii());
argv[0][PRIVATE->shell.lengthAscii()] = 0; argv[0][PRIVATE->shell.lengthAscii()] = 0;
argv[1] = 0; argv[1] = 0;
execvp(PRIVATE->shell.dataAscii(), argv); execvp(PRIVATE->shell.dataAscii(), argv);
delete[] argv[0]; delete[] argv[0];
delete[] argv; delete[] argv;
exit(0); exit(0);
} else { } else {
if (fr < 0 || PRIVATE->fd < 0) { if (fr < 0 || PRIVATE->fd < 0) {
piCoutObj << "forkpty error," << errorString(); piCoutObj << "forkpty error," << errorString();
initPrivate(); initPrivate();
return false; return false;
} }
PRIVATE->pid = fr; PRIVATE->pid = fr;
fcntl(PRIVATE->fd, F_SETFL, O_NONBLOCK); fcntl(PRIVATE->fd, F_SETFL, O_NONBLOCK);
/* /*
tcgetattr(PRIVATE->fd, &PRIVATE->desc); tcgetattr(PRIVATE->fd, &PRIVATE->desc);
PRIVATE->desc.c_oflag = PRIVATE->desc.c_lflag = PRIVATE->desc.c_cflag = 0; PRIVATE->desc.c_oflag = PRIVATE->desc.c_lflag = PRIVATE->desc.c_cflag = 0;
PRIVATE->desc.c_iflag = IGNBRK; PRIVATE->desc.c_iflag = IGNBRK;
PRIVATE->desc.c_cflag = CLOCAL | HUPCL; PRIVATE->desc.c_cflag = CLOCAL | HUPCL;
PRIVATE->desc.c_cflag |= (CSIZE & CS8); PRIVATE->desc.c_cflag |= (CSIZE & CS8);
PRIVATE->desc.c_cflag |= CREAD; PRIVATE->desc.c_cflag |= CREAD;
PRIVATE->desc.c_cc[VMIN] = 1; PRIVATE->desc.c_cc[VMIN] = 1;
PRIVATE->desc.c_cc[VTIME] = 1; PRIVATE->desc.c_cc[VTIME] = 1;
cfsetispeed(&PRIVATE->desc, B38400); cfsetispeed(&PRIVATE->desc, B38400);
cfsetospeed(&PRIVATE->desc, B38400); cfsetospeed(&PRIVATE->desc, B38400);
if (tcsetattr(PRIVATE->fd, TCSANOW, &PRIVATE->desc) < 0) { if (tcsetattr(PRIVATE->fd, TCSANOW, &PRIVATE->desc) < 0) {
piCoutObj << "Can`t set attributes for \"" << pty << "\""; piCoutObj << "Can`t set attributes for \"" << pty << "\"";
destroy(); destroy();
return false; return false;
} }
*/ */
size_x = dsize_x; size_x = dsize_x;
size_y = dsize_y; size_y = dsize_y;
resize(size_x, size_y); resize(size_x, size_y);
} }
# endif # endif
#endif #endif
cursor_blink = false; cursor_blink = false;
cursor_tm.reset(); cursor_tm.reset();
start(40); start(40);
return true; return true;
} }
void PITerminal::destroy() { void PITerminal::destroy() {
//piCout << "destroy ..."; //piCout << "destroy ...";
stop(); stop();
waitForFinish(1000); waitForFinish(1000);
#ifdef WINDOWS #ifdef WINDOWS
if (PRIVATE->pi.hProcess) { if (PRIVATE->pi.hProcess) {
//piCout << "term"; //piCout << "term";
//TerminateProcess(PRIVATE->pi.hProcess, 0); //TerminateProcess(PRIVATE->pi.hProcess, 0);
GenerateConsoleCtrlEvent(CTRL_C_EVENT, PRIVATE->pi.dwProcessId); GenerateConsoleCtrlEvent(CTRL_C_EVENT, PRIVATE->pi.dwProcessId);
CloseHandle(PRIVATE->pi.hProcess); CloseHandle(PRIVATE->pi.hProcess);
} }
if (PRIVATE->pipe != INVALID_HANDLE_VALUE) CloseHandle(PRIVATE->pipe); if (PRIVATE->pipe != INVALID_HANDLE_VALUE) CloseHandle(PRIVATE->pipe);
if (PRIVATE->hConBuf != INVALID_HANDLE_VALUE) CloseHandle(PRIVATE->hConBuf); if (PRIVATE->hConBuf != INVALID_HANDLE_VALUE) CloseHandle(PRIVATE->hConBuf);
//piCout << "destroy" << size_y; //piCout << "destroy" << size_y;
#else #else
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
if (PRIVATE->pid != 0) if (PRIVATE->pid != 0)
kill(PRIVATE->pid, SIGKILL); kill(PRIVATE->pid, SIGKILL);
if (PRIVATE->fd != 0) if (PRIVATE->fd != 0)
::close(PRIVATE->fd); ::close(PRIVATE->fd);
# endif # endif
#endif #endif
initPrivate(); initPrivate();
} }
bool PITerminal::resize(int cols, int rows) { bool PITerminal::resize(int cols, int rows) {
bool ret = true; bool ret = true;
dsize_x = cols; dsize_x = cols;
dsize_y = rows; dsize_y = rows;
#ifdef WINDOWS #ifdef WINDOWS
if (PRIVATE->pipe == INVALID_HANDLE_VALUE) return false; if (PRIVATE->pipe == INVALID_HANDLE_VALUE) return false;
PIByteArray msg; PIByteArray msg;
msg << int(mtResize) << dsize_x << dsize_y; msg << int(mtResize) << dsize_x << dsize_y;
writePipe(PRIVATE->pipe, msg); writePipe(PRIVATE->pipe, msg);
#else #else
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
if (PRIVATE->fd == 0) return false; if (PRIVATE->fd == 0) return false;
size_x = dsize_x; size_x = dsize_x;
size_y = dsize_y; size_y = dsize_y;
//piCout << "resize" << PRIVATE->fd << size_x << size_y; //piCout << "resize" << PRIVATE->fd << size_x << size_y;
winsize ws; winsize ws;
ws.ws_col = cols; ws.ws_col = cols;
ws.ws_row = rows; ws.ws_row = rows;
ioctl(PRIVATE->fd, TIOCSWINSZ, &ws); ioctl(PRIVATE->fd, TIOCSWINSZ, &ws);
PRIVATE->win_y0 = 0; PRIVATE->win_y0 = 0;
PRIVATE->win_y1 = size_y - 1; PRIVATE->win_y1 = size_y - 1;
PRIVATE->cells_save.resize(size_y); PRIVATE->cells_save.resize(size_y);
for (int i = 0; i < size_y; ++i) for (int i = 0; i < size_y; ++i)
PRIVATE->cells_save[i].resize(size_x); PRIVATE->cells_save[i].resize(size_x);
# endif # endif
#endif #endif
cells.resize(size_y); cells.resize(size_y);
for (int i = 0; i < size_y; ++i) for (int i = 0; i < size_y; ++i)
cells[i].resize(size_x); cells[i].resize(size_x);
return ret; return ret;
} }
#endif // FREERTOS #endif // FREERTOS

View File

@@ -24,7 +24,6 @@
#define PIFFT_P_H #define PIFFT_P_H
#include "pivector.h" #include "pivector.h"
#include "pimutex.h"
#include "picout.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"
@@ -37,7 +36,7 @@
template <typename T> template <typename T>
class PIP_EXPORT PIFFTW_Private class PIFFTW_Private
{ {
public: public:
explicit PIFFTW_Private() { explicit PIFFTW_Private() {

View File

@@ -55,6 +55,32 @@ PIEthUtilBase::~PIEthUtilBase() {
} }
void PIEthUtilBase::setCryptEnabled(bool on) {
_crypt = on;
}
void PIEthUtilBase::cryptEnable() {
setCryptEnabled(true);
}
void PIEthUtilBase::cryptDisable() {
setCryptEnabled(false);
}
bool PIEthUtilBase::isCryptEnabled() const {
return _crypt;
}
void PIEthUtilBase::setCryptKey(const PIByteArray & k) {
_key = k;
setCryptEnabled(true);
}
void PIEthUtilBase::createCryptKey(const PIString & k) { void PIEthUtilBase::createCryptKey(const PIString & k) {
#ifdef PIP_CRYPT #ifdef PIP_CRYPT
_key = PICrypt::hash("sodium_bug"); _key = PICrypt::hash("sodium_bug");
@@ -66,6 +92,11 @@ void PIEthUtilBase::createCryptKey(const PIString & k) {
} }
PIByteArray PIEthUtilBase::cryptKey() const {
return _key;
}
PIByteArray PIEthUtilBase::cryptData(const PIByteArray & data) { PIByteArray PIEthUtilBase::cryptData(const PIByteArray & data) {
if (!_crypt) return data; if (!_crypt) return data;
return return

View File

@@ -114,7 +114,7 @@ void PIStreamPacker::received(uchar * readed, int size) {
void PIStreamPacker::received(const PIByteArray & data) { void PIStreamPacker::received(const PIByteArray & data) {
stream.append(data); stream.append(data);
//piCout << "rec" << data.size(); //piCout << "rec" << data.size();
while (stream.size_s() >= 4) { while (stream.size_s() >= 6) {
if (packet_size < 0) { if (packet_size < 0) {
ushort sign(0); ushort sign(0);
memcpy(&sign, stream.data(), 2); memcpy(&sign, stream.data(), 2);

View File

@@ -0,0 +1,55 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2018, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#include <LuaBridge/detail/Stack.h>
#include <list>
namespace luabridge {
template <class T>
struct Stack <std::list <T> >
{
static void push (lua_State* L, std::list <T> const& list)
{
lua_createtable (L, static_cast <int> (list.size ()), 0);
typename std::list <T>::const_iterator item = list.begin ();
for (std::size_t i = 1; i <= list.size (); ++i)
{
lua_pushinteger (L, static_cast <lua_Integer> (i));
Stack <T>::push (L, *item);
lua_settable (L, -3);
++item;
}
}
static std::list <T> get (lua_State* L, int index)
{
if (!lua_istable (L, index))
{
luaL_error (L, "#%d argument must be a table", index);
}
std::list <T> list;
int const absindex = lua_absindex (L, index);
lua_pushnil (L);
while (lua_next (L, absindex) != 0)
{
list.push_back (Stack <T>::get (L, -1));
lua_pop (L, 1);
}
return list;
}
static bool isInstance (lua_State* L, int index)
{
return lua_istable (L, index);
}
};
} // namespace luabridge

View File

@@ -0,0 +1,59 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
// All #include dependencies are listed here
// instead of in the individual header files.
//
#define LUABRIDGE_MAJOR_VERSION 2
#define LUABRIDGE_MINOR_VERSION 3
#define LUABRIDGE_VERSION 203
#ifndef LUA_VERSION_NUM
#error "Lua headers must be included prior to LuaBridge ones"
#endif
#include <LuaBridge/detail/LuaHelpers.h>
#include <LuaBridge/detail/TypeTraits.h>
#include <LuaBridge/detail/TypeList.h>
#include <LuaBridge/detail/FuncTraits.h>
#include <LuaBridge/detail/Constructor.h>
#include <LuaBridge/detail/ClassInfo.h>
#include <LuaBridge/detail/LuaException.h>
#include <LuaBridge/detail/LuaRef.h>
#include <LuaBridge/detail/Iterator.h>
#include <LuaBridge/detail/Userdata.h>
#include <LuaBridge/detail/CFunctions.h>
#include <LuaBridge/detail/Security.h>
#include <LuaBridge/detail/Stack.h>
#include <LuaBridge/detail/Namespace.h>

View File

@@ -0,0 +1,56 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2018, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#include <LuaBridge/detail/Stack.h>
#include <LuaBridge/detail/dump.h>
#include <map>
namespace luabridge {
template <class K, class V>
struct Stack <std::map <K, V> >
{
typedef std::map <K, V> Map;
static void push (lua_State* L, const Map& map)
{
lua_createtable (L, 0, static_cast <int> (map.size ()));
typedef typename Map::const_iterator ConstIter;
for (ConstIter i = map.begin (); i != map.end (); ++i)
{
Stack <K>::push (L, i->first);
Stack <V>::push (L, i->second);
lua_settable (L, -3);
}
}
static Map get (lua_State* L, int index)
{
if (!lua_istable (L, index))
{
luaL_error (L, "#%d argument must be a table", index);
}
Map map;
int const absindex = lua_absindex (L, index);
lua_pushnil (L);
while (lua_next (L, absindex) != 0)
{
map.emplace (Stack <K>::get (L, -2), Stack <V>::get (L, -1));
lua_pop (L, 1);
}
return map;
}
static bool isInstance (lua_State* L, int index)
{
return lua_istable (L, index);
}
};
} // namespace luabridge

View File

@@ -0,0 +1,356 @@
//==============================================================================
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2004-11 by Raw Material Software Ltd.
This is a derivative work used by permission from part of
JUCE, available at http://www.rawaterialsoftware.com
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This file incorporates work covered by the following copyright and
permission notice:
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
*/
//==============================================================================
#pragma once
//#define LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
#include <LuaBridge/detail/TypeTraits.h>
#include <cassert>
namespace luabridge {
//==============================================================================
/**
Adds reference-counting to an object.
To add reference-counting to a class, derive it from this class, and
use the RefCountedObjectPtr class to point to it.
e.g. @code
class MyClass : public RefCountedObjectType
{
void foo();
// This is a neat way of declaring a typedef for a pointer class,
// rather than typing out the full templated name each time..
typedef RefCountedObjectPtr<MyClass> Ptr;
};
MyClass::Ptr p = new MyClass();
MyClass::Ptr p2 = p;
p = 0;
p2->foo();
@endcode
Once a new RefCountedObjectType has been assigned to a pointer, be
careful not to delete the object manually.
*/
template <class CounterType>
class RefCountedObjectType
{
public:
//==============================================================================
/** Increments the object's reference count.
This is done automatically by the smart pointer, but is public just
in case it's needed for nefarious purposes.
*/
inline void incReferenceCount() const
{
++refCount;
}
/** Decreases the object's reference count.
If the count gets to zero, the object will be deleted.
*/
inline void decReferenceCount() const
{
assert (getReferenceCount() > 0);
if (--refCount == 0)
delete this;
}
/** Returns the object's current reference count. */
inline int getReferenceCount() const
{
return static_cast <int> (refCount);
}
protected:
//==============================================================================
/** Creates the reference-counted object (with an initial ref count of zero). */
RefCountedObjectType() : refCount ()
{
}
/** Destructor. */
virtual ~RefCountedObjectType()
{
// it's dangerous to delete an object that's still referenced by something else!
assert (getReferenceCount() == 0);
}
private:
//==============================================================================
CounterType mutable refCount;
};
//==============================================================================
/** Non thread-safe reference counted object.
This creates a RefCountedObjectType that uses a non-atomic integer
as the counter.
*/
typedef RefCountedObjectType <int> RefCountedObject;
//==============================================================================
/**
A smart-pointer class which points to a reference-counted object.
The template parameter specifies the class of the object you want to point
to - the easiest way to make a class reference-countable is to simply make
it inherit from RefCountedObjectType, but if you need to, you could roll
your own reference-countable class by implementing a pair of methods called
incReferenceCount() and decReferenceCount().
When using this class, you'll probably want to create a typedef to
abbreviate the full templated name - e.g.
@code
typedef RefCountedObjectPtr <MyClass> MyClassPtr;
@endcode
*/
template <class ReferenceCountedObjectClass>
class RefCountedObjectPtr
{
public:
/** The class being referenced by this pointer. */
typedef ReferenceCountedObjectClass ReferencedType;
//==============================================================================
/** Creates a pointer to a null object. */
inline RefCountedObjectPtr() : referencedObject (0)
{
}
/** Creates a pointer to an object.
This will increment the object's reference-count if it is non-null.
*/
inline RefCountedObjectPtr (ReferenceCountedObjectClass* const refCountedObject)
: referencedObject (refCountedObject)
{
if (refCountedObject != 0)
refCountedObject->incReferenceCount();
}
/** Copies another pointer.
This will increment the object's reference-count (if it is non-null).
*/
inline RefCountedObjectPtr (const RefCountedObjectPtr& other)
: referencedObject (other.referencedObject)
{
if (referencedObject != 0)
referencedObject->incReferenceCount();
}
#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS
/** Takes-over the object from another pointer. */
inline RefCountedObjectPtr (RefCountedObjectPtr&& other)
: referencedObject (other.referencedObject)
{
other.referencedObject = 0;
}
#endif
/** Copies another pointer.
This will increment the object's reference-count (if it is non-null).
*/
template <class DerivedClass>
inline RefCountedObjectPtr (const RefCountedObjectPtr<DerivedClass>& other)
: referencedObject (static_cast <ReferenceCountedObjectClass*> (other.getObject()))
{
if (referencedObject != 0)
referencedObject->incReferenceCount();
}
/** Changes this pointer to point at a different object.
The reference count of the old object is decremented, and it might be
deleted if it hits zero. The new object's count is incremented.
*/
RefCountedObjectPtr& operator= (const RefCountedObjectPtr& other)
{
return operator= (other.referencedObject);
}
/** Changes this pointer to point at a different object.
The reference count of the old object is decremented, and it might be
deleted if it hits zero. The new object's count is incremented.
*/
template <class DerivedClass>
RefCountedObjectPtr& operator= (const RefCountedObjectPtr<DerivedClass>& other)
{
return operator= (static_cast <ReferenceCountedObjectClass*> (other.getObject()));
}
#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS
/** Takes-over the object from another pointer. */
RefCountedObjectPtr& operator= (RefCountedObjectPtr&& other)
{
std::swap (referencedObject, other.referencedObject);
return *this;
}
#endif
/** Changes this pointer to point at a different object.
The reference count of the old object is decremented, and it might be
deleted if it hits zero. The new object's count is incremented.
*/
RefCountedObjectPtr& operator= (ReferenceCountedObjectClass* const newObject)
{
if (referencedObject != newObject)
{
if (newObject != 0)
newObject->incReferenceCount();
ReferenceCountedObjectClass* const oldObject = referencedObject;
referencedObject = newObject;
if (oldObject != 0)
oldObject->decReferenceCount();
}
return *this;
}
/** Destructor.
This will decrement the object's reference-count, and may delete it if it
gets to zero.
*/
inline ~RefCountedObjectPtr()
{
if (referencedObject != 0)
referencedObject->decReferenceCount();
}
/** Returns the object that this pointer references.
The pointer returned may be zero, of course.
*/
inline operator ReferenceCountedObjectClass*() const
{
return referencedObject;
}
// the -> operator is called on the referenced object
inline ReferenceCountedObjectClass* operator->() const
{
return referencedObject;
}
/** Returns the object that this pointer references.
The pointer returned may be zero, of course.
*/
inline ReferenceCountedObjectClass* getObject() const
{
return referencedObject;
}
private:
//==============================================================================
ReferenceCountedObjectClass* referencedObject;
};
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator== (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, ReferenceCountedObjectClass* const object2)
{
return object1.getObject() == object2;
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator== (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, const RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
{
return object1.getObject() == object2.getObject();
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator== (ReferenceCountedObjectClass* object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
{
return object1 == object2.getObject();
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator!= (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectClass* object2)
{
return object1.getObject() != object2;
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator!= (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
{
return object1.getObject() != object2.getObject();
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator!= (ReferenceCountedObjectClass* object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
{
return object1 != object2.getObject();
}
//==============================================================================
template <class T>
struct ContainerTraits <RefCountedObjectPtr <T> >
{
typedef T Type;
static T* get (RefCountedObjectPtr <T> const& c)
{
return c.getObject ();
}
};
//==============================================================================
} // namespace luabridge

View File

@@ -0,0 +1,244 @@
//==============================================================================
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <unordered_map>
#include "RefCountedObject.h"
namespace luabridge {
//==============================================================================
/**
Support for our RefCountedPtr.
*/
struct RefCountedPtrBase
{
// Declaration of container for the refcounts
typedef std::unordered_map <const void *, int> RefCountsType;
protected:
RefCountsType& getRefCounts () const
{
static RefCountsType refcounts;
return refcounts ;
}
};
//==============================================================================
/**
A reference counted smart pointer.
The api is compatible with boost::RefCountedPtr and std::RefCountedPtr, in the
sense that it implements a strict subset of the functionality.
This implementation uses a hash table to look up the reference count
associated with a particular pointer.
@tparam T The class type.
@todo Decompose RefCountedPtr using a policy. At a minimum, the underlying
reference count should be policy based (to support atomic operations)
and the delete behavior should be policy based (to support custom
disposal methods).
@todo Provide an intrusive version of RefCountedPtr.
*/
template <class T>
class RefCountedPtr : private RefCountedPtrBase
{
public:
template <typename Other>
struct rebind
{
typedef RefCountedPtr <Other> other;
};
/** Construct as nullptr or from existing pointer to T.
@param p The optional, existing pointer to assign from.
*/
RefCountedPtr (T* p = 0) : m_p (p)
{
++getRefCounts () [m_p];
}
/** Construct from another RefCountedPtr.
@param rhs The RefCountedPtr to assign from.
*/
RefCountedPtr (RefCountedPtr <T> const& rhs) : m_p (rhs.get())
{
++getRefCounts () [m_p];
}
/** Construct from a RefCountedPtr of a different type.
@invariant A pointer to U must be convertible to a pointer to T.
@param rhs The RefCountedPtr to assign from.
@tparam U The other object type.
*/
template <typename U>
RefCountedPtr (RefCountedPtr <U> const& rhs) : m_p (static_cast <T*> (rhs.get()))
{
++getRefCounts () [m_p];
}
/** Release the object.
If there are no more references then the object is deleted.
*/
~RefCountedPtr ()
{
reset();
}
/** Assign from another RefCountedPtr.
@param rhs The RefCountedPtr to assign from.
@return A reference to the RefCountedPtr.
*/
RefCountedPtr <T>& operator= (RefCountedPtr <T> const& rhs)
{
if (m_p != rhs.m_p)
{
reset ();
m_p = rhs.m_p;
++getRefCounts () [m_p];
}
return *this;
}
/** Assign from another RefCountedPtr of a different type.
@note A pointer to U must be convertible to a pointer to T.
@tparam U The other object type.
@param rhs The other RefCountedPtr to assign from.
@return A reference to the RefCountedPtr.
*/
template <typename U>
RefCountedPtr <T>& operator= (RefCountedPtr <U> const& rhs)
{
reset ();
m_p = static_cast <T*> (rhs.get());
++getRefCounts () [m_p];
return *this;
}
/** Retrieve the raw pointer.
@return A pointer to the object.
*/
T* get () const
{
return m_p;
}
/** Retrieve the raw pointer.
@return A pointer to the object.
*/
T* operator* () const
{
return m_p;
}
/** Retrieve the raw pointer.
@return A pointer to the object.
*/
T* operator-> () const
{
return m_p;
}
/** Determine the number of references.
@note This is not thread-safe.
@return The number of active references.
*/
long use_count () const
{
return getRefCounts () [m_p];
}
/** Release the pointer.
The reference count is decremented. If the reference count reaches
zero, the object is deleted.
*/
void reset ()
{
if (m_p != 0)
{
if (--getRefCounts () [m_p] <= 0)
delete m_p;
m_p = 0;
}
}
private:
T* m_p;
};
template <class T>
bool operator== (const RefCountedPtr <T>& lhs, const RefCountedPtr <T>& rhs)
{
return lhs.get () == rhs.get ();
}
template <class T>
bool operator!= (const RefCountedPtr <T>& lhs, const RefCountedPtr <T>& rhs)
{
return lhs.get() != rhs.get();
}
//==============================================================================
// forward declaration
template <class T>
struct ContainerTraits;
template <class T>
struct ContainerTraits <RefCountedPtr <T> >
{
typedef T Type;
static T* get (RefCountedPtr <T> const& c)
{
return c.get ();
}
};
} // namespace luabridge

View File

@@ -0,0 +1,55 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2019, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#include <LuaBridge/detail/Stack.h>
#include <unordered_map>
namespace luabridge {
template <class K, class V>
struct Stack <std::unordered_map <K, V>>
{
typedef std::unordered_map <K, V> Map;
static void push (lua_State* L, const Map& map)
{
lua_createtable (L, 0, static_cast <int> (map.size ()));
typedef typename Map::const_iterator ConstIter;
for (ConstIter i = map.begin (); i != map.end (); ++i)
{
Stack <K>::push (L, i->first);
Stack <V>::push (L, i->second);
lua_settable (L, -3);
}
}
static Map get (lua_State* L, int index)
{
if (!lua_istable (L, index))
{
luaL_error (L, "#%d argument must be a table", index);
}
Map map;
int const absindex = lua_absindex (L, index);
lua_pushnil (L);
while (lua_next (L, absindex) != 0)
{
map.emplace (Stack <K>::get (L, -2), Stack <V>::get (L, -1));
lua_pop (L, 1);
}
return map;
}
static bool isInstance (lua_State* L, int index)
{
return lua_istable (L, index);
}
};
} // namespace luabridge

View File

@@ -0,0 +1,54 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2018, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#include <LuaBridge/detail/Stack.h>
#include <vector>
namespace luabridge {
template <class T>
struct Stack <std::vector <T> >
{
static void push (lua_State* L, std::vector <T> const& vector)
{
lua_createtable (L, static_cast <int> (vector.size ()), 0);
for (std::size_t i = 0; i < vector.size (); ++i)
{
lua_pushinteger (L, static_cast <lua_Integer> (i + 1));
Stack <T>::push (L, vector [i]);
lua_settable (L, -3);
}
}
static std::vector <T> get (lua_State* L, int index)
{
if (!lua_istable (L, index))
{
luaL_error (L, "#%d argument must be a table", index);
}
std::vector <T> vector;
vector.reserve (static_cast <std::size_t> (get_length (L, index)));
int const absindex = lua_absindex (L, index);
lua_pushnil (L);
while (lua_next (L, absindex) != 0)
{
vector.push_back (Stack <T>::get (L, -1));
lua_pop (L, 1);
}
return vector;
}
static bool isInstance (lua_State* L, int index)
{
return lua_istable (L, index);
}
};
} // namespace luabridge

View File

@@ -0,0 +1,495 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/Config.h>
#include <LuaBridge/detail/FuncTraits.h>
#include <string>
namespace luabridge {
// We use a structure so we can define everything in the header.
//
struct CFunc
{
static void addGetter (lua_State* L, const char* name, int tableIndex)
{
assert (lua_istable (L, tableIndex));
assert (lua_iscfunction (L, -1)); // Stack: getter
lua_rawgetp (L, tableIndex, getPropgetKey ()); // Stack: getter, propget table (pg)
lua_pushvalue (L, -2); // Stack: getter, pg, getter
rawsetfield (L, -2, name); // Stack: getter, pg
lua_pop (L, 2); // Stack: -
}
static void addSetter (lua_State* L, const char* name, int tableIndex)
{
assert (lua_istable (L, tableIndex));
assert (lua_iscfunction (L, -1)); // Stack: setter
lua_rawgetp (L, tableIndex, getPropsetKey ()); // Stack: setter, propset table (ps)
lua_pushvalue (L, -2); // Stack: setter, ps, setter
rawsetfield (L, -2, name); // Stack: setter, ps
lua_pop (L, 2); // Stack: -
}
//----------------------------------------------------------------------------
/**
__index metamethod for a namespace or class static and non-static members.
Retrieves functions from metatables and properties from propget tables.
Looks through the class hierarchy if inheritance is present.
*/
static int indexMetaMethod (lua_State* L)
{
assert (lua_istable (L, 1) || lua_isuserdata (L, 1)); // Stack (further not shown): table | userdata, name
lua_getmetatable (L, 1); // Stack: class/const table (mt)
assert (lua_istable (L, -1));
for (;;)
{
lua_pushvalue (L, 2); // Stack: mt, field name
lua_rawget (L, -2); // Stack: mt, field | nil
if (lua_iscfunction (L, -1)) // Stack: mt, field
{
lua_remove (L, -2); // Stack: field
return 1;
}
assert (lua_isnil (L, -1)); // Stack: mt, nil
lua_pop (L, 1); // Stack: mt
lua_rawgetp (L, -1, getPropgetKey ()); // Stack: mt, propget table (pg)
assert (lua_istable (L, -1));
lua_pushvalue (L, 2); // Stack: mt, pg, field name
lua_rawget (L, -2); // Stack: mt, pg, getter | nil
lua_remove (L, -2); // Stack: mt, getter | nil
if (lua_iscfunction (L, -1)) // Stack: mt, getter
{
lua_remove (L, -2); // Stack: getter
lua_pushvalue (L, 1); // Stack: getter, table | userdata
lua_call (L, 1, 1); // Stack: value
return 1;
}
assert (lua_isnil (L, -1)); // Stack: mt, nil
lua_pop (L, 1); // Stack: mt
// It may mean that the field may be in const table and it's constness violation.
// Don't check that, just return nil
// Repeat the lookup in the parent metafield,
// or return nil if the field doesn't exist.
lua_rawgetp (L, -1, getParentKey ()); // Stack: mt, parent mt | nil
if (lua_isnil (L, -1)) // Stack: mt, nil
{
lua_remove (L, -2); // Stack: nil
return 1;
}
// Removethe metatable and repeat the search in the parent one.
assert (lua_istable (L, -1)); // Stack: mt, parent mt
lua_remove (L, -2); // Stack: parent mt
}
// no return
}
//----------------------------------------------------------------------------
/**
__newindex metamethod for namespace or class static members.
Retrieves properties from propset tables.
*/
static int newindexStaticMetaMethod (lua_State* L)
{
return newindexMetaMethod (L, false);
}
//----------------------------------------------------------------------------
/**
__newindex metamethod for non-static members.
Retrieves properties from propset tables.
*/
static int newindexObjectMetaMethod (lua_State* L)
{
return newindexMetaMethod (L, true);
}
static int newindexMetaMethod (lua_State* L, bool pushSelf)
{
assert (lua_istable (L, 1) || lua_isuserdata (L, 1)); // Stack (further not shown): table | userdata, name, new value
lua_getmetatable (L, 1); // Stack: metatable (mt)
assert (lua_istable (L, -1));
for (;;)
{
lua_rawgetp (L, -1, getPropsetKey ()); // Stack: mt, propset table (ps) | nil
if (lua_isnil (L, -1)) // Stack: mt, nil
{
lua_pop (L, 2); // Stack: -
return luaL_error (L, "No member named '%s'", lua_tostring (L, 2));
}
assert (lua_istable (L, -1));
lua_pushvalue (L, 2); // Stack: mt, ps, field name
lua_rawget (L, -2); // Stack: mt, ps, setter | nil
lua_remove (L, -2); // Stack: mt, setter | nil
if (lua_iscfunction (L, -1)) // Stack: mt, setter
{
lua_remove (L, -2); // Stack: setter
if (pushSelf)
{
lua_pushvalue (L, 1); // Stack: setter, table | userdata
}
lua_pushvalue (L, 3); // Stack: setter, table | userdata, new value
lua_call (L, pushSelf ? 2 : 1, 0); // Stack: -
return 0;
}
assert (lua_isnil (L, -1)); // Stack: mt, nil
lua_pop (L, 1); // Stack: mt
lua_rawgetp (L, -1, getParentKey ()); // Stack: mt, parent mt | nil
if (lua_isnil (L, -1)) // Stack: mt, nil
{
lua_pop (L, 1); // Stack: -
return luaL_error (L, "No writable member '%s'", lua_tostring (L, 2));
}
assert (lua_istable (L, -1)); // Stack: mt, parent mt
lua_remove (L, -2); // Stack: parent mt
// Repeat the search in the parent
}
// no return
}
//----------------------------------------------------------------------------
/**
lua_CFunction to report an error writing to a read-only value.
The name of the variable is in the first upvalue.
*/
static int readOnlyError (lua_State* L)
{
std::string s;
s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only";
return luaL_error (L, s.c_str ());
}
//----------------------------------------------------------------------------
/**
lua_CFunction to get a variable.
This is used for global variables or class static data members.
The pointer to the data is in the first upvalue.
*/
template <class T>
static int getVariable (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
T const* ptr = static_cast <T const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (ptr != 0);
Stack <T>::push (L, *ptr);
return 1;
}
//----------------------------------------------------------------------------
/**
lua_CFunction to set a variable.
This is used for global variables or class static data members.
The pointer to the data is in the first upvalue.
*/
template <class T>
static int setVariable (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
T* ptr = static_cast <T*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (ptr != 0);
*ptr = Stack <T>::get (L, 1);
return 0;
}
//----------------------------------------------------------------------------
/**
lua_CFunction to call a function with a return value.
This is used for global functions, global properties, class static methods,
and class static properties.
The function pointer (lightuserdata) in the first upvalue.
*/
template <class FnPtr>
struct Call
{
typedef typename FuncTraits <FnPtr>::Params Params;
typedef typename FuncTraits <FnPtr>::ReturnType ReturnType;
static int f (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
FnPtr fnptr = reinterpret_cast <FnPtr> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return Invoke <ReturnType, Params, 1>::run (L, fnptr);
}
};
//----------------------------------------------------------------------------
/**
lua_CFunction to call a class member function with a return value.
The member function pointer is in the first upvalue.
The class userdata object is at the top of the Lua stack.
*/
template <class MemFnPtr>
struct CallMember
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
typedef typename FuncTraits <MemFnPtr>::Params Params;
typedef typename FuncTraits <MemFnPtr>::ReturnType ReturnType;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
T* const t = Userdata::get <T> (L, 1, false);
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return Invoke <ReturnType, Params, 2>::run (L, t, fnptr);
}
};
template <class MemFnPtr>
struct CallConstMember
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
typedef typename FuncTraits <MemFnPtr>::Params Params;
typedef typename FuncTraits <MemFnPtr>::ReturnType ReturnType;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
T const* const t = Userdata::get <T> (L, 1, true);
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return Invoke <ReturnType, Params, 2>::run (L, t, fnptr);
}
};
//--------------------------------------------------------------------------
/**
lua_CFunction to call a class member lua_CFunction.
The member function pointer is in the first upvalue.
The object userdata ('this') value is at top ot the Lua stack.
*/
template <class T>
struct CallMemberCFunction
{
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
typedef int (T::*MFP) (lua_State* L);
T* const t = Userdata::get <T> (L, 1, false);
MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return (t->*fnptr) (L);
}
};
template <class T>
struct CallConstMemberCFunction
{
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
typedef int (T::*MFP) (lua_State* L);
T const* const t = Userdata::get <T> (L, 1, true);
MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return (t->*fnptr) (L);
}
};
#ifdef LUABRIDGE_CXX11
//--------------------------------------------------------------------------
/**
lua_CFunction to call on a object.
The proxy function pointer (lightuserdata) is in the first upvalue.
The class userdata object is at the top of the Lua stack.
*/
template <class FnPtr>
struct CallProxyFunction
{
using Params = typename FuncTraits <FnPtr>::Params;
using ReturnType = typename FuncTraits <FnPtr>::ReturnType;
static int f (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
auto fnptr = reinterpret_cast <FnPtr> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return Invoke <ReturnType, Params, 1>::run (L, fnptr);
}
};
template <class Functor>
struct CallProxyFunctor
{
using Params = typename FuncTraits <Functor>::Params;
using ReturnType = typename FuncTraits <Functor>::ReturnType;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
Functor& fn = *static_cast <Functor*> (lua_touserdata (L, lua_upvalueindex (1)));
return Invoke <ReturnType, Params, 1>::run (L, fn);
}
};
#endif
//--------------------------------------------------------------------------
// SFINAE Helpers
template <class MemFnPtr, bool isConst>
struct CallMemberFunctionHelper
{
static void add (lua_State* L, char const* name, MemFnPtr mf)
{
new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
lua_pushcclosure (L, &CallConstMember <MemFnPtr>::f, 1);
lua_pushvalue (L, -1);
rawsetfield (L, -5, name); // const table
rawsetfield (L, -3, name); // class table
}
};
template <class MemFnPtr>
struct CallMemberFunctionHelper <MemFnPtr, false>
{
static void add (lua_State* L, char const* name, MemFnPtr mf)
{
new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
lua_pushcclosure (L, &CallMember <MemFnPtr>::f, 1);
rawsetfield (L, -3, name); // class table
}
};
//--------------------------------------------------------------------------
/**
__gc metamethod for a class.
*/
template <class C>
static int gcMetaMethod (lua_State* L)
{
Userdata* const ud = Userdata::getExact <C> (L, 1);
ud->~Userdata ();
return 0;
}
/**
__gc metamethod for an arbitrary class.
*/
template <class T>
static int gcMetaMethodAny (lua_State* L)
{
assert (isfulluserdata (L, 1));
T* t = static_cast <T*> (lua_touserdata (L, 1));
t->~T ();
return 0;
}
//--------------------------------------------------------------------------
/**
lua_CFunction to get a class data member.
The pointer-to-member is in the first upvalue.
The class userdata object is at the top of the Lua stack.
*/
template <class C, typename T>
static int getProperty (lua_State* L)
{
C* const c = Userdata::get <C> (L, 1, true);
T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
try
{
Stack <T&>::push (L, c->**mp);
}
catch (const std::exception& e)
{
luaL_error (L, e.what ());
}
return 1;
}
//--------------------------------------------------------------------------
/**
lua_CFunction to set a class data member.
The pointer-to-member is in the first upvalue.
The class userdata object is at the top of the Lua stack.
*/
template <class C, typename T>
static int setProperty (lua_State* L)
{
C* const c = Userdata::get <C> (L, 1, false);
T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
try
{
c->**mp = Stack <T>::get (L, 2);
}
catch (const std::exception& e)
{
luaL_error (L, e.what ());
}
return 0;
}
};
} // namespace luabridge

View File

@@ -0,0 +1,169 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
namespace luabridge {
/**
* A unique key for a type name in a metatable.
*/
inline const void* getTypeKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0x71);
#endif
}
/**
* The key of a const table in another metatable.
*/
inline const void* getConstKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0xc07);
#endif
}
/**
* The key of a class table in another metatable.
*/
inline const void* getClassKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0xc1a);
#endif
}
/**
* The key of a propget table in another metatable.
*/
inline const void* getPropgetKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0x6e7);
#endif
}
/**
* The key of a propset table in another metatable.
*/
inline const void* getPropsetKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0x5e7);
#endif
}
/**
* The key of a static table in another metatable.
*/
inline const void* getStaticKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0x57a);
#endif
}
/**
* The key of a parent table in another metatable.
*/
inline const void* getParentKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0xdad);
#endif
}
/** Unique Lua registry keys for a class.
Each registered class inserts three keys into the registry, whose
values are the corresponding static, class, and const metatables. This
allows a quick and reliable lookup for a metatable from a template type.
*/
template <class T>
class ClassInfo
{
public:
/** Get the key for the static table.
The static table holds the static data members, static properties, and
static member functions for a class.
*/
static void const* getStaticKey ()
{
static char value;
return &value;
}
/** Get the key for the class table.
The class table holds the data members, properties, and member functions
of a class. Read-only data and properties, and const member functions are
also placed here (to save a lookup in the const table).
*/
static void const* getClassKey ()
{
static char value;
return &value;
}
/** Get the key for the const table.
The const table holds read-only data members and properties, and const
member functions of a class.
*/
static void const* getConstKey ()
{
static char value;
return &value;
}
};
} // namespace luabridge

View File

@@ -0,0 +1,10 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2019, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#if !defined (LUABRIDGE_NO_CXX11) && (__cplusplus >= 201103L || (defined (_MSC_VER) && _MSC_VER >= 1900))
#define LUABRIDGE_CXX11
#endif

View File

@@ -0,0 +1,205 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
namespace luabridge {
/*
* Constructor generators. These templates allow you to call operator new and
* pass the contents of a type/value list to the Constructor. Like the
* function pointer containers, these are only defined up to 8 parameters.
*/
/** Constructor generators.
These templates call operator new with the contents of a type/value
list passed to the Constructor with up to 8 parameters. Two versions
of call() are provided. One performs a regular new, the other performs
a placement new.
*/
template <class T, typename List>
struct Constructor {};
template <class T>
struct Constructor <T, None>
{
static T* call (TypeListValues <None> const&)
{
return new T;
}
static T* call (void* mem, TypeListValues <None> const&)
{
return new (mem) T;
}
};
template <class T, class P1>
struct Constructor <T, TypeList <P1> >
{
static T* call (const TypeListValues<TypeList <P1> > &tvl)
{
return new T(tvl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1> > &tvl)
{
return new (mem) T(tvl.hd);
}
};
template <class T, class P1, class P2>
struct Constructor <T, TypeList <P1, TypeList <P2> > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd);
}
};
template <class T, class P1, class P2, class P3>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3> > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3> > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3> > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4> > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4> > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4> > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4,
class P5>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4, TypeList <P5> > > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4,
class P5, class P6>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4, TypeList <P5, TypeList <P6> > > > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4,
class P5, class P6, class P7>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
TypeList <P7> > > > > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
TypeList <P7> > > > > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4,
class P5, class P6, class P7, class P8>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7,
TypeList <P8> > > > > > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
TypeList <P7, TypeList <P8> > > > > > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
TypeList <P7, TypeList <P8> > > > > > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
}
};
} // namespace luabridge

View File

@@ -0,0 +1,942 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2020, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/Config.h>
#ifdef LUABRIDGE_CXX11
#include <functional>
#endif
namespace luabridge {
/**
Since the throw specification is part of a function signature, the FuncTraits
family of templates needs to be specialized for both types. The
LUABRIDGE_THROWSPEC macro controls whether we use the 'throw ()' form, or
'noexcept' (if C++11 is available) to distinguish the functions.
*/
#if defined (__APPLE_CPP__) || defined (__APPLE_CC__) || defined (__clang__) || defined (__GNUC__) || \
(defined (_MSC_VER) && (_MSC_VER >= 1700))
// Do not define LUABRIDGE_THROWSPEC since the Xcode and gcc compilers do not
// distinguish the throw specification in the function signature.
#define LUABRIDGE_THROWSPEC
#else
// Visual Studio 10 and earlier pay too much mind to useless throw () spec.
//
# define LUABRIDGE_THROWSPEC throw ()
#endif
//==============================================================================
/**
* Traits class for unrolling the type list values into function arguments.
*/
template <class ReturnType, size_t NUM_PARAMS>
struct Caller;
template <class ReturnType>
struct Caller <ReturnType, 0>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& params)
{
return fn ();
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>&)
{
return (obj->*fn) ();
}
};
template <class ReturnType>
struct Caller <ReturnType, 1>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 2>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 3>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 4>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 5>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 6>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 7>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 8>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 9>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType, class Fn, class Params>
ReturnType doCall (Fn& fn, TypeListValues <Params>& tvl)
{
return Caller <ReturnType, TypeListSize <Params>::value>::f (fn, tvl);
}
template <class ReturnType, class T, class MemFn, class Params>
static ReturnType doCall(T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return Caller <ReturnType, TypeListSize <Params>::value>::f (obj, fn, tvl);
}
//==============================================================================
/**
Traits for function pointers.
There are three types of functions: global, non-const member, and const
member. These templates determine the type of function, which class type it
belongs to if it is a class member, the const-ness if it is a member
function, and the type information for the return value and argument list.
Expansions are provided for functions with up to 8 parameters. This can be
manually extended, or expanded to an arbitrary amount using C++11 features.
*/
template <class MemFn, class D = MemFn>
struct FuncTraits
{
};
#ifndef LUABRIDGE_CXX11
/* Ordinary function pointers. */
template <class R, class D>
struct FuncTraits <R (*) () LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef None Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class D>
struct FuncTraits <R (*) (P1) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1> Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class D>
struct FuncTraits <R (*) (P1, P2) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2> > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class D>
struct FuncTraits <R (*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */
#ifdef _M_IX86 // Windows 32bit only
template <class R, class D>
struct FuncTraits <R (__stdcall *) (), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef None Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class D>
struct FuncTraits <R (__stdcall *) (P1), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1> Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class D>
struct FuncTraits <R (__stdcall *) (P1, P2), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2> > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5, P6), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5, P6, P7), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5, P6, P7, P8), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
#endif // _M_IX86
/* Non-const member function pointers. */
template <class T, class R, class D>
struct FuncTraits <R (T::*) () LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef None Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class D>
struct FuncTraits <R (T::*) (P1) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1> Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class D>
struct FuncTraits <R (T::*) (P1, P2) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2> > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class D>
struct FuncTraits <R (T::*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
/* Const member function pointers. */
template <class T, class R, class D>
struct FuncTraits <R (T::*) () const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef None Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class D>
struct FuncTraits <R (T::*) (P1) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1> Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class D>
struct FuncTraits <R (T::*) (P1, P2) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2> > Params;
static R call (T const* obj, R (T::*fp) (P1, P2) const, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class D>
struct FuncTraits <R (T::*) (P1, P2, P3) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
#else // ifndef LUABRIDGE_CXX11
/* Ordinary function pointers. */
template <class R, class... ParamList>
struct FuncTraits <R (*) (ParamList...)>
{
static bool const isMemberFunction = false;
using DeclType = R (*) (ParamList...);
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static R call (const DeclType& fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */
#ifdef _M_IX86 // Windows 32bit only
template <class R, class... ParamList>
struct FuncTraits <R (__stdcall *) (ParamList...)>
{
static bool const isMemberFunction = false;
using DeclType = R (__stdcall *) (ParamList...);
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static R call (const DeclType& fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
#endif // _M_IX86
/* Non-const member function pointers. */
template <class T, class R, class... ParamList>
struct FuncTraits <R (T::*) (ParamList...)>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
using DeclType = R (T::*) (ParamList...);
using ClassType = T;
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static R call (ClassType* obj, const DeclType& fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
/* Const member function pointers. */
template <class T, class R, class... ParamList>
struct FuncTraits <R (T::*) (ParamList...) const>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
using DeclType = R (T::*) (ParamList...) const;
using ClassType = T;
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static R call (const ClassType* obj, const DeclType& fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
/* std::function */
template <class R, class... ParamList>
struct FuncTraits <std::function <R (ParamList...)>>
{
static bool const isMemberFunction = false;
static bool const isConstMemberFunction = false;
using DeclType = std::function <R (ParamList...)>;
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static ReturnType call (DeclType& fn, TypeListValues <Params>& tvl)
{
return doCall <ReturnType> (fn, tvl);
}
};
#endif // ifndef LUABRIDGE_CXX11
template <class ReturnType, class Params, int startParam>
struct Invoke
{
template <class Fn>
static int run (lua_State* L, Fn& fn)
{
try
{
ArgList <Params, startParam> args (L);
Stack <ReturnType>::push (L, FuncTraits <Fn>::call (fn, args));
return 1;
}
catch (const std::exception& e)
{
return luaL_error (L, e.what ());
}
}
template <class T, class MemFn>
static int run (lua_State* L, T* object, const MemFn& fn)
{
try
{
ArgList <Params, startParam> args (L);
Stack <ReturnType>::push (L, FuncTraits <MemFn>::call (object, fn, args));
return 1;
}
catch (const std::exception& e)
{
return luaL_error (L, e.what ());
}
}
};
template <class Params, int startParam>
struct Invoke <void, Params, startParam>
{
template <class Fn>
static int run (lua_State* L, Fn& fn)
{
try
{
ArgList <Params, startParam> args (L);
FuncTraits <Fn>::call (fn, args);
return 0;
}
catch (const std::exception& e)
{
return luaL_error (L, e.what ());
}
}
template <class T, class MemFn>
static int run (lua_State* L, T* object, const MemFn& fn)
{
try
{
ArgList <Params, startParam> args (L);
FuncTraits <MemFn>::call (object, fn, args);
return 0;
}
catch (const std::exception& e)
{
return luaL_error (L, e.what ());
}
}
};
} // namespace luabridge

View File

@@ -0,0 +1,154 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2018, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/LuaRef.h>
#include <utility>
namespace luabridge {
/** Allows table iteration.
*/
class Iterator
{
lua_State* m_L;
LuaRef m_table;
LuaRef m_key;
LuaRef m_value;
void next ()
{
m_table.push ();
m_key.push ();
if (lua_next (m_L, -2))
{
m_value.pop ();
m_key.pop ();
}
else
{
m_key = Nil ();
m_value = Nil ();
}
lua_pop (m_L, 1);
}
public:
explicit Iterator (const LuaRef& table, bool isEnd = false)
: m_L (table.state ())
, m_table (table)
, m_key (table.state ()) // m_key is nil
, m_value (table.state ()) // m_value is nil
{
if (!isEnd)
{
next (); // get the first (key, value) pair from table
}
}
lua_State* state () const
{
return m_L;
}
std::pair <LuaRef, LuaRef> operator* () const
{
return std::make_pair (m_key, m_value);
}
LuaRef operator-> () const
{
return m_value;
}
bool operator!= (const Iterator& rhs) const
{
assert (m_L == rhs.m_L);
return !m_table.rawequal (rhs.m_table) || !m_key.rawequal (rhs.m_key);
}
Iterator& operator++ ()
{
if (isNil ())
{
// if the iterator reaches the end, do nothing
return *this;
}
else
{
next ();
return *this;
}
}
bool isNil () const
{
return m_key.isNil ();
}
LuaRef key () const
{
return m_key;
}
LuaRef value () const
{
return m_value;
}
private:
// Don't use postfix increment, it is less efficient
Iterator operator++ (int);
};
class Range
{
Iterator m_begin;
Iterator m_end;
public:
Range (const Iterator& begin, const Iterator& end)
: m_begin (begin)
, m_end (end)
{
}
const Iterator& begin () const { return m_begin; }
const Iterator& end () const { return m_end; }
};
inline Range pairs (const LuaRef& table)
{
return Range (Iterator (table, false), Iterator (table, true));
}
} // namespace luabridge

View File

@@ -0,0 +1,144 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <exception>
#include <string>
namespace luabridge {
class LuaException : public std::exception
{
private:
lua_State* m_L;
std::string m_what;
public:
//----------------------------------------------------------------------------
/**
Construct a LuaException after a lua_pcall().
*/
LuaException (lua_State* L, int /*code*/)
: m_L (L)
{
whatFromStack ();
}
//----------------------------------------------------------------------------
LuaException (lua_State *L,
char const*,
char const*,
long)
: m_L (L)
{
whatFromStack ();
}
//----------------------------------------------------------------------------
~LuaException() throw ()
{
}
//----------------------------------------------------------------------------
char const* what() const throw ()
{
return m_what.c_str();
}
//============================================================================
/**
Throw an exception.
This centralizes all the exceptions thrown, so that we can set
breakpoints before the stack is unwound, or otherwise customize the
behavior.
*/
template <class Exception>
static void Throw (Exception e)
{
throw e;
}
//----------------------------------------------------------------------------
/**
Wrapper for lua_pcall that throws.
*/
static void pcall (lua_State* L, int nargs = 0, int nresults = 0, int msgh = 0)
{
int code = lua_pcall (L, nargs, nresults, msgh);
if (code != LUABRIDGE_LUA_OK)
Throw (LuaException (L, code));
}
//----------------------------------------------------------------------------
/**
Initializes error handling. Subsequent Lua errors are translated to C++ exceptions.
*/
static void enableExceptions (lua_State* L)
{
lua_atpanic (L, throwAtPanic);
}
protected:
void whatFromStack ()
{
if (lua_gettop (m_L) > 0)
{
char const* s = lua_tostring (m_L, -1);
m_what = s ? s : "";
}
else
{
// stack is empty
m_what = "missing error";
}
}
private:
static int throwAtPanic (lua_State* L)
{
throw LuaException (L, -1);
}
};
//----------------------------------------------------------------------------
/**
Initializes error handling. Subsequent Lua errors are translated to C++ exceptions.
*/
static void enableExceptions (lua_State* L)
{
LuaException::enableExceptions (L);
}
} // namespace luabridge

View File

@@ -0,0 +1,151 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <cassert>
namespace luabridge {
// These are for Lua versions prior to 5.2.0.
//
#if LUA_VERSION_NUM < 502
inline int lua_absindex (lua_State* L, int idx)
{
if (idx > LUA_REGISTRYINDEX && idx < 0)
return lua_gettop (L) + idx + 1;
else
return idx;
}
inline void lua_rawgetp (lua_State* L, int idx, void const* p)
{
idx = lua_absindex (L, idx);
lua_pushlightuserdata (L, const_cast <void*> (p));
lua_rawget (L,idx);
}
inline void lua_rawsetp (lua_State* L, int idx, void const* p)
{
idx = lua_absindex (L, idx);
lua_pushlightuserdata (L, const_cast <void*> (p));
// put key behind value
lua_insert (L, -2);
lua_rawset (L, idx);
}
#define LUA_OPEQ 1
#define LUA_OPLT 2
#define LUA_OPLE 3
inline int lua_compare (lua_State* L, int idx1, int idx2, int op)
{
switch (op)
{
case LUA_OPEQ:
return lua_equal (L, idx1, idx2);
break;
case LUA_OPLT:
return lua_lessthan (L, idx1, idx2);
break;
case LUA_OPLE:
return lua_equal (L, idx1, idx2) || lua_lessthan (L, idx1, idx2);
break;
default:
return 0;
};
}
inline int get_length (lua_State* L, int idx)
{
return int (lua_objlen (L, idx));
}
#else
inline int get_length (lua_State* L, int idx)
{
lua_len (L, idx);
int len = int (luaL_checknumber (L, -1));
lua_pop (L, 1);
return len;
}
#endif
#ifndef LUA_OK
# define LUABRIDGE_LUA_OK 0
#else
# define LUABRIDGE_LUA_OK LUA_OK
#endif
/** Get a table value, bypassing metamethods.
*/
inline void rawgetfield (lua_State* L, int index, char const* key)
{
assert (lua_istable (L, index));
index = lua_absindex (L, index);
lua_pushstring (L, key);
lua_rawget (L, index);
}
/** Set a table value, bypassing metamethods.
*/
inline void rawsetfield (lua_State* L, int index, char const* key)
{
assert (lua_istable (L, index));
index = lua_absindex (L, index);
lua_pushstring (L, key);
lua_insert (L, -2);
lua_rawset (L, index);
}
/** Returns true if the value is a full userdata (not light).
*/
inline bool isfulluserdata (lua_State* L, int index)
{
return lua_isuserdata (L, index) && !lua_islightuserdata (L, index);
}
/** Test lua_State objects for global equality.
This can determine if two different lua_State objects really point
to the same global state, such as when using coroutines.
@note This is used for assertions.
*/
inline bool equalstates (lua_State* L1, lua_State* L2)
{
return lua_topointer (L1, LUA_REGISTRYINDEX) ==
lua_topointer (L2, LUA_REGISTRYINDEX);
}
} // namespace luabridge

View File

@@ -0,0 +1,1051 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2018, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/LuaException.h>
#include <LuaBridge/detail/Stack.h>
#include <iostream>
#include <string>
#include <vector>
#include <map>
namespace luabridge {
//------------------------------------------------------------------------------
/**
Type tag for representing LUA_TNIL.
Construct one of these using `Nil ()` to represent a Lua nil. This is faster
than creating a reference in the registry to nil. Example:
LuaRef t (LuaRef::createTable (L));
...
t ["k"] = Nil (); // assign nil
*/
struct Nil
{
};
//------------------------------------------------------------------------------
/**
Stack specialization for Nil.
*/
template <>
struct Stack <Nil>
{
static void push (lua_State* L, Nil)
{
lua_pushnil (L);
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TTABLE;
}
};
/**
* Base class for LuaRef and table value proxy classes.
*/
template <class Impl, class LuaRef>
class LuaRefBase
{
protected:
//----------------------------------------------------------------------------
/**
Pop the Lua stack.
Pops the specified number of stack items on destruction. We use this
when returning objects, to avoid an explicit temporary variable, since
the destructor executes after the return statement. For example:
template <class U>
U cast (lua_State* L)
{
StackPop p (L, 1);
...
return U (); // dtor called after this line
}
@note The `StackPop` object must always be a named local variable.
*/
class StackPop
{
public:
/** Create a StackPop object.
@param count The number of stack entries to pop on destruction.
*/
StackPop (lua_State* L, int count)
: m_L (L)
, m_count (count)
{
}
~StackPop ()
{
lua_pop (m_L, m_count);
}
private:
lua_State* m_L;
int m_count;
};
friend struct Stack <LuaRef>;
//----------------------------------------------------------------------------
/**
Type tag for stack construction.
*/
struct FromStack { };
LuaRefBase (lua_State* L)
: m_L (L)
{
}
//----------------------------------------------------------------------------
/**
Create a reference to this ref.
This is used internally.
*/
int createRef () const
{
impl ().push ();
return luaL_ref (m_L, LUA_REGISTRYINDEX);
}
public:
//----------------------------------------------------------------------------
/**
converts to a string using luas tostring function
*/
std::string tostring () const
{
lua_getglobal (m_L, "tostring");
impl ().push ();
lua_call (m_L, 1, 1);
const char* str = lua_tostring (m_L, -1);
lua_pop (m_L, 1);
return str;
}
//----------------------------------------------------------------------------
/**
Print a text description of the value to a stream.
This is used for diagnostics.
*/
void print (std::ostream& os) const
{
switch (type ())
{
case LUA_TNIL:
os << "nil";
break;
case LUA_TNUMBER:
os << cast <lua_Number> ();
break;
case LUA_TBOOLEAN:
os << (cast <bool> () ? "true" : "false");
break;
case LUA_TSTRING:
os << '"' << cast <std::string> () << '"';
break;
case LUA_TTABLE:
os << "table: " << tostring ();
break;
case LUA_TFUNCTION:
os << "function: " << tostring ();
break;
case LUA_TUSERDATA:
os << "userdata: " << tostring ();
break;
case LUA_TTHREAD:
os << "thread: " << tostring ();
break;
case LUA_TLIGHTUSERDATA:
os << "lightuserdata: " << tostring ();
break;
default:
os << "unknown";
break;
}
}
//------------------------------------------------------------------------------
/**
Write a LuaRef to a stream.
This allows LuaRef and table proxies to work with streams.
*/
friend std::ostream& operator<< (std::ostream& os, LuaRefBase const& ref)
{
ref.print (os);
return os;
}
//============================================================================
//
// This group of member functions is mirrored in Proxy
//
/** Retrieve the lua_State associated with the reference.
*/
lua_State* state () const
{
return m_L;
}
//----------------------------------------------------------------------------
/**
Place the object onto the Lua stack.
*/
void push (lua_State* L) const
{
assert (equalstates (L, m_L));
(void) L;
impl ().push ();
}
//----------------------------------------------------------------------------
/**
Pop the top of Lua stack and assign the ref to m_ref
*/
void pop (lua_State* L)
{
assert (equalstates (L, m_L));
(void) L;
impl ().pop ();
}
//----------------------------------------------------------------------------
/**
Determine the object type.
The return values are the same as for `lua_type`.
*/
/** @{ */
int type () const
{
impl ().push ();
StackPop p (m_L, 1);
return lua_type (m_L, -1);
}
// should never happen
// bool isNone () const { return m_ref == LUA_NOREF; }
bool isNil () const { return type () == LUA_TNIL; }
bool isBool () const { return type () == LUA_TBOOLEAN; }
bool isNumber () const { return type () == LUA_TNUMBER; }
bool isString () const { return type () == LUA_TSTRING; }
bool isTable () const { return type () == LUA_TTABLE; }
bool isFunction () const { return type () == LUA_TFUNCTION; }
bool isUserdata () const { return type () == LUA_TUSERDATA; }
bool isThread () const { return type () == LUA_TTHREAD; }
bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; }
/** @} */
//----------------------------------------------------------------------------
/**
Perform an explicit conversion.
*/
template <class T>
T cast () const
{
StackPop p (m_L, 1);
impl ().push ();
return Stack <T>::get (m_L, -1);
}
//----------------------------------------------------------------------------
/**
Type check
*/
template <class T>
bool isInstance () const
{
StackPop p (m_L, 1);
impl ().push ();
return Stack <T>::isInstance (m_L, -1);
}
//----------------------------------------------------------------------------
/**
Universal implicit conversion operator.
NOTE: Visual Studio 2010 and 2012 have a bug where this function
is not used. See:
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014
https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile
// This code snippet fails to compile in vs2010,vs2012
struct S {
template <class T> operator T () const { return T (); }
};
int main () {
S () || false;
return 0;
}
*/
template <class T>
operator T () const
{
return cast <T> ();
}
//----------------------------------------------------------------------------
/**
Universal comparison operators.
*/
/** @{ */
template <class T>
bool operator== (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();
Stack <T>::push (m_L, rhs);
return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1;
}
template <class T>
bool operator< (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
int lhsType = lua_type (m_L, -2);
int rhsType = lua_type (m_L, -1);
if (lhsType != rhsType)
{
return lhsType < rhsType;
}
return lua_compare (m_L, -2, -1, LUA_OPLT) == 1;
}
template <class T>
bool operator<= (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
int lhsType = lua_type (m_L, -2);
int rhsType = lua_type (m_L, -1);
if (lhsType != rhsType)
{
return lhsType <= rhsType;
}
return lua_compare (m_L, -2, -1, LUA_OPLE) == 1;
}
template <class T>
bool operator> (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
int lhsType = lua_type (m_L, -2);
int rhsType = lua_type (m_L, -1);
if (lhsType != rhsType)
{
return lhsType > rhsType;
}
return lua_compare (m_L, -1, -2, LUA_OPLT) == 1;
}
template <class T>
bool operator>= (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
int lhsType = lua_type (m_L, -2);
int rhsType = lua_type (m_L, -1);
if (lhsType != rhsType)
{
return lhsType >= rhsType;
}
return lua_compare (m_L, -1, -2, LUA_OPLE) == 1;
}
template <class T>
bool rawequal (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
return lua_rawequal (m_L, -1, -2) == 1;
}
/** @} */
//----------------------------------------------------------------------------
/**
Append a value to the table.
If the table is a sequence this will add another element to it.
*/
template <class T>
void append (T v) const
{
impl ().push ();;
Stack <T>::push (m_L, v);
luaL_ref (m_L, -2);
lua_pop (m_L, 1);
}
//----------------------------------------------------------------------------
/**
Call the length operator.
This is identical to applying the Lua # operator.
*/
int length () const
{
StackPop p (m_L, 1);
impl ().push ();;
return get_length (m_L, -1);
}
//----------------------------------------------------------------------------
/**
Call Lua code.
These overloads allow Lua code to be called with up to 8 parameters.
The return value is provided as a LuaRef (which may be LUA_REFNIL).
If an error occurs, a LuaException is thrown.
*/
/** @{ */
LuaRef operator() () const
{
impl ().push ();;
LuaException::pcall (m_L, 0, 1);
return LuaRef::fromStack (m_L);
}
template <class P1>
LuaRef operator() (P1 p1) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
LuaException::pcall (m_L, 1, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2>
LuaRef operator() (P1 p1, P2 p2) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
LuaException::pcall (m_L, 2, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3>
LuaRef operator() (P1 p1, P2 p2, P3 p3) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
LuaException::pcall (m_L, 3, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
LuaException::pcall (m_L, 4, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4, class P5>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
Stack <P5>::push (m_L, p5);
LuaException::pcall (m_L, 5, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4, class P5, class P6>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
Stack <P5>::push (m_L, p5);
Stack <P6>::push (m_L, p6);
LuaException::pcall (m_L, 6, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4, class P5, class P6, class P7>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
Stack <P5>::push (m_L, p5);
Stack <P6>::push (m_L, p6);
Stack <P7>::push (m_L, p7);
LuaException::pcall (m_L, 7, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const
{
impl ().push ();
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
Stack <P5>::push (m_L, p5);
Stack <P6>::push (m_L, p6);
Stack <P7>::push (m_L, p7);
Stack <P8>::push (m_L, p8);
LuaException::pcall (m_L, 8, 1);
return LuaRef::fromStack (m_L);
}
/** @} */
//============================================================================
protected:
lua_State* m_L;
private:
const Impl& impl () const
{
return static_cast <const Impl&> (*this);
}
Impl& impl ()
{
return static_cast <Impl&> (*this);
}
};
//------------------------------------------------------------------------------
/**
Lightweight reference to a Lua object.
The reference is maintained for the lifetime of the C++ object.
*/
class LuaRef : public LuaRefBase <LuaRef, LuaRef>
{
//----------------------------------------------------------------------------
/**
A proxy for representing table values.
*/
class Proxy : public LuaRefBase <Proxy, LuaRef>
{
friend class LuaRef;
public:
//--------------------------------------------------------------------------
/**
Construct a Proxy from a table value.
The table is in the registry, and the key is at the top of the stack.
The key is popped off the stack.
*/
Proxy (lua_State* L, int tableRef)
: LuaRefBase (L)
, m_tableRef (LUA_NOREF)
, m_keyRef (luaL_ref (L, LUA_REGISTRYINDEX))
{
lua_rawgeti (m_L, LUA_REGISTRYINDEX, tableRef);
m_tableRef = luaL_ref (L, LUA_REGISTRYINDEX);
}
//--------------------------------------------------------------------------
/**
Create a Proxy via copy constructor.
It is best to avoid code paths that invoke this, because it creates
an extra temporary Lua reference. Typically this is done by passing
the Proxy parameter as a `const` reference.
*/
Proxy (Proxy const& other)
: LuaRefBase (other.m_L)
, m_tableRef (LUA_NOREF)
, m_keyRef (LUA_NOREF)
{
lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_tableRef);
m_tableRef = luaL_ref (m_L, LUA_REGISTRYINDEX);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_keyRef);
m_keyRef = luaL_ref (m_L, LUA_REGISTRYINDEX);
}
//--------------------------------------------------------------------------
/**
Destroy the proxy.
This does not destroy the table value.
*/
~Proxy ()
{
luaL_unref (m_L, LUA_REGISTRYINDEX, m_keyRef);
luaL_unref (m_L, LUA_REGISTRYINDEX, m_tableRef);
}
//--------------------------------------------------------------------------
/**
Assign a new value to this table key.
This may invoke metamethods.
*/
template <class T>
Proxy& operator= (T v)
{
StackPop p (m_L, 1);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
Stack <T>::push (m_L, v);
lua_settable (m_L, -3);
return *this;
}
//--------------------------------------------------------------------------
/**
Assign a new value to this table key.
The assignment is raw, no metamethods are invoked.
*/
template <class T>
Proxy& rawset (T v)
{
StackPop p (m_L, 1);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
Stack <T>::push (m_L, v);
lua_rawset (m_L, -3);
return *this;
}
//--------------------------------------------------------------------------
/**
Push the value onto the Lua stack.
*/
using LuaRefBase::push;
void push () const
{
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
lua_gettable (m_L, -2);
lua_remove (m_L, -2); // remove the table
}
//--------------------------------------------------------------------------
/**
Access a table value using a key.
This invokes metamethods.
*/
template <class T>
Proxy operator[] (T key) const
{
return LuaRef (*this) [key];
}
//--------------------------------------------------------------------------
/**
Access a table value using a key.
The operation is raw, metamethods are not invoked. The result is
passed by value and may not be modified.
*/
template <class T>
LuaRef rawget (T key) const
{
return LuaRef (*this).rawget (key);
}
private:
int m_tableRef;
int m_keyRef;
};
friend struct Stack <Proxy>;
friend struct Stack <Proxy&>;
//----------------------------------------------------------------------------
/**
Create a reference to an object at the top of the Lua stack and pop it.
This constructor is private and not invoked directly.
Instead, use the `fromStack` function.
@note The object is popped.
*/
LuaRef (lua_State* L, FromStack)
: LuaRefBase (L)
, m_ref (luaL_ref (m_L, LUA_REGISTRYINDEX))
{
}
//----------------------------------------------------------------------------
/**
Create a reference to an object on the Lua stack.
This constructor is private and not invoked directly.
Instead, use the `fromStack` function.
@note The object is not popped.
*/
LuaRef (lua_State* L, int index, FromStack)
: LuaRefBase (L)
, m_ref (LUA_NOREF)
{
lua_pushvalue (m_L, index);
m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
}
public:
//----------------------------------------------------------------------------
/**
Create a nil reference.
The LuaRef may be assigned later.
*/
LuaRef (lua_State* L)
: LuaRefBase (L)
, m_ref (LUA_NOREF)
{
}
//----------------------------------------------------------------------------
/**
Create a reference to a value.
*/
template <class T>
LuaRef (lua_State* L, T v)
: LuaRefBase (L)
, m_ref (LUA_NOREF)
{
Stack <T>::push (m_L, v);
m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
}
//----------------------------------------------------------------------------
/**
Create a reference to a table value.
*/
LuaRef (Proxy const& v)
: LuaRefBase (v.state ())
, m_ref (v.createRef ())
{
}
//----------------------------------------------------------------------------
/**
Create a new reference to an existing reference.
*/
LuaRef (LuaRef const& other)
: LuaRefBase (other.m_L)
, m_ref (other.createRef ())
{
}
//----------------------------------------------------------------------------
/**
Destroy a reference.
The corresponding Lua registry reference will be released.
@note If the state refers to a thread, it is the responsibility of the
caller to ensure that the thread still exists when the LuaRef
is destroyed.
*/
~LuaRef ()
{
luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
}
//----------------------------------------------------------------------------
/**
Return a LuaRef from a top stack item.
The stack item is not popped.
*/
static LuaRef fromStack (lua_State* L)
{
return LuaRef (L, FromStack ());
}
//----------------------------------------------------------------------------
/**
Return a LuaRef from a stack item.
The stack item is not popped.
*/
static LuaRef fromStack (lua_State* L, int index)
{
lua_pushvalue (L, index);
return LuaRef (L, FromStack ());
}
//----------------------------------------------------------------------------
/**
Create a new empty table and return a reference to it.
It is also possible to use the free function `newTable`.
@see ::luabridge::newTable
*/
static LuaRef newTable (lua_State* L)
{
lua_newtable (L);
return LuaRef (L, FromStack ());
}
//----------------------------------------------------------------------------
/**
Return a reference to a named global.
It is also possible to use the free function `getGlobal`.
@see ::luabridge::getGlobal
*/
static LuaRef getGlobal (lua_State *L, char const* name)
{
lua_getglobal (L, name);
return LuaRef (L, FromStack ());
}
//----------------------------------------------------------------------------
/**
Assign another LuaRef to this LuaRef.
*/
LuaRef& operator= (LuaRef const& rhs)
{
LuaRef ref (rhs);
swap (ref);
return *this;
}
//----------------------------------------------------------------------------
/**
Assign Proxy to this LuaRef.
*/
LuaRef& operator= (LuaRef::Proxy const& rhs)
{
LuaRef ref (rhs);
swap (ref);
return *this;
}
//----------------------------------------------------------------------------
/**
Assign nil to this LuaRef.
*/
LuaRef& operator= (Nil const&)
{
LuaRef ref (m_L);
swap (ref);
return *this;
}
//----------------------------------------------------------------------------
/**
Assign a different value to this LuaRef.
*/
template <class T>
LuaRef& operator= (T rhs)
{
LuaRef ref (m_L, rhs);
swap (ref);
return *this;
}
//----------------------------------------------------------------------------
/**
Place the object onto the Lua stack.
*/
using LuaRefBase::push;
void push () const
{
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_ref);
}
//----------------------------------------------------------------------------
/**
Pop the top of Lua stack and assign the ref to m_ref
*/
void pop ()
{
luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
}
//----------------------------------------------------------------------------
/**
Access a table value using a key.
This invokes metamethods.
*/
template <class T>
Proxy operator[] (T key) const
{
Stack <T>::push (m_L, key);
return Proxy (m_L, m_ref);
}
//--------------------------------------------------------------------------
/**
Access a table value using a key.
The operation is raw, metamethods are not invoked. The result is
passed by value and may not be modified.
*/
template <class T>
LuaRef rawget (T key) const
{
StackPop (m_L, 1);
push (m_L);
Stack <T>::push (m_L, key);
lua_rawget (m_L, -2);
return LuaRef (m_L, FromStack ());
}
private:
void swap (LuaRef& other)
{
std::swap (m_L, other.m_L);
std::swap (m_ref, other.m_ref);
}
int m_ref;
};
//------------------------------------------------------------------------------
/**
* Stack specialization for `LuaRef`.
*/
template <>
struct Stack <LuaRef>
{
// The value is const& to prevent a copy construction.
//
static void push (lua_State* L, LuaRef const& v)
{
v.push (L);
}
static LuaRef get (lua_State* L, int index)
{
return LuaRef::fromStack (L, index);
}
};
//------------------------------------------------------------------------------
/**
* Stack specialization for `Proxy`.
*/
template <>
struct Stack <LuaRef::Proxy>
{
// The value is const& to prevent a copy construction.
//
static void push (lua_State* L, LuaRef::Proxy const& v)
{
v.push (L);
}
};
//------------------------------------------------------------------------------
/**
Create a reference to a new, empty table.
This is a syntactic abbreviation for LuaRef::newTable ().
*/
inline LuaRef newTable (lua_State* L)
{
return LuaRef::newTable (L);
}
//------------------------------------------------------------------------------
/**
Create a reference to a value in the global table.
This is a syntactic abbreviation for LuaRef::getGlobal ().
*/
inline LuaRef getGlobal (lua_State *L, char const* name)
{
return LuaRef::getGlobal (L, name);
}
//------------------------------------------------------------------------------
// more C++-like cast syntax
//
template <class T>
T LuaRef_cast (LuaRef const& lr)
{
return lr.cast <T> ();
}
} // namespace luabridge

View File

@@ -0,0 +1,1252 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/Config.h>
#include <LuaBridge/detail/ClassInfo.h>
#include <LuaBridge/detail/LuaException.h>
#include <LuaBridge/detail/Security.h>
#include <LuaBridge/detail/TypeTraits.h>
#include <stdexcept>
#include <string>
namespace luabridge {
namespace detail {
/**
* Base for class and namespace registration.
* Maintains Lua stack in the proper state.
* Once beginNamespace, beginClass or deriveClass is called the parent
* object upon its destruction may no longer clear the Lua stack.
* Then endNamespace or endClass is called, a new parent is created
* and the child transfers the responsibility for clearing stack to it.
* So there can be maximum one "active" registrar object.
*/
class Registrar
{
protected:
lua_State* const L;
int mutable m_stackSize;
Registrar (lua_State* L)
: L (L)
, m_stackSize (0)
{
}
Registrar (const Registrar& rhs)
: L (rhs.L)
, m_stackSize (rhs.m_stackSize)
{
rhs.m_stackSize = 0;
}
#ifndef _MSC_VER
// MS compiler thinks it's the 2nd copy ctor
Registrar(Registrar& rhs)
: L (rhs.L)
, m_stackSize (rhs.m_stackSize)
{
rhs.m_stackSize = 0;
}
#endif // ifndef _MSC_VER
Registrar& operator= (const Registrar& rhs)
{
Registrar tmp (rhs);
std::swap (m_stackSize, tmp.m_stackSize);
return *this;
}
~Registrar ()
{
if (m_stackSize > 0)
{
assert (m_stackSize <= lua_gettop (L));
lua_pop (L, m_stackSize);
}
}
void assertIsActive () const
{
if (m_stackSize == 0)
{
throw std::logic_error ("Unable to continue registration");
}
}
};
} // namespace detail
/** Provides C++ to Lua registration capabilities.
This class is not instantiated directly, call `getGlobalNamespace` to start
the registration process.
*/
class Namespace : public detail::Registrar
{
//============================================================================
/**
Error reporting.
VF: This function looks handy, why aren't we using it?
*/
#if 0
static int luaError (lua_State* L, std::string message)
{
assert (lua_isstring (L, lua_upvalueindex (1)));
std::string s;
// Get information on the caller's caller to format the message,
// so the error appears to originate from the Lua source.
lua_Debug ar;
int result = lua_getstack (L, 2, &ar);
if (result != 0)
{
lua_getinfo (L, "Sl", &ar);
s = ar.short_src;
if (ar.currentline != -1)
{
// poor mans int to string to avoid <strstrream>.
lua_pushnumber (L, ar.currentline);
s = s + ":" + lua_tostring (L, -1) + ": ";
lua_pop (L, 1);
}
}
s = s + message;
return luaL_error (L, s.c_str ());
}
#endif
/**
Factored base to reduce template instantiations.
*/
class ClassBase : public detail::Registrar
{
public:
explicit ClassBase (Namespace& parent)
: Registrar (parent)
{
}
using Registrar::operator=;
protected:
//--------------------------------------------------------------------------
/**
Create the const table.
*/
void createConstTable (const char* name, bool trueConst = true)
{
std::string type_name = std::string (trueConst ? "const " : "") + name;
// Stack: namespace table (ns)
lua_newtable (L); // Stack: ns, const table (co)
lua_pushvalue (L, -1); // Stack: ns, co, co
lua_setmetatable (L, -2); // co.__metatable = co. Stack: ns, co
lua_pushstring (L, type_name.c_str ());
lua_rawsetp (L, -2, getTypeKey ()); // co [typeKey] = name. Stack: ns, co
lua_pushcfunction (L, &CFunc::indexMetaMethod);
rawsetfield (L, -2, "__index");
lua_pushcfunction (L, &CFunc::newindexObjectMetaMethod);
rawsetfield (L, -2, "__newindex");
lua_newtable (L);
lua_rawsetp (L, -2, getPropgetKey ());
if (Security::hideMetatables ())
{
lua_pushnil (L);
rawsetfield (L, -2, "__metatable");
}
}
//--------------------------------------------------------------------------
/**
Create the class table.
The Lua stack should have the const table on top.
*/
void createClassTable (char const* name)
{
// Stack: namespace table (ns), const table (co)
// Class table is the same as const table except the propset table
createConstTable (name, false); // Stack: ns, co, cl
lua_newtable (L); // Stack: ns, co, cl, propset table (ps)
lua_rawsetp (L, -2, getPropsetKey ()); // cl [propsetKey] = ps. Stack: ns, co, cl
lua_pushvalue (L, -2); // Stack: ns, co, cl, co
lua_rawsetp(L, -2, getConstKey ()); // cl [constKey] = co. Stack: ns, co, cl
lua_pushvalue (L, -1); // Stack: ns, co, cl, cl
lua_rawsetp (L, -3, getClassKey ()); // co [classKey] = cl. Stack: ns, co, cl
}
//--------------------------------------------------------------------------
/**
Create the static table.
*/
void createStaticTable (char const* name)
{
// Stack: namespace table (ns), const table (co), class table (cl)
lua_newtable (L); // Stack: ns, co, cl, visible static table (vst)
lua_newtable (L); // Stack: ns, co, cl, st, static metatable (st)
lua_pushvalue (L, -1); // Stack: ns, co, cl, vst, st, st
lua_setmetatable (L, -3); // st.__metatable = mt. Stack: ns, co, cl, vst, st
lua_insert (L, -2); // Stack: ns, co, cl, st, vst
rawsetfield (L, -5, name); // ns [name] = vst. Stack: ns, co, cl, st
#if 0
lua_pushlightuserdata (L, this);
lua_pushcclosure (L, &tostringMetaMethod, 1);
rawsetfield (L, -2, "__tostring");
#endif
lua_pushcfunction (L, &CFunc::indexMetaMethod);
rawsetfield (L, -2, "__index");
lua_pushcfunction (L, &CFunc::newindexStaticMetaMethod);
rawsetfield (L, -2, "__newindex");
lua_newtable (L); // Stack: ns, co, cl, st, proget table (pg)
lua_rawsetp (L, -2, getPropgetKey ()); // st [propgetKey] = pg. Stack: ns, co, cl, st
lua_newtable (L); // Stack: ns, co, cl, st, propset table (ps)
lua_rawsetp (L, -2, getPropsetKey ()); // st [propsetKey] = pg. Stack: ns, co, cl, st
lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl
lua_rawsetp(L, -2, getClassKey()); // st [classKey] = cl. Stack: ns, co, cl, st
if (Security::hideMetatables ())
{
lua_pushnil (L);
rawsetfield (L, -2, "__metatable");
}
}
//==========================================================================
/**
lua_CFunction to construct a class object wrapped in a container.
*/
template <class Params, class C>
static int ctorContainerProxy (lua_State* L)
{
typedef typename ContainerTraits <C>::Type T;
ArgList <Params, 2> args (L);
T* const p = Constructor <T, Params>::call (args);
UserdataSharedHelper <C, false>::push (L, p);
return 1;
}
//--------------------------------------------------------------------------
/**
lua_CFunction to construct a class object in-place in the userdata.
*/
template <class Params, class T>
static int ctorPlacementProxy (lua_State* L)
{
ArgList <Params, 2> args (L);
UserdataValue <T>* value = UserdataValue <T>::place (L);
Constructor <T, Params>::call (value->getObject (), args);
value->commit ();
return 1;
}
void assertStackState () const
{
// Stack: const table (co), class table (cl), static table (st)
assert (lua_istable (L, -3));
assert (lua_istable (L, -2));
assert (lua_istable (L, -1));
}
};
//============================================================================
//
// Class
//
//============================================================================
/**
Provides a class registration in a lua_State.
After construction the Lua stack holds these objects:
-1 static table
-2 class table
-3 const table
-4 enclosing namespace table
*/
template <class T>
class Class : public ClassBase
{
public:
//==========================================================================
/**
Register a new class or add to an existing class registration.
*/
Class (char const* name, Namespace& parent)
: ClassBase (parent)
{
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
rawgetfield (L, -1, name); // Stack: ns, static table (st) | nil
if (lua_isnil (L, -1)) // Stack: ns, nil
{
lua_pop (L, 1); // Stack: ns
createConstTable (name); // Stack: ns, const table (co)
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, function
rawsetfield (L, -2, "__gc"); // co ["__gc"] = function. Stack: ns, co
++m_stackSize;
createClassTable (name); // Stack: ns, co, class table (cl)
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, cl, function
rawsetfield (L, -2, "__gc"); // cl ["__gc"] = function. Stack: ns, co, cl
++m_stackSize;
createStaticTable (name); // Stack: ns, co, cl, st
++m_stackSize;
// Map T back to its tables.
lua_pushvalue (L, -1); // Stack: ns, co, cl, st, st
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ()); // Stack: ns, co, cl, st
lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); // Stack: ns, co, cl, st
lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); // Stack: ns, co, cl, st
}
else
{
assert (lua_istable (L, -1)); // Stack: ns, st
++m_stackSize;
// Map T back from its stored tables
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); // Stack: ns, st, co
lua_insert (L, -2); // Stack: ns, co, st
++m_stackSize;
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); // Stack: ns, co, st, cl
lua_insert (L, -2); // Stack: ns, co, cl, st
++m_stackSize;
}
}
//==========================================================================
/**
Derive a new class.
*/
Class (char const* name, Namespace& parent, void const* const staticKey)
: ClassBase (parent)
{
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
createConstTable (name); // Stack: ns, const table (co)
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, function
rawsetfield (L, -2, "__gc"); // co ["__gc"] = function. Stack: ns, co
++m_stackSize;
createClassTable (name); // Stack: ns, co, class table (cl)
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, cl, function
rawsetfield (L, -2, "__gc"); // cl ["__gc"] = function. Stack: ns, co, cl
++m_stackSize;
createStaticTable (name); // Stack: ns, co, cl, st
++m_stackSize;
lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey); // Stack: ns, co, cl, st, parent st (pst) | nil
if (lua_isnil (L, -1)) // Stack: ns, co, cl, st, nil
{
++m_stackSize;
throw std::runtime_error ("Base class is not registered");
}
assert (lua_istable (L, -1)); // Stack: ns, co, cl, st, pst
lua_rawgetp (L, -1, getClassKey ()); // Stack: ns, co, cl, st, pst, parent cl (pcl)
assert (lua_istable (L, -1));
lua_rawgetp (L, -1, getConstKey ()); // Stack: ns, co, cl, st, pst, pcl, parent co (pco)
assert (lua_istable (L, -1));
lua_rawsetp (L, -6, getParentKey ()); // co [parentKey] = pco. Stack: ns, co, cl, st, pst, pcl
lua_rawsetp (L, -4, getParentKey ()); // cl [parentKey] = pcl. Stack: ns, co, cl, st, pst
lua_rawsetp (L, -2, getParentKey ()); // st [parentKey] = pst. Stack: ns, co, cl, st
lua_pushvalue (L, -1); // Stack: ns, co, cl, st, st
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ()); // Stack: ns, co, cl, st
lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); // Stack: ns, co, cl, st
lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); // Stack: ns, co, cl, st
}
//--------------------------------------------------------------------------
/**
Continue registration in the enclosing namespace.
*/
Namespace endClass ()
{
assert (m_stackSize > 3);
m_stackSize -= 3;
lua_pop (L, 3);
return Namespace (*this);
}
//--------------------------------------------------------------------------
/**
Add or replace a static data member.
*/
template <class U>
Class <T>& addStaticProperty (char const* name, U* pu, bool isWritable = true)
{
return addStaticData (name, pu, isWritable);
}
//--------------------------------------------------------------------------
/**
Add or replace a static data member.
*/
template <class U>
Class <T>& addStaticData (char const* name, U* pu, bool isWritable = true)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushlightuserdata (L, pu); // Stack: co, cl, st, pointer
lua_pushcclosure (L, &CFunc::getVariable <U>, 1); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -2); // Stack: co, cl, st
if (isWritable)
{
lua_pushlightuserdata (L, pu); // Stack: co, cl, st, ps, pointer
lua_pushcclosure (L, &CFunc::setVariable <U>, 1); // Stack: co, cl, st, ps, setter
}
else
{
lua_pushstring (L, name); // Stack: co, cl, st, name
lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: co, cl, st, error_fn
}
CFunc::addSetter (L, name, -2); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a static property member.
If the set function is null, the property is read-only.
*/
template <class U>
Class <T>& addStaticProperty (char const* name, U (*get) (), void (*set) (U) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushlightuserdata (L, reinterpret_cast <void*> (get)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <U (*) ()>::f, 1); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -2); // Stack: co, cl, st
if (set != 0)
{
lua_pushlightuserdata (L, reinterpret_cast <void*> (set)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <void (*) (U)>::f, 1); // Stack: co, cl, st, setter
}
else
{
lua_pushstring (L, name); // Stack: co, cl, st, ps, name
lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: co, cl, st, error_fn
}
CFunc::addSetter (L, name, -2); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a static member function.
*/
template <class FP>
Class <T>& addStaticFunction (char const* name, FP const fp)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushlightuserdata (L, reinterpret_cast <void*> (fp)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <FP>::f, 1); // co, cl, st, function
rawsetfield (L, -2, name); // co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a lua_CFunction.
*/
Class <T>& addStaticFunction (char const* name, int (*const fp) (lua_State*))
{
return addStaticCFunction (name, fp);
}
//--------------------------------------------------------------------------
/**
Add or replace a lua_CFunction.
*/
Class <T>& addStaticCFunction (char const* name, int (*const fp) (lua_State*))
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushcfunction (L, fp); // co, cl, st, function
rawsetfield (L, -2, name); // co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a data member.
*/
template <class U>
Class <T>& addProperty (char const* name, U T::* mp, bool isWritable = true)
{
return addData (name, mp, isWritable);
}
//--------------------------------------------------------------------------
/**
Add or replace a data member.
*/
template <class U>
Class <T>& addData (char const* name, U T::* mp, bool isWritable = true)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef const U T::*mp_t;
new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); // Stack: co, cl, st, field ptr
lua_pushcclosure (L, &CFunc::getProperty <T, U>, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st
if (isWritable)
{
new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); // Stack: co, cl, st, field ptr
lua_pushcclosure (L, &CFunc::setProperty <T, U>, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a property member.
*/
template <class TG, class TS = TG>
Class <T>& addProperty (char const* name, TG (T::* get) () const, void (T::* set) (TS) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef TG (T::*get_t) () const;
new (lua_newuserdata (L, sizeof (get_t))) get_t (get); // Stack: co, cl, st, funcion ptr
lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st
if (set != 0)
{
typedef void (T::* set_t) (TS);
new (lua_newuserdata (L, sizeof (set_t))) set_t (set); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a property member.
*/
template <class TG, class TS = TG>
Class <T>& addProperty (char const* name, TG (T::* get) (lua_State*) const, void (T::* set) (TS, lua_State*) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef TG (T::*get_t) (lua_State*) const;
new (lua_newuserdata (L, sizeof (get_t))) get_t (get); // Stack: co, cl, st, funcion ptr
lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st
if (set != 0)
{
typedef void (T::* set_t) (TS, lua_State*);
new (lua_newuserdata (L, sizeof (set_t))) set_t (set); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a property member, by proxy.
When a class is closed for modification and does not provide (or cannot
provide) the function signatures necessary to implement get or set for
a property, this will allow non-member functions act as proxies.
Both the get and the set functions require a T const* and T* in the first
argument respectively.
*/
template <class TG, class TS = TG>
Class <T>& addProperty (char const* name, TG (*get) (T const*), void (*set) (T*, TS) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushlightuserdata (L, reinterpret_cast <void*> (get)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <TG (*) (const T*)>::f, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st,, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st
if (set != 0)
{
lua_pushlightuserdata (L, reinterpret_cast <void*> (set)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <void (*) (T*, TS)>::f, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a property member, by proxy C-function.
When a class is closed for modification and does not provide (or cannot
provide) the function signatures necessary to implement get or set for
a property, this will allow non-member functions act as proxies.
The object userdata ('this') value is at the index 1.
The new value for set function is at the index 2.
*/
Class <T>& addProperty (char const* name, int (*get) (lua_State*), int (*set) (lua_State*) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushcfunction (L, get);
lua_pushvalue (L, -1); // Stack: co, cl, st,, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st,, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st,
if (set != 0)
{
lua_pushcfunction (L, set);
CFunc::addSetter (L, name, -3); // Stack: co, cl, st,
}
return *this;
}
#ifdef LUABRIDGE_CXX11
template <class TG, class TS = TG>
Class <T>& addProperty (char const* name,
std::function <TG (const T*)> get,
std::function <void (T*, TS)> set = nullptr)
{
using GetType = decltype (get);
new (lua_newuserdata (L, sizeof (get))) GetType (std::move (get)); // Stack: co, cl, st, function userdata (ud)
lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
lua_pushcfunction (L, &CFunc::gcMetaMethodAny <GetType>); // Stack: co, cl, st, ud, mt, gc function
rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
lua_setmetatable (L, -2); // Stack: co, cl, st, ud
lua_pushcclosure (L, &CFunc::CallProxyFunctor <GetType>::f, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
CFunc::addGetter (L, name, -4); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -4); // Stack: co, cl, st
if (set != nullptr)
{
using SetType = decltype (set);
new (lua_newuserdata (L, sizeof (set))) SetType (std::move (set)); // Stack: co, cl, st, function userdata (ud)
lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
lua_pushcfunction (L, &CFunc::gcMetaMethodAny <SetType>); // Stack: co, cl, st, ud, mt, gc function
rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
lua_setmetatable (L, -2); // Stack: co, cl, st, ud
lua_pushcclosure (L, &CFunc::CallProxyFunctor <SetType>::f, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
#endif // LUABRIDGE_CXX11
#ifndef LUABRIDGE_CXX11
//--------------------------------------------------------------------------
/**
Add or replace a member function.
*/
template <class MemFn>
Class <T>& addFunction (char const* name, MemFn mf)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
return *this;
}
#else // ifndef LUABRIDGE_CXX11
//--------------------------------------------------------------------------
/**
Add or replace a member function by std::function.
*/
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, std::function <ReturnType (T*, Params...)> function)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
using FnType = decltype (function);
new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: co, cl, st, function userdata (ud)
lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
lua_pushcfunction (L, &CFunc::gcMetaMethodAny <FnType>); // Stack: co, cl, st, ud, mt, gc function
rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
lua_setmetatable (L, -2); // Stack: co, cl, st, ud
lua_pushcclosure (L, &CFunc::CallProxyFunctor <FnType>::f, 1); // Stack: co, cl, st, function
rawsetfield (L, -3, name); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a const member function by std::function.
*/
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, std::function <ReturnType (const T*, Params...)> function)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
using FnType = decltype (function);
new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: co, cl, st, function userdata (ud)
lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
lua_pushcfunction (L, &CFunc::gcMetaMethodAny <FnType>); // Stack: co, cl, st, ud, mt, gc function
rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
lua_setmetatable (L, -2); // Stack: co, cl, st, ud
lua_pushcclosure (L, &CFunc::CallProxyFunctor <FnType>::f, 1); // Stack: co, cl, st, function
lua_pushvalue (L, -1); // Stack: co, cl, st, function, function
rawsetfield (L, -4, name); // Stack: co, cl, st, function
rawsetfield (L, -4, name); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a member function.
*/
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, ReturnType (T::* mf) (Params...))
{
using MemFn = ReturnType (T::*) (Params...);
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
CFunc::CallMemberFunctionHelper <MemFn, false>::add (L, name, mf);
return *this;
}
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, ReturnType (T::* mf) (Params...) const)
{
using MemFn = ReturnType (T::*) (Params...) const;
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
CFunc::CallMemberFunctionHelper <MemFn, true>::add (L, name, mf);
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a proxy function.
*/
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, ReturnType (*proxyFn) (T* object, Params...))
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
using FnType = decltype (proxyFn);
lua_pushlightuserdata (L, reinterpret_cast <void*> (proxyFn)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallProxyFunction <FnType>::f, 1); // Stack: co, cl, st, function
rawsetfield (L, -3, name); // Stack: co, cl, st
return *this;
}
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, ReturnType (*proxyFn) (const T* object, Params...))
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
using FnType = decltype (proxyFn);
lua_pushlightuserdata (L, reinterpret_cast <void*> (proxyFn)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallProxyFunction <FnType>::f, 1); // Stack: co, cl, st, function
lua_pushvalue (L, -1); // Stack: co, cl, st, function, function
rawsetfield (L, -4, name); // Stack: co, cl, st, function
rawsetfield (L, -4, name); // Stack: co, cl, st
return *this;
}
#endif
//--------------------------------------------------------------------------
/**
Add or replace a member lua_CFunction.
*/
Class <T>& addFunction (char const* name, int (T::*mfp) (lua_State*))
{
return addCFunction (name, mfp);
}
//--------------------------------------------------------------------------
/**
Add or replace a member lua_CFunction.
*/
Class <T>& addCFunction (char const* name, int (T::*mfp) (lua_State*))
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef int (T::*MFP) (lua_State*);
new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallMemberCFunction <T>::f, 1); // Stack: co, cl, st, function
rawsetfield (L, -3, name); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a const member lua_CFunction.
*/
Class <T>& addFunction (char const* name, int (T::*mfp) (lua_State*) const)
{
return addCFunction (name, mfp);
}
//--------------------------------------------------------------------------
/**
Add or replace a const member lua_CFunction.
*/
Class <T>& addCFunction (char const* name, int (T::*mfp) (lua_State*) const)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef int (T::*MFP) (lua_State*) const;
new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
lua_pushcclosure (L, &CFunc::CallConstMemberCFunction <T>::f, 1);
lua_pushvalue (L, -1); // Stack: co, cl, st, function, function
rawsetfield (L, -4, name); // Stack: co, cl, st, function
rawsetfield (L, -4, name); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a primary Constructor.
The primary Constructor is invoked when calling the class type table
like a function.
The template parameter should be a function pointer type that matches
the desired Constructor (since you can't take the address of a Constructor
and pass it as an argument).
*/
template <class MemFn, class C>
Class <T>& addConstructor ()
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushcclosure (L, &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0);
rawsetfield (L, -2, "__call");
return *this;
}
template <class MemFn>
Class <T>& addConstructor ()
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushcclosure (L, &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0);
rawsetfield (L, -2, "__call");
return *this;
}
};
private:
//----------------------------------------------------------------------------
/**
Open the global namespace for registrations.
*/
explicit Namespace (lua_State* L)
: Registrar (L)
{
lua_getglobal (L, "_G");
++m_stackSize;
}
//----------------------------------------------------------------------------
/**
Open a namespace for registrations.
The namespace is created if it doesn't already exist.
The parent namespace is at the top of the Lua stack.
*/
Namespace (char const* name, Namespace& parent)
: Registrar (parent)
{
assert (lua_istable (L, -1)); // Stack: parent namespace (pns)
rawgetfield (L, -1, name); // Stack: pns, namespace (ns) | nil
if (lua_isnil (L, -1)) // Stack: pns, nil
{
lua_pop (L, 1); // Stack: pns
lua_newtable (L); // Stack: pns, ns
lua_pushvalue (L, -1); // Stack: pns, ns, ns
// na.__metatable = ns
lua_setmetatable (L, -2); // Stack: pns, ns
// ns.__index = indexMetaMethod
lua_pushcfunction (L, &CFunc::indexMetaMethod);
rawsetfield (L, -2, "__index"); // Stack: pns, ns
// ns.__newindex = newindexMetaMethod
lua_pushcfunction (L, &CFunc::newindexStaticMetaMethod);
rawsetfield (L, -2, "__newindex"); // Stack: pns, ns
lua_newtable (L); // Stack: pns, ns, propget table (pg)
lua_rawsetp (L, -2, getPropgetKey ()); // ns [propgetKey] = pg. Stack: pns, ns
lua_newtable (L); // Stack: pns, ns, propset table (ps)
lua_rawsetp (L, -2, getPropsetKey ()); // ns [propsetKey] = ps. Stack: pns, ns
// pns [name] = ns
lua_pushvalue (L, -1); // Stack: pns, ns, ns
rawsetfield (L, -3, name); // Stack: pns, ns
#if 0
lua_pushcfunction (L, &tostringMetaMethod);
rawsetfield (L, -2, "__tostring");
#endif
}
++m_stackSize;
}
//----------------------------------------------------------------------------
/**
Close the class and continue the namespace registrations.
*/
explicit Namespace (ClassBase& child)
: Registrar (child)
{
}
using Registrar::operator=;
public:
//----------------------------------------------------------------------------
/**
Open the global namespace.
*/
static Namespace getGlobalNamespace (lua_State* L)
{
enableExceptions (L);
return Namespace (L);
}
//----------------------------------------------------------------------------
/**
Open a new or existing namespace for registrations.
*/
Namespace beginNamespace (char const* name)
{
assertIsActive ();
return Namespace (name, *this);
}
//----------------------------------------------------------------------------
/**
Continue namespace registration in the parent.
Do not use this on the global namespace.
*/
Namespace endNamespace ()
{
if (m_stackSize == 1)
{
throw std::logic_error ("endNamespace () called on global namespace");
}
assert (m_stackSize > 1);
--m_stackSize;
lua_pop (L, 1);
return Namespace (*this);
}
//----------------------------------------------------------------------------
/**
Add or replace a variable.
*/
template <class T>
Namespace& addProperty (char const* name, T* pt, bool isWritable = true)
{
return addVariable (name, pt, isWritable);
}
//----------------------------------------------------------------------------
/**
Add or replace a variable.
*/
template <class T>
Namespace& addVariable (char const* name, T* pt, bool isWritable = true)
{
if (m_stackSize == 1)
{
throw std::logic_error ("addProperty () called on global namespace");
}
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushlightuserdata (L, pt); // Stack: ns, pointer
lua_pushcclosure (L, &CFunc::getVariable <T>, 1); // Stack: ns, getter
CFunc::addGetter (L, name, -2); // Stack: ns
if (isWritable)
{
lua_pushlightuserdata (L, pt); // Stack: ns, pointer
lua_pushcclosure (L, &CFunc::setVariable <T>, 1); // Stack: ns, setter
}
else
{
lua_pushstring (L, name); // Stack: ns, ps, name
lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: ns, error_fn
}
CFunc::addSetter (L, name, -2); // Stack: ns
return *this;
}
//----------------------------------------------------------------------------
/**
Add or replace a property.
If the set function is omitted or null, the property is read-only.
*/
template <class TG, class TS = TG>
Namespace& addProperty (char const* name, TG (*get) (), void (*set) (TS) = 0)
{
if (m_stackSize == 1)
{
throw std::logic_error ("addProperty () called on global namespace");
}
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushlightuserdata (L, reinterpret_cast <void*> (get)); // Stack: ns, function ptr
lua_pushcclosure (L, &CFunc::Call <TG (*) ()>::f, 1); // Stack: ns, getter
CFunc::addGetter (L, name, -2);
if (set != 0)
{
lua_pushlightuserdata(L, reinterpret_cast <void*> (set)); // Stack: ns, function ptr
lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1);
}
else
{
lua_pushstring (L, name);
lua_pushcclosure (L, &CFunc::readOnlyError, 1);
}
CFunc::addSetter (L, name, -2);
return *this;
}
//----------------------------------------------------------------------------
/**
Add or replace a property.
If the set function is omitted or null, the property is read-only.
*/
Namespace& addProperty (char const* name, int (*get) (lua_State*), int (*set) (lua_State*) = 0)
{
if (m_stackSize == 1)
{
throw std::logic_error ("addProperty () called on global namespace");
}
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushcfunction (L, get); // Stack: ns, getter
CFunc::addGetter (L, name, -2); // Stack: ns
if (set != 0)
{
lua_pushcfunction(L, set); // Stack: ns, setter
CFunc::addSetter(L, name, -2); // Stack: ns
}
else
{
lua_pushstring(L, name); // Stack: ns, name
lua_pushcclosure(L, &CFunc::readOnlyError, 1); // Stack: ns, name, readOnlyError
CFunc::addSetter(L, name, -2); // Stack: ns
}
return *this;
}
//----------------------------------------------------------------------------
/**
Add or replace a free function.
*/
template <class FP>
Namespace& addFunction (char const* name, FP const fp)
{
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushlightuserdata (L, reinterpret_cast <void*> (fp)); // Stack: ns, function ptr
lua_pushcclosure (L, &CFunc::Call <FP>::f, 1); // Stack: ns, function
rawsetfield (L, -2, name); // Stack: ns
return *this;
}
//----------------------------------------------------------------------------
/**
Add or replace a lua_CFunction.
*/
Namespace& addFunction (char const* name, int (*const fp) (lua_State*))
{
return addCFunction (name, fp);
}
//----------------------------------------------------------------------------
/**
Add or replace a lua_CFunction.
*/
Namespace& addCFunction (char const* name, int (*const fp) (lua_State*))
{
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushcfunction (L, fp); // Stack: ns, function
rawsetfield (L, -2, name); // Stack: ns
return *this;
}
//----------------------------------------------------------------------------
/**
Open a new or existing class for registrations.
*/
template <class T>
Class <T> beginClass (char const* name)
{
assertIsActive ();
return Class <T> (name, *this);
}
//----------------------------------------------------------------------------
/**
Derive a new class for registrations.
To continue registrations for the class later, use beginClass ().
Do not call deriveClass () again.
*/
template <class Derived, class Base>
Class <Derived> deriveClass (char const* name)
{
assertIsActive ();
return Class <Derived> (name, *this, ClassInfo <Base>::getStaticKey ());
}
};
//------------------------------------------------------------------------------
/**
Retrieve the global namespace.
It is recommended to put your namespace inside the global namespace, and
then add your classes and functions to it, rather than adding many classes
and functions directly to the global namespace.
*/
inline Namespace getGlobalNamespace (lua_State* L)
{
return Namespace::getGlobalNamespace (L);
}
} // namespace luabridge

View File

@@ -0,0 +1,62 @@
#pragma once
namespace luabridge {
//------------------------------------------------------------------------------
/**
security options.
*/
class Security
{
public:
static bool hideMetatables()
{
return getSettings().hideMetatables;
}
static void setHideMetatables(bool shouldHide)
{
getSettings().hideMetatables = shouldHide;
}
private:
struct Settings
{
Settings() : hideMetatables(true)
{
}
bool hideMetatables;
};
static Settings& getSettings()
{
static Settings settings;
return settings;
}
};
//------------------------------------------------------------------------------
/**
Set a global value in the lua_State.
@note This works on any type specialized by `Stack`, including `LuaRef` and
its table proxies.
*/
template <class T>
inline void setGlobal(lua_State* L, T t, char const* name)
{
push(L, t);
lua_setglobal(L, name);
}
//------------------------------------------------------------------------------
/**
Change whether or not metatables are hidden (on by default).
*/
inline void setHideMetatables(bool shouldHide)
{
Security::setHideMetatables(shouldHide);
}
} // namespace luabridge

View File

@@ -0,0 +1,622 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/LuaHelpers.h>
#include <LuaBridge/detail/Userdata.h>
#include <string>
namespace luabridge {
template <class T>
struct Stack;
template <>
struct Stack <void>
{
static void push (lua_State* L)
{
}
};
//------------------------------------------------------------------------------
/**
Receive the lua_State* as an argument.
*/
template <>
struct Stack <lua_State*>
{
static lua_State* get (lua_State* L, int)
{
return L;
}
};
//------------------------------------------------------------------------------
/**
Push a lua_CFunction.
*/
template <>
struct Stack <lua_CFunction>
{
static void push (lua_State* L, lua_CFunction f)
{
lua_pushcfunction (L, f);
}
static lua_CFunction get (lua_State* L, int index)
{
return lua_tocfunction (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return lua_iscfunction (L, index);
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `int`.
*/
template <>
struct Stack <int>
{
static void push (lua_State* L, int value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static int get (lua_State* L, int index)
{
return static_cast <int> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `unsigned int`.
*/
template <>
struct Stack <unsigned int>
{
static void push (lua_State* L, unsigned int value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned int get (lua_State* L, int index)
{
return static_cast <unsigned int> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `unsigned char`.
*/
template <>
struct Stack <unsigned char>
{
static void push (lua_State* L, unsigned char value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned char get (lua_State* L, int index)
{
return static_cast <unsigned char> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `short`.
*/
template <>
struct Stack <short>
{
static void push (lua_State* L, short value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static short get (lua_State* L, int index)
{
return static_cast <short> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `unsigned short`.
*/
template <>
struct Stack <unsigned short>
{
static void push (lua_State* L, unsigned short value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned short get (lua_State* L, int index)
{
return static_cast <unsigned short> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `long`.
*/
template <>
struct Stack <long>
{
static void push (lua_State* L, long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static long get (lua_State* L, int index)
{
return static_cast <long> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `unsigned long`.
*/
template <>
struct Stack <unsigned long>
{
static void push (lua_State* L, unsigned long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned long get (lua_State* L, int index)
{
return static_cast <unsigned long> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
* Stack specialization for `long long`.
*/
template <>
struct Stack <long long>
{
static void push (lua_State* L, long long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static long long get (lua_State* L, int index)
{
return static_cast <long long> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
* Stack specialization for `unsigned long long`.
*/
template <>
struct Stack <unsigned long long>
{
static void push (lua_State* L, unsigned long long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned long long get (lua_State* L, int index)
{
return static_cast <unsigned long long> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `float`.
*/
template <>
struct Stack <float>
{
static void push (lua_State* L, float value)
{
lua_pushnumber (L, static_cast <lua_Number> (value));
}
static float get (lua_State* L, int index)
{
return static_cast <float> (luaL_checknumber (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `double`.
*/
template <>
struct Stack <double>
{
static void push (lua_State* L, double value)
{
lua_pushnumber (L, static_cast <lua_Number> (value));
}
static double get (lua_State* L, int index)
{
return static_cast <double> (luaL_checknumber (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `bool`.
*/
template <>
struct Stack <bool>
{
static void push (lua_State* L, bool value)
{
lua_pushboolean (L, value ? 1 : 0);
}
static bool get (lua_State* L, int index)
{
return lua_toboolean (L, index) ? true : false;
}
static bool isInstance (lua_State* L, int index)
{
return lua_isboolean (L, index);
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `char`.
*/
template <>
struct Stack <char>
{
static void push (lua_State* L, char value)
{
lua_pushlstring (L, &value, 1);
}
static char get (lua_State* L, int index)
{
return luaL_checkstring (L, index) [0];
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TSTRING;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `const char*`.
*/
template <>
struct Stack <char const*>
{
static void push (lua_State* L, char const* str)
{
if (str != 0)
lua_pushstring (L, str);
else
lua_pushnil (L);
}
static char const* get (lua_State* L, int index)
{
return lua_isnil (L, index) ? 0 : luaL_checkstring (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return lua_isnil (L, index) || lua_type (L, index) == LUA_TSTRING;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `std::string`.
*/
template <>
struct Stack <std::string>
{
static void push (lua_State* L, std::string const& str)
{
lua_pushlstring (L, str.data (), str.size ());
}
static std::string get (lua_State* L, int index)
{
size_t len;
if (lua_type (L, index) == LUA_TSTRING)
{
const char* str = lua_tolstring (L, index, &len);
return std::string (str, len);
}
// Lua reference manual:
// If the value is a number, then lua_tolstring also changes the actual value in the stack to a string.
// (This change confuses lua_next when lua_tolstring is applied to keys during a table traversal.)
lua_pushvalue (L, index);
const char* str = lua_tolstring(L, -1, &len);
std::string string (str, len);
lua_pop (L, 1); // Pop the temporary string
return string;
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TSTRING;
}
};
template <class T>
struct StackOpSelector <T&, false>
{
typedef T ReturnType;
static void push (lua_State* L, T& value)
{
Stack <T>::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Stack <T>::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
};
template <class T>
struct StackOpSelector <const T&, false>
{
typedef T ReturnType;
static void push (lua_State* L, const T& value)
{
Stack <T>::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Stack <T>::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
};
template <class T>
struct StackOpSelector <T*, false>
{
typedef T ReturnType;
static void push (lua_State* L, T* value)
{
Stack <T>::push (L, *value);
}
static ReturnType get (lua_State* L, int index)
{
return Stack <T>::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
};
template <class T>
struct StackOpSelector <const T*, false>
{
typedef T ReturnType;
static void push (lua_State* L, const T* value)
{
Stack <T>::push (L, *value);
}
static ReturnType get (lua_State* L, int index)
{
return Stack <T>::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
};
template <class T>
struct Stack <T&>
{
typedef StackOpSelector <T&, IsUserdata <T>::value> Helper;
typedef typename Helper::ReturnType ReturnType;
static void push (lua_State* L, T& value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
};
template <class T>
struct Stack <const T&>
{
typedef StackOpSelector <const T&, IsUserdata <T>::value> Helper;
typedef typename Helper::ReturnType ReturnType;
static void push (lua_State* L, const T& value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
};
template <class T>
struct Stack <T*>
{
typedef StackOpSelector <T*, IsUserdata <T>::value> Helper;
typedef typename Helper::ReturnType ReturnType;
static void push (lua_State* L, T* value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
};
template <class T>
struct Stack <const T*>
{
typedef StackOpSelector <const T*, IsUserdata <T>::value> Helper;
typedef typename Helper::ReturnType ReturnType;
static void push (lua_State* L, const T* value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
};
//------------------------------------------------------------------------------
/**
* Push an object onto the Lua stack.
*/
template <class T>
inline void push (lua_State* L, T t)
{
Stack <T>::push (L, t);
}
//------------------------------------------------------------------------------
/**
* Check whether an object on the Lua stack is of type T.
*/
template <class T>
inline bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
} // namespace luabridge

View File

@@ -0,0 +1,218 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This file incorporates work covered by the following copyright and
permission notice:
The Loki Library
Copyright (c) 2001 by Andrei Alexandrescu
This code accompanies the book:
Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
Patterns Applied". Copyright (c) 2001. Addison-Wesley.
Permission to use, copy, modify, distribute and sell this software for any
purpose is hereby granted without fee, provided that the above copyright
notice appear in all copies and that both that copyright notice and this
permission notice appear in supporting documentation.
The author or Addison-Welsey Longman make no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/Config.h>
#include <LuaBridge/detail/Stack.h>
#include <string>
#include <typeinfo>
namespace luabridge {
/**
None type means void parameters or return value.
*/
typedef void None;
template <typename Head, typename Tail = None>
struct TypeList
{
typedef Tail TailType;
};
template <class List>
struct TypeListSize
{
static const size_t value = TypeListSize <typename List::TailType>::value + 1;
};
template <>
struct TypeListSize <None>
{
static const size_t value = 0;
};
#ifdef LUABRIDGE_CXX11
template <class... Params>
struct MakeTypeList;
template <class Param, class... Params>
struct MakeTypeList <Param, Params...>
{
using Result = TypeList <Param, typename MakeTypeList <Params...>::Result>;
};
template <>
struct MakeTypeList <>
{
using Result = None;
};
#endif
/**
A TypeList with actual values.
*/
template <typename List>
struct TypeListValues
{
static std::string const tostring (bool)
{
return "";
}
};
/**
TypeListValues recursive template definition.
*/
template <typename Head, typename Tail>
struct TypeListValues <TypeList <Head, Tail> >
{
Head hd;
TypeListValues <Tail> tl;
TypeListValues (Head hd_, TypeListValues <Tail> const& tl_)
: hd (hd_), tl (tl_)
{
}
static std::string tostring (bool comma = false)
{
std::string s;
if (comma)
s = ", ";
s = s + typeid (Head).name ();
return s + TypeListValues <Tail>::tostring (true);
}
};
// Specializations of type/value list for head types that are references and
// const-references. We need to handle these specially since we can't count
// on the referenced object hanging around for the lifetime of the list.
template <typename Head, typename Tail>
struct TypeListValues <TypeList <Head&, Tail> >
{
Head hd;
TypeListValues <Tail> tl;
TypeListValues (Head& hd_, TypeListValues <Tail> const& tl_)
: hd (hd_), tl (tl_)
{
}
static std::string const tostring (bool comma = false)
{
std::string s;
if (comma)
s = ", ";
s = s + typeid (Head).name () + "&";
return s + TypeListValues <Tail>::tostring (true);
}
};
template <typename Head, typename Tail>
struct TypeListValues <TypeList <Head const&, Tail> >
{
Head hd;
TypeListValues <Tail> tl;
TypeListValues (Head const& hd_, const TypeListValues <Tail>& tl_)
: hd (hd_), tl (tl_)
{
}
static std::string const tostring (bool comma = false)
{
std::string s;
if (comma)
s = ", ";
s = s + typeid (Head).name () + " const&";
return s + TypeListValues <Tail>::tostring (true);
}
};
//==============================================================================
/**
Subclass of a TypeListValues constructable from the Lua stack.
*/
template <typename List, int Start = 1>
struct ArgList
{
};
template <int Start>
struct ArgList <None, Start> : public TypeListValues <None>
{
ArgList (lua_State*)
{
}
};
template <typename Head, typename Tail, int Start>
struct ArgList <TypeList <Head, Tail>, Start>
: public TypeListValues <TypeList <Head, Tail> >
{
ArgList (lua_State* L)
: TypeListValues <TypeList <Head, Tail> > (Stack <Head>::get (L, Start),
ArgList <Tail, Start + 1> (L))
{
}
};
} // namespace luabridge

View File

@@ -0,0 +1,135 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <string>
namespace luabridge {
//------------------------------------------------------------------------------
/**
Container traits.
Unspecialized ContainerTraits has the isNotContainer typedef for SFINAE.
All user defined containers must supply an appropriate specialization for
ContinerTraits (without the typedef isNotContainer). The containers that
come with LuaBridge also come with the appropriate ContainerTraits
specialization. See the corresponding declaration for details.
A specialization of ContainerTraits for some generic type ContainerType
looks like this:
template <class T>
struct ContainerTraits <ContainerType <T> >
{
typedef typename T Type;
static T* get (ContainerType <T> const& c)
{
return c.get (); // Implementation-dependent on ContainerType
}
};
*/
template <class T>
struct ContainerTraits
{
typedef bool isNotContainer;
typedef T Type;
};
//------------------------------------------------------------------------------
/**
Type traits.
Specializations return information about a type.
*/
struct TypeTraits
{
/** Determine if type T is a container.
To be considered a container, there must be a specialization of
ContainerTraits with the required fields.
*/
template <typename T>
class isContainer
{
private:
typedef char yes[1]; // sizeof (yes) == 1
typedef char no [2]; // sizeof (no) == 2
template <typename C>
static no& test (typename C::isNotContainer*);
template <typename>
static yes& test (...);
public:
static const bool value = sizeof (test <ContainerTraits <T> >(0)) == sizeof (yes);
};
/** Determine if T is const qualified.
*/
/** @{ */
template <class T>
struct isConst
{
static bool const value = false;
};
template <class T>
struct isConst <T const>
{
static bool const value = true;
};
/** @} */
/** Remove the const qualifier from T.
*/
/** @{ */
template <class T>
struct removeConst
{
typedef T Type;
};
template <class T>
struct removeConst <T const>
{
typedef T Type;
};
/**@}*/
};
template <class T>
struct Stack;
} // namespace luabridge

View File

@@ -0,0 +1,829 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/ClassInfo.h>
#include <cassert>
#include <stdexcept>
namespace luabridge {
//==============================================================================
/**
Return the identity pointer for our lightuserdata tokens.
Because of Lua's dynamic typing and our improvised system of imposing C++
class structure, there is the possibility that executing scripts may
knowingly or unknowingly cause invalid data to get passed to the C functions
created by LuaBridge. In particular, our security model addresses the
following:
1. Scripts cannot create a userdata (ignoring the debug lib).
2. Scripts cannot create a lightuserdata (ignoring the debug lib).
3. Scripts cannot set the metatable on a userdata.
*/
/**
Interface to a class pointer retrievable from a userdata.
*/
class Userdata
{
protected:
void* m_p; // subclasses must set this
Userdata() : m_p (0)
{
}
//--------------------------------------------------------------------------
/**
Get an untyped pointer to the contained class.
*/
void* getPointer ()
{
return m_p;
}
private:
//--------------------------------------------------------------------------
/**
Validate and retrieve a Userdata on the stack.
The Userdata must exactly match the corresponding class table or
const table, or else a Lua error is raised. This is used for the
__gc metamethod.
*/
static Userdata* getExactClass (lua_State* L, int index, void const* /*classKey*/)
{
return static_cast <Userdata*> (lua_touserdata (L, lua_absindex (L, index)));
}
//--------------------------------------------------------------------------
/**
Validate and retrieve a Userdata on the stack.
The Userdata must be derived from or the same as the given base class,
identified by the key. If canBeConst is false, generates an error if
the resulting Userdata represents to a const object. We do the type check
first so that the error message is informative.
*/
static Userdata* getClass (lua_State* L,
int index,
void const* registryConstKey,
void const* registryClassKey,
bool canBeConst)
{
index = lua_absindex (L, index);
lua_getmetatable (L, index); // Stack: object metatable (ot) | nil
if (!lua_istable (L, -1))
{
lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: registry metatable (rt) | nil
return throwBadArg (L, index);
}
lua_rawgetp (L, -1, getConstKey ()); // Stack: ot | nil, const table (co) | nil
assert (lua_istable (L, -1) || lua_isnil (L, -1));
// If const table is NOT present, object is const. Use non-const registry table
// if object cannot be const, so constness validation is done automatically.
// E.g. nonConstFn (constObj)
// -> canBeConst = false, isConst = true
// -> 'Class' registry table, 'const Class' object table
// -> 'expected Class, got const Class'
bool isConst = lua_isnil (L, -1); // Stack: ot | nil, nil, rt
if (isConst && canBeConst)
{
lua_rawgetp (L, LUA_REGISTRYINDEX, registryConstKey); // Stack: ot, nil, rt
}
else
{
lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: ot, co, rt
}
lua_insert (L, -3); // Stack: rt, ot, co | nil
lua_pop (L, 1); // Stack: rt, ot
for (;;)
{
if (lua_rawequal (L, -1, -2)) // Stack: rt, ot
{
lua_pop (L, 2); // Stack: -
return static_cast <Userdata*> (lua_touserdata (L, index));
}
// Replace current metatable with it's base class.
lua_rawgetp (L, -1, getParentKey ()); // Stack: rt, ot, parent ot (pot) | nil
if (lua_isnil (L, -1)) // Stack: rt, ot, nil
{
// Drop the object metatable because it may be some parent metatable
lua_pop (L, 2); // Stack: rt
return throwBadArg (L, index);
}
lua_remove (L, -2); // Stack: rt, pot
}
// no return
}
static bool isInstance (lua_State* L, int index, void const* registryClassKey)
{
index = lua_absindex (L, index);
int result = lua_getmetatable (L, index); // Stack: object metatable (ot) | nothing
if (result == 0)
{
return false; // Nothing was pushed on the stack
}
if (!lua_istable (L, -1))
{
lua_pop (L, 1); // Stack: -
return false;
}
lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: ot, rt
lua_insert (L, -2); // Stack: rt, ot
for (;;)
{
if (lua_rawequal (L, -1, -2)) // Stack: rt, ot
{
lua_pop (L, 2); // Stack: -
return true;
}
// Replace current metatable with it's base class.
lua_rawgetp (L, -1, getParentKey ()); // Stack: rt, ot, parent ot (pot) | nil
if (lua_isnil (L, -1)) // Stack: rt, ot, nil
{
lua_pop (L, 3); // Stack: -
return false;
}
lua_remove (L, -2); // Stack: rt, pot
}
}
static Userdata* throwBadArg (lua_State* L, int index)
{
assert (lua_istable (L, -1) || lua_isnil (L, -1)); // Stack: rt | nil
const char* expected = 0;
if (lua_isnil (L, -1)) // Stack: nil
{
expected = "unregistered class";
}
else
{
lua_rawgetp (L, -1, getTypeKey ()); // Stack: rt, registry type
expected = lua_tostring (L, -1);
}
const char* got = 0;
if (lua_isuserdata (L, index))
{
lua_getmetatable (L, index); // Stack: ..., ot | nil
if (lua_istable (L, -1)) // Stack: ..., ot
{
lua_rawgetp (L, -1, getTypeKey ()); // Stack: ..., ot, object type | nil
if (lua_isstring (L, -1))
{
got = lua_tostring (L, -1);
}
}
}
if (!got)
{
got = lua_typename (L, lua_type (L, index));
}
luaL_argerror (L, index, lua_pushfstring (L, "%s expected, got %s", expected, got));
return 0;
}
public:
virtual ~Userdata () { }
//--------------------------------------------------------------------------
/**
Returns the Userdata* if the class on the Lua stack matches.
If the class does not match, a Lua error is raised.
*/
template <class T>
static Userdata* getExact (lua_State* L, int index)
{
return getExactClass (L, index, ClassInfo <T>::getClassKey ());
}
//--------------------------------------------------------------------------
/**
Get a pointer to the class from the Lua stack.
If the object is not the class or a subclass, or it violates the
const-ness, a Lua error is raised.
*/
template <class T>
static T* get (lua_State* L, int index, bool canBeConst)
{
if (lua_isnil (L, index))
return 0;
return static_cast <T*> (getClass (
L, index, ClassInfo <T>::getConstKey (),
ClassInfo <T>::getClassKey (),
canBeConst)->getPointer ());
}
template <class T>
static bool isInstance (lua_State* L, int index)
{
return isInstance (L, index, ClassInfo <T>::getClassKey ());
}
};
//----------------------------------------------------------------------------
/**
Wraps a class object stored in a Lua userdata.
The lifetime of the object is managed by Lua. The object is constructed
inside the userdata using placement new.
*/
template <class T>
class UserdataValue : public Userdata
{
private:
UserdataValue <T> (UserdataValue <T> const&);
UserdataValue <T> operator= (UserdataValue <T> const&);
char m_storage [sizeof (T)];
private:
/**
Used for placement construction.
*/
UserdataValue ()
{
m_p = 0;
}
~UserdataValue ()
{
if (getPointer () != 0)
{
getObject ()->~T ();
}
}
public:
/**
Push a T via placement new.
The caller is responsible for calling placement new using the
returned uninitialized storage.
*/
static UserdataValue <T>* place (lua_State* const L)
{
UserdataValue <T>* const ud = new (
lua_newuserdata (L, sizeof (UserdataValue <T>))) UserdataValue <T> ();
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
if (!lua_istable (L, -1))
{
throw std::logic_error ("The class is not registered in LuaBridge");
}
lua_setmetatable (L, -2);
return ud;
}
/**
Push T via copy construction from U.
*/
template <class U>
static inline void push (lua_State* const L, U const& u)
{
UserdataValue <T>* ud = place (L);
new (ud->getObject ()) U (u);
ud->commit ();
}
/**
Confirm object construction.
*/
void commit ()
{
m_p = getObject ();
}
T* getObject ()
{
// If this fails to compile it means you forgot to provide
// a Container specialization for your container!
//
return reinterpret_cast <T*> (&m_storage [0]);
}
};
//----------------------------------------------------------------------------
/**
Wraps a pointer to a class object inside a Lua userdata.
The lifetime of the object is managed by C++.
*/
class UserdataPtr : public Userdata
{
private:
UserdataPtr (UserdataPtr const&);
UserdataPtr operator= (UserdataPtr const&);
private:
/** Push a pointer to object using metatable key.
*/
static void push (lua_State* L, const void* p, void const* const key)
{
new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (const_cast <void*> (p));
lua_rawgetp (L, LUA_REGISTRYINDEX, key);
if (!lua_istable (L, -1))
{
throw std::logic_error ("The class is not registered in LuaBridge");
}
lua_setmetatable (L, -2);
}
explicit UserdataPtr (void* const p)
{
m_p = p;
// Can't construct with a null pointer!
//
assert (m_p != 0);
}
public:
/** Push non-const pointer to object.
*/
template <class T>
static void push (lua_State* const L, T* const p)
{
if (p)
push (L, p, ClassInfo <T>::getClassKey ());
else
lua_pushnil (L);
}
/** Push const pointer to object.
*/
template <class T>
static void push (lua_State* const L, T const* const p)
{
if (p)
push (L, p, ClassInfo <T>::getConstKey ());
else
lua_pushnil (L);
}
};
//============================================================================
/**
Wraps a container that references a class object.
The template argument C is the container type, ContainerTraits must be
specialized on C or else a compile error will result.
*/
template <class C>
class UserdataShared : public Userdata
{
private:
UserdataShared (UserdataShared <C> const&);
UserdataShared <C>& operator= (UserdataShared <C> const&);
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
C m_c;
private:
~UserdataShared ()
{
}
public:
/**
Construct from a container to the class or a derived class.
*/
template <class U>
explicit UserdataShared (U const& u) : m_c (u)
{
m_p = const_cast <void*> (reinterpret_cast <void const*> (
(ContainerTraits <C>::get (m_c))));
}
/**
Construct from a pointer to the class or a derived class.
*/
template <class U>
explicit UserdataShared (U* u) : m_c (u)
{
m_p = const_cast <void*> (reinterpret_cast <void const*> (
(ContainerTraits <C>::get (m_c))));
}
};
//----------------------------------------------------------------------------
//
// SFINAE helpers.
//
// non-const objects
template <class C, bool makeObjectConst>
struct UserdataSharedHelper
{
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
static void push (lua_State* L, C const& c)
{
if (ContainerTraits <C>::get (c) != 0)
{
new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
// If this goes off it means the class T is unregistered!
assert (lua_istable (L, -1));
lua_setmetatable (L, -2);
}
else
{
lua_pushnil (L);
}
}
static void push (lua_State* L, T* const t)
{
if (t)
{
new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
// If this goes off it means the class T is unregistered!
assert (lua_istable (L, -1));
lua_setmetatable (L, -2);
}
else
{
lua_pushnil (L);
}
}
};
// const objects
template <class C>
struct UserdataSharedHelper <C, true>
{
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
static void push (lua_State* L, C const& c)
{
if (ContainerTraits <C>::get (c) != 0)
{
new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
// If this goes off it means the class T is unregistered!
assert (lua_istable (L, -1));
lua_setmetatable (L, -2);
}
else
{
lua_pushnil (L);
}
}
static void push (lua_State* L, T* const t)
{
if (t)
{
new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
// If this goes off it means the class T is unregistered!
assert (lua_istable (L, -1));
lua_setmetatable (L, -2);
}
else
{
lua_pushnil (L);
}
}
};
/**
Pass by container.
The container controls the object lifetime. Typically this will be a
lifetime shared by C++ and Lua using a reference count. Because of type
erasure, containers like std::shared_ptr will not work. Containers must
either be of the intrusive variety, or in the style of the RefCountedPtr
type provided by LuaBridge (that uses a global hash table).
*/
template <class C, bool byContainer>
struct StackHelper
{
static void push (lua_State* L, C const& c)
{
UserdataSharedHelper <C,
TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, c);
}
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
static C get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, true);
}
};
/**
Pass by value.
Lifetime is managed by Lua. A C++ function which accesses a pointer or
reference to an object outside the activation record in which it was
retrieved may result in undefined behavior if Lua garbage collected it.
*/
template <class T>
struct StackHelper <T, false>
{
static inline void push (lua_State* L, T const& t)
{
UserdataValue <T>::push (L, t);
}
static inline T const& get (lua_State* L, int index)
{
return *Userdata::get <T> (L, index, true);
}
};
//------------------------------------------------------------------------------
/**
Lua stack conversions for pointers and references to class objects.
Lifetime is managed by C++. Lua code which remembers a reference to the
value may result in undefined behavior if C++ destroys the object. The
handling of the const and volatile qualifiers happens in UserdataPtr.
*/
template <class C, bool byContainer>
struct RefStackHelper
{
typedef C return_type;
static inline void push (lua_State* L, C const& t)
{
UserdataSharedHelper <C,
TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, t);
}
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
static return_type get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, true);
}
};
template <class T>
struct RefStackHelper <T, false>
{
typedef T& return_type;
static void push (lua_State* L, T const& t)
{
UserdataPtr::push (L, &t);
}
static return_type get (lua_State* L, int index)
{
T* t = Userdata::get <T> (L, index, true);
if (!t)
luaL_error (L, "nil passed to reference");
return *t;
}
};
/**
* Voider class template. Used to force a comiler to instantiate
* an otherwise probably unused template parameter type T.
* See the C++20 std::void_t <> for details.
*/
template <class T>
struct Void
{
typedef void Type;
};
/**
* Trait class that selects whether to return a user registered
* class object by value or by reference.
*/
template <class T, class Enabler = void>
struct UserdataGetter
{
typedef T* ReturnType;
static ReturnType get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, false);
}
};
template <class T>
struct UserdataGetter <T, typename Void <T (*) ()>::Type>
{
typedef T ReturnType;
static ReturnType get (lua_State* L, int index)
{
return StackHelper <T, TypeTraits::isContainer <T>::value>::get (L, index);
}
};
//==============================================================================
/**
Lua stack conversions for class objects passed by value.
*/
template <class T>
struct Stack
{
typedef void IsUserdata;
typedef UserdataGetter <T> Getter;
typedef typename Getter::ReturnType ReturnType;
static void push (lua_State* L, T const& value)
{
StackHelper <T, TypeTraits::isContainer <T>::value>::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Getter::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
/**
* Trait class indicating whether the parameter type must be
* a user registered class. The trait checks the existence of
* member type Stack <T>::IsUserdata specialization for detection.
*/
template <class T, class Enable = void>
struct IsUserdata
{
static const bool value = false;
};
template <class T>
struct IsUserdata <T, typename Void <typename Stack <T>::IsUserdata>::Type>
{
static const bool value = true;
};
/**
* Trait class that selects a specific push/get implemenation.
*/
template <class T, bool isUserdata>
struct StackOpSelector;
// pointer
template <class T>
struct StackOpSelector <T*, true>
{
typedef T* ReturnType;
static void push (lua_State* L, T* value)
{
UserdataPtr::push (L, value);
}
static T* get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, false);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
// pointer to const
template <class T>
struct StackOpSelector <const T*, true>
{
typedef const T* ReturnType;
static void push (lua_State* L, const T* value)
{
UserdataPtr::push (L, value);
}
static const T* get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, true);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
// reference
template <class T>
struct StackOpSelector <T&, true>
{
typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> Helper;
typedef typename Helper::return_type ReturnType;
static void push (lua_State* L, T& value)
{
UserdataPtr::push (L, &value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
// reference to const
template <class T>
struct StackOpSelector <const T&, true>
{
typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> Helper;
typedef typename Helper::return_type ReturnType;
static void push (lua_State* L, const T& value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
} // namespace luabridge

View File

@@ -0,0 +1,143 @@
//==============================================================================
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include "LuaBridge/detail/ClassInfo.h"
#include <iostream>
#include <string>
namespace luabridge {
namespace debug {
inline void putIndent (std::ostream& stream, unsigned level)
{
for (unsigned i = 0; i < level; ++i)
{
stream << " ";
}
}
inline void dumpTable (lua_State* L, int index, std::ostream& stream, unsigned level);
inline void dumpValue (lua_State* L, int index, std::ostream& stream, unsigned level = 0)
{
const int type = lua_type (L, index);
switch (type)
{
case LUA_TNIL:
stream << "nil";
break;
case LUA_TBOOLEAN:
stream << (lua_toboolean (L, index) ? "true" : "false");
break;
case LUA_TNUMBER:
stream << lua_tonumber (L, index);
break;
case LUA_TSTRING:
stream << '"' << lua_tostring (L, index) << '"';
break;
case LUA_TFUNCTION:
if (lua_iscfunction (L, index))
{
stream << "cfunction@" << lua_topointer (L, index);
}
else
{
stream << "function@" << lua_topointer (L, index);
}
break;
case LUA_TTHREAD:
stream << "thread@" << lua_tothread (L, index);
break;
case LUA_TLIGHTUSERDATA:
stream << "lightuserdata@" << lua_touserdata (L, index);
break;
case LUA_TTABLE:
dumpTable (L, index, stream, level);
break;
case LUA_TUSERDATA:
stream << "userdata@" << lua_touserdata (L, index);
break;
default:
stream << lua_typename (L, type);;
break;
}
}
inline void dumpTable (lua_State* L, int index, std::ostream& stream, unsigned level)
{
stream << "table@" << lua_topointer (L, index);
if (level > 0)
{
return;
}
index = lua_absindex (L, index);
stream << " {";
lua_pushnil (L); // Initial key
while (lua_next (L, index))
{
stream << "\n";
putIndent (stream, level + 1);
dumpValue (L, -2, stream, level + 1); // Key
stream << ": ";
dumpValue (L, -1, stream, level + 1); // Value
lua_pop (L, 1); // Value
}
putIndent (stream, level);
stream << "\n}";
}
inline void dumpState (lua_State *L, std::ostream& stream = std::cerr)
{
int top = lua_gettop (L);
for (int i = 1; i <= top; ++i)
{
stream << "stack #" << i << ": ";
dumpValue (L, i, stream, 0);
stream << "\n";
}
}
} // namespace debug
} // namespace luabridge

53
lib/lua/piluaprogram.cpp Normal file
View File

@@ -0,0 +1,53 @@
/*
PIP - Platform Independent Primitives
PILuaProgram
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/>.
*/
#include "piluaprogram.h"
PRIVATE_DEFINITION_START(PILuaProgram)
lua_State * lua_state;
PRIVATE_DEFINITION_END(PILuaProgram)
PILuaProgram::PILuaProgram() {
PRIVATE->lua_state = luaL_newstate();
luaL_openlibs(PRIVATE->lua_state);
}
bool PILuaProgram::load(const PIString & script) {
int ret = luaL_dostring(PRIVATE->lua_state, script.dataUTF8());
if (ret != 0) return false;
return true;
}
bool PILuaProgram::prepare() {
return (lua_pcall(PRIVATE->lua_state, 0, 0, 0) == 0);
}
luabridge::LuaRef PILuaProgram::getGlobal(const PIString & name) {
return luabridge::getGlobal(PRIVATE->lua_state, name.dataUTF8());
}
luabridge::Namespace PILuaProgram::getGlobalNamespace() {
return luabridge::getGlobalNamespace(PRIVATE->lua_state);
}

View File

@@ -1,38 +1,48 @@
/*! \file piccloudclient.h /*! \file piccloudclient.h
* \brief PICloud Client * \brief PICloud Client
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Client PICloud Client
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PICCLOUDCLIENT_H #ifndef PICCLOUDCLIENT_H
#define PICCLOUDCLIENT_H #define PICCLOUDCLIENT_H
#include "piiodevice.h" #include "pip_cloud_export.h"
#include "piiodevice.h"
class PIP_EXPORT PICloudClient { class PIEthernet;
public:
//!
explicit PICloudClient(); class PIP_CLOUD_EXPORT PICloudClient : public PIIODevice
{
private: PIIODEVICE(PICloudClient)
public:
}; //!
explicit PICloudClient();
#endif // PICCLOUDCLIENT_H virtual ~PICloudClient();
protected:
bool openDevice();
bool closeDevice();
private:
PIEthernet * eth;
};
#endif // PICCLOUDCLIENT_H

View File

@@ -1,39 +1,40 @@
/*! \file piccloudserver.h /*! \file piccloudserver.h
* \brief PICloud Server * \brief PICloud Server
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Server PICloud Server
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PICCLOUDSERVER_H #ifndef PICCLOUDSERVER_H
#define PICCLOUDSERVER_H #define PICCLOUDSERVER_H
#include "piiodevice.h" #include "pip_cloud_export.h"
#include "piiodevice.h"
class PIP_EXPORT PICloudServer {
public: class PIP_CLOUD_EXPORT PICloudServer {
//! public:
explicit PICloudServer(); //!
explicit PICloudServer();
private:
private:
};
};
#endif // PICCLOUDSERVER_H
#endif // PICCLOUDSERVER_H

View File

@@ -1,38 +1,39 @@
/*! \file piccloudtcp.h /*! \file piccloudtcp.h
* \brief PICloud TCP transport * \brief PICloud TCP transport
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud TCP transport PICloud TCP transport
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PICCLOUDTCP_H #ifndef PICCLOUDTCP_H
#define PICCLOUDTCP_H #define PICCLOUDTCP_H
#include "pistring.h" #include "pip_cloud_export.h"
#include "pistring.h"
class PIP_EXPORT PICloudTCP {
public: class PIP_CLOUD_EXPORT PICloudTCP {
//! public:
PICloudTCP(); //!
PICloudTCP();
private:
private:
};
};
#endif // PICCLOUDTCP_H
#endif // PICCLOUDTCP_H

View File

View File

@@ -30,7 +30,7 @@ class PIVariant;
namespace PICodeInfo { namespace PICodeInfo {
enum PIP_EXPORT TypeFlag { enum TypeFlag {
NoFlag, NoFlag,
Const = 0x01, Const = 0x01,
Static = 0x02, Static = 0x02,
@@ -153,10 +153,10 @@ inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
return s; return s;
} }
extern PIMap<PIString, PICodeInfo::ClassInfo * > * classesInfo; extern PIP_EXPORT PIMap<PIString, PICodeInfo::ClassInfo * > * classesInfo;
extern PIMap<PIString, PICodeInfo::EnumInfo * > * enumsInfo; extern PIP_EXPORT PIMap<PIString, PICodeInfo::EnumInfo * > * enumsInfo;
extern PIMap<PIString, PICodeInfo::AccessValueFunction> * accessValueFunctions; extern PIP_EXPORT PIMap<PIString, PICodeInfo::AccessValueFunction> * accessValueFunctions;
extern PIMap<PIString, PICodeInfo::AccessTypeFunction> * accessTypeFunctions; extern PIP_EXPORT PIMap<PIString, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) { inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) {
if (!p || !class_name || !member_name || !accessValueFunctions) return PIByteArray(); if (!p || !class_name || !member_name || !accessValueFunctions) return PIByteArray();
@@ -172,11 +172,11 @@ inline const char * getMemberType(const char * class_name, const char * member_n
return af(member_name); return af(member_name);
} }
PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name); PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name);
} }
class __PICodeInfoInitializer__ { class PIP_EXPORT __PICodeInfoInitializer__ {
public: public:
__PICodeInfoInitializer__() { __PICodeInfoInitializer__() {
if (_inited_) return; if (_inited_) return;

View File

@@ -24,7 +24,7 @@
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()) {
int ci = args_.find(","), bi = args_.find("("); int ci = args_.find(','), bi = args_.find('(');
if (ci < 0) { if (ci < 0) {
arg_vals << args_; arg_vals << args_;
break; break;
@@ -33,7 +33,7 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
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(); bi -= ca.size_s(); ci -= ca.size_s(); bi -= ca.size_s();
ca += "(" + args_.takeRange("(", ")") + ")"; ca += '(' + args_.takeRange('(', ')') + ')';
} else { } else {
ca = args_.takeLeft(ci); ca = args_.takeLeft(ci);
} }
@@ -41,7 +41,7 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
args_.trim(); args_.takeLeft(1); args_.trim(); 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") piCout << ("Error: in expansion of macro \"" + name + '(' + args.join(", ") + ")\": expect")
<< args.size() << "arguments but takes" << 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();
@@ -57,7 +57,7 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
if (ind + an.size_s() < ret.size_s()) nc = ret.mid(ind + an.size_s(),1)[0]; if (ind + an.size_s() < ret.size_s()) nc = ret.mid(ind + an.size_s(),1)[0];
if (ppc != '#' && pc == '#' && !_isCChar(nc)) { // to chars if (ppc != '#' && pc == '#' && !_isCChar(nc)) { // to chars
ind--; ind--;
ret.replace(ind, an.size_s() + 1, "\"" + av + "\""); ret.replace(ind, an.size_s() + 1, '\"' + av + '\"');
ind -= an.size_s() - av.size_s() - 1; ind -= an.size_s() - av.size_s() - 1;
continue; continue;
} }
@@ -66,7 +66,7 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
ind -= an.size_s() - av.size_s(); ind -= an.size_s() - av.size_s();
} }
} }
ret.replaceAll("##", ""); ret.replaceAll(PIStringAscii("##"), "");
if (ok != 0) *ok = true; if (ok != 0) *ok = true;
return ret; return ret;
} }
@@ -99,42 +99,42 @@ void PICodeParser::parseFile(const PIString & file, bool follow_includes) {
} }
piCout << "\n\nDefines:"; piCout << "\n\nDefines:";
piForeachC (Define & m, defines) piForeachC (Define & m, defines)
piCout << "define" << m.first << m.second; piCout << PIStringAscii("define") << m.first << m.second;
piCout << "\n\nMacros:"; piCout << "\n\nMacros:";
piForeachC (Macro & m, macros) piForeachC (Macro & m, macros)
piCout << "Macro:" << m.name << m.args << m.value; piCout << "Macro:" << m.name << m.args << m.value;
piCout << "\n\nClasses:"; piCout << "\n\nClasses:";
piCout << "\n\nEnums:"; piCout << "\n\nEnums:";
piForeachC (Enum & c, enums) { piForeachC (Enum & c, enums) {
piCout << "enum" << c.name << c.meta; piCout << PIStringAscii("enum") << c.name << c.meta;
piForeachC (EnumeratorInfo & e, c.members) piForeachC (EnumeratorInfo & e, c.members)
piCout << " " << e.name << "=" << e.value << e.meta; piCout << " " << e.name << '=' << e.value << e.meta;
} }
piCout << "\n\nTypedefs:"; piCout << "\n\nTypedefs:";
piForeachC (Typedef & c, typedefs) piForeachC (Typedef & c, typedefs)
piCout << "typedef" << c;*/ piCout << PIStringAscii("typedef") << c;*/
} }
void PICodeParser::parseFiles(const PIStringList & files, bool follow_includes) { void PICodeParser::parseFiles(const PIStringList & files, bool follow_includes) {
clear(); clear();
piForeachC (PIString & f, files) piForeachC (PIString & f, files)
parseFileInternal(f, follow_includes); parseFileInternal(f, follow_includes);
/*piCout << "\n\nDefines:"; /*piCout << "\n\nDefines:";
piForeachC (Define & m, defines) piForeachC (Define & m, defines)
piCout << "define" << m.first << m.second; piCout << PIStringAscii("define") << m.first << m.second;
piCout << "\n\nMacros:"; piCout << "\n\nMacros:";
piForeachC (Macro & m, macros) piForeachC (Macro & m, macros)
piCout << "Macro:" << m.name << m.args << m.value; piCout << "Macro:" << m.name << m.args << m.value;
piCout << "\n\nClasses:"; piCout << "\n\nClasses:";
piForeachC (Entity * c, entities) piForeachC (Entity * c, entities)
piCout << "class" << c->name << c->parents; piCout << PIStringAscii("class") << c->name << c->parents;
piCout << "\n\nEnums:"; piCout << "\n\nEnums:";
piForeachC (Enum & c, enums) piForeachC (Enum & c, enums)
piCout << "enum" << c.name << c.members; piCout << PIStringAscii("enum") << c.name << c.members;
piCout << "\n\nTypedefs:"; piCout << "\n\nTypedefs:";
piForeachC (Typedef & c, typedefs) piForeachC (Typedef & c, typedefs)
piCout << "typedef" << c;*/ piCout << PIStringAscii("typedef") << c;*/
} }
@@ -153,7 +153,7 @@ bool PICodeParser::parseFileInternal(const PIString & file, bool follow_includes
PIFile f(file, PIIODevice::ReadOnly); PIFile f(file, PIIODevice::ReadOnly);
int ii = 0; int ii = 0;
while (!f.isOpened() && ii < (includes.size_s() - 1)) { while (!f.isOpened() && ii < (includes.size_s() - 1)) {
f.setPath(includes[++ii] + "/" + file); f.setPath(includes[++ii] + '/' + file);
//piCout << "try" << f.path(); //piCout << "try" << f.path();
f.open(PIIODevice::ReadOnly); f.open(PIIODevice::ReadOnly);
} }
@@ -186,7 +186,10 @@ void PICodeParser::clear() {
evaluator.clearCustomVariables(); evaluator.clearCustomVariables();
cur_def_vis = Global; cur_def_vis = Global;
anon_num = 0; anon_num = 0;
defines << Define("PICODE", "") << custom_defines; PIStringList defs = PIStringAscii(PICODE_DEFINES).split(",");
piForeachC (PIString & d, defs)
defines << Define(d, "");
defines << Define(PIStringAscii("PICODE"), "") << custom_defines;
} }
@@ -197,9 +200,9 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
PIString pfc, line, ccmn, tmp; PIString pfc, line, ccmn, tmp;
PIMap<PIString, PIString> cchars; PIMap<PIString, PIString> cchars;
/// Remove comments, join multiline "*" and replace "*" to $n (cchars) /// Remove comments, join multiline '*' and replace '*' to $n (cchars)
fc.replaceAll("\r\n", "\n"); fc.replaceAll("\r\n", '\n');
fc.replaceAll("\r", "\n"); fc.replaceAll('\r', '\n');
for (int i = 0; i < fc.size_s() - 1; ++i) { for (int i = 0; i < fc.size_s() - 1; ++i) {
if (fc[i].unicode16Code() >= 255) continue; if (fc[i].unicode16Code() >= 255) continue;
if (i > 0) pc = c; if (i > 0) pc = c;
@@ -256,7 +259,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
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; bool ok(false); PIString ret, range; 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;
int rlen = pfc.find(range, ind + m.name.size_s()) + range.size_s() + 1 - ind; int rlen = pfc.find(range, ind + m.name.size_s()) + range.size_s() + 1 - ind;
@@ -274,46 +277,46 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
int nl = pfc.size_s(); int nl = pfc.size_s();
if (pl == nl) break; if (pl == nl) break;
pl = nl; pl = nl;
if (pfc.left(9) == "namespace") { if (pfc.left(9) == PIStringAscii("namespace")) {
pfc.cutLeft(pfc.find("{") + 1); pfc.cutLeft(pfc.find('{') + 1);
continue; continue;
} }
if (pfc.left(8) == "template") { if (pfc.left(8) == PIStringAscii("template")) {
pfc.cutLeft(8); pfc.cutLeft(8);
pfc.takeRange("<", ">"); pfc.takeRange('<', '>');
bool def = !isDeclaration(pfc, 0, &end); bool def = !isDeclaration(pfc, 0, &end);
pfc.cutLeft(end); pfc.cutLeft(end);
if (def) pfc.takeRange("{", "}"); if (def) pfc.takeRange('{', '}');
else pfc.takeSymbol(); else pfc.takeSymbol();
continue; continue;
} }
if (pfc.left(5) == "class" || pfc.left(6) == "struct" || pfc.left(5) == "union") { if (pfc.left(5) == PIStringAscii("class") || pfc.left(6) == PIStringAscii("struct") || pfc.left(5) == PIStringAscii("union")) {
int dind = pfc.find("{", 0), find = pfc.find(";", 0); int dind = pfc.find('{', 0), find = pfc.find(';', 0);
if (dind < 0 && find < 0) {pfc.cutLeft(6); continue;} if (dind < 0 && find < 0) {pfc.cutLeft(6); continue;}
if (dind < 0 || find < dind) {pfc.cutLeft(6); continue;} if (dind < 0 || find < dind) {pfc.cutLeft(6); continue;}
ccmn = pfc.left(dind) + "{\n" + pfc.mid(dind).takeRange('{', '}') + "\n}\n"; ccmn = pfc.left(dind) + PIStringAscii("{\n") + pfc.mid(dind).takeRange('{', '}') + PIStringAscii("\n}\n");
pfc.remove(0, ccmn.size()); pfc.remove(0, ccmn.size());
parseClass(0, ccmn); parseClass(0, ccmn);
continue; continue;
} }
if (pfc.left(4) == "enum") { if (pfc.left(4) == PIStringAscii("enum")) {
pfc.cutLeft(4); pfc.cutLeft(4);
tmp = pfc.takeCWord(); tmp = pfc.takeCWord();
pfc.trim(); pfc.trim();
MetaMap meta = maybeMeta(pfc); MetaMap meta = maybeMeta(pfc);
parseEnum(0, cur_namespace + tmp, pfc.takeRange("{", "}"), meta); parseEnum(0, cur_namespace + tmp, pfc.takeRange('{', '}'), meta);
pfc.takeSymbol(); pfc.takeSymbol();
continue; continue;
} }
if (pfc.left(7) == "typedef") { if (pfc.left(7) == PIStringAscii("typedef")) {
pfc.cutLeft(7); pfc.cutLeft(7);
typedefs << parseTypedef(pfc.takeLeft(pfc.find(";"))); typedefs << parseTypedef(pfc.takeLeft(pfc.find(';')));
if (typedefs.back().first.isEmpty()) typedefs.pop_back(); if (typedefs.back().first.isEmpty()) typedefs.pop_back();
else root_.typedefs << typedefs.back(); else root_.typedefs << typedefs.back();
pfc.takeSymbol(); pfc.takeSymbol();
continue; continue;
} }
int sci = pfc.find(";", 0), obi = pfc.find("{", 0); int sci = pfc.find(';', 0), obi = pfc.find('{', 0);
if (sci < 0 && obi < 0) { if (sci < 0 && obi < 0) {
pfc.takeLeft(1); pfc.takeLeft(1);
continue; continue;
@@ -323,7 +326,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
str = pfc.takeLeft(sci + 1); str = pfc.takeLeft(sci + 1);
} else { } else {
str = pfc.takeLeft(obi); str = pfc.takeLeft(obi);
pfc.cutLeft(pfc.takeRange("{", "}").toInt()); pfc.cutLeft(pfc.takeRange('{', '}').toInt());
} }
parseMember(&root_, str); parseMember(&root_, str);
} }
@@ -333,22 +336,22 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc) { PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc) {
PIString cd = fc.trimmed().removeAll('\n').replaceAll("\t", " ").replaceAll(" ", " "), pn; PIString cd = fc.trimmed().removeAll('\n').replaceAll('\t', ' ').replaceAll(PIStringAscii(" "), ' '), pn;
MetaMap meta; MetaMap meta;
int ind = cd.find("$M"); int ind = cd.find(PIStringAscii("$M"));
if (ind >= 0) { if (ind >= 0) {
meta = tmp_meta.value(cd.takeMid(ind, 5)); meta = tmp_meta.value(cd.takeMid(ind, 5));
cd.replaceAll(" ", " "); cd.replaceAll(PIStringAscii(" "), ' ');
} }
//piCout << "found class <****\n" << cd << "\n****>"; //piCout << "found class <****\n" << cd << "\n****>";
ind = cd.find(":"); ind = cd.find(':');
PIVector<Entity * > parents; PIVector<Entity * > parents;
if (ind > 0) { if (ind > 0) {
PIStringList pl = cd.takeMid(ind + 1).trim().split(","); PIStringList pl = cd.takeMid(ind + 1).trim().split(',');
cd.cutRight(1); cd.cutRight(1);
Entity * pe = 0; Entity * pe = 0;
piForeachC (PIString & p, pl) { piForeachC (PIString & p, pl) {
if (p.contains(" ")) pn = p.mid(p.find(" ") + 1); if (p.contains(' ')) pn = p.mid(p.find(' ') + 1);
else pn = p; else pn = p;
pe = findEntityByName(pn); pe = findEntityByName(pn);
if (pe == 0) ;//{piCout << "Error: can`t find" << pn;} if (pe == 0) ;//{piCout << "Error: can`t find" << pn;}
@@ -356,11 +359,11 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
} }
} }
PIString typename_ = cd.left(6).trim(); PIString typename_ = cd.left(6).trim();
bool is_class = typename_ == "class"; bool is_class = typename_ == PIStringAscii("class");
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 = "<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 0; if (cn.isEmpty()) return 0;
Entity * e = new Entity(); Entity * e = new Entity();
@@ -377,7 +380,7 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
PIString PICodeParser::parseClass(Entity * parent, PIString & fc) { PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
Visibility prev_vis = cur_def_vis; Visibility prev_vis = cur_def_vis;
int dind = fc.find("{"), find = fc.find(";"), end = 0; int dind = fc.find('{'), find = fc.find(';'), end = 0;
if (dind < 0 && find < 0) return PIString(); if (dind < 0 && find < 0) return PIString();
if (dind < 0 || find < dind) return fc.left(find); if (dind < 0 || find < dind) return fc.left(find);
//piCout << "parse class <****\n" << fc.left(20) << "\n****>"; //piCout << "parse class <****\n" << fc.left(20) << "\n****>";
@@ -390,43 +393,43 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
int ps = -1; int ps = -1;
bool def = false; bool def = false;
PIString prev_namespace = cur_namespace, stmp; PIString prev_namespace = cur_namespace, stmp;
cur_namespace = ce->name + "::"; cur_namespace = ce->name + PIStringAscii("::");
//piCout << "parse class" << ce->name << "namespace" << cur_namespace; //piCout << "parse class" << ce->name << "namespace" << cur_namespace;
//piCout << "\nparse class" << ce->name << "namespace" << cur_namespace; //piCout << "\nparse class" << ce->name << "namespace" << cur_namespace;
while (!fc.isEmpty()) { while (!fc.isEmpty()) {
PIString cw = fc.takeCWord(), tmp; PIString cw = fc.takeCWord(), tmp;
//piCout << "\ntaked word" << cw; //piCout << "\ntaked word" << cw;
if (cw == "public") {cur_def_vis = Public; fc.cutLeft(1); continue;} if (cw == PIStringAscii("public" )) {cur_def_vis = Public; fc.cutLeft(1); continue;}
if (cw == "protected") {cur_def_vis = Protected; fc.cutLeft(1); continue;} if (cw == PIStringAscii("protected")) {cur_def_vis = Protected; fc.cutLeft(1); continue;}
if (cw == "private") {cur_def_vis = Private; fc.cutLeft(1); continue;} if (cw == PIStringAscii("private" )) {cur_def_vis = Private; fc.cutLeft(1); continue;}
if (cw == "class" || cw == "struct" || cw == "union") { if (cw == PIStringAscii("class") || cw == PIStringAscii("struct") || cw == PIStringAscii("union")) {
if (isDeclaration(fc, 0, &end)) { if (isDeclaration(fc, 0, &end)) {
fc.cutLeft(end); fc.cutLeft(end);
fc.takeSymbol(); fc.takeSymbol();
continue; continue;
} }
tmp = fc.takeLeft(fc.find("{")); tmp = fc.takeLeft(fc.find('{'));
stmp = fc.takeRange("{", "}"); stmp = fc.takeRange('{', '}');
fc.takeSymbol(); fc.takeSymbol();
stmp = cw + " " + tmp + "{" + stmp + "}"; stmp = cw + ' ' + tmp + '{' + stmp + '}';
parseClass(ce, stmp); parseClass(ce, stmp);
continue; continue;
} }
if (cw == "enum") { if (cw == PIStringAscii("enum")) {
tmp = fc.takeCWord(); tmp = fc.takeCWord();
fc.trim(); fc.trim();
MetaMap meta = maybeMeta(fc); MetaMap meta = maybeMeta(fc);
parseEnum(ce, cur_namespace + tmp, fc.takeRange("{", "}"), meta); parseEnum(ce, cur_namespace + tmp, fc.takeRange('{', '}'), meta);
fc.takeSymbol(); fc.takeSymbol();
continue; continue;
} }
if (cw == "friend") {fc.cutLeft(fc.find(";") + 1); continue;} if (cw == PIStringAscii("friend")) {fc.cutLeft(fc.find(';') + 1); continue;}
if (cw == "typedef") {ce->typedefs << parseTypedef(fc.takeLeft(fc.find(";"))); typedefs << ce->typedefs.back(); typedefs.back().first.insert(0, cur_namespace); if (ce->typedefs.back().first.isEmpty()) ce->typedefs.pop_back(); fc.takeSymbol(); continue;} if (cw == PIStringAscii("typedef")) {ce->typedefs << parseTypedef(fc.takeLeft(fc.find(';'))); typedefs << ce->typedefs.back(); typedefs.back().first.insert(0, cur_namespace); if (ce->typedefs.back().first.isEmpty()) ce->typedefs.pop_back(); fc.takeSymbol(); continue;}
if (cw == "template") { if (cw == PIStringAscii("template")) {
fc.takeRange("<", ">"); fc.takeRange('<', '>');
def = !isDeclaration(fc, 0, &end); def = !isDeclaration(fc, 0, &end);
fc.cutLeft(end); fc.cutLeft(end);
if (def) fc.takeRange("{", "}"); if (def) fc.takeRange('{', '}');
else fc.takeSymbol(); else fc.takeSymbol();
continue; continue;
} }
@@ -434,7 +437,7 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
tmp = (cw + fc.takeLeft(end)).trim(); tmp = (cw + fc.takeLeft(end)).trim();
if (!tmp.isEmpty()) if (!tmp.isEmpty())
parseMember(ce, tmp); parseMember(ce, tmp);
if (def) fc.takeRange("{", "}"); if (def) fc.takeRange('{', '}');
else fc.takeSymbol(); else 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();
@@ -448,13 +451,13 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
PICodeParser::MetaMap PICodeParser::parseMeta(PIString & fc) { PICodeParser::MetaMap PICodeParser::parseMeta(PIString & fc) {
PICodeParser::MetaMap ret; PICodeParser::MetaMap ret;
if (fc.isEmpty()) return ret; if (fc.isEmpty()) return ret;
PIStringList ml = fc.split(","); PIStringList ml = fc.split(',');
piForeachC (PIString & m, ml) { piForeachC (PIString & m, ml) {
int i = m.find("="); int i = m.find('=');
if (i < 0) continue; if (i < 0) continue;
PIString mv = m.mid(i + 1).trim(); PIString mv = m.mid(i + 1).trim();
if (mv.startsWith("\"")) mv.cutLeft(1); if (mv.startsWith('\"')) mv.cutLeft(1);
if (mv.endsWith("\"")) mv.cutRight(1); if (mv.endsWith('\"')) mv.cutRight(1);
ret[m.left(i).trim()] = mv; ret[m.left(i).trim()] = mv;
} }
//piCout << ms << ret; //piCout << ms << ret;
@@ -463,20 +466,22 @@ PICodeParser::MetaMap PICodeParser::parseMeta(PIString & fc) {
bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta) { bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta) {
//piCout << "enum" << name << fc; static const PIString s_ss = PIStringAscii(" ");
static const PIString s_M = PIStringAscii("$M");
//piCout << PIStringAscii("enum") << name << fc;
Enum e(name); Enum e(name);
e.meta = meta; e.meta = meta;
PIStringList vl(fc.split(",")); PIStringList vl(fc.split(','));
PIString vn; PIString vn;
int cv = -1, ind = 0; int cv = -1, ind = 0;
piForeach (PIString & v, vl) { piForeach (PIString & v, vl) {
MetaMap meta; MetaMap meta;
int mi = v.find("$M"); int mi = v.find(s_M);
if (mi >= 0) { if (mi >= 0) {
meta = tmp_meta.value(v.takeMid(mi, 5)); meta = tmp_meta.value(v.takeMid(mi, 5));
v.replaceAll(" ", " "); v.replaceAll(s_ss, ' ');
} }
vn = v; ind = v.find("="); vn = v; 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);
@@ -492,15 +497,15 @@ bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc
PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) { PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) {
//piCout << "parse typedef" << fc; //piCout << "parse typedef" << fc;
Typedef td; Typedef td;
fc.replaceAll("\t", " "); fc.replaceAll('\t', ' ');
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) == "*") {td.first.cutLeft(1).trim(); fc.insert(start + 1, "*");} if (td.first.left(1) == PIChar('*')) {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();
td.second = fc.trim(); td.second = fc.trim();
} }
//piCout << "found typedef" << td; //piCout << "found typedef" << td;
@@ -509,34 +514,53 @@ PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) {
bool PICodeParser::parseMember(Entity * parent, PIString & fc) { bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
static const PIString s_operator = PIStringAscii("operator");
static const PIString s_ss = PIStringAscii(" ");
static const PIString s_cs = PIStringAscii(", ");
static const PIString s_sb = PIStringAscii(" (");
static const PIString s_sM = PIStringAscii(" $M");
static const PIString s_M = PIStringAscii("$M");
static const PIString s_T = PIStringAscii("$T");
static const PIString s_inline_s = PIStringAscii("inline ");
static const PIString s_static_s = PIStringAscii("static ");
static const PIString s_virtual_s = PIStringAscii("virtual ");
static const PIString s_void = PIStringAscii("void");
static const PIString s_using = PIStringAscii("using");
static const PIString s_s5 = PIStringAscii(" ");
static const PIString s_s_const_s = PIStringAscii(" const ");
static const PIString s_s_static_s = PIStringAscii(" static ");
static const PIString s_s_mutable_s = PIStringAscii(" mutable ");
static const PIString s_s_volatile_s = PIStringAscii(" volatile ");
static const PIString s_s_extern_s = PIStringAscii(" extern ");
if (fc.trim().isEmpty()) return true; if (fc.trim().isEmpty()) return true;
if (fc.find("operator") >= 0) return true; if (fc.find(s_operator) >= 0) return true;
tmp_temp.clear(); tmp_temp.clear();
//piCout << "parse member" << fc; //piCout << "parse member" << fc;
int ts = fc.find("<"), te = 0; int ts = fc.find('<'), te = 0;
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()) {te = ts + 1; ts = fc.find("<", te); continue;} if (ctemp.isEmpty()) {te = ts + 1; ts = fc.find('<', te); continue;}
crepl = "$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 + '>';
ts = fc.find("<", te); ts = fc.find('<', te);
} }
fc.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ").replaceAll(", ", ",").replaceAll(" (", "(").replaceAll(" $M", "$M"); fc.replaceAll('\n', ' ').replaceAll('\t', ' ').replaceAll(s_ss, ' ').replaceAll(s_cs, ',').replaceAll(s_sb, '(').replaceAll(s_sM, s_M);
//piCout << "parse member" << fc; //piCout << "parse member" << fc;
PIStringList tl, al; PIStringList tl, al;
Member me; Member me;
//piCout << fc; //piCout << fc;
if (fc.contains("(")) { if (fc.contains('(')) {
MetaMap meta; MetaMap meta;
int ind = fc.find("$M"); int ind = fc.find(s_M);
if (ind >= 0) { if (ind >= 0) {
meta = tmp_meta.value(fc.takeMid(ind, 5)); meta = tmp_meta.value(fc.takeMid(ind, 5));
fc.replaceAll(" ", " ").replaceAll(" (", "("); fc.replaceAll(s_ss, ' ').replaceAll(s_sb, '(');
} }
fc.cutRight(fc.size_s() - fc.findLast(")") - 1); fc.cutRight(fc.size_s() - fc.findLast(')') - 1);
te = fc.find("("); te = fc.find('(');
//piCout << fc; //piCout << fc;
for (ts = te - 1; ts >= 0; --ts) for (ts = te - 1; ts >= 0; --ts)
if (!_isCChar(fc[ts]) && !(fc[ts].isDigit())) break; if (!_isCChar(fc[ts]) && !(fc[ts].isDigit())) break;
@@ -544,37 +568,37 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
me.meta = meta; me.meta = meta;
me.name = fc.takeMid(ts + 1, te - ts - 1); me.name = fc.takeMid(ts + 1, te - ts - 1);
if (me.name == parent->name) return true; if (me.name == parent->name) return true;
me.arguments_full = fc.takeMid(ts + 2).cutRight(1).split(","); me.arguments_full = fc.takeMid(ts + 2).cutRight(1).split(',');
me.type = fc.cutRight(1).trim(); me.type = fc.cutRight(1).trim();
me.visibility = cur_def_vis; me.visibility = cur_def_vis;
if (me.type.find("inline ") >= 0) { if (me.type.find(s_inline_s) >= 0) {
me.attributes |= Inline; me.attributes |= Inline;
me.type.removeAll("inline "); me.type.removeAll(s_inline_s);
} }
if (me.type.find("static ") >= 0) { if (me.type.find(s_static_s) >= 0) {
me.attributes |= Static; me.attributes |= Static;
me.type.removeAll("static "); me.type.removeAll(s_static_s);
} }
if (me.type.find("virtual ") >= 0) { if (me.type.find(s_virtual_s) >= 0) {
me.attributes |= Virtual; me.attributes |= Virtual;
me.type.removeAll("virtual "); me.type.removeAll(s_virtual_s);
} }
normalizeEntityNamespace(me.type); normalizeEntityNamespace(me.type);
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) if ((i = a.find('=')) > 0)
a.cutRight(a.size_s() - i).trim(); 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] == "void") { if (me.arguments_full[j] == s_void) {
me.arguments_full.remove(j); me.arguments_full.remove(j);
--j; --j;
} }
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("[")) if (a.contains('['))
crepl = a.takeMid(a.find("["), a.findLast("]") - a.find("[") + 1); 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);
@@ -586,18 +610,18 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
//piCout << "func" << me.type << me.name << me.arguments_full << me.arguments_type; //piCout << "func" << me.type << me.name << me.arguments_full << me.arguments_type;
parent->functions << me; parent->functions << me;
} else { } else {
if (fc.endsWith(";")) fc.cutRight(1); if (fc.endsWith(';')) fc.cutRight(1);
if (fc.startsWith("using") || !(fc.contains(' ') || fc.contains('\t') || fc.contains('\n'))) return true; if (fc.startsWith(s_using) || !(fc.contains(' ') || fc.contains('\t') || fc.contains('\n'))) return true;
int bits = extractMemberBits(fc); int bits = extractMemberBits(fc);
tl = fc.split(","); tl = fc.split(',');
//piCout << "member" << fc << tl; //piCout << "member" << fc << tl;
//piCout << "member after eb" << fc << ", bits =" << bits; //piCout << "member after eb" << fc << ", bits =" << bits;
if (tl.isEmpty()) return true; if (tl.isEmpty()) return true;
bool vn = true; bool vn = true;
ctemp = tl.front().trim(); ctemp = tl.front().trim();
PIString meta_t; PIString meta_t;
if (ctemp.contains("$M")) if (ctemp.contains(s_M))
meta_t = ctemp.takeMid(ctemp.find("$M")); meta_t = ctemp.takeMid(ctemp.find(s_M));
for (ts = ctemp.size_s() - 1; ts > 0; --ts) { for (ts = ctemp.size_s() - 1; ts > 0; --ts) {
if (vn) {if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;} if (vn) {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;}
@@ -606,26 +630,26 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
me.visibility = cur_def_vis; me.visibility = cur_def_vis;
ctemp += meta_t; ctemp += meta_t;
restoreTmpTemp(&me); restoreTmpTemp(&me);
PIString type = " " + me.type; PIString type = s_s5 + me.type;
if (type.find(" const ") >= 0) { if (type.find(s_s_const_s) >= 0) {
me.attributes |= Const; me.attributes |= Const;
type.replaceAll(" const ", " "); type.replaceAll(s_s_const_s, ' ');
} }
if (type.find(" static ") >= 0) { if (type.find(s_s_static_s) >= 0) {
me.attributes |= Static; me.attributes |= Static;
type.replaceAll(" static ", " "); type.replaceAll(s_s_static_s, ' ');
} }
if (type.find(" mutable ") >= 0) { if (type.find(s_s_mutable_s) >= 0) {
me.attributes |= Mutable; me.attributes |= Mutable;
type.replaceAll(" mutable ", " "); type.replaceAll(s_s_mutable_s, ' ');
} }
if (type.find(" volatile ") >= 0) { if (type.find(s_s_volatile_s) >= 0) {
me.attributes |= Volatile; me.attributes |= Volatile;
type.replaceAll(" volatile ", " "); type.replaceAll(s_s_volatile_s, ' ');
} }
if (type.find(" extern ") >= 0) { if (type.find(s_s_extern_s) >= 0) {
me.attributes |= Extern; me.attributes |= Extern;
type.replaceAll(" extern ", " "); type.replaceAll(s_s_extern_s, ' ');
} }
type.trim(); type.trim();
normalizeEntityNamespace(type); normalizeEntityNamespace(type);
@@ -637,15 +661,15 @@ 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("[")) if (me.name.contains('['))
crepl = me.name.takeMid(me.name.find("["), me.name.findLast("]") - me.name.find("[") + 1); 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() == "*" || me.name.front() == "&") { 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 break; } else break;
} }
me.is_type_ptr = (me.type.right(1) == "]" || me.type.right(1) == "*"); me.is_type_ptr = (me.type.right(1) == PIChar(']') || me.type.right(1) == PIChar('*'));
me.type += crepl; me.type += crepl;
me.bits = bits; me.bits = bits;
while (!crepl.isEmpty()) { while (!crepl.isEmpty()) {
@@ -664,7 +688,7 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
int PICodeParser::extractMemberBits(PIString & fc) { int PICodeParser::extractMemberBits(PIString & fc) {
int i = fc.findLast(":"); int i = fc.findLast(':');
if (i <= 0) return -1; if (i <= 0) return -1;
if (fc[i - 1].toAscii() == ':') return -1; if (fc[i - 1].toAscii() == ':') return -1;
PIString bs = fc.takeMid(i).mid(1).trim(); PIString bs = fc.takeMid(i).mid(1).trim();
@@ -674,6 +698,14 @@ int PICodeParser::extractMemberBits(PIString & fc) {
void PICodeParser::normalizeEntityNamespace(PIString & n) { void PICodeParser::normalizeEntityNamespace(PIString & n) {
static const PIString s_const_s = PIStringAscii("const ");
static const PIString s_static_s = PIStringAscii("static ");
static const PIString s_mutable_s = PIStringAscii("mutable ");
static const PIString s_volatile_s = PIStringAscii("volatile ");
static const PIString s_s_const_s = PIStringAscii(" const ");
static const PIString s_s_static_s = PIStringAscii(" static ");
static const PIString s_s_mutable_s = PIStringAscii(" mutable ");
static const PIString s_s_volatile_s = PIStringAscii(" volatile ");
PIString suff, pref; PIString suff, pref;
for (int i = n.size_s() - 1; i > 0; --i) for (int i = n.size_s() - 1; i > 0; --i)
if (_isCChar(n[i]) || n[i].isDigit()) { if (_isCChar(n[i]) || n[i].isDigit()) {
@@ -681,11 +713,11 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
n.cutRight(suff.size_s()); n.cutRight(suff.size_s());
break; break;
} }
n.push_front(" "); n.push_front(' ');
if (n.find(" static ") >= 0) {n.replaceAll(" static ", ""); pref += "static ";} if (n.find(s_s_const_s) >= 0) {n.replaceAll(s_s_const_s, ""); pref += s_const_s;}
if (n.find(" const ") >= 0) {n.replaceAll(" const ", ""); pref += "const ";} if (n.find(s_s_static_s) >= 0) {n.replaceAll(s_s_static_s, ""); pref += s_static_s;}
if (n.find(" mutable ") >= 0) {n.replaceAll(" mutable ", ""); pref += "mutable ";} if (n.find(s_s_mutable_s) >= 0) {n.replaceAll(s_s_mutable_s, ""); pref += s_mutable_s;}
if (n.find(" volatile ") >= 0) {n.replaceAll(" volatile ", ""); pref += "volatile ";} 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) {
@@ -694,27 +726,29 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
return; return;
} }
if ((f = e->name.find(n)) >= 0) if ((f = e->name.find(n)) >= 0)
if (e->name.mid(f - 1, 1) == ":") if (e->name.at(f - 1) == PIChar(':'))
if (e->name.find(cur_namespace) >= 0) { if (e->name.find(cur_namespace) >= 0) {
n = pref + e->name + suff; n = pref + e->name + suff;
return; return;
} }
} }
piForeachC (Enum & e, enums) piForeachC (Enum & e, enums) {
if ((f = e.name.find(n)) >= 0) if ((f = e.name.find(n)) >= 0)
if (e.name.mid(f - 1, 1) == ":") if (e.name.at(f - 1) == PIChar(':'))
if (e.name.find(cur_namespace) >= 0) { if (e.name.find(cur_namespace) >= 0) {
//piCout << "change" << n << "to" << e.name + suff; //piCout << "change" << n << "to" << e.name + suff;
n = pref + e.name + suff; n = pref + e.name + suff;
return; return;
}
} }
piForeachC (Typedef & e, typedefs) piForeachC (Typedef & e, typedefs) {
if ((f = e.first.find(n)) >= 0) if ((f = e.first.find(n)) >= 0)
if (e.first.mid(f - 1, 1) == ":") if (e.first.at(f - 1) == PIChar(':'))
if (e.first.find(cur_namespace) >= 0) { if (e.first.find(cur_namespace) >= 0) {
//piCout << "change" << n << "to" << e.name + suff; //piCout << "change" << n << "to" << e.name + suff;
n = pref + e.first + suff; n = pref + e.first + suff;
return; return;
}
} }
n = (pref + n + suff).trim(); n = (pref + n + suff).trim();
} }
@@ -723,20 +757,20 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
void PICodeParser::restoreTmpTemp(Member * e) { void PICodeParser::restoreTmpTemp(Member * e) {
int i = 0; int i = 0;
piForeach (PIString & a, e->arguments_full) { piForeach (PIString & a, e->arguments_full) {
while ((i = a.find("$T")) >= 0) while ((i = a.find(PIStringAscii("$T"))) >= 0)
a.replace(i, 5, tmp_temp[a.mid(i, 5)]); a.replace(i, 5, tmp_temp[a.mid(i, 5)]);
} }
piForeach (PIString & a, e->arguments_type) { piForeach (PIString & a, e->arguments_type) {
while ((i = a.find("$T")) >= 0) while ((i = a.find(PIStringAscii("$T"))) >= 0)
a.replace(i, 5, tmp_temp[a.mid(i, 5)]); a.replace(i, 5, tmp_temp[a.mid(i, 5)]);
} }
while ((i = e->type.find("$T")) >= 0) while ((i = e->type.find(PIStringAscii("$T"))) >= 0)
e->type.replace(i, 5, tmp_temp[e->type.mid(i, 5)]); e->type.replace(i, 5, tmp_temp[e->type.mid(i, 5)]);
} }
void PICodeParser::restoreTmpMeta(PICodeParser::Member * e) { void PICodeParser::restoreTmpMeta(PICodeParser::Member * e) {
int i = e->name.find("$M"); int i = e->name.find(PIStringAscii("$M"));
if (i < 0) return; if (i < 0) return;
e->meta = tmp_meta[e->name.takeMid(i, 5)]; e->meta = tmp_meta[e->name.takeMid(i, 5)];
} }
@@ -744,7 +778,7 @@ void PICodeParser::restoreTmpMeta(PICodeParser::Member * e) {
PICodeParser::MetaMap PICodeParser::maybeMeta(PIString & fc) { PICodeParser::MetaMap PICodeParser::maybeMeta(PIString & fc) {
PICodeParser::MetaMap ret; PICodeParser::MetaMap ret;
if (fc.left(2) == "$M") { if (fc.left(2) == PIStringAscii("$M")) {
ret = tmp_meta.value(fc.takeLeft(5)); ret = tmp_meta.value(fc.takeLeft(5));
fc.trim(); fc.trim();
} }
@@ -754,10 +788,10 @@ PICodeParser::MetaMap PICodeParser::maybeMeta(PIString & fc) {
bool PICodeParser::macroCondition(const PIString & mif, PIString mifcond) { bool PICodeParser::macroCondition(const PIString & mif, PIString mifcond) {
//piCout << "macroCondition" << mif << mifcond; //piCout << "macroCondition" << mif << mifcond;
if (mif == "ifdef") return isDefineExists(mifcond); if (mif == PIStringAscii("ifdef")) return isDefineExists(mifcond);
if (mif == "ifndef") return !isDefineExists(mifcond); if (mif == PIStringAscii("ifndef")) return !isDefineExists(mifcond);
if (mif == "if" || mif == "elif") { if (mif == PIStringAscii("if") || mif == PIStringAscii("elif")) {
mifcond.removeAll(" ").removeAll("\t"); mifcond.removeAll(' ').removeAll('\t');
return procMacrosCond(mifcond) > 0.; return procMacrosCond(mifcond) > 0.;
} }
return false; return false;
@@ -770,7 +804,7 @@ double PICodeParser::procMacrosCond(PIString fc) {
int oper = 0, ps = -1; int oper = 0, ps = -1;
char cc, nc; char cc, nc;
PIString ce; PIString ce;
fc.removeAll("defined"); fc.removeAll(PIStringAscii("defined"));
//piCout << "procMacrosCond" << fc; //piCout << "procMacrosCond" << fc;
while (!fc.isEmpty()) { while (!fc.isEmpty()) {
cc = fc[0].toAscii(); cc = fc[0].toAscii();
@@ -825,17 +859,17 @@ double PICodeParser::defineValue(const PIString & dn) {
void PICodeParser::replaceMeta(PIString & dn) { void PICodeParser::replaceMeta(PIString & dn) {
tmp_meta.clear(); tmp_meta.clear();
if (dn.isEmpty()) return; if (dn.isEmpty()) return;
int s = dn.find("PIMETA"); int s = dn.find(PIStringAscii("PIMETA"));
while (s >= 0) { while (s >= 0) {
int ms = 0, ml = 0; int ms = 0, ml = 0;
ms = dn.findRange('(', ')', '\\', s + 6, &ml); ms = dn.findRange('(', ')', '\\', s + 6, &ml);
if (ms < 0) return; if (ms < 0) return;
PIString meta = dn.mid(ms, ml).trim(); PIString meta = dn.mid(ms, ml).trim();
PIString rm = "$M" + PIString::fromNumber(tmp_meta.size_s()).expandLeftTo(3, "0"); PIString rm = PIStringAscii("$M") + PIString::fromNumber(tmp_meta.size_s()).expandLeftTo(3, '0');
dn.replace(s, ms + ml + 1 - s, rm); dn.replace(s, ms + ml + 1 - s, rm);
//piCout << "FOUND META \"" << meta << "\""; //piCout << "FOUND META \"" << meta << '\"';
tmp_meta[rm] = parseMeta(meta); tmp_meta[rm] = parseMeta(meta);
s = dn.find("PIMETA"); s = dn.find(PIStringAscii("PIMETA"));
} }
} }
@@ -849,7 +883,7 @@ 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 (end) *end = -1; return true;} if (dind < 0 && find < 0) {if (end) *end = -1; return true;}
if (dind < 0 || find < dind) {if (end) *end = find; return true;} if (dind < 0 || find < dind) {if (end) *end = find; return true;}
@@ -861,17 +895,17 @@ bool PICodeParser::isDeclaration(const PIString & fc, int start, int * end) {
bool PICodeParser::isMainFile(const PIString & fc) { bool PICodeParser::isMainFile(const PIString & fc) {
int si = 0; int si = 0;
while (si >= 0) { while (si >= 0) {
int csi = fc.find(" main", si); int csi = fc.find(PIStringAscii(" main"), si);
if (csi < 0) csi = fc.find("\tmain", si); if (csi < 0) csi = fc.find(PIStringAscii("\tmain"), si);
if (csi < 0) csi = fc.find("\nmain", si); if (csi < 0) csi = fc.find(PIStringAscii("\nmain"), si);
if (csi < 0) return false; if (csi < 0) return false;
si = csi; si = csi;
int fi = fc.find("(", si + 5); int fi = fc.find('(', si + 5);
if (fi < 0) return false; if (fi < 0) return false;
if (fi - si < 10) { if (fi - si < 10) {
PIString ms(fc.mid(si, fi - si + 1)); PIString ms(fc.mid(si, fi - si + 1));
ms.removeAll(" ").removeAll("\t").removeAll("\n"); ms.removeAll(' ').removeAll('\t').removeAll('\n');
if (ms == "main(") return true; if (ms == PIStringAscii("main(")) return true;
} }
si += 5; si += 5;
} }
@@ -885,17 +919,17 @@ PIString PICodeParser::procMacros(PIString fc) {
bool grab = false, skip = false, cond_ok = false; bool grab = false, skip = false, cond_ok = false;
PIString pfc, nfc, line, mif, mifcond; PIString pfc, nfc, line, mif, mifcond;
//piCout << "procMacros\n<******" << fc << "\n******>"; //piCout << "procMacros\n<******" << fc << "\n******>";
fc += "\n"; fc += '\n';
while (!fc.isEmpty()) { while (!fc.isEmpty()) {
line = fc.takeLine().trimmed(); line = fc.takeLine().trimmed();
if (line.left(1) == "#") { if (line.left(1) == PIChar('#')) {
mifcond = line.mid(1); mifcond = line.mid(1);
mif = mifcond.takeCWord(); mif = mifcond.takeCWord();
//piCout << mif; //piCout << mif;
//piCout << "mif mifcond" << mif << mifcond << ifcnt; //piCout << "mif mifcond" << mif << mifcond << ifcnt;
if (skip || grab) { if (skip || grab) {
if (mif.left(2) == "if") ifcnt++; if (mif.left(2) == PIStringAscii("if")) ifcnt++;
if (mif.left(5) == "endif") { if (mif.left(5) == PIStringAscii("endif")) {
if (ifcnt > 0) ifcnt--; if (ifcnt > 0) ifcnt--;
else { else {
//piCout << "main endif" << skip << grab; //piCout << "main endif" << skip << grab;
@@ -904,7 +938,7 @@ PIString PICodeParser::procMacros(PIString fc) {
continue; continue;
} }
} }
if (mif.left(4) == "elif" && ifcnt == 0) { if (mif.left(4) == PIStringAscii("elif") && ifcnt == 0) {
//piCout << "main elif" << skip << grab << cond_ok; //piCout << "main elif" << skip << grab << cond_ok;
if (cond_ok) { if (cond_ok) {
if (grab) { if (grab) {
@@ -922,17 +956,17 @@ PIString PICodeParser::procMacros(PIString fc) {
} }
continue; continue;
} }
if (mif.left(4) == "else" && ifcnt == 0) { if (mif.left(4) == PIStringAscii("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) {skip = false; grab = true;} if (skip && !cond_ok) {skip = false; grab = true;}
else {skip = true; grab = false;} else {skip = true; grab = false;}
continue; continue;
} }
if (grab) nfc << line << "\n"; if (grab) nfc << line << '\n';
continue; continue;
} }
if (mif.left(2) == "if") { if (mif.left(2) == PIStringAscii("if")) {
//piCout << "main if"; //piCout << "main if";
skip = grab = cond_ok = false; skip = grab = cond_ok = false;
if (macroCondition(mif, mifcond.trimmed())) grab = cond_ok = true; if (macroCondition(mif, mifcond.trimmed())) grab = cond_ok = true;
@@ -944,8 +978,8 @@ PIString PICodeParser::procMacros(PIString fc) {
//return false; /// WARNING: now skip errors //return false; /// WARNING: now skip errors
} }
} else { } else {
if (grab) nfc << line << "\n"; if (grab) nfc << line << '\n';
else if (!skip) pfc << line << "\n"; else if (!skip) pfc << line << '\n';
} }
} }
return pfc; return pfc;
@@ -956,21 +990,21 @@ bool PICodeParser::parseDirective(PIString d) {
if (d.isEmpty()) return true; if (d.isEmpty()) return true;
PIString dname = d.takeCWord(); PIString dname = d.takeCWord();
//piCout << "parseDirective" << d; //piCout << "parseDirective" << d;
if (dname == "include") { if (dname == PIStringAscii("include")) {
d.replaceAll("<", "\"").replaceAll(">", "\""); d.replaceAll('<', '\"').replaceAll('>', '\"');
PIString cf = cur_file, ifc = d.takeRange("\"", "\""); PIString cf = cur_file, ifc = d.takeRange('\"', '\"');
if (with_includes) { if (with_includes) {
bool ret = parseFileInternal(ifc, with_includes); bool ret = parseFileInternal(ifc, with_includes);
cur_file = cf; cur_file = cf;
return ret; return ret;
} }
} }
if (dname == "define") { if (dname == PIStringAscii("define")) {
PIString mname = d.takeCWord(); PIString mname = d.takeCWord();
//piCout << mname; //piCout << mname;
if (mname == "PIMETA") return true; if (mname == PIStringAscii("PIMETA")) return true;
if (d.left(1) == "(") { // macro if (d.left(1) == PIChar('(')) { // macro
PIStringList args = d.takeRange("(", ")").split(",").trim(); PIStringList args = d.takeRange('(', ')').split(',').trim();
macros << Macro(mname, d.trim(), args); macros << Macro(mname, d.trim(), args);
} else { // define } else { // define
d.trim(); d.trim();
@@ -979,7 +1013,7 @@ bool PICodeParser::parseDirective(PIString d) {
} }
return true; return true;
} }
if (dname == "undef") { if (dname == PIStringAscii("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) {defines.remove(i); --i;} if (defines[i].first == mname) {defines.remove(i); --i;}

View File

@@ -33,8 +33,8 @@ class PIP_EXPORT PICodeParser {
public: public:
PICodeParser(); PICodeParser();
enum PIP_EXPORT Visibility {Global, Public, Protected, Private}; enum Visibility {Global, Public, Protected, Private};
enum PIP_EXPORT Attribute { enum Attribute {
NoAttributes = 0x0, NoAttributes = 0x0,
Const = 0x01, Const = 0x01,
Static = 0x02, Static = 0x02,

View File

@@ -1,32 +1,33 @@
/*! \file picompress.h /*! \file picompress.h
* \brief Compress class using zlib * \brief Compress class using zlib
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Compress class using zlib Compress class using zlib
Andrey Bychkov work.a.b@yandex.ru Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PICOMPRESS_H #ifndef PICOMPRESS_H
#define PICOMPRESS_H #define PICOMPRESS_H
#include "pibytearray.h" #include "pip_compress_export.h"
#include "pibytearray.h"
PIByteArray piCompress(const PIByteArray & ba, int level = 6);
PIP_COMPRESS_EXPORT PIByteArray piCompress(const PIByteArray & ba, int level = 6);
PIByteArray piDecompress(const PIByteArray & zba);
PIP_COMPRESS_EXPORT PIByteArray piDecompress(const PIByteArray & zba);
#endif // PICOMPRESS_H
#endif // PICOMPRESS_H

View File

@@ -21,7 +21,6 @@
#define PICONSOLEMODULE_H #define PICONSOLEMODULE_H
#include "pikbdlistener.h" #include "pikbdlistener.h"
#include "piconsole.h"
#include "piscreen.h" #include "piscreen.h"
#include "piscreentiles.h" #include "piscreentiles.h"

View File

@@ -77,7 +77,7 @@ public:
typedef PIFlags<KeyModifier> KeyModifiers; typedef PIFlags<KeyModifier> KeyModifiers;
//! This struct contains information about pressed keyboard key //! This struct contains information about pressed keyboard key
struct KeyEvent { struct PIP_EXPORT KeyEvent {
KeyEvent(int k = 0, KeyModifiers m = 0) {key = k; modifiers = m;} KeyEvent(int k = 0, KeyModifiers m = 0) {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)
@@ -106,7 +106,7 @@ public:
typedef PIFlags<MouseButton> MouseButtons; typedef PIFlags<MouseButton> MouseButtons;
//! This struct contains information about mouse action //! This struct contains information about mouse action
struct MouseEvent { struct PIP_EXPORT MouseEvent {
MouseEvent(MouseAction a = MouseButtonPress, MouseButtons b = 0, KeyModifiers m = 0) {x = y = 0; action = a; buttons = b; modifiers = m;} MouseEvent(MouseAction a = MouseButtonPress, MouseButtons b = 0, KeyModifiers m = 0) {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
@@ -126,18 +126,14 @@ public:
}; };
//! This struct contains information about mouse wheel action //! This struct contains information about mouse wheel action
struct WheelEvent: public MouseEvent { struct PIP_EXPORT WheelEvent: public MouseEvent {
WheelEvent(): MouseEvent() {direction = false;} WheelEvent(): MouseEvent() {direction = false;}
//! Wheel direction, /b true - up, /b fasle - down //! Wheel direction, /b true - up, /b fasle - down
bool direction; bool direction;
}; };
#ifdef PIP_CXX11_SUPPORT
typedef std::function<void(KeyEvent, void *)> KBFunc; typedef std::function<void(KeyEvent, void *)> KBFunc;
#else
typedef void (*KBFunc)(KeyEvent, void * );
#endif
//! Constructs keyboard listener with external function "slot" and custom data "data" //! Constructs keyboard listener with external function "slot" and custom data "data"
explicit PIKbdListener(KBFunc slot = 0, void * data = 0, bool startNow = true); explicit PIKbdListener(KBFunc slot = 0, void * data = 0, bool startNow = true);
@@ -154,10 +150,8 @@ public:
//! Set external function to "slot" //! Set external function to "slot"
void setSlot(KBFunc slot) {ret_func = slot;} void setSlot(KBFunc slot) {ret_func = slot;}
#ifdef PIP_CXX11_SUPPORT
//! Set external function to "slot" //! Set external function to "slot"
void setSlot(std::function<void(KeyEvent)> slot) {ret_func = [slot](KeyEvent e, void *){slot(e);};} void setSlot(std::function<void(KeyEvent)> slot) {ret_func = [slot](KeyEvent e, void *){slot(e);};}
#endif
//! Returns if exit key if awaiting //! Returns if exit key if awaiting
bool exitCaptured() const {return exit_enabled;} bool exitCaptured() const {return exit_enabled;}
@@ -213,7 +207,7 @@ private:
void end(); void end();
#ifndef WINDOWS #ifndef WINDOWS
struct EscSeq { struct PIP_EXPORT EscSeq {
const char * seq; const char * seq;
int key; int key;
int mod; int mod;
@@ -234,7 +228,7 @@ private:
static const EscSeq esc_seq[]; static const EscSeq esc_seq[];
#endif #endif
PRIVATE_DECLARATION PRIVATE_DECLARATION(PIP_EXPORT)
KBFunc ret_func; KBFunc ret_func;
int exit_key; int exit_key;
bool exit_enabled, is_active; bool exit_enabled, is_active;

View File

@@ -1,159 +1,160 @@
/*! \file piscreen.h /*! \file piscreen.h
* \brief Console GUI class * \brief Console GUI class
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console GUI Console GUI
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PISCREEN_H #ifndef PISCREEN_H
#define PISCREEN_H #define PISCREEN_H
#include "piscreentile.h" #include "pip_console_export.h"
#include "piscreendrawer.h" #include "piscreentile.h"
#include "piscreendrawer.h"
class PIP_EXPORT PIScreen: public PIThread, public PIScreenTypes::PIScreenBase
{ class PIP_CONSOLE_EXPORT PIScreen: public PIThread, public PIScreenTypes::PIScreenBase
PIOBJECT_SUBCLASS(PIScreen, PIThread) {
class SystemConsole; PIOBJECT_SUBCLASS(PIScreen, PIThread)
public: class SystemConsole;
public:
//! Constructs %PIScreen with key handler "slot" and if "startNow" start it
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0); //! Constructs %PIScreen with key handler "slot" and if "startNow" start it
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0);
~PIScreen();
~PIScreen();
//! Directly call function from \a PIKbdListener
void enableExitCapture(int key = 'Q') {listener->enableExitCapture(key);} //! Directly call function from \a PIKbdListener
void enableExitCapture(int key = 'Q') {listener->enableExitCapture(key);}
//! Directly call function from \a PIKbdListener
void disableExitCapture() {listener->disableExitCapture();} //! Directly call function from \a PIKbdListener
void disableExitCapture() {listener->disableExitCapture();}
//! Directly call function from \a PIKbdListener
bool exitCaptured() const {return listener->exitCaptured();} //! Directly call function from \a PIKbdListener
bool exitCaptured() const {return listener->exitCaptured();}
//! Directly call function from \a PIKbdListener
int exitKey() const {return listener->exitKey();} //! Directly call function from \a PIKbdListener
int exitKey() const {return listener->exitKey();}
int windowWidth() const {return console.width;}
int windowHeight() const {return console.height;} int windowWidth() const {return console.width;}
int windowHeight() const {return console.height;}
bool isMouseEnabled() const {return mouse_;}
void setMouseEnabled(bool on); bool isMouseEnabled() const {return mouse_;}
void setMouseEnabled(bool on);
PIScreenTile * rootTile() {return &root;}
PIScreenTile * tileByName(const PIString & name); PIScreenTile * rootTile() {return &root;}
PIScreenTile * tileByName(const PIString & name);
void setDialogTile(PIScreenTile * t);
PIScreenTile * dialogTile() const {return tile_dialog;} void setDialogTile(PIScreenTile * t);
PIScreenTile * dialogTile() const {return tile_dialog;}
PIScreenDrawer * drawer() {return &drawer_;}
void clear() {drawer_.clear();} PIScreenDrawer * drawer() {return &drawer_;}
void resize(int w, int h) {console.resize(w, h);} void clear() {drawer_.clear();}
void resize(int w, int h) {console.resize(w, h);}
EVENT_HANDLER0(void, waitForFinish);
EVENT_HANDLER0(void, start) {start(false);} EVENT_HANDLER0(void, waitForFinish);
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();} EVENT_HANDLER0(void, start) {start(false);}
EVENT_HANDLER0(void, stop) {stop(false);} EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
EVENT_HANDLER1(void, stop, bool, clear); EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER1(void, stop, bool, clear);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e) EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e)
//! \handlers
//! \{ //! \handlers
//! \{
//! \fn void waitForFinish()
//! \brief block until finished (exit key will be pressed) //! \fn void waitForFinish()
//! \brief block until finished (exit key will be pressed)
//! \fn void start(bool wait = false)
//! \brief Start console output and if "wait" block until finished (exit key will be pressed) //! \fn void start(bool wait = false)
//! \brief Start console output and if "wait" block until finished (exit key will be pressed)
//! \fn void stop(bool clear = false)
//! \brief Stop console output and if "clear" clear the screen //! \fn void stop(bool clear = false)
//! \brief Stop console output and if "clear" clear the screen
//! \}
//! \events //! \}
//! \{ //! \events
//! \{
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
//! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object //! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
//! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
//! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e)
//! \brief Raise on some event "e" from tile "tile" //! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e)
//! \brief Raise on some event "e" from tile "tile"
//! \}
//! \}
private:
class SystemConsole { private:
public: class PIP_CONSOLE_EXPORT SystemConsole {
SystemConsole(); public:
~SystemConsole(); SystemConsole();
void begin(); ~SystemConsole();
void end(); void begin();
void prepare(); void end();
void clear(); void prepare();
void print(); void clear();
void resize(int w, int h); void print();
void toUpperLeft(); void resize(int w, int h);
void moveTo(int x = 0, int y = 0); void toUpperLeft();
void hideCursor(); void moveTo(int x = 0, int y = 0);
void showCursor(); void hideCursor();
void clearScreen(); void showCursor();
void clearScreenLower(); void clearScreen();
#ifdef WINDOWS void clearScreenLower();
void getWinCurCoord(); #ifdef WINDOWS
void clearLine(); void getWinCurCoord();
void newLine(); void clearLine();
ushort attributes(const PIScreenTypes::Cell & c); void newLine();
#else ushort attributes(const PIScreenTypes::Cell & c);
PIString formatString(const PIScreenTypes::Cell & c); #else
#endif PIString formatString(const PIScreenTypes::Cell & c);
PRIVATE_DECLARATION #endif
int width, height, pwidth, pheight; PRIVATE_DECLARATION(PIP_CONSOLE_EXPORT)
int mouse_x, mouse_y; int width, height, pwidth, pheight;
PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells; int mouse_x, mouse_y;
}; PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells;
};
void begin();
void run(); void begin();
void end(); void run();
void key_event(PIKbdListener::KeyEvent key); void end();
EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me); void key_event(PIKbdListener::KeyEvent key);
EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we); EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me);
static void key_eventS(PIKbdListener::KeyEvent key, void * t) {((PIScreen*)t)->key_event(key);} EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we);
PIVector<PIScreenTile*> tiles() {return root.children();} static void key_eventS(PIKbdListener::KeyEvent key, void * t) {((PIScreen*)t)->key_event(key);}
PIVector<PIScreenTile*> prepareMouse(PIKbdListener::MouseEvent * e); PIVector<PIScreenTile*> tiles() {return root.children();}
PIVector<PIScreenTile*> tilesUnderMouse(int x, int y); PIVector<PIScreenTile*> prepareMouse(PIKbdListener::MouseEvent * e);
bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent()); PIVector<PIScreenTile*> tilesUnderMouse(int x, int y);
void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e); bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent());
void tileRemovedInternal(PIScreenTile * t); void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e);
void tileSetFocusInternal(PIScreenTile * t); void tileRemovedInternal(PIScreenTile * t);
void tileSetFocusInternal(PIScreenTile * t);
bool mouse_;
SystemConsole console; bool mouse_;
PIScreenDrawer drawer_; SystemConsole console;
PIKbdListener * listener; PIScreenDrawer drawer_;
PIKbdListener::KBFunc ret_func; PIKbdListener * listener;
PIScreenTile root; PIKbdListener::KBFunc ret_func;
PIScreenTile * tile_focus, * tile_dialog; PIScreenTile root;
PIScreenTile * tile_focus, * tile_dialog;
};
};
#endif // PISCREEN_H
#endif // PISCREEN_H

View File

@@ -1,77 +1,78 @@
/*! \file piscreenconsole.h /*! \file piscreenconsole.h
* \brief Tile for PIScreen with PIConsole API * \brief Tile for PIScreen with PIConsole API
* *
* This file declares TileVars * This file declares TileVars
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API Tile for PIScreen with PIConsole API
Andrey Bychkov work.a.b@yandex.ru Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PISCREENCONSOLE_H #ifndef PISCREENCONSOLE_H
#define PISCREENCONSOLE_H #define PISCREENCONSOLE_H
#include "piscreentiles.h" #include "pip_console_export.h"
#include "piscreentiles.h"
/// NOTE: incomplete class
/// TODO: write TileVars /// NOTE: incomplete class
/// TODO: write TileVars
class PIP_EXPORT TileVars: public PIScreenTile {
public: class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile {
TileVars(const PIString & n = PIString()); public:
protected: TileVars(const PIString & n = PIString());
struct Variable { protected:
Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = PIScreenTypes::CellFormat(); ptr = 0;} struct PIP_CONSOLE_EXPORT Variable {
bool isEmpty() const {return (ptr == 0);} Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = PIScreenTypes::CellFormat(); ptr = 0;}
PIString name; bool isEmpty() const {return (ptr == 0);}
PIScreenTypes::CellFormat format; PIString name;
int nx; PIScreenTypes::CellFormat format;
int ny; int nx;
int type; int ny;
int offset; int type;
int bitFrom; int offset;
int bitCount; int bitFrom;
int size; int bitCount;
const void * ptr; int size;
/*void operator =(const Variable & src) { const void * ptr;
name = src.name; /*void operator =(const Variable & src) {
format = src.format; name = src.name;
nx = src.nx; format = src.format;
ny = src.ny; nx = src.nx;
type = src.type; ny = src.ny;
offset = src.offset; type = src.type;
bitFrom = src.bitFrom; offset = src.offset;
bitCount = src.bitCount; bitFrom = src.bitFrom;
size = src.size; bitCount = src.bitCount;
ptr = src.ptr; size = src.size;
}*/ ptr = src.ptr;
}; }*/
PIVector<Variable> variables; };
PIScreenTypes::Alignment alignment; PIVector<Variable> variables;
void sizeHint(int & w, int & h) const; PIScreenTypes::Alignment alignment;
void drawEvent(PIScreenDrawer * d); void sizeHint(int & w, int & h) const;
}; void drawEvent(PIScreenDrawer * d);
};
class PIP_EXPORT PIScreenConsoleTile : public PIScreenTile
{ class PIP_CONSOLE_EXPORT PIScreenConsoleTile : public PIScreenTile
public: {
PIScreenConsoleTile(); public:
}; PIScreenConsoleTile();
};
#endif // PISCREENCONSOLE_H
#endif // PISCREENCONSOLE_H

View File

@@ -1,68 +1,69 @@
/*! \file piscreendrawer.h /*! \file piscreendrawer.h
* \brief Drawer for PIScreen * \brief Drawer for PIScreen
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Drawer for PIScreen Drawer for PIScreen
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PISCREENDRAWER_H #ifndef PISCREENDRAWER_H
#define PISCREENDRAWER_H #define PISCREENDRAWER_H
#include "piscreentypes.h" #include "pip_console_export.h"
#include "pistring.h" #include "piscreentypes.h"
#include "pistring.h"
class PIP_EXPORT PIScreenDrawer
{ class PIP_CONSOLE_EXPORT PIScreenDrawer
friend class PIScreen; {
PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell> > & c); friend class PIScreen;
public: PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell> > & c);
enum ArtChar { public:
LineVertical = 1, enum ArtChar {
LineHorizontal, LineVertical = 1,
Cross, LineHorizontal,
CornerTopLeft, Cross,
CornerTopRight, CornerTopLeft,
CornerBottomLeft, CornerTopRight,
CornerBottomRight, CornerBottomLeft,
Unchecked, CornerBottomRight,
Checked Unchecked,
}; Checked
};
void clear();
void clearRect(int x0, int y0, int x1, int y1) {fillRect(x0, y0, x1, y1, ' ');} void clear();
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); void clearRect(int x0, int y0, int x1, int y1) {fillRect(x0, y0, x1, y1, ' ');}
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 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);
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 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 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 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 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 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 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 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, PIVector<PIVector<PIScreenTypes::Cell> > & content); 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);
PIChar artChar(const ArtChar type) const {return arts_.value(type, PIChar(' '));}
PIChar artChar(const ArtChar type) const {return arts_.value(type, PIChar(' '));}
static void clear(PIVector<PIVector<PIScreenTypes::Cell> > & cells);
static void clear(PIVector<PIVector<PIScreenTypes::Cell> > & cells);
private:
PIVector<PIVector<PIScreenTypes::Cell> > & cells; private:
int width, height; PIVector<PIVector<PIScreenTypes::Cell> > & cells;
PIMap<ArtChar, PIChar> arts_; int width, height;
PIMap<ArtChar, PIChar> arts_;
};
};
#endif // PISCREENDRAWER_H
#endif // PISCREENDRAWER_H

View File

@@ -1,106 +1,107 @@
/*! \file piscreentile.h /*! \file piscreentile.h
* \brief Basic PIScreen tile * \brief Basic PIScreen tile
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic PIScreen tile Basic PIScreen tile
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PISCREENTILE_H #ifndef PISCREENTILE_H
#define PISCREENTILE_H #define PISCREENTILE_H
#include "piscreentypes.h" #include "pip_console_export.h"
#include "pikbdlistener.h" #include "piscreentypes.h"
#include "pikbdlistener.h"
class PIScreenDrawer;
class PIScreenDrawer;
class PIP_EXPORT PIScreenTile: public PIObject {
friend class PIScreen; class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
PIOBJECT_SUBCLASS(PIScreenTile, PIObject) friend class PIScreen;
public: PIOBJECT_SUBCLASS(PIScreenTile, PIObject)
PIScreenTile(const PIString & n = PIString(), PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred); public:
virtual ~PIScreenTile(); PIScreenTile(const PIString & n = PIString(), PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
virtual ~PIScreenTile();
void addTile(PIScreenTile * t);
void takeTile(PIScreenTile * t); void addTile(PIScreenTile * t);
void removeTile(PIScreenTile * t); void takeTile(PIScreenTile * t);
PIScreenTile * parentTile() const {return parent;} void removeTile(PIScreenTile * t);
PIVector<PIScreenTile * > children(bool only_visible = false); PIScreenTile * parentTile() const {return parent;}
PIScreenTile * childUnderMouse(int x, int y); PIVector<PIScreenTile * > children(bool only_visible = false);
void show() {visible = true;} PIScreenTile * childUnderMouse(int x, int y);
void hide() {visible = false;} void show() {visible = true;}
void setFocus(); void hide() {visible = false;}
bool hasFocus() const {return has_focus;} void setFocus();
void setMargins(int m) {marginLeft = marginRight = marginTop = marginBottom = m;} bool hasFocus() const {return has_focus;}
void setMargins(int l, int r, int t, int b) {marginLeft = l; marginRight = r; marginTop = t; marginBottom = b;} void setMargins(int m) {marginLeft = marginRight = marginTop = marginBottom = m;}
void setMargins(int l, int r, int t, int b) {marginLeft = l; marginRight = r; marginTop = t; marginBottom = b;}
int x() const {return x_;}
int y() const {return y_;} int x() const {return x_;}
int width() const {return width_;} int y() const {return y_;}
int height() const {return height_;} int width() const {return width_;}
int height() const {return height_;}
PIScreenTypes::Direction direction;
PIScreenTypes::SizePolicy size_policy; PIScreenTypes::Direction direction;
PIScreenTypes::FocusFlags focus_flags; PIScreenTypes::SizePolicy size_policy;
PIScreenTypes::CellFormat back_format; PIScreenTypes::FocusFlags focus_flags;
PIChar back_symbol; PIScreenTypes::CellFormat back_format;
int minimumWidth, minimumHeight; PIChar back_symbol;
int maximumWidth, maximumHeight; int minimumWidth, minimumHeight;
int marginLeft, marginRight, marginTop, marginBottom; int maximumWidth, maximumHeight;
int spacing; int marginLeft, marginRight, marginTop, marginBottom;
bool visible; int spacing;
bool visible;
protected:
protected:
//! Returns desired tile size in "w" and "h"
virtual void sizeHint(int & w, int & h) const; //! Returns desired tile size in "w" and "h"
virtual void sizeHint(int & w, int & h) const;
//! Tile has been resized to "w"x"h"
virtual void resizeEvent(int w, int h) {} //! Tile has been resized to "w"x"h"
virtual void resizeEvent(int w, int h) {}
//! Draw tile with drawer "d" in world-space coordinates
virtual void drawEvent(PIScreenDrawer * d) {} //! Draw tile with drawer "d" in world-space coordinates
virtual void drawEvent(PIScreenDrawer * d) {}
//! Return "true" if you process key
virtual bool keyEvent(PIKbdListener::KeyEvent key) {return false;} //! Return "true" if you process key
virtual bool keyEvent(PIKbdListener::KeyEvent key) {return false;}
//! Return "true" if you process event
virtual bool mouseEvent(PIKbdListener::MouseEvent me) {return false;} //! Return "true" if you process event
virtual bool mouseEvent(PIKbdListener::MouseEvent me) {return false;}
//! Return "true" if you process wheel
virtual bool wheelEvent(PIKbdListener::WheelEvent we) {return false;} //! Return "true" if you process wheel
virtual bool wheelEvent(PIKbdListener::WheelEvent we) {return false;}
void raiseEvent(PIScreenTypes::TileEvent e);
void setScreen(PIScreenTypes::PIScreenBase * s); void raiseEvent(PIScreenTypes::TileEvent e);
void deleteChildren(); void setScreen(PIScreenTypes::PIScreenBase * s);
void drawEventInternal(PIScreenDrawer * d); void deleteChildren();
void layout(); void drawEventInternal(PIScreenDrawer * d);
bool needLayout() {return size_policy != PIScreenTypes::Ignore;} void layout();
bool needLayout() {return size_policy != PIScreenTypes::Ignore;}
PIVector<PIScreenTile * > tiles;
PIScreenTile * parent; PIVector<PIScreenTile * > tiles;
PIScreenTypes::PIScreenBase * screen; PIScreenTile * parent;
int x_, y_, width_, height_; PIScreenTypes::PIScreenBase * screen;
bool has_focus; int x_, y_, width_, height_;
bool has_focus;
private:
int pw, ph; private:
int pw, ph;
};
};
#endif // PISCREENTILE_H
#endif // PISCREENTILE_H

View File

@@ -1,213 +1,214 @@
/*! \file piscreentiles.h /*! \file piscreentiles.h
* \brief Various tiles for PIScreen * \brief Various tiles for PIScreen
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Various tiles for PIScreen Various tiles for PIScreen
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PISCREENTILES_H #ifndef PISCREENTILES_H
#define PISCREENTILES_H #define PISCREENTILES_H
#include "piscreentile.h" #include "pip_console_export.h"
#include "piscreentile.h"
class PIP_EXPORT TileSimple: public PIScreenTile {
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile) class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
public: PIOBJECT_SUBCLASS(TileSimple, PIScreenTile)
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; public:
TileSimple(const PIString & n = PIString()); typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
TileSimple(const Row & r); TileSimple(const PIString & n = PIString());
virtual ~TileSimple() {} TileSimple(const Row & r);
PIVector<Row> content; virtual ~TileSimple() {}
PIScreenTypes::Alignment alignment; PIVector<Row> content;
protected: PIScreenTypes::Alignment alignment;
void sizeHint(int & w, int & h) const; protected:
void drawEvent(PIScreenDrawer * d); void sizeHint(int & w, int & h) const;
}; void drawEvent(PIScreenDrawer * d);
};
class TileList;
class TileList;
class PIP_EXPORT TileScrollBar: public PIScreenTile {
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile) class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
friend class TileList; PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile)
public: friend class TileList;
TileScrollBar(const PIString & n = PIString()); public:
virtual ~TileScrollBar() {} TileScrollBar(const PIString & n = PIString());
void setMinimum(int v); virtual ~TileScrollBar() {}
void setMaximum(int v); void setMinimum(int v);
void setValue(int v); void setMaximum(int v);
int minimum() const {return minimum_;} void setValue(int v);
int maximum() const {return maximum_;} int minimum() const {return minimum_;}
int value() const {return value_;} int maximum() const {return maximum_;}
int thickness; int value() const {return value_;}
protected: int thickness;
void _check(); protected:
void sizeHint(int & w, int & h) const; void _check();
void drawEvent(PIScreenDrawer * d); void sizeHint(int & w, int & h) const;
bool mouseEvent(PIKbdListener::MouseEvent me); void drawEvent(PIScreenDrawer * d);
int minimum_, maximum_, value_; bool mouseEvent(PIKbdListener::MouseEvent me);
PIChar line_char; int minimum_, maximum_, value_;
}; PIChar line_char;
};
class PIP_EXPORT TileList: public PIScreenTile {
PIOBJECT_SUBCLASS(TileList, PIScreenTile) class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
public: PIOBJECT_SUBCLASS(TileList, PIScreenTile)
TileList(const PIString & n = PIString()); public:
virtual ~TileList() {} TileList(const PIString & n = PIString());
enum SelectionMode { virtual ~TileList() {}
NoSelection, enum SelectionMode {
SingleSelection, NoSelection,
MultiSelection SingleSelection,
}; MultiSelection
enum EventType { };
SelectionChanged, enum EventType {
RowPressed SelectionChanged,
}; RowPressed
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; };
PIDeque<Row> content; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
PIScreenTypes::Alignment alignment; PIDeque<Row> content;
SelectionMode selection_mode; PIScreenTypes::Alignment alignment;
PISet<int> selected; SelectionMode selection_mode;
int lhei, cur, offset; PISet<int> selected;
protected: int lhei, cur, offset;
void sizeHint(int & w, int & h) const; protected:
void resizeEvent(int w, int h); void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d); void resizeEvent(int w, int h);
bool keyEvent(PIKbdListener::KeyEvent key); void drawEvent(PIScreenDrawer * d);
bool mouseEvent(PIKbdListener::MouseEvent me); bool keyEvent(PIKbdListener::KeyEvent key);
bool wheelEvent(PIKbdListener::WheelEvent we); bool mouseEvent(PIKbdListener::MouseEvent me);
TileScrollBar * scroll; bool wheelEvent(PIKbdListener::WheelEvent we);
bool mouse_sel; TileScrollBar * scroll;
}; bool mouse_sel;
};
class PIP_EXPORT TileButton: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButton, PIScreenTile) class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
public: PIOBJECT_SUBCLASS(TileButton, PIScreenTile)
TileButton(const PIString & n = PIString()); public:
virtual ~TileButton() {} TileButton(const PIString & n = PIString());
enum EventType { virtual ~TileButton() {}
ButtonClicked enum EventType {
}; ButtonClicked
PIScreenTypes::CellFormat format; };
PIString text; PIScreenTypes::CellFormat format;
protected: PIString text;
void sizeHint(int & w, int & h) const; protected:
void drawEvent(PIScreenDrawer * d); void sizeHint(int & w, int & h) const;
bool keyEvent(PIKbdListener::KeyEvent key); void drawEvent(PIScreenDrawer * d);
bool mouseEvent(PIKbdListener::MouseEvent me); bool keyEvent(PIKbdListener::KeyEvent key);
}; bool mouseEvent(PIKbdListener::MouseEvent me);
};
class PIP_EXPORT TileButtons: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile) class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
public: PIOBJECT_SUBCLASS(TileButtons, PIScreenTile)
TileButtons(const PIString & n = PIString()); public:
virtual ~TileButtons() {} TileButtons(const PIString & n = PIString());
enum EventType { virtual ~TileButtons() {}
ButtonSelected enum EventType {
}; ButtonSelected
typedef PIPair<PIString, PIScreenTypes::CellFormat> Button; };
PIScreenTypes::Alignment alignment; typedef PIPair<PIString, PIScreenTypes::CellFormat> Button;
PIVector<Button> content; PIScreenTypes::Alignment alignment;
int cur; PIVector<Button> content;
protected: int cur;
void sizeHint(int & w, int & h) const; protected:
void drawEvent(PIScreenDrawer * d); void sizeHint(int & w, int & h) const;
bool keyEvent(PIKbdListener::KeyEvent key); void drawEvent(PIScreenDrawer * d);
bool mouseEvent(PIKbdListener::MouseEvent me); bool keyEvent(PIKbdListener::KeyEvent key);
struct Rect { bool mouseEvent(PIKbdListener::MouseEvent me);
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0),y0(_y0),x1(_x1),y1(_y1) {} struct Rect {
int x0,y0,x1,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;
PIVector<Rect> btn_rects; };
}; PIVector<Rect> btn_rects;
};
class PIP_EXPORT TileCheck: public PIScreenTile {
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile) class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
public: PIOBJECT_SUBCLASS(TileCheck, PIScreenTile)
TileCheck(const PIString & n = PIString()); public:
virtual ~TileCheck() {} TileCheck(const PIString & n = PIString());
enum EventType { virtual ~TileCheck() {}
Toggled enum EventType {
}; Toggled
PIScreenTypes::CellFormat format; };
PIString text; PIScreenTypes::CellFormat format;
bool toggled; PIString text;
protected: bool toggled;
void sizeHint(int & w, int & h) const; protected:
void drawEvent(PIScreenDrawer * d); void sizeHint(int & w, int & h) const;
bool keyEvent(PIKbdListener::KeyEvent key); void drawEvent(PIScreenDrawer * d);
bool mouseEvent(PIKbdListener::MouseEvent me); bool keyEvent(PIKbdListener::KeyEvent key);
}; bool mouseEvent(PIKbdListener::MouseEvent me);
};
class PIP_EXPORT TileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile) class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
public: PIOBJECT_SUBCLASS(TileProgress, PIScreenTile)
TileProgress(const PIString & n = PIString()); public:
virtual ~TileProgress() {} TileProgress(const PIString & n = PIString());
PIScreenTypes::CellFormat format; virtual ~TileProgress() {}
PIString prefix; PIScreenTypes::CellFormat format;
PIString suffix; PIString prefix;
double maximum; PIString suffix;
double value; double maximum;
protected: double value;
void sizeHint(int & w, int & h) const; protected:
void drawEvent(PIScreenDrawer * d); void sizeHint(int & w, int & h) const;
}; void drawEvent(PIScreenDrawer * d);
};
class PIP_EXPORT TilePICout: public TileList {
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile) class PIP_CONSOLE_EXPORT TilePICout: public TileList {
public: PIOBJECT_SUBCLASS(TilePICout, PIScreenTile)
TilePICout(const PIString & n = PIString()); public:
virtual ~TilePICout() {} TilePICout(const PIString & n = PIString());
PIScreenTypes::CellFormat format; virtual ~TilePICout() {}
int max_lines; PIScreenTypes::CellFormat format;
protected: int max_lines;
void drawEvent(PIScreenDrawer * d); protected:
bool keyEvent(PIKbdListener::KeyEvent key); void drawEvent(PIScreenDrawer * d);
}; bool keyEvent(PIKbdListener::KeyEvent key);
};
class PIP_EXPORT TileInput: public PIScreenTile {
PIOBJECT_SUBCLASS(TileInput, PIScreenTile) class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
public: PIOBJECT_SUBCLASS(TileInput, PIScreenTile)
TileInput(const PIString & n = PIString()); public:
virtual ~TileInput() {} TileInput(const PIString & n = PIString());
PIScreenTypes::CellFormat format; virtual ~TileInput() {}
PIString text; PIScreenTypes::CellFormat format;
int max_length; PIString text;
protected: int max_length;
void sizeHint(int & w, int & h) const; protected:
void drawEvent(PIScreenDrawer * d); void sizeHint(int & w, int & h) const;
bool keyEvent(PIKbdListener::KeyEvent key); void drawEvent(PIScreenDrawer * d);
void reserCursor(); bool keyEvent(PIKbdListener::KeyEvent key);
int cur, offset; void reserCursor();
bool inv; int cur, offset;
PITimeMeasurer tm_blink; bool inv;
}; PITimeMeasurer tm_blink;
};
#endif // PISCREENTILES_H
#endif // PISCREENTILES_H

View File

@@ -1,146 +1,147 @@
/*! \file piscreentypes.h /*! \file piscreentypes.h
* \brief Types for PIScreen * \brief Types for PIScreen
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Types for PIScreen Types for PIScreen
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PISCREENTYPES_H #ifndef PISCREENTYPES_H
#define PISCREENTYPES_H #define PISCREENTYPES_H
#include "pivariant.h" #include "pip_console_export.h"
#include "pivariant.h"
class PIScreenTile;
class PIScreenTile;
namespace PIScreenTypes {
namespace PIScreenTypes {
//! Color for chars or background
enum PIP_EXPORT Color { //! Color for chars or background
Default /** Default */, enum Color {
Black /** Black */, Default /** Default */,
Red /** Red */, Black /** Black */,
Green /** Green */, Red /** Red */,
Blue /** Blue */, Green /** Green */,
Cyan /** Cyan */, Blue /** Blue */,
Magenta /** Magenta */, Cyan /** Cyan */,
Yellow /** Yellow */, Magenta /** Magenta */,
White /** White */, Yellow /** Yellow */,
Transparent /** Save previous color */ White /** White */,
}; Transparent /** Save previous color */
};
//! Flags for chars
enum PIP_EXPORT CharFlag { //! Flags for chars
Bold /** Bold or bright */ = 0x1, enum CharFlag {
Blink /** Blink text */ = 0x2, Bold /** Bold or bright */ = 0x1,
Underline /** Underline text */ = 0x4, Blink /** Blink text */ = 0x2,
Inverse = 0x08 Underline /** Underline text */ = 0x4,
}; Inverse = 0x08
};
//! Alignment
enum PIP_EXPORT Alignment { //! Alignment
Left /** Left */ , enum Alignment {
Center /** Center */ , Left /** Left */ ,
Right /** Right */ Center /** Center */ ,
}; Right /** Right */
};
//! Size policy
enum PIP_EXPORT SizePolicy { //! Size policy
Fixed /** Fixed size */ , enum SizePolicy {
Preferred /** Preferred size */ , Fixed /** Fixed size */ ,
Expanding /** Maximum available size */ , Preferred /** Preferred size */ ,
Ignore /** Ignore layout logic */ Expanding /** Maximum available size */ ,
}; Ignore /** Ignore layout logic */
};
//! Direction
enum PIP_EXPORT Direction { //! Direction
Horizontal /** Horizontal */ , enum Direction {
Vertical /** Vertical */ Horizontal /** Horizontal */ ,
}; Vertical /** Vertical */
};
//! Focus flags
enum PIP_EXPORT FocusFlag { //! Focus flags
CanHasFocus /** Tile can has focus */ = 0x1, enum FocusFlag {
NextByTab /** Focus passed to next tile by tab key */ = 0x2, CanHasFocus /** Tile can has focus */ = 0x1,
NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4, NextByTab /** Focus passed to next tile by tab key */ = 0x2,
NextByArrowsVertical /** Focus passed to next tile by arrow keys up or down */ = 0x8, NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4,
NextByArrowsAll /** Focus passed to next tile by any arrow key */ = NextByArrowsHorizontal | NextByArrowsVertical, NextByArrowsVertical /** Focus passed to next tile by arrow keys up or down */ = 0x8,
FocusOnMouse /** Tile focused on mouse press */ = 0x10, NextByArrowsAll /** Focus passed to next tile by any arrow key */ = NextByArrowsHorizontal | NextByArrowsVertical,
FocusOnWheel /** Tile focused on wheel */ = 0x20, FocusOnMouse /** Tile focused on mouse press */ = 0x10,
FocusOnMouseOrWheel /** Tile focused on mouse press or wheel */ = FocusOnMouse | FocusOnWheel FocusOnWheel /** Tile focused on wheel */ = 0x20,
}; FocusOnMouseOrWheel /** Tile focused on mouse press or wheel */ = FocusOnMouse | FocusOnWheel
};
typedef PIFlags<CharFlag> CharFlags;
typedef PIFlags<FocusFlag> FocusFlags; typedef PIFlags<CharFlag> CharFlags;
typedef PIFlags<FocusFlag> FocusFlags;
union PIP_EXPORT CellFormat {
CellFormat(ushort f = 0) {raw_format = f;} union PIP_CONSOLE_EXPORT CellFormat {
CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) { CellFormat(ushort f = 0) {raw_format = f;}
color_char = col_char; CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) {
color_back = col_back; color_char = col_char;
flags = flags_; color_back = col_back;
} flags = flags_;
ushort raw_format; }
struct { ushort raw_format;
ushort color_char : 4; struct {
ushort color_back : 4; ushort color_char : 4;
ushort flags : 8; ushort color_back : 4;
}; ushort flags : 8;
bool operator ==(const CellFormat & c) const {return raw_format == c.raw_format;} };
bool operator !=(const CellFormat & c) const {return raw_format != c.raw_format;} bool operator ==(const CellFormat & c) const {return raw_format == c.raw_format;}
}; bool operator !=(const CellFormat & c) const {return raw_format != c.raw_format;}
};
struct PIP_EXPORT Cell {
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {symbol = c; format = f;} struct PIP_CONSOLE_EXPORT Cell {
CellFormat format; Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {symbol = c; format = f;}
PIChar symbol; CellFormat format;
bool operator ==(const Cell & c) const {return format == c.format && symbol == c.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;}
Cell & operator =(const Cell & c) { bool operator !=(const Cell & c) const {return format != c.format || symbol != c.symbol;}
symbol = c.symbol; Cell & operator =(const Cell & c) {
if (c.format.color_back == Transparent) { symbol = c.symbol;
format.color_char = c.format.color_char; if (c.format.color_back == Transparent) {
format.flags = c.format.flags; format.color_char = c.format.color_char;
} else format = c.format; format.flags = c.format.flags;
return *this; } else format = c.format;
} return *this;
}; }
};
struct PIP_EXPORT TileEvent {
TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {} struct PIP_CONSOLE_EXPORT TileEvent {
int type; TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
PIVariant data; int type;
}; PIVariant data;
};
class PIScreenBase {
public: class PIP_CONSOLE_EXPORT PIScreenBase {
PIScreenBase() {} public:
virtual ~PIScreenBase() {} PIScreenBase() {}
virtual void tileEventInternal(PIScreenTile * , TileEvent) {} virtual ~PIScreenBase() {}
virtual void tileRemovedInternal(PIScreenTile * ) {} virtual void tileEventInternal(PIScreenTile * , TileEvent) {}
virtual void tileSetFocusInternal(PIScreenTile * ) {} virtual void tileRemovedInternal(PIScreenTile * ) {}
}; virtual void tileSetFocusInternal(PIScreenTile * ) {}
};
}
}
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
#endif // PISCREENTYPES_H
#endif // PISCREENTYPES_H

View File

@@ -1,76 +1,77 @@
/*! \file piterminal.h /*! \file piterminal.h
* \brief Virtual terminal * \brief Virtual terminal
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Virtual terminal Virtual terminal
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PITERMINAL_H #ifndef PITERMINAL_H
#define PITERMINAL_H #define PITERMINAL_H
#include "pikbdlistener.h" #include "pip_console_export.h"
#include "piscreentypes.h" #include "pikbdlistener.h"
#include "piscreentypes.h"
class PIP_EXPORT PITerminal: public PIThread
{ class PIP_CONSOLE_EXPORT PITerminal: public PIThread
PIOBJECT_SUBCLASS(PITerminal, PIThread) {
public: PIOBJECT_SUBCLASS(PITerminal, PIThread)
public:
//! Constructs %PITerminal
PITerminal(); //! Constructs %PITerminal
PITerminal();
~PITerminal();
~PITerminal();
int columns() const {return size_x;}
int rows() const {return size_y;} int columns() const {return size_x;}
bool resize(int cols, int rows); int rows() const {return size_y;}
bool resize(int cols, int rows);
void write(const PIByteArray & d);
void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m); void write(const PIByteArray & d);
void write(PIKbdListener::KeyEvent ke); void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m);
PIVector<PIVector<PIScreenTypes::Cell> > content(); void write(PIKbdListener::KeyEvent ke);
static bool isSpecialKey(int k); PIVector<PIVector<PIScreenTypes::Cell> > content();
static bool isSpecialKey(int k);
bool initialize();
void destroy(); bool initialize();
private: void destroy();
void initPrivate(); private:
void readConsole(); void initPrivate();
void getCursor(int & x, int & y); void readConsole();
uchar invertColor(uchar c); void getCursor(int & x, int & y);
void run(); uchar invertColor(uchar c);
#ifndef WINDOWS void run();
void parseInput(const PIString & s); #ifndef WINDOWS
bool isCompleteEscSeq(const PIString & es); void parseInput(const PIString & s);
void applyEscSeq(PIString es); bool isCompleteEscSeq(const PIString & es);
void moveCursor(int dx, int dy); void applyEscSeq(PIString es);
int termType(const PIString & t); void moveCursor(int dx, int dy);
#endif int termType(const PIString & t);
#endif
PRIVATE_DECLARATION
int dsize_x, dsize_y; PRIVATE_DECLARATION(PIP_CONSOLE_EXPORT)
int size_x, size_y, cursor_x, cursor_y; int dsize_x, dsize_y;
bool cursor_blink, cursor_visible; int size_x, size_y, cursor_x, cursor_y;
PITimeMeasurer cursor_tm; bool cursor_blink, cursor_visible;
PIVector<PIVector<PIScreenTypes::Cell> > cells; PITimeMeasurer cursor_tm;
PIVector<PIVector<PIScreenTypes::Cell> > cells;
};
};
#endif // PITERMINAL_H
#endif // PITERMINAL_H

View File

@@ -0,0 +1,374 @@
/*
PIP - Platform Independent Primitives
Generic containers
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \class PIVector
* \brief Dynamic array of any type
* \details This class used to store dynamic array of any
* type of data. In memory data stored linear. You can insert
* item in any place of remove some items from any place.
* For quick add elements this is stream operator <<.
* \fn PIVector::PIVector();
* Contructs an empty vector
* \fn PIVector::PIVector(size_t size, const T & value = T());
* \brief Contructs vector with size "size" filled elements "value"
* \details Example: \snippet picontainers.cpp PIVector::PIVector
* \fn const T & PIVector::at(size_t index) const;
* \brief Read-only access to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::at_c
* \sa \a operator[]
* \fn T & PIVector::at(size_t index);
* \brief Full access to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::at
* \sa \a operator[]
* \fn const T * PIVector::data(size_t index = 0) const;
* \brief Read-only pointer to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::data_c
* \fn T * PIVector::data(size_t index = 0);
* \brief Pointer to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::data
* \fn size_t PIVector::size() const;
* \brief Elements count
* \fn ssize_t PIVector::size_s() const;
* \brief Elements count
* \fn bool PIVector::isEmpty() const;
* \brief Return \c "true" if vector is empty, i.e. size = 0
* \fn bool PIVector::has(const T & t) const;
* \fn bool PIVector::contains(const T & v) const;
* \brief Return \c "true" if vector has at least one element equal "t"
* \fn int PIVector::etries(const T & t) const;
* \brief Return how many times element "t" appears in vector
* \fn ssize_t PIVector::indexOf(const T & t) const;
* \brief Return index of first element equal "t" or -1 if there is no such element
* \fn ssize_t PIVector::lastIndexOf(const T & t) const;
* \brief Return index of last element equal "t" or -1 if there is no such element
* \fn static int PIVector::compare_func(const T * t0, const T * t1);
* \brief Standard compare function for type "T". Return 0 if t0 = t1, -1 if t0 < t1 and 1 if t0 > t1.
* \fn void PIVector::resize(size_t size, const T & new_type = T());
* \brief Resize vector to size "size"
* \details Elements removed from end of vector if new size < old size, or added new elements = "new_type" if new size > old size.\n
* Example: \snippet picontainers.cpp PIVector::resize
* \sa \a size(), \a clear()
* \fn PIVector & PIVector::enlarge(size_t size);
* \brief Increase vector size with "size" elements
* \fn void PIVector::clear();
* \brief Clear vector. Equivalent to call <tt>"resize(0)"</tt>
* \fn PIVector & PIVector::sort(CompareFunc compare = compare_func);
* \brief Sort vector using quick sort algorithm and standard compare function
* \details Example: \snippet picontainers.cpp PIVector::sort_0
* With custom compare function: \snippet picontainers.cpp PIVector::sort_1
* \fn PIVector & PIVector::fill(const T & t);
* \brief Fill vector with elements "t" leave size is unchanged and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::fill
* \fn PIVector & PIVector::assign(const T & t = T());
* \brief Synonym of \a fill(t)
* \fn PIVector & PIVector::assign(size_t new_size, const T & t);
* \brief Resize to "new_size", then fill with "t"
* \fn T & PIVector::back();
* \brief Last element of the vector
* \fn const T & PIVector::back() const;
* \brief Last element of the vector
* \fn T & PIVector::front();
* \brief First element of the vector
* \fn const T & PIVector::front() const;
* \brief First element of the vector
* \fn PIVector & PIVector::push_back(const T & t);
* \brief Add new element "t" at the end of vector and return reference to vector
* \fn PIVector & PIVector::push_front(const T & t);
* \brief Add new element "t" at the beginning of vector and return reference to vector
* \fn PIVector & PIVector::pop_back();
* \brief Remove one element from the end of vector and return reference to vector
* \fn PIVector & PIVector::pop_front();
* \brief Remove one element from the beginning of vector and return reference to vector
* \fn T PIVector::take_back();
* \brief Remove one element from the end of vector and return it
* \fn T PIVector::take_front();
* \brief Remove one element from the beginning of vector and return it
* \fn PIVector & PIVector::remove(size_t index);
* \brief Remove one element by index "index" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::remove_0
* \sa \a removeOne(), \a removeAll()
* \fn PIVector & PIVector::remove(size_t index, size_t count);
* \brief Remove "count" elements by first index "index" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::remove_1
* \sa \a removeOne(), \a removeAll()
* \fn PIVector & PIVector::removeOne(const T & v);
* \brief Remove no more than one element equal "v" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::removeOne
* \sa \a remove(), \a removeAll()
* \fn PIVector & PIVector::removeAll(const T & v);
* \brief Remove all elements equal "v" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::removeAll
* \sa \a remove(), \a removeOne()
* \fn PIVector & PIVector::insert(size_t pos, const T & t);
* \brief Insert element "t" after index "pos" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::insert_0
* \fn PIVector & PIVector::insert(size_t pos, const PIVector & t);
* \brief Insert other vector "t" after index "pos" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::insert_1
* \fn T & PIVector::operator [](size_t index);
* \brief Full access to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::()
* \sa \a at()
* \fn const T & PIVector::operator [](size_t index) const;
* \brief Read-only access to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::()_c
* \sa \a at()
* \fn PIVector & PIVector::operator <<(const T & t);
* \brief Add new element "t" at the end of vector and return reference to vector
* \fn PIVector & PIVector::operator <<(const PIVector & t);
* \brief Add vector "t" at the end of vector and return reference to vector
* \fn bool PIVector::operator ==(const PIVector & t);
* \brief Compare with vector "t"
* \fn bool PIVector::operator !=(const PIVector & t);
* \brief Compare with vector "t"
* */
/** \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.
* */

View File

@@ -0,0 +1,130 @@
/*! \file picontainers.h
* \brief Base for generic containers
*
* This file declare all containers and useful macros
* to use them
*/
/*
PIP - Platform Independent Primitives
Base for generic containers
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICONTAINERS_H
#define PICONTAINERS_H
#include "picout.h"
#include "piintrospection_containers.h"
#ifdef PIP_DEBUG
# ifdef NDEBUG
# undef NDEBUG
# endif
# include <cassert>
#endif
#ifndef assert
# define assert(x)
#endif
#ifdef MAC_OS
# include <stdlib.h>
#else
# include <malloc.h>
#endif
#include <string.h>
#include <new>
#ifndef PIP_MEMALIGN_BYTES
# define PIP_MEMALIGN_BYTES (sizeof(void*)*4)
#endif
#ifdef WINDOWS
# ifdef CC_GCC
# define amalloc(s) __mingw_aligned_malloc(s, PIP_MEMALIGN_BYTES)
# define afree(p) __mingw_aligned_free(p)
# else
# ifdef CC_VC
# define amalloc(s) _aligned_malloc(s, PIP_MEMALIGN_BYTES)
# define afree(p) _aligned_free(p)
# endif
# endif
#else
# define amalloc(s) aligned_alloc(PIP_MEMALIGN_BYTES, s)
# define afree(p) free(p)
#endif
#ifdef DOXYGEN
/*!\brief Macro for iterate any container
* \details Use this macros instead of standard "for"
* to get read/write access to each element of container.
* Pass direction is direct \n
* Example: \snippet picontainers.cpp foreach
*/
# define piForeach(i,c)
/*!\brief Macro for iterate any container only for read
* \details Use this macros instead of standard "for"
* to get read access to each element of container.
* Pass direction is direct \n
* Example: \snippet picontainers.cpp foreachC
*/
# define piForeachC(i,c)
/*!\brief Macro for iterate any container with reverse direction
* \details Use this macros instead of standard "for"
* to get read/write access to each element of container.
* Pass direction is reverse \n
* Example: \snippet picontainers.cpp foreachR
*/
# define piForeachR(i,c)
/*!\brief Macro for iterate any container only for read with reverse direction
* \details Use this macros instead of standard "for"
* to get read access to each element of container.
* Pass direction is reverse \n
* Example: \snippet picontainers.cpp foreachCR
*/
# define piForeachCR(i,c)
#else
template <typename C>
struct _reverse_wrapper {
C & c_;
_reverse_wrapper(C & c): c_(c) {}
_reverse_wrapper(const C & c): c_(const_cast<C&>(c)) {}
typename C::reverse_iterator begin() {return c_.rbegin();}
typename C::reverse_iterator end() {return c_.rend(); }
typename C::const_reverse_iterator begin() const {return c_.rbegin();}
typename C::const_reverse_iterator end() const {return c_.rend(); }
};
template <typename C> _reverse_wrapper<C> _reverse_wrap(C & c) {return _reverse_wrapper<C>(c);}
template <typename C> _reverse_wrapper<C> _reverse_wrap(const C & c) {return _reverse_wrapper<C>(c);}
# define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c)
# define piForeach(i,c) for(i : c)
# define piForeachC(i,c) for(const i : c)
# define piForeachR(i,c) for(i : _reverse_wrap(c))
# define piForeachRC(i,c) for(const i : _reverse_wrap(c))
# define piForeachCR piForeachRC
#endif // DOXYGEN
#endif // PICONTAINERS_H

View File

@@ -32,7 +32,6 @@ template <typename T>
class PIDeque { class PIDeque {
public: public:
inline PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { inline PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
//piCout << "PIDeque";
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
} }
inline PIDeque(const PIDeque<T> & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { inline PIDeque(const PIDeque<T> & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
@@ -49,8 +48,10 @@ public:
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(pid_size, f); resize(pid_size, f);
} }
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) {
other._reset();
}
inline virtual ~PIDeque() { inline virtual ~PIDeque() {
//piCout << "~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);
@@ -66,6 +67,11 @@ public:
return *this; return *this;
} }
inline PIDeque<T> & operator =(PIDeque<T> && other) {
swap(other);
return *this;
}
typedef T value_type; typedef T value_type;
class iterator { class iterator {
@@ -256,6 +262,23 @@ public:
elementNew(pid_data + pid_start + index, v); elementNew(pid_data + pid_start + index, v);
return *this; return *this;
} }
inline PIDeque<T> & insert(size_t index, T && v) {
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
if (dir) {
alloc(pid_size + 1, true);
if (index < pid_size - 1) {
size_t os = pid_size - index - 1;
memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
}
} else {
alloc(pid_size + 1, false, -1);
if (index > 0)
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
}
PIINTROSPECTION_CONTAINER_USED(T, 1)
elementNew(pid_data + pid_start + index, std::move(v));
return *this;
}
inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) { inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) {
if (other.isEmpty()) return *this; if (other.isEmpty()) return *this;
assert(&other != this); assert(&other != this);
@@ -336,7 +359,14 @@ public:
elementNew(pid_data + pid_start + pid_size - 1, v); elementNew(pid_data + pid_start + pid_size - 1, v);
return *this; return *this;
} }
inline PIDeque<T> & push_back(T && v) {
alloc(pid_size + 1, true);
PIINTROSPECTION_CONTAINER_USED(T, 1);
elementNew(pid_data + pid_start + pid_size - 1, std::move(v));
return *this;
}
inline PIDeque<T> & append(const T & v) {return push_back(v);} inline PIDeque<T> & append(const T & v) {return push_back(v);}
inline PIDeque<T> & append(T && v) {return push_back(std::move(v));}
inline PIDeque<T> & append(const PIDeque<T> & t) { inline PIDeque<T> & append(const PIDeque<T> & t) {
assert(&t != this); assert(&t != this);
size_t ps = pid_size; size_t ps = pid_size;
@@ -345,10 +375,13 @@ public:
return *this; return *this;
} }
inline PIDeque<T> & operator <<(const T & v) {return push_back(v);} inline PIDeque<T> & operator <<(const T & v) {return push_back(v);}
inline PIDeque<T> & operator <<(T && v) {return push_back(std::move(v));}
inline PIDeque<T> & operator <<(const PIDeque<T> & t) {return append(t);} inline PIDeque<T> & operator <<(const PIDeque<T> & t) {return append(t);}
inline PIDeque<T> & push_front(const T & v) {insert(0, v); return *this;} inline PIDeque<T> & push_front(const T & v) {insert(0, v); return *this;}
inline PIDeque<T> & push_front(T && v) {insert(0, std::move(v)); return *this;}
inline PIDeque<T> & prepend(const T & v) {return push_front(v);} inline PIDeque<T> & prepend(const T & v) {return push_front(v);}
inline PIDeque<T> & prepend(T && v) {return push_front(std::move(v));}
inline PIDeque<T> & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;} inline PIDeque<T> & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;}
inline PIDeque<T> & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;} inline PIDeque<T> & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;}
@@ -364,7 +397,6 @@ public:
return ret; return ret;
} }
#ifdef PIP_CXX11_SUPPORT
const PIDeque<T> & forEach(std::function<void(const T &)> f) const { const PIDeque<T> & forEach(std::function<void(const T &)> f) const {
for (uint i = 0; i < pid_size; ++i) for (uint i = 0; i < pid_size; ++i)
f(pid_data[i + pid_start]); f(pid_data[i + pid_start]);
@@ -388,7 +420,6 @@ public:
ret << f(pid_data[i + pid_start]); ret << f(pid_data[i + pid_start]);
return ret; return ret;
} }
#endif
private: private:
inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;} inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;}
@@ -414,6 +445,7 @@ private:
} }
} }
inline void elementNew(T * to, const T & from) {new(to)T(from);} inline void elementNew(T * to, const T & from) {new(to)T(from);}
inline void elementNew(T * to, T && from) {new(to)T(std::move(from));}
inline void elementDelete(T & from) {from.~T();} inline void elementDelete(T & from) {from.~T();}
inline void dealloc() { inline void dealloc() {
if ((uchar*)pid_data != 0) free((uchar*)pid_data); if ((uchar*)pid_data != 0) free((uchar*)pid_data);
@@ -487,6 +519,7 @@ private:
template<> inline void PIDeque<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \ template<> inline void PIDeque<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \
template<> inline void PIDeque<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \ template<> inline void PIDeque<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \
template<> inline void PIDeque<T>::elementNew(T * to, const T & from) {(*to) = from;} \ template<> inline void PIDeque<T>::elementNew(T * to, const T & from) {(*to) = from;} \
template<> inline void PIDeque<T>::elementNew(T * to, T && from) {(*to) = std::move(from);} \
template<> inline void PIDeque<T>::elementDelete(T &) {;} \ template<> inline void PIDeque<T>::elementDelete(T &) {;} \
template<> inline PIDeque<T> & PIDeque<T>::_resizeRaw(size_t new_size) { \ template<> inline PIDeque<T> & PIDeque<T>::_resizeRaw(size_t new_size) { \
if (new_size > pid_size) { \ if (new_size > pid_size) { \
@@ -538,5 +571,7 @@ inline PICout operator <<(PICout s, const PIDeque<T> & v) {
return s; return s;
} }
template<typename T> inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {f.swap(s);}
#endif // PIDEQUE_H #endif // PIDEQUE_H

View File

@@ -57,7 +57,7 @@ void piQuickSort(T * a, ssize_t N) {
if (i <= j) { if (i <= j) {
if (i != j) { if (i != j) {
//piCout << "swap" << i << j << a[i] << a[j]; //piCout << "swap" << i << j << a[i] << a[j];
piSwapBinary<T>(a[i], a[j]); piSwap<T>(a[i], a[j]);
} }
i++; j--; i++; j--;
} }
@@ -67,13 +67,20 @@ void piQuickSort(T * a, ssize_t N) {
} }
} }
template <typename Key, typename T>
class PIMapIterator;
template <typename Key, typename T> template <typename Key, typename T>
class PIMap { class PIMap {
template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIMap<Key1, T1> & v); template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIMap<Key1, T1> & v);
template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIMap<Key1, T1> & v); template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIMap<Key1, T1> & v);
template <typename Key1, typename T1> friend class PIMapIterator;
public: public:
PIMap() {;} PIMap() {;}
PIMap(const PIMap<Key, T> & other) {*this = other;} PIMap(const PIMap<Key, T> & other) {*this = other;}
PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {}
virtual ~PIMap() {;} virtual ~PIMap() {;}
PIMap<Key, T> & operator =(const PIMap<Key, T> & other) { PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
@@ -84,6 +91,11 @@ public:
return *this; return *this;
} }
PIMap<Key, T> & operator =(PIMap<Key, T> && other) {
swap(other);
return *this;
}
typedef T mapped_type; typedef T mapped_type;
typedef Key key_type; typedef Key key_type;
typedef PIPair<Key, T> value_type; typedef PIPair<Key, T> value_type;
@@ -177,6 +189,9 @@ public:
const_reverse_iterator constRbegin() const {return const_reverse_iterator(this, size() - 1);} const_reverse_iterator constRbegin() const {return const_reverse_iterator(this, size() - 1);}
const_reverse_iterator constRend() const {return const_reverse_iterator(this, -1);} const_reverse_iterator constRend() const {return const_reverse_iterator(this, -1);}
PIMapIterator<Key, T> makeIterator() const {return PIMapIterator<Key, T>(*this);}
PIMapIterator<Key, T> makeReverseIterator() const {return PIMapIterator<Key, T>(*this, true);}
size_t size() const {return pim_content.size();} size_t size() const {return pim_content.size();}
int size_s() const {return pim_content.size_s();} int size_s() const {return pim_content.size_s();}
size_t length() const {return pim_content.size();} size_t length() const {return pim_content.size();}
@@ -216,8 +231,8 @@ public:
PIMap<Key, T> & clear() {pim_content.clear(); pim_index.clear(); return *this;} PIMap<Key, T> & clear() {pim_content.clear(); pim_index.clear(); return *this;}
void swap(PIMap<Key, T> & other) { void swap(PIMap<Key, T> & other) {
piSwapBinary<PIVector<T> >(pim_content, other.pim_content); pim_content.swap(other.pim_content);
piSwapBinary<PIDeque<MapIndex> >(pim_index, other.pim_index); pim_index.swap(other.pim_index);
} }
PIMap<Key, T> & insert(const Key & key, const T & value) { PIMap<Key, T> & insert(const Key & key, const T & value) {
@@ -232,6 +247,18 @@ public:
} }
return *this; return *this;
} }
PIMap<Key, T> & insert(const Key & key, T && value) {
bool f(false);
ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
if (f) {
pim_content[pim_index[i].index] = std::move(value);
} else {
pim_content.push_back(std::move(value));
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
}
return *this;
}
const T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];} const T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];}
PIVector<T> values() const {return pim_content;} PIVector<T> values() const {return pim_content;}
Key key(const T & value_, const Key & default_ = Key()) const {for (int i = 0; i < pim_index.size_s(); ++i) if (pim_content[pim_index[i].index] == value_) return pim_index[i].key; return default_;} Key key(const T & value_, const Key & default_ = Key()) const {for (int i = 0; i < pim_index.size_s(); ++i) if (pim_content[pim_index[i].index] == value_) return pim_index[i].key; return default_;}
@@ -292,7 +319,7 @@ protected:
pim_index[i].index = ci; pim_index[i].index = ci;
break; break;
} }
piSwapBinary<T>(pim_content[ci], pim_content.back()); piSwap<T>(pim_content[ci], pim_content.back());
pim_content.resize(pim_index.size()); pim_content.resize(pim_index.size());
} }
const value_type _pair(ssize_t index) const { const value_type _pair(ssize_t index) const {
@@ -309,6 +336,41 @@ protected:
}; };
template <typename Key, typename T>
class PIMapIterator {
typedef PIMap<Key, T> MapType;
public:
PIMapIterator(const PIMap<Key, T> & map, bool reverse = false): m(map), pos(-1), rev(reverse) {
if (rev) pos = m.size_s();
}
const Key & key() const {return const_cast<MapType & >(m)._key(pos);}
const T & value() const {return const_cast<MapType & >(m)._value(pos);}
T & valueRef() const {return const_cast<MapType & >(m)._value(pos);}
inline bool hasNext() const {
if (rev) {
return pos > 0;
} else {
return pos < (m.size_s() - 1);
}
return false;
}
inline bool next() {
if (rev) {
--pos;
return pos >= 0;
} else {
++pos;
return pos < m.size_s();
}
return false;
}
private:
const MapType & m;
ssize_t pos;
bool rev;
};
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
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) {
@@ -342,5 +404,7 @@ inline PICout operator <<(PICout s, const PIMap<Key, Type> & v) {
return s; return s;
} }
template<typename Key, typename Type> inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {f.swap(s);}
#endif // PIMAP_H #endif // PIMAP_H

View File

@@ -1,55 +1,55 @@
/*! \file pipair.h /*! \file pipair.h
* \brief pair * \brief pair
* *
* This file declare PIPair * This file declare PIPair
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
pair pair
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PIPAIR_H #ifndef PIPAIR_H
#define PIPAIR_H #define PIPAIR_H
#include "pibase.h" #include "pibase.h"
class PICout; class PICout;
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
class PIP_EXPORT PIPair { class PIPair {
public: public:
PIPair() {first = Type0(); second = Type1();} PIPair() {first = Type0(); second = Type1();}
PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;} PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;}
Type0 first; Type0 first;
Type1 second; Type1 second;
}; };
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;} inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;}
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline bool operator ==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first == value1.first) && (value0.second == value1.second);} inline bool operator ==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first == value1.first) && (value0.second == value1.second);}
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline bool operator !=(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first != value1.first) || (value0.second != value1.second);} inline bool operator !=(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first != value1.first) || (value0.second != value1.second);}
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {s << "(" << v.first << ", " << v.second << ")"; return s;} inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {s << "(" << v.first << ", " << v.second << ")"; return s;}
#endif #endif
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;} inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;}
#endif // PIPAIR_H #endif // PIPAIR_H

View File

@@ -30,18 +30,20 @@
template<typename T> template<typename T>
class PIP_EXPORT PIQueue: public PIDeque<T> { class PIQueue: public PIDeque<T> {
public: public:
PIQueue() {} PIQueue() {}
virtual ~PIQueue() {} virtual ~PIQueue() {}
PIDeque<T> & enqueue(const T & v) {PIDeque<T>::push_front(v); return *this;} PIDeque<T> & enqueue(const T & v) {PIDeque<T>::push_front(v); return *this;}
PIDeque<T> & enqueue(T && v) {PIDeque<T>::push_front(std::move(v)); return *this;}
T dequeue() {return PIDeque<T>::take_back();} T dequeue() {return PIDeque<T>::take_back();}
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() { PIVector<T> toVector() {
PIVector<T> v(PIDeque<T>::size()); PIVector<T> v;
v.reserve(PIDeque<T>::size());
for (uint i = 0; i < PIDeque<T>::size(); ++i) for (uint i = 0; i < PIDeque<T>::size(); ++i)
v[i] = PIDeque<T>::at(i); v.push_back(PIDeque<T>::at(i));
return v; return v;
} }
}; };

View File

@@ -35,7 +35,7 @@
* has logarithmic complexity. * has logarithmic complexity.
*/ */
template <typename T> template <typename T>
class PIP_EXPORT PISet: public PIMap<T, uchar> { class PISet: public PIMap<T, uchar> {
typedef PIMap<T, uchar> _CSet; typedef PIMap<T, uchar> _CSet;
public: public:
@@ -75,6 +75,7 @@ public:
typedef T key_type; typedef T key_type;
PISet<T> & operator <<(const T & t) {_CSet::insert(t, 0); return *this;} PISet<T> & operator <<(const T & t) {_CSet::insert(t, 0); 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;} 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

View File

@@ -28,15 +28,22 @@
#include "pivector.h" #include "pivector.h"
template<typename T> template<typename T>
class PIP_EXPORT PIStack: public PIVector<T> { class PIStack: public PIVector<T> {
public: public:
PIStack() {;} PIStack() {;}
virtual ~PIStack() {;} virtual ~PIStack() {;}
PIVector<T> & push(const T & v) {PIVector<T>::push_back(v); return *this;} PIVector<T> & push(const T & v) {PIVector<T>::push_back(v); return *this;}
PIVector<T> & push(T && v) {PIVector<T>::push_back(std::move(v)); return *this;}
T pop() {return PIVector<T>::take_back();} T pop() {return PIVector<T>::take_back();}
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() {PIVector<T> v(PIVector<T>::size()); for (uint i = 0; i < PIVector<T>::size(); ++i) v[i] = PIVector<T>::at(i); return v;} PIVector<T> toVector() {
PIVector<T> v;
v.reserve(PIVector<T>::size());
for (uint i = 0; i < PIVector<T>::size(); ++i)
v.push_back(PIVector<T>::at(i));
return v;
}
}; };
#endif // PISTACK_H #endif // PISTACK_H

View File

@@ -48,6 +48,9 @@ public:
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(piv_size, f); resize(piv_size, f);
} }
inline PIVector(PIVector<T> && other): piv_data(other.piv_data), piv_size(other.piv_size), piv_rsize(other.piv_rsize) {
other._reset();
}
inline virtual ~PIVector() { inline virtual ~PIVector() {
PIINTROSPECTION_CONTAINER_DELETE(T) PIINTROSPECTION_CONTAINER_DELETE(T)
PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize)) PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize))
@@ -65,6 +68,11 @@ public:
return *this; return *this;
} }
inline PIVector<T> & operator =(PIVector<T> && other) {
swap(other);
return *this;
}
typedef T value_type; typedef T value_type;
class iterator { class iterator {
@@ -253,6 +261,16 @@ public:
elementNew(piv_data + index, v); elementNew(piv_data + index, v);
return *this; return *this;
} }
inline PIVector<T> & insert(size_t index, T && v) {
alloc(piv_size + 1);
if (index < piv_size - 1) {
size_t os = piv_size - index - 1;
memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T));
}
PIINTROSPECTION_CONTAINER_USED(T, 1)
elementNew(piv_data + index, std::move(v));
return *this;
}
inline PIVector<T> & insert(size_t index, const PIVector<T> & other) { inline PIVector<T> & insert(size_t index, const PIVector<T> & other) {
if (other.isEmpty()) return *this; if (other.isEmpty()) return *this;
assert(&other != this); assert(&other != this);
@@ -320,7 +338,14 @@ public:
elementNew(piv_data + piv_size - 1, v); elementNew(piv_data + piv_size - 1, v);
return *this; return *this;
} }
inline PIVector<T> & push_back(T && v) {
alloc(piv_size + 1);
PIINTROSPECTION_CONTAINER_USED(T, 1);
elementNew(piv_data + piv_size - 1, std::move(v));
return *this;
}
inline PIVector<T> & append(const T & v) {return push_back(v);} inline PIVector<T> & append(const T & v) {return push_back(v);}
inline PIVector<T> & append(T && v) {return push_back(std::move(v));}
inline PIVector<T> & append(const PIVector<T> & other) { inline PIVector<T> & append(const PIVector<T> & other) {
assert(&other != this); assert(&other != this);
size_t ps = piv_size; size_t ps = piv_size;
@@ -329,10 +354,13 @@ public:
return *this; return *this;
} }
inline PIVector<T> & operator <<(const T & v) {return push_back(v);} inline PIVector<T> & operator <<(const T & v) {return push_back(v);}
inline PIVector<T> & operator <<(T && v) {return push_back(std::move(v));}
inline PIVector<T> & operator <<(const PIVector<T> & other) {return append(other);} inline PIVector<T> & operator <<(const PIVector<T> & other) {return append(other);}
inline PIVector<T> & push_front(const T & v) {insert(0, v); return *this;} inline PIVector<T> & push_front(const T & v) {insert(0, v); return *this;}
inline PIVector<T> & push_front(T && v) {insert(0, std::move(v)); return *this;}
inline PIVector<T> & prepend(const T & v) {return push_front(v);} inline PIVector<T> & prepend(const T & v) {return push_front(v);}
inline PIVector<T> & prepend(T && v) {return push_front(std::move(v));}
inline PIVector<T> & pop_back() { inline PIVector<T> & pop_back() {
if (piv_size == 0) if (piv_size == 0)
@@ -358,7 +386,6 @@ public:
return ret; return ret;
} }
#ifdef PIP_CXX11_SUPPORT
const PIVector<T> & forEach(std::function<void(const T &)> f) const { const PIVector<T> & forEach(std::function<void(const T &)> f) const {
for (uint i = 0; i < piv_size; ++i) for (uint i = 0; i < piv_size; ++i)
f(piv_data[i]); f(piv_data[i]);
@@ -382,7 +409,6 @@ public:
ret << f(piv_data[i]); ret << f(piv_data[i]);
return ret; return ret;
} }
#endif
private: private:
inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;} inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;}
@@ -407,6 +433,7 @@ private:
} }
} }
inline void elementNew(T * to, const T & from) {new(to)T(from);} inline void elementNew(T * to, const T & from) {new(to)T(from);}
inline void elementNew(T * to, T && from) {new(to)T(std::move(from));}
inline void elementDelete(T & from) {from.~T();} inline void elementDelete(T & from) {from.~T();}
inline void dealloc() { inline void dealloc() {
if ((uchar*)piv_data != 0) free((uchar*)piv_data); if ((uchar*)piv_data != 0) free((uchar*)piv_data);
@@ -436,6 +463,7 @@ private:
template<> inline void PIVector<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \ template<> inline void PIVector<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \
template<> inline void PIVector<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \ template<> inline void PIVector<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \
template<> inline void PIVector<T>::elementNew(T * to, const T & from) {(*to) = from;} \ template<> inline void PIVector<T>::elementNew(T * to, const T & from) {(*to) = from;} \
template<> inline void PIVector<T>::elementNew(T * to, T && from) {(*to) = std::move(from);} \
template<> inline void PIVector<T>::elementDelete(T &) {;} \ template<> inline void PIVector<T>::elementDelete(T &) {;} \
template<> inline PIVector<T> & PIVector<T>::_resizeRaw(size_t new_size) { \ template<> inline PIVector<T> & PIVector<T>::_resizeRaw(size_t new_size) { \
if (new_size > piv_size) { \ if (new_size > piv_size) { \
@@ -487,5 +515,7 @@ inline PICout operator <<(PICout s, const PIVector<T> & v) {
return s; return s;
} }
template<typename T> inline void piSwap(PIVector<T> & f, PIVector<T> & s) {f.swap(s);}
#endif // PIVECTOR_H #endif // PIVECTOR_H

View File

@@ -1,307 +1,308 @@
/*! \file pivecto2d.h /*! \file pivecto2d.h
* \brief 2D wrapper around PIVector * \brief 2D wrapper around PIVector
* *
* This file declares PIVector * This file declares PIVector
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
2D wrapper around PIVector 2D wrapper around PIVector
Andrey Bychkov work.a.b@yandex.ru Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PIVECTOR2D_H #ifndef PIVECTOR2D_H
#define PIVECTOR2D_H #define PIVECTOR2D_H
#include "pivector.h" #include "pivector.h"
/*! \brief 2D array, /*! \brief 2D array,
* \details This class used to store 2D array of any type elements as plain vector. * \details This class used to store 2D array of any type elements as plain vector.
* You can read/write any element via operators [][], first dimension - row, second - column. * You can read/write any element via operators [][], first dimension - row, second - column.
* The first dimension is Row, and you can operate with Row as PIVector<T>: modify any element, assign to another Row and etc. * The first dimension is Row, and you can operate with Row as PIVector<T>: modify any element, assign to another Row and etc.
* You can't add values to array, but you can modify any elements or create another PIVector2D. * You can't add values to array, but you can modify any elements or create another PIVector2D.
* PIVector2D has constructors from PIVector<T> and PIVector<PIVector<T> > * PIVector2D has constructors from PIVector<T> and PIVector<PIVector<T> >
*/ */
template <typename T> 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) { inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v) : rows_(rows), cols_(cols), mat(v) {
mat = v; mat.resize(rows*cols);
rows_ = rows; }
cols_ = cols; inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v) : rows_(rows), cols_(cols), mat(std::move(v)) {
mat.resize(rows*cols); 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_) {
cols_ = v[0].size(); cols_ = v[0].size();
for (size_t i = 0; i < rows_; i++) { for (size_t i = 0; i < rows_; i++) {
mat.append(v[i]); mat.append(v[i]);
} }
mat.resize(rows_*cols_); mat.resize(rows_*cols_);
} }
if (mat.isEmpty()) rows_ = cols_ = 0; if (mat.isEmpty()) rows_ = cols_ = 0;
} }
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();}
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)) {st_ = p->cols_ * row; sz_ = p->cols_;} inline Row(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {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];}
inline const T & operator [](size_t index) const {return (*p_)[st_ + index];} inline const T & operator [](size_t index) const {return (*p_)[st_ + index];}
inline T * data(size_t index = 0) {return p_->data(st_ + index);} inline T * data(size_t index = 0) {return p_->data(st_ + index);}
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;
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) {
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;
} }
inline PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);} inline PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);}
}; };
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)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;} inline Col(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {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_];}
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_];}
inline T * data(size_t index = 0) {return p_->data(index * step_ + row_);} inline T * data(size_t index = 0) {return p_->data(index * step_ + row_);}
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;
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) (*p_)[i * step_ + row_] = other[i]; for (int i=0; i<sz; ++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) {
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) (*p_)[i * step_ + row_] = other[i]; for (int i=0; i<sz; ++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++) ret << (*p_)[i * step_ + row_]; for (size_t i=0; i<sz_; i++) 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)) {st_ = p->cols_ * row; sz_ = p->cols_;} inline RowConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {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];}
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 PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);} inline PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);}
}; };
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)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;} inline ColConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {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_];}
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 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++) ret << (*p_)[i * step_ + row_]; for (int i=0; i<size(); i++) ret << (*p_)[i * step_ + row_];
return ret; return ret;
} }
}; };
inline T & element(size_t row, size_t col) {return mat[row * cols_ + col];} inline T & element(size_t row, size_t col) {return mat[row * cols_ + col];}
inline const T & element(size_t row, size_t col) const {return mat[row * cols_ + col];} inline const T & element(size_t row, size_t col) const {return mat[row * cols_ + col];}
inline Row operator[](size_t index) {return Row(this, index);} inline Row operator[](size_t index) {return Row(this, index);}
inline RowConst operator[](size_t index) const {return RowConst(this, index);} inline RowConst operator[](size_t index) const {return RowConst(this, index);}
inline T * data(size_t index = 0) {return mat.data(index);} inline T * data(size_t index = 0) {return mat.data(index);}
inline const T * data(size_t index = 0) const {return mat.data(index);} inline const T * data(size_t index = 0) const {return mat.data(index);}
inline Row row(size_t index) {return Row(this, index);} inline Row row(size_t index) {return Row(this, index);}
inline RowConst row(size_t index) const {return RowConst(this, index);} inline RowConst row(size_t index) const {return RowConst(this, index);}
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) {
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) {
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) {
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_;
size_t sz = piMin<size_t>(cols_, other.sz_); size_t sz = piMin<size_t>(cols_, other.sz_);
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_++;
return *this; return *this;
} }
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_;
size_t sz = piMin<size_t>(cols_, other.sz_); size_t sz = piMin<size_t>(cols_, other.sz_);
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_++;
return *this; return *this;
} }
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();
size_t sz = piMin<size_t>(cols_, other.size()); size_t sz = piMin<size_t>(cols_, other.size());
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_++;
return *this; return *this;
} }
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;
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);
} }
} }
mat.resize(rows*cols, f); mat.resize(rows*cols, f);
if (!mat.isEmpty()) { if (!mat.isEmpty()) {
if (cs > 0) { if (cs > 0) {
for (size_t r=0; r<rows_; ++r) { for (size_t r=0; r<rows_; ++r) {
for (int i=0; i<cs; ++i) for (int i=0; i<cs; ++i)
mat.insert(r*cols + cols_, mat.take_back()); mat.insert(r*cols + cols_, mat.take_back());
} }
} }
} }
cols_ = cols; cols_ = cols;
return *this; return *this;
} }
PIVector<PIVector<T> > toVectors() const { PIVector<PIVector<T> > toVectors() const {
PIVector<PIVector<T> > ret; PIVector<PIVector<T> > ret;
for(size_t i = 0; i < rows_; ++i) ret.reserve(rows_);
ret << PIVector<T>(mat.data(i*cols_), cols_); for(size_t i = 0; i < rows_; ++i)
return ret; ret << PIVector<T>(mat.data(i*cols_), cols_);
} return ret;
PIVector<T> toPlainVector() const {return mat;} }
PIVector<T> & plainVector() {return mat;} PIVector<T> toPlainVector() const {return mat;}
const PIVector<T> & plainVector() const {return mat;} PIVector<T> & plainVector() {return mat;}
const PIVector<T> & plainVector() const {return mat;}
inline void swap(PIVector2D<T> & other) {
mat.swap(other.mat); inline void swap(PIVector2D<T> & other) {
piSwap<size_t>(rows_, other.rows_); mat.swap(other.mat);
piSwap<size_t>(cols_, other.cols_); piSwap<size_t>(rows_, other.rows_);
} piSwap<size_t>(cols_, other.cols_);
}
inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) {
piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIVECTOR_SIMPLE_TYPE__ macro!"; inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) {
assert(0); piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIVECTOR_SIMPLE_TYPE__ macro!";
return *this; assert(0);
} return *this;
}
inline void clear() {
rows_ = cols_ = 0; inline void clear() {
mat.clear(); rows_ = cols_ = 0;
} mat.clear();
}
protected:
size_t rows_, cols_; protected:
PIVector<T> mat; size_t rows_, cols_;
}; PIVector<T> mat;
};
template<typename T>
inline PICout operator <<(PICout s, const PIVector2D<T> & v) { template<typename T>
s.setControl(0, true); inline PICout operator <<(PICout s, const PIVector2D<T> & v) {
s << "{"; s.setControl(0, true);
for (size_t i = 0; i < v.rows(); ++i) { s << "{";
s << "{ "; for (size_t i = 0; i < v.rows(); ++i) {
for (size_t j = 0; j < v.cols(); ++j) { s << "{ ";
s << v[i][j]; for (size_t j = 0; j < v.cols(); ++j) {
if (j < v.cols() - 1) s << ", "; s << v[i][j];
} if (j < v.cols() - 1) s << ", ";
s << " }"; }
if (i < v.rows() - 1) s << PICoutManipulators::NewLine ; s << " }";
} if (i < v.rows() - 1) s << PICoutManipulators::NewLine ;
if (v.isEmpty()) s << "{ }"; }
s << "}"; if (v.isEmpty()) s << "{ }";
s.restoreControl(); s << "}";
return s; s.restoreControl();
} return s;
}
#define __PIVECTOR2D_SIMPLE_TYPE__(T) \
template<> inline PIVector2D<T> & PIVector2D<T>::_resizeRaw(size_t r, size_t c) {rows_ = r; cols_ = c; mat._resizeRaw(r*c); return *this;} #define __PIVECTOR2D_SIMPLE_TYPE__(T) \
template<> inline PIVector2D<T> & PIVector2D<T>::_resizeRaw(size_t r, size_t c) {rows_ = r; cols_ = c; mat._resizeRaw(r*c); return *this;}
__PIVECTOR2D_SIMPLE_TYPE__(bool)
__PIVECTOR2D_SIMPLE_TYPE__(char) __PIVECTOR2D_SIMPLE_TYPE__(bool)
__PIVECTOR2D_SIMPLE_TYPE__(uchar) __PIVECTOR2D_SIMPLE_TYPE__(char)
__PIVECTOR2D_SIMPLE_TYPE__(short) __PIVECTOR2D_SIMPLE_TYPE__(uchar)
__PIVECTOR2D_SIMPLE_TYPE__(ushort) __PIVECTOR2D_SIMPLE_TYPE__(short)
__PIVECTOR2D_SIMPLE_TYPE__(int) __PIVECTOR2D_SIMPLE_TYPE__(ushort)
__PIVECTOR2D_SIMPLE_TYPE__(uint) __PIVECTOR2D_SIMPLE_TYPE__(int)
__PIVECTOR2D_SIMPLE_TYPE__(long) __PIVECTOR2D_SIMPLE_TYPE__(uint)
__PIVECTOR2D_SIMPLE_TYPE__(ulong) __PIVECTOR2D_SIMPLE_TYPE__(long)
__PIVECTOR2D_SIMPLE_TYPE__(llong) __PIVECTOR2D_SIMPLE_TYPE__(ulong)
__PIVECTOR2D_SIMPLE_TYPE__(ullong) __PIVECTOR2D_SIMPLE_TYPE__(llong)
__PIVECTOR2D_SIMPLE_TYPE__(float) __PIVECTOR2D_SIMPLE_TYPE__(ullong)
__PIVECTOR2D_SIMPLE_TYPE__(double) __PIVECTOR2D_SIMPLE_TYPE__(float)
__PIVECTOR2D_SIMPLE_TYPE__(ldouble) __PIVECTOR2D_SIMPLE_TYPE__(double)
__PIVECTOR2D_SIMPLE_TYPE__(ldouble)
#endif // PIVECTOR2D_H
#endif // PIVECTOR2D_H

View File

@@ -1,557 +1,563 @@
/*! \file pibase.h /*! \file pibase.h
* \brief Base types and functions * \brief Base types and functions
* *
* This file implements first layer above the system and * This file implements first layer above the system and
* declares some basic useful functions * declares some basic useful functions
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Base types and functions Base types and functions
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PIBASE_H #ifndef PIBASE_H
#define PIBASE_H #define PIBASE_H
#include "piversion.h" #include "piversion.h"
#include "piplatform.h" #include "piplatform.h"
#include "pip_export.h" #include "pip_export.h"
#include "pip_defs.h" #include "pip_defs.h"
#include "string.h" #include "string.h"
//! Meta-information section for any entity. //! Meta-information section for any entity.
//! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo. //! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo.
//! Contains sequence of key=value pairs, e.g. //! Contains sequence of key=value pairs, e.g.
//! PIMETA(id=12345,tag="my string") //! PIMETA(id=12345,tag="my string")
#define PIMETA(...) #define PIMETA(...)
#ifdef DOXYGEN #ifdef DOXYGEN
//! Major value of PIP version //! Major value of PIP version
# define PIP_VERSION_MAJOR # define PIP_VERSION_MAJOR
//! Minor value of PIP version //! Minor value of PIP version
# define PIP_VERSION_MINOR # define PIP_VERSION_MINOR
//! Revision value of PIP version //! Revision value of PIP version
# define PIP_VERSION_REVISION # define PIP_VERSION_REVISION
//! Suffix of PIP version //! Suffix of PIP version
# define PIP_VERSION_SUFFIX # define PIP_VERSION_SUFFIX
//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision) //! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
# define PIP_VERSION # define PIP_VERSION
//! Macro is defined when compile-time debug is enabled //! Macro is defined when compile-time debug is enabled
# define PIP_DEBUG # define PIP_DEBUG
//! Macro is defined when host is any Windows //! Macro is defined when host is any Windows
# define WINDOWS # define WINDOWS
//! Macro is defined when host is QNX or Blackberry //! Macro is defined when host is QNX or Blackberry
# define QNX # define QNX
//! Macro is defined when host is Blackberry //! Macro is defined when host is Blackberry
# define BLACKBERRY # define BLACKBERRY
//! Macro is defined when host is FreeBSD //! Macro is defined when host is FreeBSD
# define FREE_BSD # define FREE_BSD
//! Macro is defined when host is Mac OS //! Macro is defined when host is Mac OS
# define MAC_OS # define MAC_OS
//! Macro is defined when host is Android //! Macro is defined when host is Android
# define ANDROID # define ANDROID
//! Macro is defined when host is any Linux //! Macro is defined when host is any Linux
# define LINUX # define LINUX
//! Macro is defined when compiler is GCC or MinGW //! Macro is defined when compiler is GCC or MinGW
# define CC_GCC # define CC_GCC
//! Macro is defined when PIP is decided that host is support language //! Macro is defined when PIP is decided that host is support language
# define HAS_LOCALE # define HAS_LOCALE
//! Macro is defined when compiler is Visual Studio //! Macro is defined when compiler is Visual Studio
# define CC_VC # define CC_VC
//! Macro is defined when compiler is unknown //! Macro is defined when compiler is unknown
# define CC_OTHER # define CC_OTHER
//! Macro is defined when PIP can use "rt" library for "PITimer::ThreadRT" timers implementation //! Macro is defined when PIP can use "rt" library for "PITimer::ThreadRT" timers implementation
# define PIP_TIMER_RT # define PIP_TIMER_RT
#endif #endif
#ifdef PIP_CXX11_SUPPORT #include <functional>
# include <functional>
#endif #include <cstddef>
#ifdef WINDOWS
#include <cstddef> # ifdef CC_VC
#ifdef WINDOWS # define SHUT_RDWR 2
# ifdef CC_VC # pragma comment(lib, "Ws2_32.lib")
# define SHUT_RDWR 2 # pragma comment(lib, "Iphlpapi.lib")
# pragma comment(lib, "Ws2_32.lib") # pragma comment(lib, "Psapi.lib")
# pragma comment(lib, "Iphlpapi.lib") # ifdef ARCH_BITS_32
# pragma comment(lib, "Psapi.lib") # define _X86_
# ifdef ARCH_BITS_32 # else
# define _X86_ # define _IA64_
# else # endif
# define _IA64_ # else
# endif # define SHUT_RDWR SD_BOTH
# else # endif
# define SHUT_RDWR SD_BOTH typedef int socklen_t;
# endif extern long long __pi_perf_freq;
typedef int socklen_t; #endif
extern long long __pi_perf_freq;
#endif #ifdef ANDROID
///# define tcdrain(fd) ioctl(fd, TCSBRK, 1)
#ifdef ANDROID //inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;}
///# define tcdrain(fd) ioctl(fd, TCSBRK, 1) //inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;}
//inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;} #endif
//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())
#ifdef MAC_OS typedef long time_t;
# define environ (*_NSGetEnviron()) #endif
typedef long time_t;
#endif #ifdef LINUX
# define environ __environ
#ifdef LINUX #endif
# define environ __environ
#endif #ifdef FREE_BSD
extern char ** environ;
#ifdef FREE_BSD #endif
extern char ** environ;
#endif
#ifdef CC_GCC
# undef DEPRECATED
#ifdef CC_GCC # define DEPRECATED __attribute__((deprecated))
# undef DEPRECATED # if CC_GCC_VERSION > 0x025F // > 2.95
# define DEPRECATED __attribute__((deprecated)) # ifdef LINUX
# if CC_GCC_VERSION > 0x025F // > 2.95 # define HAS_LOCALE
# ifdef LINUX # endif
# define HAS_LOCALE # ifdef MAC_OS
# endif # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
# ifdef MAC_OS # pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
# pragma GCC diagnostic ignored "-Wdeprecated-declarations" # pragma GCC diagnostic ignored "-Wc++11-extensions"
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion" # endif
# pragma GCC diagnostic ignored "-Wc++11-extensions" # endif
# endif # ifdef ANDROID
# endif # pragma GCC diagnostic ignored "-Wunused-parameter"
# ifdef ANDROID # pragma GCC diagnostic ignored "-Wextra"
# pragma GCC diagnostic ignored "-Wunused-parameter" # pragma GCC diagnostic ignored "-Wc++11-extensions"
# pragma GCC diagnostic ignored "-Wextra" # pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
# pragma GCC diagnostic ignored "-Wc++11-extensions" //# pragma GCC diagnostic ignored "-Wliteral-suffix"
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion" # endif
//# pragma GCC diagnostic ignored "-Wliteral-suffix" #endif
# endif
#endif #ifdef CC_VC
# undef DEPRECATED
#ifdef CC_VC # define DEPRECATED
# undef DEPRECATED # pragma warning(disable: 4018)
# define DEPRECATED # pragma warning(disable: 4061)
# pragma warning(disable: 4018) # pragma warning(disable: 4100)
# pragma warning(disable: 4061) # pragma warning(disable: 4239)
# pragma warning(disable: 4100) # pragma warning(disable: 4242)
# pragma warning(disable: 4239) # pragma warning(disable: 4244)
# pragma warning(disable: 4242) # pragma warning(disable: 4251)
# pragma warning(disable: 4244) # pragma warning(disable: 4365)
# pragma warning(disable: 4251) # pragma warning(disable: 4512)
# pragma warning(disable: 4365) # pragma warning(disable: 4668)
# pragma warning(disable: 4512) # pragma warning(disable: 4710)
# pragma warning(disable: 4668) # pragma warning(disable: 4800)
# pragma warning(disable: 4710) # pragma warning(disable: 4820)
# pragma warning(disable: 4800) # pragma warning(disable: 4986)
# pragma warning(disable: 4820) # pragma warning(disable: 4996)
# pragma warning(disable: 4986) # ifdef ARCH_BITS_32
# pragma warning(disable: 4996) typedef long ssize_t;
# ifdef ARCH_BITS_32 # else
typedef long ssize_t; typedef long long ssize_t;
# else # endif
typedef long long ssize_t; #endif
# endif
#endif #ifdef CC_OTHER
# undef DEPRECATED
#ifdef CC_OTHER # define DEPRECATED
# undef DEPRECATED #endif
# define DEPRECATED
#endif
// Private data macros
// Private data macros #define PRIVATE_DECLARATION(e) \
struct __Private__; \
#define PRIVATE_DECLARATION \ friend struct __Private__; \
struct __Private__; \ struct e __PrivateInitializer__ { \
friend struct __Private__; \ __PrivateInitializer__(); \
struct __PrivateInitializer__ { \ __PrivateInitializer__(const __PrivateInitializer__ & o); \
__PrivateInitializer__(); \ ~__PrivateInitializer__(); \
__PrivateInitializer__(const __PrivateInitializer__ & o); \ __PrivateInitializer__ & operator =(const __PrivateInitializer__ & o); \
~__PrivateInitializer__(); \ __Private__ * p; \
__PrivateInitializer__ & operator =(const __PrivateInitializer__ & o); \ }; \
__Private__ * p; \ __PrivateInitializer__ __privateinitializer__;
}; \
__PrivateInitializer__ __privateinitializer__; #define PRIVATE_DEFINITION_START(c) \
struct c::__Private__ {
#define PRIVATE_DEFINITION_START(c) \
struct c::__Private__ { #define PRIVATE_DEFINITION_END(c) \
}; \
#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__() {p = new c::__Private__();} \ c::__PrivateInitializer__::~__PrivateInitializer__() {delete p; p = 0;} \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ & ) {/*if (p) delete p;*/ p = new c::__Private__();} \ c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & ) {if (p) delete p; p = new c::__Private__(); return *this;}
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
#define PRIVATE (__privateinitializer__.p)
#define PRIVATEWB __privateinitializer__.p #define NO_COPY_CLASS(name) \
name(const name&) = delete; \
#define NO_COPY_CLASS(name) \ name& operator=(const name&) = delete;
explicit name(const name & ); \
void operator =(const name & ); #ifdef FREERTOS
# define PIP_MIN_MSLEEP 10.
#ifdef FREERTOS #else
# define PIP_MIN_MSLEEP 10. # define PIP_MIN_MSLEEP 1.
#else #endif
# define PIP_MIN_MSLEEP 1.
#endif
//! Macro used for infinite loop
#define FOREVER for (;;)
//! Macro used for infinite loop
#define FOREVER for (;;) //! Macro used for infinite wait
#define FOREVER_WAIT FOREVER msleep(PIP_MIN_MSLEEP);
//! Macro used for infinite wait
#define FOREVER_WAIT FOREVER msleep(PIP_MIN_MSLEEP); //! Macro used for infinite wait
#define WAIT_FOREVER FOREVER msleep(PIP_MIN_MSLEEP);
//! Macro used for infinite wait
#define WAIT_FOREVER FOREVER msleep(PIP_MIN_MSLEEP);
//! global variable enabling output to piCout, default is true
extern PIP_EXPORT bool piDebug;
//! global variable enabling output to piCout, default is true
extern PIP_EXPORT bool piDebug; //! global variable that set minimum real update interval
//! for function PIInit::mountInfo(), default is 10000 ms
//! global variable that set minimum real update interval extern PIP_EXPORT double piMountInfoRefreshIntervalMs;
//! for function PIInit::mountInfo(), default is 10000 ms
extern PIP_EXPORT double piMountInfoRefreshIntervalMs; typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned char uchar; typedef unsigned int uint;
typedef unsigned short ushort; typedef unsigned long ulong;
typedef unsigned int uint; typedef unsigned long long ullong;
typedef unsigned long ulong; typedef long long llong;
typedef unsigned long long ullong; typedef long double ldouble;
typedef long long llong;
typedef long double ldouble; /*! \brief Templated function for swap two values
* \details Example:\n \snippet piincludes.cpp swap */
/*! \brief Templated function for swap two values template<typename T> inline void piSwap(T & f, T & s) {T t(std::move(f)); f = std::move(s); s = std::move(t);}
* \details Example:\n \snippet piincludes.cpp swap */
template<typename T> inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;} /*! \brief Templated function for swap two values without "="
* \details Example:\n \snippet piincludes.cpp swapBinary */
/*! \brief Templated function for swap two values without "=" template<typename T> inline void piSwapBinary(T & f, T & s) {
* \details Example:\n \snippet piincludes.cpp swapBinary */ if ((size_t*)&f == (size_t*)&s) return;
template<typename T> inline void piSwapBinary(T & f, T & s) { size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
if ((size_t*)&f == (size_t*)&s) return; size_t i = 0;
size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T); for (i = 0; i < j; ++i) {
size_t i = 0; ((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
for (i = 0; i < j; ++i) { ((size_t*)(&s))[i] ^= ((size_t*)(&f))[i];
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i]; ((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
((size_t*)(&s))[i] ^= ((size_t*)(&f))[i]; }
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i]; for (i = bs; i < bf; ++i) {
} ((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
for (i = bs; i < bf; ++i) { ((uchar*)(&s))[i] ^= ((uchar*)(&f))[i];
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i]; ((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
((uchar*)(&s))[i] ^= ((uchar*)(&f))[i]; }
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i]; }
}
} template<> inline void piSwapBinary(const void *& f, const void *& s) {
if ((size_t*)f == (size_t*)s) return;
template<> inline void piSwapBinary(const void *& f, const void *& s) { size_t j = (sizeof(void *) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(void *);
if ((size_t*)f == (size_t*)s) return; size_t i = 0;
size_t j = (sizeof(void *) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(void *); void * pf = const_cast<void*>(f), * ps = const_cast<void*>(s);
size_t i = 0; for (i = 0; i < j; ++i) {
void * pf = const_cast<void*>(f), * ps = const_cast<void*>(s); ((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i];
for (i = 0; i < j; ++i) { ((size_t*)(&ps))[i] ^= ((size_t*)(&pf))[i];
((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i]; ((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i];
((size_t*)(&ps))[i] ^= ((size_t*)(&pf))[i]; }
((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i]; for (i = bs; i < bf; ++i) {
} ((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i];
for (i = bs; i < bf; ++i) { ((uchar*)(&ps))[i] ^= ((uchar*)(&pf))[i];
((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i]; ((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i];
((uchar*)(&ps))[i] ^= ((uchar*)(&pf))[i]; }
((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i]; }
}
} template<> inline void piSwap(double & f, double & s) {piSwapBinary<double>(f, s);}
template<> inline void piSwap(ldouble & f, ldouble & s) {piSwapBinary<ldouble>(f, s);}
/*! \brief Function for compare two values without "=" by raw content #ifdef ARCH_BITS_32
* \details Example:\n \snippet piincludes.cpp compareBinary */ template<> inline void piSwap(float & f, float & s) {piSwapBinary<float>(f, s);}
inline bool piCompareBinary(const void * f, const void * s, size_t size) { template<> inline void piSwap(llong & f, llong & s) {piSwapBinary<llong>(f, s);}
for (size_t i = 0; i < size; ++i) template<> inline void piSwap(ullong & f, ullong & s) {piSwapBinary<ullong>(f, s);}
if (((const uchar*)f)[i] != ((const uchar*)s)[i]) #endif
return false;
return true; /*! \brief Function for compare two values without "=" by raw content
} * \details Example:\n \snippet piincludes.cpp compareBinary */
inline bool piCompareBinary(const void * f, const void * s, size_t size) {
/*! \brief Templated function return round of float falue for (size_t i = 0; i < size; ++i)
* \details Round is the nearest integer value \n if (((const uchar*)f)[i] != ((const uchar*)s)[i])
* There are some macros: return false;
* - \c piRoundf for "float" return true;
* - \c piRoundd for "double" }
*
* Example: /*! \brief Templated function return round of float falue
* \snippet piincludes.cpp round */ * \details Round is the nearest integer value \n
template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));} * There are some macros:
* - \c piRoundf for "float"
/*! \brief Templated function return floor of float falue * - \c piRoundd for "double"
* \details Floor is the largest integer that is not greater than value \n *
* There are some macros: * Example:
* - \c piFloorf for "float" * \snippet piincludes.cpp round */
* - \c piFloord for "double" template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
*
* Example: /*! \brief Templated function return floor of float falue
* \snippet piincludes.cpp floor */ * \details Floor is the largest integer that is not greater than value \n
template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);} * There are some macros:
* - \c piFloorf for "float"
/*! \brief Templated function return ceil of float falue * - \c piFloord for "double"
* \details Ceil is the smallest integer that is not less than value \n *
* There are some macros: * Example:
* - \c piCeilf for "float" * \snippet piincludes.cpp floor */
* - \c piCeild for "double" template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
*
* Example: /*! \brief Templated function return ceil of float falue
* \snippet piincludes.cpp ceil */ * \details Ceil is the smallest integer that is not less than value \n
template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;} * There are some macros:
* - \c piCeilf for "float"
/*! \brief Templated function return absolute of numeric falue * - \c piCeild for "double"
* \details Absolute is the positive or equal 0 value \n *
* There are some macros: * Example:
* - \c piAbss for "short" * \snippet piincludes.cpp ceil */
* - \c piAbsi for "int" template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
* - \c piAbsl for "long"
* - \c piAbsll for "llong" /*! \brief Templated function return absolute of numeric falue
* - \c piAbsf for "float" * \details Absolute is the positive or equal 0 value \n
* - \c piAbsd for "double" * There are some macros:
* * - \c piAbss for "short"
* Example: * - \c piAbsi for "int"
* \snippet piincludes.cpp abs */ * - \c piAbsl for "long"
template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);} * - \c piAbsll for "llong"
* - \c piAbsf for "float"
/*! \brief Templated function return minimum of two values * - \c piAbsd for "double"
* \details There are some macros: *
* - \c piMins for "short" * Example:
* - \c piMini for "int" * \snippet piincludes.cpp abs */
* - \c piMinl for "long" template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
* - \c piMinll for "llong"
* - \c piMinf for "float" /*! \brief Templated function return minimum of two values
* - \c piMind for "double" * \details There are some macros:
* * - \c piMins for "short"
* Example: * - \c piMini for "int"
* \snippet piincludes.cpp min2 */ * - \c piMinl for "long"
template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);} * - \c piMinll for "llong"
* - \c piMinf for "float"
/*! \brief Templated function return minimum of tree values * - \c piMind for "double"
* \details There are some macros: *
* - \c piMins for "short" * Example:
* - \c piMini for "int" * \snippet piincludes.cpp min2 */
* - \c piMinl for "long" template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
* - \c piMinll for "llong"
* - \c piMinf for "float" /*! \brief Templated function return minimum of tree values
* - \c piMind for "double" * \details There are some macros:
* * - \c piMins for "short"
* Example: * - \c piMini for "int"
* \snippet piincludes.cpp min3 */ * - \c piMinl for "long"
template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));} * - \c piMinll for "llong"
* - \c piMinf for "float"
/*! \brief Templated function return maximum of two values * - \c piMind for "double"
* \details There are some macros: *
* - \c piMaxs for "short" * Example:
* - \c piMaxi for "int" * \snippet piincludes.cpp min3 */
* - \c piMaxl for "long" template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
* - \c piMaxll for "llong"
* - \c piMaxf for "float" /*! \brief Templated function return maximum of two values
* - \c piMaxd for "double" * \details There are some macros:
* * - \c piMaxs for "short"
* Example: * - \c piMaxi for "int"
* \snippet piincludes.cpp max2 */ * - \c piMaxl for "long"
template<typename T> inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);} * - \c piMaxll for "llong"
* - \c piMaxf for "float"
/*! \brief Templated function return maximum of tree values * - \c piMaxd for "double"
* \details There are some macros: *
* - \c piMaxs for "short" * Example:
* - \c piMaxi for "int" * \snippet piincludes.cpp max2 */
* - \c piMaxl for "long" template<typename T> inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
* - \c piMaxll for "llong"
* - \c piMaxf for "float" /*! \brief Templated function return maximum of tree values
* - \c piMaxd for "double" * \details There are some macros:
* * - \c piMaxs for "short"
* Example: * - \c piMaxi for "int"
* \snippet piincludes.cpp max3 */ * - \c piMaxl for "long"
template<typename T> inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));} * - \c piMaxll for "llong"
* - \c piMaxf for "float"
/*! \brief Templated function return clamped value * - \c piMaxd for "double"
* \details Clamped is the not greater than "max" and not lesser than "min" value \n *
* There are some macros: * Example:
* - \c piClamps for "short" * \snippet piincludes.cpp max3 */
* - \c piClampi for "int" template<typename T> inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));}
* - \c piClampl for "long"
* - \c piClampll for "llong" /*! \brief Templated function return clamped value
* - \c piClampf for "float" * \details Clamped is the not greater than "max" and not lesser than "min" value \n
* - \c piClampd for "double" * There are some macros:
* * - \c piClamps for "short"
* Example: * - \c piClampi for "int"
* \snippet piincludes.cpp clamp */ * - \c piClampl for "long"
template<typename T> inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));} * - \c piClampll for "llong"
* - \c piClampf for "float"
/// Function inverse byte order in memory block * - \c piClampd for "double"
inline void piLetobe(void * data, int size) { *
for (int i = 0; i < size / 2; i++) * Example:
piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]); * \snippet piincludes.cpp clamp */
} template<typename T> inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
/// \brief Templated function that inverse byte order of value "v" /// Function inverse byte order in memory block
template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));} inline void piLetobe(void * data, int size) {
for (int i = 0; i < size / 2; i++)
/*! \brief Templated function that returns "v" with inversed byte order piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]);
* \details This function used to convert values between little and big endian \n }
* There are some macros:
* - \c piLetobes for "ushort" /// \brief Templated function that inverse byte order of value "v"
* - \c piLetobei for "uint" template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
* - \c piLetobel for "ulong"
* - \c piLetobell for "ullong" /*! \brief Templated function that returns "v" with inversed byte order
* * \details This function used to convert values between little and big endian \n
* Example: * There are some macros:
* \snippet piincludes.cpp letobe */ * - \c piLetobes for "ushort"
template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;} * - \c piLetobei for "uint"
* - \c piLetobel for "ulong"
// specialization * - \c piLetobell for "ullong"
template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);} *
template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} * Example:
template<> inline float piLetobe(const float & v) { * \snippet piincludes.cpp letobe */
union _pletobe_f { template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;}
_pletobe_f(const float &f_) {f = f_;}
float f; // specialization
uint v; template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);}
}; template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
_pletobe_f a(v); template<> inline float piLetobe(const float & v) {
a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000); union _pletobe_f {
return a.f; _pletobe_f(const float &f_) {f = f_;}
} float f;
uint v;
DEPRECATED inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);} };
DEPRECATED inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} _pletobe_f a(v);
a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000);
#ifdef DOXYGEN return a.f;
}
/// \deprecated \brief Use \a piLetobe() instead of this function
ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);} DEPRECATED inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);}
DEPRECATED inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
/// \deprecated \brief Use \a piLetobe() instead of this function
uint letobe_i(uint v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} #ifdef DOXYGEN
#endif /// \deprecated \brief Use \a piLetobe() instead of this function
ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);}
/// \brief Generic hash function, impements murmur3/32 algorithm
inline uint piHashData(const uchar * data, uint len, uint seed = 0) { /// \deprecated \brief Use \a piLetobe() instead of this function
if (!data || len <= 0) return 0u; uint letobe_i(uint v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
uint h = seed;
if (len > 3) { #endif
uint i = len >> 2;
do { /// \brief Generic hash function, impements murmur3/32 algorithm
uint k; inline uint piHashData(const uchar * data, uint len, uint seed = 0) {
memcpy(&k, data, sizeof(uint)); if (!data || len <= 0) return 0u;
data += sizeof(uint); uint h = seed;
k *= 0xcc9e2d51; if (len > 3) {
k = (k << 15) | (k >> 17); uint i = len >> 2;
k *= 0x1b873593; do {
h ^= k; uint k;
h = (h << 13) | (h >> 19); memcpy(&k, data, sizeof(uint));
h = h * 5 + 0xe6546b64; data += sizeof(uint);
} while (--i); k *= 0xcc9e2d51;
} k = (k << 15) | (k >> 17);
if (len & 3) { k *= 0x1b873593;
uint i = len & 3; h ^= k;
uint k = 0; h = (h << 13) | (h >> 19);
do { h = h * 5 + 0xe6546b64;
k <<= 8; } while (--i);
k |= data[i - 1]; }
} while (--i); if (len & 3) {
k *= 0xcc9e2d51; uint i = len & 3;
k = (k << 15) | (k >> 17); uint k = 0;
k *= 0x1b873593; do {
h ^= k; k <<= 8;
} k |= data[i - 1];
h ^= len; } while (--i);
h ^= h >> 16; k *= 0xcc9e2d51;
h *= 0x85ebca6b; k = (k << 15) | (k >> 17);
h ^= h >> 13; k *= 0x1b873593;
h *= 0xc2b2ae35; h ^= k;
h ^= h >> 16; }
return h; h ^= len;
} h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
template<typename T> inline uint piHash(const T & v) { h *= 0xc2b2ae35;
return 0; h ^= h >> 16;
} return h;
}
template<> inline uint piHash(const char & v) {return (uint)v;}
template<> inline uint piHash(const uchar & v) {return (uint)v;}
template<> inline uint piHash(const short & v) {return (uint)v;} template<typename T> inline uint piHash(const T & v) {
template<> inline uint piHash(const ushort & v) {return (uint)v;} return 0;
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 char & v) {return (uint)v;}
template<> inline uint piHash(const ullong & v) {return piHashData((const uchar *)&v, sizeof(v));} template<> inline uint piHash(const uchar & v) {return (uint)v;}
template<> inline uint piHash(const float & v) {return (uint)v;} template<> inline uint piHash(const short & v) {return (uint)v;}
template<> inline uint piHash(const double & v) {return piHashData((const uchar *)&v, sizeof(v));} template<> inline uint piHash(const ushort & v) {return (uint)v;}
template<> inline uint piHash(const ldouble & v) {return piHashData((const uchar *)&v, sizeof(v));} template<> inline uint piHash(const int & v) {return (uint)v;}
template<> inline uint piHash(const uint & v) {return (uint)v;}
#define piRoundf piRound<float> template<> inline uint piHash(const llong & v) {return piHashData((const uchar *)&v, sizeof(v));}
#define piRoundd piRound<double> template<> inline uint piHash(const ullong & v) {return piHashData((const uchar *)&v, sizeof(v));}
#define piFloorf piFloor<float> template<> inline uint piHash(const float & v) {return (uint)v;}
#define piFloord piFloor<double> template<> inline uint piHash(const double & v) {return piHashData((const uchar *)&v, sizeof(v));}
#define piCeilf piCeil<float> template<> inline uint piHash(const ldouble & v) {return piHashData((const uchar *)&v, sizeof(v));}
#define piCeild piCeil<double>
#define piAbss piAbs<short> #define piRoundf piRound<float>
#define piAbsi piAbs<int> #define piRoundd piRound<double>
#define piAbsl piAbs<long> #define piFloorf piFloor<float>
#define piAbsll piAbs<llong> #define piFloord piFloor<double>
#define piAbsf piAbs<float> #define piCeilf piCeil<float>
#define piAbsd piAbs<double> #define piCeild piCeil<double>
#define piMins piMin<short> #define piAbss piAbs<short>
#define piMini piMin<int> #define piAbsi piAbs<int>
#define piMinl piMin<long> #define piAbsl piAbs<long>
#define piMinll piMin<llong> #define piAbsll piAbs<llong>
#define piMinf piMin<float> #define piAbsf piAbs<float>
#define piMind piMin<double> #define piAbsd piAbs<double>
#define piMaxs piMax<short> #define piMins piMin<short>
#define piMaxi piMax<int> #define piMini piMin<int>
#define piMaxl piMax<long> #define piMinl piMin<long>
#define piMaxll piMax<llong> #define piMinll piMin<llong>
#define piMaxf piMax<float> #define piMinf piMin<float>
#define piMaxd piMax<double> #define piMind piMin<double>
#define piClamps piClamp<short> #define piMaxs piMax<short>
#define piClampi piClamp<int> #define piMaxi piMax<int>
#define piClampl piClamp<long> #define piMaxl piMax<long>
#define piClampll piClamp<llong> #define piMaxll piMax<llong>
#define piClampf piClamp<float> #define piMaxf piMax<float>
#define piClampd piClamp<double> #define piMaxd piMax<double>
#define piLetobes piLetobe<ushort> #define piClamps piClamp<short>
#define piLetobei piLetobe<uint> #define piClampi piClamp<int>
#define piLetobel piLetobe<ulong> #define piClampl piClamp<long>
#define piLetobell piLetobe<ullong> #define piClampll piClamp<llong>
#define piLetobef piLetobe<float> #define piClampf piClamp<float>
#define piClampd piClamp<double>
#define piLetobes piLetobe<ushort>
#endif // PIBASE_H #define piLetobei piLetobe<uint>
#define piLetobel piLetobe<ulong>
#define piLetobell piLetobe<ullong>
#define piLetobef piLetobe<float>
#endif // PIBASE_H

View File

@@ -1,44 +1,44 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Bit array Bit array
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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 "pibitarray.h" #include "pibitarray.h"
#include "picout.h" #include "picout.h"
PICout operator <<(PICout s, const PIBitArray & ba) { PICout operator <<(PICout s, const PIBitArray & ba) {
s.space(); s.space();
s.setControl(0, true); s.setControl(0, true);
for (uint i = 0; i < ba.bitSize(); ++i) { for (uint i = 0; i < ba.bitSize(); ++i) {
s << int(ba[i]); s << int(ba[i]);
if (i % 8 == 7) s << ' '; if (i % 8 == 7) s << ' ';
} }
s.restoreControl(); s.restoreControl();
return s; return s;
} }
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
std::ostream &operator <<(std::ostream & s, const PIBitArray & ba) { std::ostream &operator <<(std::ostream & s, const PIBitArray & ba) {
for (uint i = 0; i < ba.bitSize(); ++i) { for (uint i = 0; i < ba.bitSize(); ++i) {
s << ba[i]; s << ba[i];
if (i % 8 == 7) s << ' '; if (i % 8 == 7) s << ' ';
} }
return s; return s;
} }
#endif #endif

View File

View File

View File

@@ -56,6 +56,10 @@ public:
//! Constructs an empty byte array //! Constructs an empty byte array
PIByteArray() {;} PIByteArray() {;}
PIByteArray(const PIByteArray & o): PIDeque<uchar>(o) {}
PIByteArray(PIByteArray && o): PIDeque<uchar>(std::move(o)) {}
//! Constructs 0-filled byte array with size "size" //! Constructs 0-filled byte array with size "size"
PIByteArray(const uint size) {resize(size);} PIByteArray(const uint size) {resize(size);}
@@ -124,6 +128,10 @@ public:
void operator =(const PIDeque<uchar> & d) {resize(d.size()); memcpy(data(), d.data(), d.size());} 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 fromUserInput(PIString str);
static PIByteArray fromHex(PIString str); static PIByteArray fromHex(PIString str);
static PIByteArray fromBase64(const PIByteArray & base64); static PIByteArray fromBase64(const PIByteArray & base64);
@@ -138,7 +146,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
#endif #endif
//! \relatesalso PIByteArray \brief Output to PICout operator //! \relatesalso PIByteArray \brief Output to PICout operator
PICout operator <<(PICout s, const PIByteArray & ba); PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
#define PBA_OPERATOR_TO int os = s.size_s(); s.enlarge(sizeof(v)); memcpy(s.data(os), &v, sizeof(v)); #define PBA_OPERATOR_TO int os = s.size_s(); s.enlarge(sizeof(v)); memcpy(s.data(os), &v, sizeof(v));
@@ -212,7 +220,7 @@ inline PIByteArray & operator >>(PIByteArray & s, ldouble & v) {assert(s.size()
//! \relatesalso PIByteArray \brief Restore operator //! \relatesalso PIByteArray \brief Restore operator
template<typename T> inline PIByteArray & operator >>(PIByteArray & s, PIFlags<T> & v) {PBA_OPERATOR_FROM return s;} template<typename T> inline PIByteArray & operator >>(PIByteArray & s, PIFlags<T> & v) {PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details //! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
PIByteArray & operator >>(PIByteArray & s, PIByteArray & v); PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details //! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {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;} inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {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;}
@@ -316,6 +324,7 @@ __PIBYTEARRAY_SIMPLE_TYPE__(PIChar)
template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();} template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);}
#endif // PIBYTEARRAY_H #endif // PIBYTEARRAY_H

6
src_main/core/pichar.h → lib/main/core/pichar.h Executable file → Normal file
View File

@@ -25,9 +25,9 @@
#include "piincludes.h" #include "piincludes.h"
extern char * __syslocname__; extern PIP_EXPORT char * __syslocname__;
extern char * __sysoemname__; extern PIP_EXPORT char * __sysoemname__;
extern char * __utf8name__; extern PIP_EXPORT char * __utf8name__;
class PIP_EXPORT PIChar class PIP_EXPORT PIChar
{ {

View File

@@ -54,12 +54,18 @@ public:
int id; int id;
T data; T data;
}; };
template <typename T>
struct ChunkConst {
ChunkConst(int i, const T & d): id(i), data(d) {}
int id;
const T & data;
};
//! Returns chunk with ID "id" and value "data" for write to stream //! Returns chunk with ID "id" and value "data" for write to stream
template <typename T> static Chunk<T> chunk(int id, const T & data) {return Chunk<T>(id, data);} template <typename T> static ChunkConst<T> chunk(int id, const T & data) {return ChunkConst<T>(id, data);}
//! Add data to this chunk strean with ID "id" and value "data" //! Add data to this chunk strean with ID "id" and value "data"
template <typename T> PIChunkStream & add(int id, const T & data) {*this << Chunk<T>(id, data); return *this;} template <typename T> PIChunkStream & add(int id, const T & data) {*this << ChunkConst<T>(id, data); return *this;}
void setSource(const PIByteArray & data); void setSource(const PIByteArray & data);
void setSource(PIByteArray * data); void setSource(PIByteArray * data);
@@ -112,6 +118,7 @@ private:
PIMap<int, PIByteArray> data_map; PIMap<int, PIByteArray> data_map;
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c); template <typename T> 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> template <typename T>
@@ -133,5 +140,24 @@ PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c
} }
return s; return s;
} }
template <typename T>
PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::ChunkConst<T> & c) {
PIByteArray ba;
ba << c.data;
switch (s.version_) {
case PIChunkStream::Version_1:
(*(s.data_)) << c.id << ba;
break;
case PIChunkStream::Version_2:
if (s.data_->isEmpty())
(*(s.data_)) << uchar(uchar(s.version_) | 0x80);
PIChunkStream::writeVInt(*(s.data_), c.id);
PIChunkStream::writeVInt(*(s.data_), ba.size());
s.data_->append(ba);
break;
default: break;
}
return s;
}
#endif // PICHUNKSTREAM_H #endif // PICHUNKSTREAM_H

0
src_main/core/picli.cpp → lib/main/core/picli.cpp Executable file → Normal file
View File

0
src_main/core/picli.h → lib/main/core/picli.h Executable file → Normal file
View File

View File

View File

@@ -64,13 +64,13 @@ public:
static bool addToGroup(const PIString & group, const PIObject * element); static bool addToGroup(const PIString & group, const PIObject * element);
class CollectionAdder { class PIP_EXPORT CollectionAdder {
public: public:
CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString(), bool own = false); CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString(), bool own = false);
}; };
protected: protected:
struct Group { struct PIP_EXPORT Group {
Group(const PIString & name_ = PIString()) {name = name_;} Group(const PIString & name_ = PIString()) {name = name_;}
PIString name; PIString name;
PIVector<const PIObject * > elements; PIVector<const PIObject * > elements;

View File

@@ -18,9 +18,9 @@
*/ */
#include "piincludes_p.h" #include "piincludes_p.h"
#include "picout.h" #include "picout.h"
#include "piconsole.h"
#include "pibytearray.h" #include "pibytearray.h"
#include "pistack.h" #include "pistack.h"
#include "piobject.h"
#include "pistring_std.h" #include "pistring_std.h"
#ifdef WINDOWS #ifdef WINDOWS
# include <windows.h> # include <windows.h>

View File

@@ -1,301 +1,301 @@
/*! \file picout.h /*! \file picout.h
* \brief Universal output to console class * \brief Universal output to console class
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Universal output to console class Universal output to console class
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PICOUT_H #ifndef PICOUT_H
#define PICOUT_H #define PICOUT_H
#include "piincludes.h" #include "piincludes.h"
#ifdef DOXYGEN #ifdef DOXYGEN
//! \brief Macro used for conditional (piDebug) output to PICout //! \brief Macro used for conditional (piDebug) output to PICout
# define piCout # define piCout
//! \relatesalso PIObject \brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject //! \relatesalso PIObject \brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject
# define piCoutObj # define piCoutObj
#else #else
# define piCout PICout(piDebug) # define piCout PICout(piDebug)
# define piCoutObj PICout(piDebug && debug()) << (PIStringAscii("[") + className() + PIStringAscii(" \"") + name() + PIStringAscii("\"]")) # define piCoutObj PICout(piDebug && debug()) << (PIStringAscii("[") + className() + PIStringAscii(" \"") + name() + PIStringAscii("\"]"))
#endif #endif
class PIObject; class PIObject;
//! \brief Namespace contains enums controlled PICout //! \brief Namespace contains enums controlled PICout
namespace PICoutManipulators { namespace PICoutManipulators {
//! \brief Enum contains special characters //! \brief Enum contains special characters
enum PIP_EXPORT PICoutSpecialChar { enum PICoutSpecialChar {
Null /*! Null-character, '\\0' */, Null /*! Null-character, '\\0' */,
NewLine /*! New line character, '\\n' */, NewLine /*! New line character, '\\n' */,
Tab /*! Tab character, '\\t' */, Tab /*! Tab character, '\\t' */,
Esc /*! Escape character, '\\e' */, Esc /*! Escape character, '\\e' */,
Quote /*! Quote character, '"' */ Quote /*! Quote character, '"' */
}; };
//! \brief Enum contains immediate action //! \brief Enum contains immediate action
enum PIP_EXPORT PICoutAction { enum PICoutAction {
Flush /*! Flush the output */, Flush /*! Flush the output */,
Backspace /*! Remove last symbol */, Backspace /*! Remove last symbol */,
ShowCursor /*! Show cursor */, ShowCursor /*! Show cursor */,
HideCursor /*! Hide cursor */, HideCursor /*! Hide cursor */,
ClearLine /*! Clear current line */, ClearLine /*! Clear current line */,
ClearScreen /*! Clear the screen */, ClearScreen /*! Clear the screen */,
SaveContol /*! Save control flags, equivalent to \a saveControl() */, SaveContol /*! Save control flags, equivalent to \a saveControl() */,
RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */ RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */
}; };
//! \brief Enum contains control of PICout //! \brief Enum contains control of PICout
enum PIP_EXPORT PICoutControl { enum PICoutControl {
AddNone /*! No controls */ = 0x0, AddNone /*! No controls */ = 0x0,
AddSpaces /*! Spaces will be appear after each output */ = 0x1, AddSpaces /*! Spaces will be appear after each output */ = 0x1,
AddNewLine /*! New line will be appear after all output */ = 0x2, AddNewLine /*! New line will be appear after all output */ = 0x2,
AddQuotes /*! Each string will be quoted */ = 0x4, AddQuotes /*! Each string will be quoted */ = 0x4,
DefaultControls /*! Default controls */ = AddSpaces | AddNewLine, DefaultControls /*! Default controls */ = AddSpaces | AddNewLine,
AddAll /*! All controls */ = 0xFF, AddAll /*! All controls */ = 0xFF,
NoLock /*! Don`t use mutex for output */ = 0x100, NoLock /*! Don`t use mutex for output */ = 0x100,
}; };
//! \brief Enum contains output format //! \brief Enum contains output format
enum PIP_EXPORT PICoutFormat { enum PICoutFormat {
Bin /*! Binary representation of integers */ = 0x01, Bin /*! Binary representation of integers */ = 0x01,
Oct /*! Octal representation of integers */ = 0x02, Oct /*! Octal representation of integers */ = 0x02,
Dec /*! Decimal representation of integers */ = 0x04, Dec /*! Decimal representation of integers */ = 0x04,
Hex /*! Hexadecimal representation of integers */ = 0x08, Hex /*! Hexadecimal representation of integers */ = 0x08,
Bold /*! Bold */ = 0x10, Bold /*! Bold */ = 0x10,
Faint /*! */ = 0x20, Faint /*! */ = 0x20,
Italic /*! */ = 0x40, Italic /*! */ = 0x40,
Underline /*! Underline */ = 0x80, Underline /*! Underline */ = 0x80,
Blink /*! Blink */ = 0x100, Blink /*! Blink */ = 0x100,
Black /*! Black font */ = 0x400, Black /*! Black font */ = 0x400,
Red /*! Red font */ = 0x800, Red /*! Red font */ = 0x800,
Green /*! Green font */ = 0x1000, Green /*! Green font */ = 0x1000,
Blue /*! Blue font */ = 0x2000, Blue /*! Blue font */ = 0x2000,
Yellow /*! Yellow font */ = 0x4000, Yellow /*! Yellow font */ = 0x4000,
Magenta /*! Magenta font */ = 0x8000, Magenta /*! Magenta font */ = 0x8000,
Cyan /*! Cyan font */ = 0x10000, Cyan /*! Cyan font */ = 0x10000,
White /*! White font */ = 0x20000, White /*! White font */ = 0x20000,
BackBlack /*! Black background */ = 0x40000, BackBlack /*! Black background */ = 0x40000,
BackRed /*! Red background */ = 0x80000, BackRed /*! Red background */ = 0x80000,
BackGreen /*! Green background */ = 0x100000, BackGreen /*! Green background */ = 0x100000,
BackBlue /*! Blue background */ = 0x200000, BackBlue /*! Blue background */ = 0x200000,
BackYellow /*! Yellow background */ = 0x400000, BackYellow /*! Yellow background */ = 0x400000,
BackMagenta /*! Magenta background */ = 0x800000, BackMagenta /*! Magenta background */ = 0x800000,
BackCyan /*! Cyan background */ = 0x1000000, BackCyan /*! Cyan background */ = 0x1000000,
BackWhite /*! White background */ = 0x2000000, BackWhite /*! White background */ = 0x2000000,
Default /*! Default format */ = 0x4000000 Default /*! Default format */ = 0x4000000
}; };
typedef PIFlags<PICoutControl> PICoutControls; typedef PIFlags<PICoutControl> PICoutControls;
} }
class PIP_EXPORT PICout { class PIP_EXPORT PICout {
public: public:
//! Default constructor with default features (AddSpaces and AddNewLine) //! Default constructor with default features (AddSpaces and AddNewLine)
PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls); PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls);
PICout(PICoutManipulators::PICoutControl control = PICoutManipulators::DefaultControls); PICout(PICoutManipulators::PICoutControl control = PICoutManipulators::DefaultControls);
//! Construct with default features (AddSpaces and AddNewLine), but if \"active\" is false does nothing //! Construct with default features (AddSpaces and AddNewLine), but if \"active\" is false does nothing
PICout(bool active); PICout(bool active);
//! Construct with external buffer and id "id". See \a Notifier for details //! Construct with external buffer and id "id". See \a Notifier for details
PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine); PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);
PICout(const PICout & other); PICout(const PICout & other);
~PICout(); ~PICout();
class Notifier { class PIP_EXPORT Notifier {
public: public:
static Notifier * instance(); static Notifier * instance();
static PIObject * object(); static PIObject * object();
private: private:
Notifier(); Notifier();
PIObject * o; PIObject * o;
}; };
//! \brief Enum contains output devices of PICout //! \brief Enum contains output devices of PICout
enum OutputDevice { enum OutputDevice {
NoDevices /** PICout is disabled */ = 0x0, NoDevices /** PICout is disabled */ = 0x0,
StdOut /** Standard console output */ = 0x1, StdOut /** Standard console output */ = 0x1,
Buffer /** Internal buffer */ = 0x2, Buffer /** Internal buffer */ = 0x2,
AllDevices /** All */ = 0xFFFF, AllDevices /** All */ = 0xFFFF,
}; };
typedef PIFlags<OutputDevice> OutputDevices; typedef PIFlags<OutputDevice> OutputDevices;
//! Output operator for strings with <tt>"const char * "</tt> type //! Output operator for strings with <tt>"const char * "</tt> type
PICout operator <<(const char * v); PICout operator <<(const char * v);
//! Output operator for strings with <tt>"std::string"</tt> type //! Output operator for strings with <tt>"std::string"</tt> type
//PICout operator <<(const std::string & v); //PICout operator <<(const std::string & v);
//! Output operator for boolean values //! Output operator for boolean values
PICout operator <<(const bool v); PICout operator <<(const bool v);
//! Output operator for <tt>"char"</tt> values //! Output operator for <tt>"char"</tt> values
PICout operator <<(const char v); PICout operator <<(const char v);
//! Output operator for <tt>"unsigned char"</tt> values //! Output operator for <tt>"unsigned char"</tt> values
PICout operator <<(const uchar v); PICout operator <<(const uchar v);
//! Output operator for <tt>"short"</tt> values //! Output operator for <tt>"short"</tt> values
PICout operator <<(const short v); PICout operator <<(const short v);
//! Output operator for <tt>"unsigned short"</tt> values //! Output operator for <tt>"unsigned short"</tt> values
PICout operator <<(const ushort v); PICout operator <<(const ushort v);
//! Output operator for <tt>"int"</tt> values //! Output operator for <tt>"int"</tt> values
PICout operator <<(const int v); PICout operator <<(const int v);
//! Output operator for <tt>"unsigned int"</tt> values //! Output operator for <tt>"unsigned int"</tt> values
PICout operator <<(const uint v); PICout operator <<(const uint v);
//! Output operator for <tt>"long"</tt> values //! Output operator for <tt>"long"</tt> values
PICout operator <<(const long v); PICout operator <<(const long v);
//! Output operator for <tt>"unsigned long"</tt> values //! Output operator for <tt>"unsigned long"</tt> values
PICout operator <<(const ulong v); PICout operator <<(const ulong v);
//! Output operator for <tt>"long long"</tt> values //! Output operator for <tt>"long long"</tt> values
PICout operator <<(const llong v); PICout operator <<(const llong v);
//! Output operator for <tt>"unsigned long long"</tt> values //! Output operator for <tt>"unsigned long long"</tt> values
PICout operator <<(const ullong v); PICout operator <<(const ullong v);
//! Output operator for <tt>"float"</tt> values //! Output operator for <tt>"float"</tt> values
PICout operator <<(const float v); PICout operator <<(const float v);
//! Output operator for <tt>"double"</tt> values //! Output operator for <tt>"double"</tt> values
PICout operator <<(const double v); PICout operator <<(const double v);
//! Output operator for pointers //! Output operator for pointers
PICout operator <<(const void * v); PICout operator <<(const void * v);
//! Output operator for PIObject and ancestors //! Output operator for PIObject and ancestors
PICout operator <<(const PIObject * v); PICout operator <<(const PIObject * v);
//! Output operator for \a PICoutSpecialChar values //! Output operator for \a PICoutSpecialChar values
PICout operator <<(const PICoutManipulators::PICoutSpecialChar v); PICout operator <<(const PICoutManipulators::PICoutSpecialChar v);
//! Output operator for \a PIFlags<PICoutFormat> values //! Output operator for \a PIFlags<PICoutFormat> values
PICout operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v) { 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;
if (v[PICoutManipulators::Hex]) cnb_ = 16; if (v[PICoutManipulators::Hex]) cnb_ = 16;
if (v[PICoutManipulators::Bold]) applyFormat(PICoutManipulators::Bold); if (v[PICoutManipulators::Bold]) applyFormat(PICoutManipulators::Bold);
if (v[PICoutManipulators::Faint]) applyFormat(PICoutManipulators::Faint); if (v[PICoutManipulators::Faint]) applyFormat(PICoutManipulators::Faint);
if (v[PICoutManipulators::Italic]) applyFormat(PICoutManipulators::Italic); if (v[PICoutManipulators::Italic]) applyFormat(PICoutManipulators::Italic);
if (v[PICoutManipulators::Underline]) applyFormat(PICoutManipulators::Underline); if (v[PICoutManipulators::Underline]) applyFormat(PICoutManipulators::Underline);
if (v[PICoutManipulators::Blink]) applyFormat(PICoutManipulators::Blink); if (v[PICoutManipulators::Blink]) applyFormat(PICoutManipulators::Blink);
if (v[PICoutManipulators::Black]) applyFormat(PICoutManipulators::Black); if (v[PICoutManipulators::Black]) applyFormat(PICoutManipulators::Black);
if (v[PICoutManipulators::Red]) applyFormat(PICoutManipulators::Red); if (v[PICoutManipulators::Red]) applyFormat(PICoutManipulators::Red);
if (v[PICoutManipulators::Green]) applyFormat(PICoutManipulators::Green); if (v[PICoutManipulators::Green]) applyFormat(PICoutManipulators::Green);
if (v[PICoutManipulators::Blue]) applyFormat(PICoutManipulators::Blue); if (v[PICoutManipulators::Blue]) applyFormat(PICoutManipulators::Blue);
if (v[PICoutManipulators::Yellow]) applyFormat(PICoutManipulators::Yellow); if (v[PICoutManipulators::Yellow]) applyFormat(PICoutManipulators::Yellow);
if (v[PICoutManipulators::Magenta]) applyFormat(PICoutManipulators::Magenta); if (v[PICoutManipulators::Magenta]) applyFormat(PICoutManipulators::Magenta);
if (v[PICoutManipulators::Cyan]) applyFormat(PICoutManipulators::Cyan); if (v[PICoutManipulators::Cyan]) applyFormat(PICoutManipulators::Cyan);
if (v[PICoutManipulators::White]) applyFormat(PICoutManipulators::White); if (v[PICoutManipulators::White]) applyFormat(PICoutManipulators::White);
if (v[PICoutManipulators::BackBlack]) applyFormat(PICoutManipulators::BackBlack); if (v[PICoutManipulators::BackBlack]) applyFormat(PICoutManipulators::BackBlack);
if (v[PICoutManipulators::BackRed]) applyFormat(PICoutManipulators::BackRed); if (v[PICoutManipulators::BackRed]) applyFormat(PICoutManipulators::BackRed);
if (v[PICoutManipulators::BackGreen]) applyFormat(PICoutManipulators::BackGreen); if (v[PICoutManipulators::BackGreen]) applyFormat(PICoutManipulators::BackGreen);
if (v[PICoutManipulators::BackBlue]) applyFormat(PICoutManipulators::BackBlue); if (v[PICoutManipulators::BackBlue]) applyFormat(PICoutManipulators::BackBlue);
if (v[PICoutManipulators::BackYellow]) applyFormat(PICoutManipulators::BackYellow); if (v[PICoutManipulators::BackYellow]) applyFormat(PICoutManipulators::BackYellow);
if (v[PICoutManipulators::BackMagenta]) applyFormat(PICoutManipulators::BackMagenta); if (v[PICoutManipulators::BackMagenta]) applyFormat(PICoutManipulators::BackMagenta);
if (v[PICoutManipulators::BackCyan]) applyFormat(PICoutManipulators::BackCyan); if (v[PICoutManipulators::BackCyan]) applyFormat(PICoutManipulators::BackCyan);
if (v[PICoutManipulators::BackWhite]) applyFormat(PICoutManipulators::BackWhite); if (v[PICoutManipulators::BackWhite]) applyFormat(PICoutManipulators::BackWhite);
if (v[PICoutManipulators::Default]) applyFormat(PICoutManipulators::Default); if (v[PICoutManipulators::Default]) applyFormat(PICoutManipulators::Default);
return *this; return *this;
} }
//! Output operator for \a PICoutFormat values //! Output operator for \a PICoutFormat values
PICout operator <<(const PICoutManipulators::PICoutFormat v) { 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;
case PICoutManipulators::Dec: cnb_ = 10; break; case PICoutManipulators::Dec: cnb_ = 10; break;
case PICoutManipulators::Hex: cnb_ = 16; break; case PICoutManipulators::Hex: cnb_ = 16; break;
default: applyFormat(v); default: applyFormat(v);
}; };
return *this; return *this;
} }
//! Do some action //! Do some action
PICout operator <<(const PICoutManipulators::PICoutAction v); PICout operator <<(const PICoutManipulators::PICoutAction v);
//! Set control flag "c" is "on" state //! Set control flag "c" is "on" state
PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;} PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;}
//! Set control flags "c" and if "save" exec \a saveControl() //! Set control flags "c" and if "save" exec \a saveControl()
PICout & setControl(PICoutManipulators::PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;} PICout & setControl(PICoutManipulators::PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;}
//! Save control flags to internal stack \sa \a restoreControl() //! Save control flags to internal stack \sa \a restoreControl()
PICout & saveControl(); PICout & saveControl();
//! Restore control flags from internal stack \sa \a saveControl() //! Restore control flags from internal stack \sa \a saveControl()
PICout & restoreControl(); PICout & restoreControl();
/*! \brief Conditional put space character to output /*! \brief Conditional put space character to output
* \details If it is not a first output and control \a AddSpaces is set * \details If it is not a first output and control \a AddSpaces is set
* space character is put \sa \a quote(), \a newLine() */ * space character is put \sa \a quote(), \a newLine() */
PICout & space(); PICout & space();
/*! \brief Conditional put quote character to output /*! \brief Conditional put quote character to output
* \details If control \a AddQuotes is set * \details If control \a AddQuotes is set
* quote character is put \sa \a space(), \a newLine() */ * quote character is put \sa \a space(), \a newLine() */
PICout & quote(); PICout & quote();
/*! \brief Conditional put new line character to output /*! \brief Conditional put new line character to output
* \details If control \a AddNewLine is set * \details If control \a AddNewLine is set
* new line character is put \sa \a space(), \a quote() */ * new line character is put \sa \a space(), \a quote() */
PICout & newLine(); PICout & newLine();
static bool setBufferActive(bool on, bool clear = false); static bool setBufferActive(bool on, bool clear = false);
static bool isBufferActive(); static bool isBufferActive();
static PIString buffer(bool clear = false); static PIString buffer(bool clear = false);
static void clearBuffer(); static void clearBuffer();
static bool setOutputDevice(OutputDevice d, bool on = true); static bool setOutputDevice(OutputDevice d, bool on = true);
static void setOutputDevices(OutputDevices d); static void setOutputDevices(OutputDevices d);
static bool isOutputDeviceActive(OutputDevice d); static bool isOutputDeviceActive(OutputDevice d);
static PIMutex & __mutex__(); static PIMutex & __mutex__();
static PIString & __string__(); static PIString & __string__();
private: private:
void init(); void init();
void applyFormat(PICoutManipulators::PICoutFormat f); void applyFormat(PICoutManipulators::PICoutFormat f);
static OutputDevices devs; static OutputDevices devs;
PRIVATE_DECLARATION PRIVATE_DECLARATION(PIP_EXPORT)
bool fo_, cc_, fc_, act_; bool fo_, cc_, fc_, act_;
int cnb_, attr_, id_; int cnb_, attr_, id_;
PIString * buffer_; PIString * buffer_;
PICoutManipulators::PICoutControls co_; PICoutManipulators::PICoutControls co_;
}; };
#endif // PICOUT_H #endif // PICOUT_H

View File

@@ -1,137 +1,137 @@
/*! \file piflags.h /*! \file piflags.h
* \brief General flags class * \brief General flags class
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
General flags class General flags class
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PIFLAGS_H #ifndef PIFLAGS_H
#define PIFLAGS_H #define PIFLAGS_H
#include "pip_export.h" #include "pip_export.h"
/*! \brief This class used as container for bit flags /*! \brief This class used as container for bit flags
* \details PIFlags is wrapper around \c "int". There are many * \details PIFlags is wrapper around \c "int". There are many
* bit-wise operators, native conversion to int and function * bit-wise operators, native conversion to int and function
* to test flag. \n Example: * to test flag. \n Example:
* \snippet piincludes.cpp flags * \snippet piincludes.cpp flags
*/ */
template<typename Enum> template<typename Enum>
class PIP_EXPORT PIFlags { class PIFlags {
public: public:
//! Constructor with flags = 0 //! Constructor with flags = 0
PIFlags(): flags(0) {;} PIFlags(): flags(0) {;}
//! Constructor with flags = Enum "e" //! Constructor with flags = Enum "e"
PIFlags(Enum e): flags(e) {;} PIFlags(Enum e): flags(e) {;}
//! Constructor with flags = PIFlags "f" //! Constructor with flags = PIFlags "f"
PIFlags(const PIFlags & f): flags(f.flags) {;} PIFlags(const PIFlags & f): flags(f.flags) {;}
//! Constructor with flags = int "i" //! Constructor with flags = int "i"
PIFlags(const int i): flags(i) {;} PIFlags(const int i): flags(i) {;}
//! Set flags "f" to value "on" //! Set flags "f" to value "on"
PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;} PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;}
//! Set flag "e" to value "on" //! Set flag "e" to value "on"
PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;} PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;}
//! Set flag "i" to value "on" //! Set flag "i" to value "on"
PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;} PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;}
//! copy operator //! copy operator
void operator =(const PIFlags & f) {flags = f.flags;} void operator =(const PIFlags & f) {flags = f.flags;}
//! copy operator //! copy operator
void operator =(const Enum & e) {flags = e;} void operator =(const Enum & e) {flags = e;}
//! copy operator //! copy operator
void operator =(const int & i) {flags = i;} void operator =(const int & i) {flags = i;}
//! compare operator //! compare operator
bool operator ==(const PIFlags & f) {return flags == f.flags;} bool operator ==(const PIFlags & f) {return flags == f.flags;}
//! compare operator //! compare operator
bool operator ==(const Enum & e) {return flags == e;} bool operator ==(const Enum & e) {return flags == e;}
//! compare operator //! compare operator
bool operator ==(const int i) {return flags == i;} bool operator ==(const int i) {return flags == i;}
//! compare operator //! compare operator
bool operator !=(const PIFlags & f) {return flags != f.flags;} bool operator !=(const PIFlags & f) {return flags != f.flags;}
//! compare operator //! compare operator
bool operator !=(const Enum & e) {return flags != e;} bool operator !=(const Enum & e) {return flags != e;}
//! compare operator //! compare operator
bool operator !=(const int i) {return flags != i;} bool operator !=(const int i) {return flags != i;}
//! compare operator //! compare operator
bool operator >(const PIFlags & f) {return flags > f.flags;} bool operator >(const PIFlags & f) {return flags > f.flags;}
//! compare operator //! compare operator
bool operator >(const Enum & e) {return flags > e;} bool operator >(const Enum & e) {return flags > e;}
//! compare operator //! compare operator
bool operator >(const int i) {return flags > i;} bool operator >(const int i) {return flags > i;}
//! compare operator //! compare operator
bool operator <(const PIFlags & f) {return flags < f.flags;} bool operator <(const PIFlags & f) {return flags < f.flags;}
//! compare operator //! compare operator
bool operator <(const Enum & e) {return flags < e;} bool operator <(const Enum & e) {return flags < e;}
//! compare operator //! compare operator
bool operator <(const int i) {return flags < i;} bool operator <(const int i) {return flags < i;}
//! compare operator //! compare operator
bool operator >=(const PIFlags & f) {return flags >= f.flags;} bool operator >=(const PIFlags & f) {return flags >= f.flags;}
//! compare operator //! compare operator
bool operator >=(const Enum & e) {return flags >= e;} bool operator >=(const Enum & e) {return flags >= e;}
//! compare operator //! compare operator
bool operator >=(const int i) {return flags >= i;} bool operator >=(const int i) {return flags >= i;}
//! compare operator //! compare operator
bool operator <=(const PIFlags & f) {return flags <= f.flags;} bool operator <=(const PIFlags & f) {return flags <= f.flags;}
//! compare operator //! compare operator
bool operator <=(const Enum & e) {return flags <= e;} bool operator <=(const Enum & e) {return flags <= e;}
//! compare operator //! compare operator
bool operator <=(const int i) {return flags <= i;} bool operator <=(const int i) {return flags <= i;}
//! Bit-wise AND operator //! Bit-wise AND operator
void operator &=(const PIFlags & f) {flags &= f.flags;} void operator &=(const PIFlags & f) {flags &= f.flags;}
//! Bit-wise AND operator //! Bit-wise AND operator
void operator &=(const Enum & e) {flags &= e;} void operator &=(const Enum & e) {flags &= e;}
//! Bit-wise AND operator //! Bit-wise AND operator
void operator &=(const int i) {flags &= i;} void operator &=(const int i) {flags &= i;}
//! Bit-wise OR operator //! Bit-wise OR operator
void operator |=(const PIFlags & f) {flags |= f.flags;} void operator |=(const PIFlags & f) {flags |= f.flags;}
//! Bit-wise OR operator //! Bit-wise OR operator
void operator |=(const Enum & e) {flags |= e;} void operator |=(const Enum & e) {flags |= e;}
//! Bit-wise OR operator //! Bit-wise OR operator
void operator |=(const int i) {flags |= i;} void operator |=(const int i) {flags |= i;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
void operator ^=(const PIFlags & f) {flags ^= f.flags;} void operator ^=(const PIFlags & f) {flags ^= f.flags;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
void operator ^=(const Enum & e) {flags ^= e;} void operator ^=(const Enum & e) {flags ^= e;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
void operator ^=(const int i) {flags ^= i;} void operator ^=(const int i) {flags ^= i;}
//! Bit-wise AND operator //! Bit-wise AND operator
PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;} PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;}
//! Bit-wise AND operator //! Bit-wise AND operator
PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;} PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;}
//! Bit-wise AND operator //! Bit-wise AND operator
PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;} PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;}
//! Bit-wise OR operator //! Bit-wise OR operator
PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;} PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;}
//! Bit-wise OR operator //! Bit-wise OR operator
PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;} PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;}
//! Bit-wise OR operator //! Bit-wise OR operator
PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;} PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;} PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;} PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;} PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;}
//! Test flag operator //! Test flag operator
bool operator [](Enum e) const {return (flags & e) == e;} bool operator [](Enum e) const {return (flags & e) == e;}
//! Implicity conversion to \c int //! Implicity conversion to \c int
operator int() const {return flags;} operator int() const {return flags;}
private: private:
int flags; int flags;
}; };
#endif // PIFLAGS_H #endif // PIFLAGS_H

View File

@@ -19,7 +19,6 @@
#include "piincludes.h" #include "piincludes.h"
#include "piincludes_p.h" #include "piincludes_p.h"
#include "piconsole.h"
#include "pitime.h" #include "pitime.h"
#ifndef QNX #ifndef QNX
# include <clocale> # include <clocale>

114
src_main/core/piincludes.h → lib/main/core/piincludes.h Executable file → Normal file
View File

@@ -1,56 +1,58 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Minimal PIP includes Minimal PIP includes
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PIINCLUDES_H #ifndef PIINCLUDES_H
#define PIINCLUDES_H #define PIINCLUDES_H
#include "pibase.h" #include "pibase.h"
#include "piflags.h" #include "piflags.h"
#include <sys/types.h> #include <sys/types.h>
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
# include <iostream> # include <iostream>
#endif #endif
#include <atomic>
class PIObject;
class PIMutex; class PIMutex;
class PIString; class PIMutexLocker;
class PIByteArray; class PIObject;
class PIInit; class PIString;
class PIChar; class PIByteArray;
class PICout; class PIInit;
class PIChar;
struct lconv; class PICout;
extern lconv * currentLocale; struct lconv;
/*! \fn errorString() extern PIP_EXPORT lconv * currentLocale;
* \brief Return readable error description in format "code <number> - <description>" */
PIP_EXPORT PIString errorString(); /*! \fn errorString()
* \brief Return readable error description in format "code <number> - <description>" */
PIP_EXPORT void errorClear(); PIP_EXPORT PIString errorString();
PIP_EXPORT void piqsort(void* base, size_t num, size_t size, int (*compar)(const void*,const void*)); PIP_EXPORT void errorClear();
PIP_EXPORT void randomize(); PIP_EXPORT void piqsort(void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
PIP_EXPORT int randomi();
PIP_EXPORT void randomize();
/// Return readable version of PIP PIP_EXPORT int randomi();
PIP_EXPORT PIString PIPVersion();
/// Return readable version of PIP
#endif // PIINCLUDES_H PIP_EXPORT PIString PIPVersion();
#endif // PIINCLUDES_H

View File

@@ -1,45 +1,45 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Private PIP includes Private PIP includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
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/>.
*/ */
#ifndef PIINCLUDES_P_H #ifndef PIINCLUDES_P_H
#define PIINCLUDES_P_H #define PIINCLUDES_P_H
#include "picout.h" #include "picout.h"
#ifdef WINDOWS #ifdef WINDOWS
# include <stdarg.h> # include <stdarg.h>
# include <windef.h> # include <windef.h>
# include <winbase.h> # include <winbase.h>
typedef LONG(NTAPI*PINtQueryTimerResolution)(PULONG, PULONG, PULONG); typedef LONG(NTAPI*PINtQueryTimerResolution)(PULONG, PULONG, PULONG);
typedef LONG(NTAPI*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG); typedef LONG(NTAPI*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
#endif #endif
#ifdef CC_GCC #ifdef CC_GCC
# include <unistd.h> # include <unistd.h>
#endif #endif
#include <string.h> #include <string.h>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <stdlib.h> #include <stdlib.h>
#include <cstdlib> #include <cstdlib>
#include <stdio.h> #include <stdio.h>
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#endif // PIINCLUDES_P_H #endif // PIINCLUDES_P_H

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