103 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
99e93dfc62 PIInit 2020-06-10 15:11:22 +03:00
902a40d622 smaaaaal clean 2020-06-10 14:35:52 +03:00
4bd54274c9 clean yet 2020-06-10 14:11:44 +03:00
c59579d5d5 BIG deep clean 2020-06-10 13:14:16 +03:00
f579718e0b version 1.19.0_alpha
general bug fixes and optimization
Merge branch 'master' of https://git.shs.tools/SHS/pip
2020-06-09 18:04:33 +03:00
4ec87e0e2a optimization and fixes 2020-06-09 17:52:17 +03:00
2c6f87839c PIStringList operators 2020-06-09 17:37:06 +03:00
d5cef947ee Merge branch 'master' of https://git.shs.tools/SHS/pip 2020-06-02 13:05:39 +03:00
a01c3144f3 fix math/pimathmatrix.h 2020-06-02 13:05:35 +03:00
2d868d6d68 README.md 2020-05-28 18:20:14 +03:00
86b25303ef Merge branch 'master' of https://git.shs.tools/SHS/pip 2020-05-28 17:08:42 +03:00
67f82558d5 version 1.8.0
PIString: version functions
2020-05-28 17:08:00 +03:00
988ebac3b7 fix PVector2D resize 2020-05-28 14:03:47 +03:00
6b9fa87570 Merge branch 'master' of https://git.shs.tools/SHS/pip 2020-05-28 10:16:20 +03:00
6c98600fe7 PIVector2D resize 2020-05-28 10:15:05 +03:00
bfc6d0f18e PISerial::DeviceInfo operators 2020-05-26 18:21:14 +03:00
15515a2954 CMakeLists.txt fix 2020-05-26 16:49:08 +03:00
b6ab5aa202 version 1.16.0_alpha
PISerial::availableDevicesInfo (Linux and Windows)
2020-05-26 16:08:38 +03:00
6413e7747e doc 2020-05-23 21:55:15 +03:00
16bc3891c6 multiline fix 2020-05-23 21:52:16 +03:00
21f8a035d8 PIConfig multiline support 2020-05-23 21:41:47 +03:00
a5809d5f39 - 2020-05-23 17:42:18 +03:00
e04e6199e3 PIGPIO user permission patch 2020-05-22 21:58:05 +03:00
299d1e1708 version 1.15.0_alpha
add PIGPIO class
gcc warnings fix
2020-05-22 21:34:21 +03:00
51a76be487 Merge branch 'master' of https://git.shs.tools/SHS/pip 2020-05-22 12:19:56 +03:00
a2898ac737 correct regexp in DeployMacros.cmake 2020-05-22 12:19:50 +03:00
336 changed files with 35344 additions and 37422 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/src_main/piversion.h
/.svn
/doc/rtf
_unsused

View File

@@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip)
set(_PIP_MAJOR 1)
set(_PIP_MINOR 14)
set(_PIP_REVISION 0)
set(_PIP_SUFFIX beta)
set(_PIP_MINOR 99)
set(_PIP_REVISION 3)
set(_PIP_SUFFIX _prebeta)
set(_PIP_COMPANY SHS)
set(_PIP_DOMAIN org.SHS)
@@ -14,6 +14,7 @@ endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
set(PIP_BUILD 1)
include(CheckFunctionExists)
include(GenerateExportHeader)
include(DeployMacros)
include(PIPMacros)
if(NOT DEFINED BUILD_NUMBER)
@@ -40,54 +41,94 @@ set(PIP_UTILS 1)
if(LIBPROJECT)
set(PIP_UTILS ${UTILS})
endif()
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_STANDARD 11)
# Apple crosscompiling rpath patch
# macro(apple_rpath_patch _T)
# if (APPLE AND CMAKE_CROSSCOMPILING AND CMAKE_MACOSX_RPATH)
# foreach(_RP ${CMAKE_INSTALL_RPATH})
# add_custom_command(TARGET ${_T} POST_BUILD
# COMMAND "${CMAKE_INSTALL_NAME_TOOL}"
# "-add_rpath" "${_RP}"
# "$<TARGET_FILE_DIR:${_T}>/$<TARGET_FILE_NAME:${_T}>"
# COMMENT "Add to ${_T} rpath \"${_RP}\"")
# endforeach()
# endif()
# endmacro()
# Basic
macro(gather_src DIR CPP H H_P)
set(CS)
set(HS)
set(PHS)
file(GLOB CS "${DIR}/*.cpp")
file(GLOB HS "${DIR}/*.h")
file(GLOB PHS "${DIR}/*_p.h")
list(REMOVE_ITEM HS "${PHS}")
list(APPEND ${CPP} ${CS})
list(APPEND ${H} ${HS})
list(APPEND ${H_P} ${PHS})
endmacro()
set(PIP_SRC_MAIN "src_main")
set(PIP_SRC_CRYPT "src_crypt")
set(PIP_SRC_COMPRESS "src_compress")
set(PIP_SRC_USB "src_usb")
set(PIP_SRC_FFTW "src_fftw")
set(PIP_SRC_OPENCL "src_opencl")
set(PIP_SRC_IO_UTILS "src_io_utils")
set(PIP_SRC_CONCURRENT "src_concurrent")
set(PIP_SRC_CLOUD "src_cloud")
set(PIP_SRC_DIRS "src_main" "src_crypt" "src_compress" "src_usb" "src_fftw" "src_opencl" "src_io_utils" "src_concurrent" "src_cloud")
set(PIP_LIBS_TARGETS pip)
set(PIP_MODULES)
set(LIBS_MAIN)
set(LIBS_STATUS)
set(HDRS)
set(PHDRS)
set(HDR_DIRS)
set(PIP_UTILS_LIST)
set(PIP_TESTS_LIST)
set(PIP_EXPORTS)
if (TESTS)
set(PIP_SRC_CONCURRENT_TEST "src_concurrent/test")
set(PIP_SRC_MODULES "console;crypt;compress;usb;fftw;opencl;io_utils;cloud;lua")
foreach(_m ${PIP_SRC_MODULES})
set(PIP_MSG_${_m} "no")
endforeach()
macro(pip_module NAME LIBS LABEL INCLUDES MSG)
set(CPPS)
set(HS)
set(PHS)
set(CRES)
file(GLOB_RECURSE CPPS "lib/${NAME}/*.cpp")
file(GLOB_RECURSE HS "lib/${NAME}/*.h")
file(GLOB_RECURSE PHS "lib/${NAME}/*_p.h")
file(GLOB_RECURSE RES "lib/${NAME}/*conf.h")
list(REMOVE_ITEM HS "${PHS}")
list(APPEND HDRS ${HS})
list(APPEND PHDRS ${PHS})
set(_target "pip_${NAME}")
set(_libs "${LIBS}")
if ("${NAME}" STREQUAL "main")
set(_target "pip")
else()
list(APPEND _libs "pip")
endif()
string(TOUPPER "${_target}" DEF_NAME)
set(PIP_MSG_${NAME} "yes${MSG}")
import_version(${_target} PIP)
set_deploy_property(${_target} ${PIP_LIB_TYPE}
LABEL "${LABEL}"
FULLNAME "${_PIP_DOMAIN}.${_target}"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(${_target} _RC)
set(LINK_LIBS)
foreach (_l ${_libs})
if (${${_l}_FOUND})
list(APPEND LINK_LIBS ${${_l}_LIBRARIES})
else()
list(APPEND LINK_LIBS ${_l})
endif()
endforeach()
if (NOT "${RES}" STREQUAL "")
pip_resources(CRES "${RES}")
endif()
add_definitions(-D${DEF_NAME})
add_library(${_target} ${PIP_LIB_TYPE} ${CPPS} ${CRES} ${_RC})
if (NOT "${RES}" STREQUAL "")
add_dependencies(${_target} pip_rc)
endif()
if (NOT "${INCLUDES}" STREQUAL "")
target_include_directories(${_target} PRIVATE ${INCLUDES})
endif()
generate_export_header(${_target})
list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/${_target}_export.h")
list(APPEND PIP_EXPORTS "${DEF_NAME}_EXPORT")
target_link_libraries(${_target} ${LINK_LIBS})
list(APPEND PIP_MODULES ${_target})
if (NOT "${LIBS}" STREQUAL "")
list(APPEND LIBS_STATUS ${LIBS})
endif()
endmacro()
macro(pip_find_lib NAME)
find_library(${NAME}_LIBRARIES ${NAME} ${ARGN})
set(${NAME}_FOUND FALSE)
if(${NAME}_LIBRARIES)
set(${NAME}_FOUND TRUE)
endif()
endmacro()
if (DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
set(STATIC_LIB ON)
@@ -95,11 +136,11 @@ endif()
if(STATIC_LIB)
set(PIP_LIB_TYPE STATIC)
set(PIP_LIB_TYPE_MSG "Static")
add_definitions(-DPIP_STATIC_DEFINE)
#message(STATUS "Building PIP static library")
else()
set(PIP_LIB_TYPE SHARED)
#message(STATUS "Building PIP shared library")
set(PIP_LIB_TYPE_MSG "Shared")
endif()
@@ -110,14 +151,11 @@ set_version(PIP
REVISION "${_PIP_REVISION}"
BUILD "${BUILD_NUMBER}"
SUFFIX "${_PIP_SUFFIX}"
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h")
set_deploy_property(pip ${PIP_LIB_TYPE}
LABEL "PIP main library"
FULLNAME "${_PIP_DOMAIN}.pip"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
message(STATUS "Building PIP version ${PIP_VERSION} (${PIP_LIB_TYPE})")
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/piversion.h")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h")
file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h")
endif()
list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/piversion.h")
if(MINGW)
find_package(MinGW REQUIRED)
@@ -169,50 +207,26 @@ endif()
# Compiler
get_filename_component(C_COMPILER "${CMAKE_C_COMPILER}" NAME)
#link_directories(${CMAKE_CURRENT_BINARY_DIR})
#message("${C_COMPILER}")
# Sources
# Main lib
set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io_devices" "io_utils" "console" "math" "code" "geo" "resources" "opencl" "crypt" "introspection" "concurrent" "cloud")
if(PIP_FREERTOS)
#list(REMOVE_ITEM PIP_FOLDERS "console")
#include_directories("${PIP_SRC_MAIN}/console")
endif()
include_directories("${PIP_SRC_MAIN}")
file(GLOB PIP_FOLDERS LIST_DIRECTORIES TRUE "${CMAKE_CURRENT_SOURCE_DIR}/lib/main/*")
list(APPEND PIP_FOLDERS "${CMAKE_CURRENT_SOURCE_DIR}/lib/main")
set(PIP_MAIN_FOLDERS)
foreach(F ${PIP_FOLDERS})
list(APPEND PIP_MAIN_FOLDERS "\"${PROJECT_SOURCE_DIR}/${PIP_SRC_MAIN}/${F}\"")
include_directories("${PIP_SRC_MAIN}/${F}")
gather_src("${PIP_SRC_MAIN}/${F}" CPP_LIB_MAIN HDRS PHDRS)
if (IS_DIRECTORY "${F}")
list(APPEND PIP_MAIN_FOLDERS "${F}")
include_directories("${F}")
endif()
endforeach(F)
# Crypt lib
gather_src("${PIP_SRC_CRYPT}" CPP_LIB_CRYPT HDRS PHDRS)
if (DEFINED LIBPROJECT)
set(PIP_MAIN_FOLDERS "${PIP_MAIN_FOLDERS}" PARENT_SCOPE)
endif()
# Compress lib
gather_src("${PIP_SRC_COMPRESS}" CPP_LIB_COMPRESS HDRS PHDRS)
# USB lib
gather_src("${PIP_SRC_USB}" CPP_LIB_USB HDRS PHDRS)
# FFTW lib
gather_src("${PIP_SRC_FFTW}" CPP_LIB_FFTW HDRS PHDRS)
# OpenCL lib
gather_src("${PIP_SRC_OPENCL}" CPP_LIB_OPENCL HDRS PHDRS)
# IO Utils lib
gather_src("${PIP_SRC_IO_UTILS}" CPP_LIB_IO_UTILS HDRS PHDRS)
# Concurrent lib
gather_src("${PIP_SRC_CONCURRENT}" CPP_LIB_CONCURRENT HDRS PHDRS)
gather_src("${PIP_SRC_CONCURRENT_TEST}" CPP_CONCURRENT_TEST HDRS PHDRS)
# Cloud lib
gather_src("${PIP_SRC_CLOUD}" CPP_LIB_CLOUD HDRS PHDRS)
if (TESTS)
set(PIP_ROOT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
add_subdirectory(tests)
endif()
if(PIP_FREERTOS)
add_definitions(-DPIP_FREERTOS)
@@ -263,59 +277,40 @@ CHECK_FUNCTION_EXISTS(timer_delete PIP_TIMER_RT_2)
# Check if build debug version
if (CMAKE_BUILD_TYPE MATCHES Debug)
set(PIP_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall")
add_definitions(-DPIP_DEBUG)
message(STATUS "Building PIP debug version")
else()
set(PIP_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
message(STATUS "Building PIP release version")
endif()
if (TESTS)
include(DownloadGTest)
set(CONCURRENT_TESTS 1) #"Enable tests for concurrent library"
else()
set(CONCURRENT_TESTS 0)
endif()
# Check if std::iostream operators support
set(PIP_STD_IOSTREAM "no")
if(STD_IOSTREAM)
set(PIP_STD_IOSTREAM "yes")
add_definitions(-DPIP_STD_IOSTREAM)
message(STATUS "Building PIP with std iostream operators support")
else()
message(STATUS "Building PIP without std iostream operators support")
endif()
# Check if STL containers is on (to enable use "-DSTL=" argument of cmake)
if(STL)
message(STATUS "Building PIP with STL containers")
add_definitions(-DPIP_CONTAINERS_STL)
else()
message(STATUS "Building PIP with PIP containers")
endif()
# Check if ICU used for PIString and PIChar
set(PIP_ICU "no")
if(ICU)
message(STATUS "Building PIP with ICU")
set(PIP_ICU "yes")
add_definitions(-DPIP_ICU)
list(APPEND LIBS_MAIN icuuc)
else()
message(STATUS "Building PIP without ICU")
endif()
# Check if PIP should be built with introspection
set(_PIP_DEFS "")
set(_PIP_DEFS_FILE "${CMAKE_CURRENT_BINARY_DIR}/pip_defs.h")
set(PIP_INTROSPECTION "no")
if(INTROSPECTION)
message(STATUS "Building PIP with introspection")
message(STATUS "Warning: Introspection reduces the performance!")
set(PIP_INTROSPECTION "yes")
add_definitions(-DPIP_INTROSPECTION)
set(_PIP_DEFS "PIP_INTROSPECTION")
else()
message(STATUS "Building PIP without introspection")
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)
@@ -330,10 +325,10 @@ list(APPEND HDRS ${_PIP_DEFS_FILE})
# Check if RT timers exists
if(PIP_TIMER_RT_0 AND PIP_TIMER_RT_1 AND PIP_TIMER_RT_2)
set(PIP_TIMERS "Thread, ThreadRT, Pool")
add_definitions(-DPIP_TIMER_RT)
message(STATUS "Building PIP with timers: Thread, ThreadRT, Pool")
else()
message(STATUS "Building PIP with timers: Thread, Pool")
set(PIP_TIMERS "Thread, Pool")
endif()
@@ -344,7 +339,6 @@ if(APPLE)
endif()
if ((NOT DEFINED LIBPROJECT) AND (DEFINED ANDROID_PLATFORM))
include_directories(${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${ANDROID_NDK}/sysroot/usr/include")
#message("${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include")
#message("${ANDROID_NDK}/sysroot/usr/include")
endif()
@@ -352,7 +346,7 @@ if(NOT PIP_FREERTOS)
if(WIN32)
if(${C_COMPILER} STREQUAL "cl.exe")
else()
list(APPEND LIBS_MAIN ws2_32 iphlpapi psapi)
list(APPEND LIBS_MAIN ws2_32 iphlpapi psapi cfgmgr32 setupapi)
endif()
else()
list(APPEND LIBS_MAIN dl)
@@ -370,19 +364,12 @@ if(PIP_FREERTOS)
set(PIP_LIBS ${LIBS_MAIN})
else()
foreach(LIB_ ${LIBS_MAIN})
find_library(${LIB_}_FOUND ${LIB_})
if(${LIB_}_FOUND)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${${LIB_}_FOUND})
list(APPEND PIP_LIBS ${${LIB_}_FOUND})
endif()
pip_find_lib(${LIB_})
endforeach()
endif()
list(APPEND LIBS_STATUS ${LIBS_MAIN})
import_version(pip PIP)
if(WIN32)
make_rc(pip _RC)
add_definitions(-DPSAPI_VERSION=1)
add_library(pip ${PIP_LIB_TYPE} ${CPP_LIB_MAIN} ${HDRS} ${PHDRS} ${_RC})
if(${C_COMPILER} STREQUAL "cl.exe")
set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0")
endif()
@@ -390,78 +377,37 @@ else()
set(${CMAKE_CXX_FLAGS} "${CMAKE_CXX_FLAGS} -fPIC")
if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32")
else()
endif()
add_library(pip ${PIP_LIB_TYPE} ${CPP_LIB_MAIN})
endif()
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}")
include(GenerateExportHeader)
generate_export_header(pip)
list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/pip_export.h")
target_link_libraries(pip ${PIP_LIBS})
pip_module(main "${LIBS_MAIN}" "PIP main library" "" "")
if (NOT CROSSTOOLS)
if (NOT PIP_FREERTOS)
# Check if USB is supported
find_library(usb_FOUND usb SHARED)
pip_module(console "" "PIP console support" "" "")
pip_find_lib(usb)
if(usb_FOUND)
message(STATUS "Building PIP with USB support")
import_version(pip_usb pip)
set_deploy_property(pip_usb ${PIP_LIB_TYPE}
LABEL "PIP usb support"
FULLNAME "${_PIP_DOMAIN}.pip_usb"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_usb _RC)
add_definitions(-DPIP_USB)
add_library(pip_usb ${PIP_LIB_TYPE} ${CPP_LIB_USB} ${_RC})
target_link_libraries(pip_usb pip ${usb_FOUND})
list(APPEND LIBS_STATUS usb)
list(APPEND PIP_LIBS_TARGETS pip_usb)
else()
message(STATUS "Building PIP without USB support")
pip_module(usb "usb" "PIP usb support" "" "")
endif()
# Check if PIP support cryptographic encryption/decryption using sodium library
find_library(sodium_FOUND sodium)
if(sodium_FOUND)
message(STATUS "Building PIP with crypt support")
import_version(pip_crypt pip)
set_deploy_property(pip_crypt ${PIP_LIB_TYPE}
LABEL "PIP crypt support"
FULLNAME "${_PIP_DOMAIN}.pip_crypt"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_crypt _RC)
add_definitions(-DPIP_CRYPT)
add_library(pip_crypt ${PIP_LIB_TYPE} ${CPP_LIB_CRYPT} ${_RC})
target_link_libraries(pip_crypt pip ${sodium_FOUND})
list(APPEND LIBS_STATUS sodium)
list(APPEND PIP_LIBS_TARGETS pip_crypt)
else()
message(STATUS "Building PIP without crypt support")
endif()
# Check if PIP support compress/decompress using zlib library
find_library(zlib_FOUND NAMES z zlib)
pip_find_lib(zlib NAMES z zlib)
if(zlib_FOUND)
message(STATUS "Building PIP with zlib compress support")
import_version(pip_compress pip)
set_deploy_property(pip_compress ${PIP_LIB_TYPE}
LABEL "PIP compression support"
FULLNAME "${_PIP_DOMAIN}.pip_compress"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_compress _RC)
add_definitions(-DPIP_COMPRESS)
add_library(pip_compress ${PIP_LIB_TYPE} ${CPP_LIB_COMPRESS} ${_RC})
target_link_libraries(pip_compress pip ${zlib_FOUND})
list(APPEND LIBS_STATUS zlib)
list(APPEND PIP_LIBS_TARGETS pip_compress)
else()
message(STATUS "Building PIP without compress support")
pip_module(compress "zlib" "PIP compression support" "" "")
endif()
pip_find_lib(sodium)
if(sodium_FOUND)
pip_module(crypt "sodium" "PIP crypt support" "" "")
pip_module(cloud "pip_crypt" "PIP cloud support" "" "")
endif()
@@ -471,7 +417,6 @@ if (NOT CROSSTOOLS)
set(FFTW_LIB_SUFFIXES2 "" "-3")
set(FFTW_LIBS)
set(FFTW_ABS_LIBS)
set(PIP_FFTW_FOUND)
set(CMAKE_REQUIRED_INCLUDES fftw3.h)
foreach(FFTW_S_ IN LISTS FFTW_LIB_SUFFIXES)
set(FFTW_BREAK false)
@@ -479,140 +424,63 @@ if (NOT CROSSTOOLS)
if(NOT FFTW_BREAK)
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_library(${FFTW_CLNT}_FOUND ${FFTW_CLNT})
if(${FFTW_CLN}_FOUND)
find_library(${FFTW_CLN}_LIBRARIES ${FFTW_CLN})
find_library(${FFTW_CLNT}_LIBRARIES ${FFTW_CLNT})
set(${FFTW_CLN}_FOUND FALSE)
set(${FFTW_CLNT}_FOUND FALSE)
if(${FFTW_CLN}_LIBRARIES)
set(${FFTW_CLN}_FOUND TRUE)
list(APPEND FFTW_LIBS "${FFTW_CLN}")
list(APPEND FFTW_ABS_LIBS "${${FFTW_CLN}_FOUND}")
#message(STATUS "PIFFTW found ${FFTW_CLN} = ${${FFTW_CLN}_FOUND}")
list(APPEND FFTW_ABS_LIBS "${${FFTW_CLN}_LIBRARIES}")
set(${FFTW_CLN}_CTS "${FFTW_CLN}")
if(${FFTW_CLNT}_FOUND)
if(${FFTW_CLNT}_FLIBRARIES)
set(${FFTW_CLNT}_FOUND TRUE)
list(APPEND FFTW_LIBS "${FFTW_CLNT}")
list(APPEND FFTW_ABS_LIBS "${${FFTW_CLNT}_FOUND}")
list(APPEND FFTW_ABS_LIBS "${${FFTW_CLNT}_LIBRARIES}")
list(APPEND ${FFTW_CLN}_CTS "${FFTW_CLNT}")
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_})
set(PIP_FFTW_FOUND true)
if(${FFTW_CLN}_TSFE)
add_definitions(-DPIP_FFTW${FFTW_S_}_THREADSAFE)
else()
message(STATUS "Warning: PIFFTW${FFTW_S_}::preparePlan was not threadsafe")
endif()
#message(STATUS "${FFTW_CLN} -> ${${FFTW_CLN}_TSFE}")
endif()
endif()
endforeach()
endforeach()
if(FFTW_LIBS)
message(STATUS "Building PIP with fftw3 support: ${FFTW_LIBS}")
import_version(pip_fftw pip)
set_deploy_property(pip_fftw ${PIP_LIB_TYPE}
LABEL "PIP FFTW support"
FULLNAME "${_PIP_DOMAIN}.pip_fftw"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_fftw _RC)
add_library(pip_fftw ${PIP_LIB_TYPE} ${CPP_LIB_FFTW} ${_RC})
target_link_libraries(pip_fftw pip ${FFTW_ABS_LIBS})
list(APPEND LIBS_STATUS ${FFTW_LIBS})
list(APPEND PIP_LIBS_TARGETS pip_fftw)
else()
message(STATUS "Building PIP without fftw3 support")
pip_module(fftw "${FFTW_LIBS}" "PIP FFTW support" "" "")
endif()
# Check if PIP support OpenCL
find_package(OpenCL QUIET)
find_package(OpenCL QUIET) #OpenCL_VERSION_STRING
if(OpenCL_FOUND)
message(STATUS "Building PIP with OpenCL support")
import_version(pip_opencl pip)
set_deploy_property(pip_opencl ${PIP_LIB_TYPE}
LABEL "PIP OpenCL support"
FULLNAME "${_PIP_DOMAIN}.pip_opencl"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_opencl _RC)
if(APPLE)
include_directories(${OpenCL_INCLUDE_DIRS}/Headers)
else()
include_directories(${OpenCL_INCLUDE_DIRS})
endif()
add_definitions(-DPIP_OPENCL)
pip_resources(CL_RES "src_opencl/resources.conf")
add_library(pip_opencl ${PIP_LIB_TYPE} ${CPP_LIB_OPENCL} ${CL_RES} ${_RC})
add_dependencies(pip_opencl pip_rc)
set(_opencl_lib OpenCL::OpenCL)
if(${CMAKE_VERSION} VERSION_LESS "3.7.0")
target_link_libraries(pip_opencl pip OpenCL)
else()
target_link_libraries(pip_opencl pip OpenCL::OpenCL)
target_link_libraries(_opencl_lib OpenCL)
endif()
list(APPEND LIBS_STATUS OpenCL)
list(APPEND PIP_LIBS_TARGETS pip_opencl)
set(OpenCL_FOUND ${OpenCL_LIBRARIES})
else()
message(STATUS "Building PIP without OpenCL support")
pip_module(opencl "${_opencl_lib}" "PIP OpenCL support" "" " (${OpenCL_VERSION_STRING})")
endif()
# Check if PIP IO Utils library supports crypt
set(IO_UTILS_LIBS pip)
import_version(pip_io_utils pip)
set_deploy_property(pip_io_utils ${PIP_LIB_TYPE}
LABEL "PIP I/O utilites"
FULLNAME "${_PIP_DOMAIN}.pip_io_utils"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_io_utils _RC)
add_library(pip_io_utils ${PIP_LIB_TYPE} ${CPP_LIB_IO_UTILS} ${_RC})
if(sodium_FOUND)
message(STATUS "Building PIP IO Utils library with crypt support")
list(APPEND IO_UTILS_LIBS pip_crypt)
pip_module(io_utils "pip_crypt" "PIP I/O support" "" " (+crypt)")
else()
message(STATUS "Building PIP IO Utils library without crypt support, attention!")
endif()
target_link_libraries(pip_io_utils ${IO_UTILS_LIBS})
list(APPEND PIP_LIBS_TARGETS pip_io_utils)
# Concurrent module
set(CONCURRENT_LIBS pip)
import_version(pip_concurrent pip)
set_deploy_property(pip_concurrent ${PIP_LIB_TYPE}
LABEL "PIP concurrent support"
FULLNAME "${_PIP_DOMAIN}.pip_concurrent"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_concurrent _RC)
add_library(pip_concurrent ${PIP_LIB_TYPE} ${CPP_LIB_CONCURRENT} ${_RC})
target_link_libraries(pip_concurrent ${CONCURRENT_LIBS})
set_property(TARGET pip_concurrent PROPERTY CXX_STANDARD 11)
list(APPEND PIP_LIBS_TARGETS pip_concurrent)
# Enable build tests for concurrent module
if(CONCURRENT_TESTS)
add_executable(pip_concurrent_test ${CPP_CONCURRENT_TEST})
target_link_libraries(pip_concurrent_test gtest_main gmock_main pip_concurrent)
add_test(NAME pip_concurrent_test COMMAND tests)
add_custom_target(pip_concurrent_test_perform ALL COMMAND pip_concurrent_test)
pip_module(io_utils "" "PIP I/O support" "" "")
endif()
# Build cloud library if crypt enabled
if(sodium_FOUND)
message(STATUS "Building PICloud support")
import_version(pip_cloud pip)
set_deploy_property(pip_cloud ${PIP_LIB_TYPE}
LABEL "PIP cloud transport support"
FULLNAME "${_PIP_DOMAIN}.pip_cloud"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_cloud _RC)
add_definitions(-DPIP_CLOUD)
add_library(pip_cloud ${PIP_LIB_TYPE} ${CPP_LIB_CLOUD} ${_RC})
target_link_libraries(pip_cloud pip pip_crypt)
list(APPEND PIP_LIBS_TARGETS pip_cloud)
# Check Lua support
if(MINGW)
set(LUA_INCLUDE_DIR ${MINGW_INCLUDE})
endif()
find_package(Lua QUIET)
if (LUA_FOUND)
pip_module(lua "LUA" "PIP Lua support" "${LUA_INCLUDE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/lib/lua/3rd" " (${LUA_VERSION_STRING})")
list(APPEND HDR_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/lib/lua/3rd/LuaBridge")
endif()
@@ -620,30 +488,36 @@ if (NOT CROSSTOOLS)
if(PIP_UTILS)
add_executable(pip_test "main.cpp")
target_link_libraries(pip_test pip)
if (LUA_FOUND)
target_link_libraries(pip_test pip_lua ${LUA_LIBRARIES})
endif()
endif()
else()
message(STATUS "Building PIP with crypt support")
set(PIP_MSG_crypt "yes")
set(PIP_MSG_compress "yes")
set(PIP_MODULES pip)
add_definitions(-DPIP_CRYPT)
add_library(pip_crypt ${PIP_LIB_TYPE} ${CPP_LIB_CRYPT})
target_link_libraries(pip_crypt pip)
list(APPEND PIP_LIBS_TARGETS pip_crypt)
list(APPEND PIP_MODULES pip_crypt)
set(IO_UTILS_LIBS pip)
add_library(pip_io_utils ${PIP_LIB_TYPE} ${CPP_LIB_IO_UTILS})
message(STATUS "Building PIP IO Utils library with crypt support")
list(APPEND IO_UTILS_LIBS pip_crypt)
target_link_libraries(pip_io_utils ${IO_UTILS_LIBS})
list(APPEND PIP_LIBS_TARGETS pip_io_utils)
message(STATUS "Building PIP with zlib compress support")
list(APPEND PIP_MODULES pip_io_utils)
add_definitions(-DPIP_COMPRESS)
add_library(pip_compress ${PIP_LIB_TYPE} ${CPP_LIB_COMPRESS})
target_link_libraries(pip_compress pip)
list(APPEND PIP_LIBS_TARGETS pip_compress)
list(APPEND PIP_MODULES pip_compress)
endif()
endif()
string(REPLACE ";" "," PIP_EXPORTS_STR "${PIP_EXPORTS}")
target_compile_definitions(pip PRIVATE "PICODE_DEFINES=\"${PIP_EXPORTS_STR}\"")
# Install
# Check if system or local install will be used (to system install use "-DLIB=" argument of cmake)
if(LIB)
@@ -651,9 +525,13 @@ if(LIB)
if(MINGW)
if (NOT CROSSTOOLS)
install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE}/pip)
install(TARGETS ${PIP_LIBS_TARGETS} ARCHIVE DESTINATION ${MINGW_LIB})
install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE}/pip)
if(HDR_DIRS)
install(DIRECTORY ${HDR_DIRS} DESTINATION ${MINGW_INCLUDE}/pip)
endif()
install(TARGETS ${PIP_LIBS_TARGETS} RUNTIME DESTINATION ${MINGW_BIN})
install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION ${MINGW_LIB})
endif()
install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION ${MINGW_BIN})
find_library(STDLIB "stdc++-6" PATHS ${MINGW_BIN} NO_DEFAULT_PATH)
find_library(STDLIB "stdc++-6")
#message("${STDLIB}")
@@ -663,43 +541,39 @@ if(LIB)
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/deploy_tool")
endif()
else()
#message("${CMAKE_CURRENT_BINARY_DIR}/pip_export.h")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pip_export.h DESTINATION include)
endif()
else()
if (NOT CROSSTOOLS)
install(FILES ${HDRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip)
if(HDR_DIRS)
install(DIRECTORY ${HDR_DIRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip)
endif()
install(TARGETS ${PIP_LIBS_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
# Precompiled header
#add_custom_target(pip_pch ALL COMMAND ${CMAKE_CXX_COMPILER} -O2 -fPIC -g3 ${CMAKE_INSTALL_PREFIX}/include/pip/pip.h DEPENDS pip SOURCES ${HDRS})
#list(APPEND HDRS "pip.h.gch")
install(TARGETS ${PIP_MODULES} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in" "cmake/android_debug.keystore")
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
else()
if(NOT PIP_FREERTOS)
if(WIN32)
install(TARGETS ${PIP_LIBS_TARGETS} RUNTIME DESTINATION bin)
install(TARGETS ${PIP_LIBS_TARGETS} ARCHIVE DESTINATION lib)
install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION bin)
install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION lib)
else()
install(TARGETS ${PIP_LIBS_TARGETS} DESTINATION lib)
install(TARGETS ${PIP_MODULES} DESTINATION lib)
endif()
install(FILES ${HDRS} DESTINATION include/pip)
message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"")
if(HDR_DIRS)
install(DIRECTORY ${HDR_DIRS} DESTINATION include/pip)
endif()
endif()
endif()
# foreach(_T ${PIP_LIBS_TARGETS})
# apple_rpath_patch(${_T})
# endforeach()
if(NOT PIP_FREERTOS)
# Auxiliary
if (NOT CROSSTOOLS)
add_subdirectory("${PIP_SRC_MAIN}/auxiliary/piterminal")
add_subdirectory("utils/piterminal")
endif()
# Utils
@@ -708,7 +582,6 @@ if(NOT PIP_FREERTOS)
add_subdirectory("utils/deploy_tool")
if(PIP_UTILS AND (NOT CROSSTOOLS))
add_subdirectory("utils/system_test")
add_subdirectory("utils/remote_console")
add_subdirectory("utils/udp_file_transfer")
if(sodium_FOUND)
add_subdirectory("utils/system_daemon")
@@ -721,45 +594,15 @@ 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(PIP_MODULES ${PIP_MODULES} PARENT_SCOPE)
list(APPEND _ALL_TARGETS ${PIP_MODULES})
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
#
# find_package(Doxygen QUIET)
# if(Doxygen_FOUND)
# message(STATUS "Building PIP with documentation via Doxygen")
# #set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in)
# set(DOXYFILE ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
# #configure_file(${DOXYFILE_IN} ${DOXYFILE} @ONLY)
# add_custom_target(DOC
# COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE}
# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
# COMMENT "Generating API documentation with Doxygen"
# VERBATIM)
# add_custom_command(TARGET DOC
# POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/source/doc/Documentation.html ${CMAKE_SOURCE_DIR}/doc
# )
# install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/doc)
# endif()
if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
include(PIPDocumentation)
find_package(Doxygen)
@@ -767,8 +610,9 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
set(DOXY_PROJECT_NUMBER "${PIP_VERSION}")
set(DOXY_QHP_CUST_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
set(DOXY_QHP_SECT_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
set(DOXY_EXAMPLE_PATH "\"${PROJECT_SOURCE_DIR}/doc/examples\"")
set(DOXY_IMAGE_PATH "\"${PROJECT_SOURCE_DIR}/doc/images\"")
set(DOXY_EXAMPLE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/examples\"")
set(DOXY_IMAGE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/images\"")
set(DOXY_EXCLUDE "\"${CMAKE_CURRENT_SOURCE_DIR}/lib/lua/3rd\"")
if(DOXYGEN_DOT_EXECUTABLE)
string(REPLACE "\\" "" _DOT_PATH "${DOXYGEN_DOT_PATH}")
set(DOXY_DOT_PATH "\"${_DOT_PATH}\"")
@@ -776,13 +620,70 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
set(DOXY_DIA_PATH "\"${_DOT_PATH}\"")
endif()
set(DOXY_INPUT)
foreach(F ${PIP_SRC_DIRS})
list(APPEND DOXY_INPUT "\"${PROJECT_SOURCE_DIR}/${F}\"")
foreach(F ${PIP_MAIN_FOLDERS})
list(APPEND DOXY_INPUT "\"${F}\"")
endforeach(F)
string(REPLACE ";" " " DOXY_INPUT "${DOXY_INPUT}")
string(REPLACE ";" " " DOXY_INCLUDE_PATH "${PIP_MAIN_FOLDERS}")
add_documentation(doc Doxyfile.in)
string(REPLACE ";" " " DOXY_INPUT "\"${CMAKE_CURRENT_SOURCE_DIR}/lib\"")
string(REPLACE ";" " " DOXY_INCLUDE_PATH "${DOXY_INPUT}")
string(REPLACE ";" " " DOXY_DEFINES "${PIP_EXPORTS};DOXYGEN;PIOBJECT;PIOBJECT_SUBCLASS")
add_documentation(doc doc/Doxyfile.in)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html DESTINATION ../share/doc/pip COMPONENT doc EXCLUDE_FROM_ALL OPTIONAL)
endif()
endif()
list(REMOVE_ITEM LIBS_STATUS ${PIP_MODULES})
message("----------PIP----------")
message(" Version: ${PIP_VERSION} ")
message(" Linkage: ${PIP_LIB_TYPE_MSG}")
message(" Type : ${PIP_BUILD_TYPE}")
if(LIB)
message(" Install: \"${CMAKE_INSTALL_PREFIX}\"")
else()
if(NOT PIP_FREERTOS)
message(" Install: local \"bin\", \"lib\" and \"include\"")
endif()
endif()
message("")
message(" Options:")
message(" std::iostream: ${PIP_STD_IOSTREAM}")
message(" ICU strings : ${PIP_ICU}")
message(" Timer types : ${PIP_TIMERS}")
message(" Introspection: ${PIP_INTROSPECTION}")
if(INTROSPECTION)
message(STATUS " Warning: Introspection reduces the performance!")
endif()
message("")
message(" Modules:")
foreach(_m ${PIP_SRC_MODULES})
message(" ${_m}: ${PIP_MSG_${_m}}")
endforeach()
message("")
if (PIP_TESTS_LIST)
message(" Tests:")
foreach(_test ${PIP_TESTS_LIST})
message(" * ${_test}")
endforeach()
else()
message(" Tests: skip (tests off)")
endif()
message("")
message(" Utilites:")
foreach(_util ${PIP_UTILS_LIST})
message(" * ${_util}")
endforeach()
if(NOT PIP_FREERTOS)
message("")
message(" Using libraries:")
foreach(LIB_ ${LIBS_STATUS})
if (NOT TARGET ${LIB_})
if(${LIB_}_FOUND)
message(" ${LIB_} -> ${${LIB_}_LIBRARIES}")
else()
message(" ${LIB_} not found, may fail")
endif()
endif()
endforeach()
endif()
message("-----------------------")

View File

@@ -30,3 +30,7 @@ You should add ${<out_var>} to your target.
Generate C++ files for resource file.
You should add ${<out_var>} to your target.
## Documentation
[Online documentation](https://shs.tools/pip/html/index.html)

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,13 +383,19 @@ endmacro()
macro(__add_file_or_dir _DIR_VAR _FILE_VAR _PATH _RELPATH)
set(_p)
set(_abs 0)
if (IS_ABSOLUTE "${_PATH}")
set(_abs 1)
endif()
if ("${_PATH}" MATCHES "^\$<")
set(_abs 1)
endif()
if (_abs)
set(_p "${_PATH}")
else()
set(_p "${_RELPATH}/${_PATH}")
endif()
#if (EXISTS "${_p}")
if ("${_p}" MATCHES ".*/")
if ("${_p}" MATCHES ".*/$")
string(LENGTH "${_p}" __sl)
math(EXPR __sl ${__sl}-1)
string(SUBSTRING "${_p}" 0 ${__sl} _p)
@@ -397,7 +403,6 @@ macro(__add_file_or_dir _DIR_VAR _FILE_VAR _PATH _RELPATH)
else()
list(APPEND ${_FILE_VAR} "${_p}")
endif()
#endif()
endmacro()
set(__win_host 0)
@@ -617,7 +622,6 @@ macro(deploy_target _T)
foreach (_L ${DEPLOY_ADD_LIBPATH})
set(_add_search_path "${_add_search_path}${_dt_delim}${_L}")
endforeach()
#set(_add_search_path "${_add_search_path}")
#message("app depend ${_T} libpath ${_add_search_path}")
set(_CMD_)
set(_deployed)
@@ -643,8 +647,6 @@ macro(deploy_target _T)
endif()
endforeach()
endif()
#execute_process(COMMAND "lsb_release -si" OUTPUT_VARIABLE _os_id)
#execute_process(COMMAND "lsb_release -sr" OUTPUT_VARIABLE _os_ver)
set(_build "${${_T}_VERSION_BUILD}")
if (NOT "x${_build}" STREQUAL "x")
set(_build "-${_build}")
@@ -770,7 +772,6 @@ macro(deploy_target _T)
COMMAND mkdir ${_VERB} -p "${_AGD}/DEBIAN"
${_CMD_}
#COMMAND -l "${CMAKE_LDD}" -P xcb -q ${Qt5_ROOT} -s "\"${CMAKE_PREFIX_PATH}/lib;${_add_search_path}\"" -o ${_AGD}/usr/lib -p ${_AGD}/usr/ ${_AGD}/Contents/MacOS/${_T}
# generate deb
COMMAND cd ${_AGD} "&&" md5deep -rl opt usr ">" DEBIAN/md5sums
COMMAND mkdir ${_VERB} -p ${_DESTINATION}
@@ -826,7 +827,6 @@ macro(deploy_target _T)
${_CMD_}
# generate deb
#COMMAND cd ${_AGD} "&&" md5deep -rl * ">" DEBIAN/md5sums
COMMAND mkdir ${_VERB} -p ${_DESTINATION}
COMMAND dpkg-deb -Z gzip -b ${_AGD} ${_DESTINATION}/${_deb_name}
VERBATIM
@@ -893,13 +893,8 @@ macro(deploy_target _T)
endif()
set(_dmg_name "${_TV}_macosx_x64.dmg")
set(_cmd_gen_dmg COMMAND genisoimage -quiet -V "${MACOSX_BUNDLE_BUNDLE_NAME}" -D -R -apple -no-pad -o ${_DESTINATION}/${_dmg_name} ${_DMG})
#set(_cmd_int)
if (__mac_host)
set(_cmd_gen_dmg COMMAND hdiutil create ${_DESTINATION}/${_dmg_name} -ov -volname "${MACOSX_BUNDLE_BUNDLE_NAME}" -fs HFS+ -srcfolder ${_DMG})
#set(_rpathes "@executable_path/../Frameworks" "@executable_path/lib" "@loader_path/../lib")
#foreach (_r ${_rpathes})
# set(_cmd_int ${_cmd_int} COMMAND install_name_tool -add_rpath "${_r}" \"${_AGD}/Contents/MacOS/${_T}\")
#endforeach()
endif()
if (_ZIP_DMG)
set(_cmd_gen_dmg ${_cmd_gen_dmg} COMMAND zip -q -r "\"${_DESTINATION}/${_dmg_name}.zip\"" "\"${_DESTINATION}/${_dmg_name}\"")
@@ -915,10 +910,7 @@ macro(deploy_target _T)
COMMAND mkdir ${_VERB} -p ${_AGD}/Contents/Frameworks
COMMAND mkdir ${_VERB} -p ${_DESTINATION}
${_CMD_}
#COMMAND cp ${_ICON_FN} ${_AGD}/Contents/Resources
#COMMAND cp -r ${_DEPLOY_DIR}/lang ${_AGD}/Contents/Resources
COMMAND ${PIP_DEPLOY_TOOL} ${_VERB} ${_OPTIONS} -M "${CMAKE_OTOOL}" -P cocoa,minimal -S mac -q ${Qt5_ROOT} -s "\"${CMAKE_PREFIX_PATH}/lib${_add_search_path}\"" -o ${_AGD}/Contents/Frameworks -p ${_AGD}/Contents/PlugIns ${_AGD}/Contents/MacOS/${_T} ${_ADD_DEPS}
#${_cmd_int}
# prepare dmg dir
COMMAND rm -rf ${_DMG}
COMMAND mkdir ${_VERB} -p ${_DMG}
@@ -949,8 +941,6 @@ macro(deploy_target _T)
endforeach()
set(_res_qrc "${CMAKE_CURRENT_BINARY_DIR}/android_res.qrc")
file(WRITE "${_res_qrc}" "<RCC>${_res_files}\n</RCC>")
#__make_copy(_CMD_ _RES_DIRS _RES_FILES "${_AGD}/res")
#__make_copy(_CMD_ _FILE_DIRS _FILE_FILES "${_AGD}/Contents/MacOS")
set(_AT ${_T}_lib)
set(_ATA ${_AT}_${ANDROID_ABI})
get_target_property(_sources ${_T} SOURCES)
@@ -976,9 +966,7 @@ macro(deploy_target _T)
set(_file "${Qt5_ROOT}/src/3rdparty/gradle/gradlew"
"${Qt5_ROOT}/src/3rdparty/gradle/gradlew.bat")
__make_copy(_CMD_ _dir _file "${_AGD}")
#__make_copy(_CMD_ _PLUG_DIRS _PLUG_FILES "${_AGD}/")
#message("bindir = ${CMAKE_CURRENT_SOURCE_DIR}")
#get_target_property(_LL ${_T} )
set(SDK_ROOT "$ENV{ANDROID_SDK_ROOT}")
if("x${SDK_ROOT}" STREQUAL "x")
set(SDK_ROOT "$ENV{ANDROID_HOME}")
@@ -1059,7 +1047,6 @@ macro(deploy_target _T)
if (NOT __win_host)
set(_gradle_home "-g" "${CMAKE_BINARY_DIR}")
endif()
#set(_CMD_ ${_CMD_} COMMAND "${SDK_ROOT}/tools/android" update project --path "\"${_AGD}\"" --target android-${ANDROID_TARGET_SDK} --name QtApp)
set(_CMD_ ${_CMD_} COMMAND "${Qt5_BIN}/androiddeployqt" --aux-mode --android-platform ${ANDROID_PLATFORM} --output "\"${_AGD}\"" --input "\"${_out_json}\"")
set(_CMD_ ${_CMD_} COMMAND "${_AGD}/gradlew" ${_gradle_home} --no-daemon -p "\"${_AGD}\"" assembleDebug)
set(_CMD_ ${_CMD_} COMMAND "${_AGD}/gradlew" ${_gradle_home} --no-daemon -p "\"${_AGD}\"" bundleRelease)

View File

@@ -12,7 +12,6 @@ if(${MINGW})
PATH_SUFFIXES
include)
#message(STATUS "Find MinGW = ${MINGW_INCLUDE}")
#if(NOT ${MINGW_INCLUDE}) MINGW_INCLUDE = ${MINGW_DIR}/include
find_library(MINGW_LIB m HINTS ${MINGW_BIN}/../lib ${MINGW_INCLUDE}/../lib)
get_filename_component(MINGW_LIB ${MINGW_LIB} PATH)
if (NOT _MGW_MSG)

View File

@@ -3,12 +3,14 @@
Also create imported targets:
* PIP - main library
* PIP::USB
* PIP::Console
* PIP::Crypt
* PIP::FFTW
* PIP::Compress
* PIP::FFTW
* PIP::OpenCL
* PIP::IOUtils
* PIP::Concurrent
* PIP::Cloud
* PIP::Lua
These targets include directories and depends on
main library
@@ -16,7 +18,6 @@ main library
]]
cmake_policy(SET CMP0011 NEW) # don`t affect includer policies
#set(_PIP_MODULES pip pip_usb pip_crypt pip_fftw)
if(WIN32)
find_package(MinGW REQUIRED)
endif()
@@ -33,10 +34,6 @@ endif()
if(CMAKE_CROSSCOMPILING)
list(APPEND _PIP_INCDIR "${CMAKE_PREFIX_PATH}/include/pip")
list(APPEND _PIP_LIBDIR "${CMAKE_PREFIX_PATH}/lib")
#if (DEFINED ANDROID_PLATFORM)
# list(APPEND _PIP_INCDIR ${CMAKE_PREFIX_PATH}/include/pip)
# list(APPEND _PIP_LIBDIR ${CMAKE_PREFIX_PATH}/lib)
#endif()
else()
if(NOT WIN32)
list(APPEND _PIP_INCDIR "/usr/include/pip" "/usr/local/include/pip")
@@ -60,24 +57,19 @@ else()
endif()
list(APPEND _PIP_BINDIR "${PIP_DIR}/bin")
set(_pip_suffix "")
#if(DEFINED ANDROID_PLATFORM)
# set(_pip_suffix "_${ANDROID_ABI}")
#endif()
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_CONSOLE_LIBRARY pip_console${_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_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_CONCURRENT_LIBRARY pip_concurrent${_pip_suffix} HINTS ${_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)
#if (DEFINED ANDROID_PLATFORM)
# set(PIP_INCLUDES ${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include/pip)
#else()
get_filename_component(PIP_INCLUDES ${PIP_H_INCLUDE} PATH)
#endif()
set(__ext "")
if ("x${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "xWindows")
set(__ext ".exe")
@@ -104,6 +96,19 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
list(APPEND PIP_LIBRARY ${_PIP_ADD_LIBS_})
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)
include(CheckSymbolExists)
@@ -127,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!")
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_Console "${PIP_CONSOLE_LIBRARY}" )
set(__module_Crypt "${PIP_CRYPT_LIBRARY}" )
set(__module_FFTW "${PIP_FFTW_LIBRARY}" )
set(__module_Compress "${PIP_COMPRESS_LIBRARY}" )
set(__module_OpenCL "${PIP_OPENCL_LIBRARY}" )
set(__module_IOUtils "${PIP_IO_UTILS_LIBRARY}" )
set(__module_Concurrent "${PIP_CONCURRENT_LIBRARY}")
set(__module_Cloud "${PIP_CLOUD_LIBRARY}" )
set(__module_Lua "${PIP_LUA_LIBRARY}" )
if((NOT TARGET PIP) AND PIP_LIBRARY)
add_library(PIP UNKNOWN IMPORTED)
set_target_properties(PIP PROPERTIES
@@ -150,8 +157,15 @@ foreach (_m ${__modules})
INTERFACE_LINK_LIBRARIES "PIP")
endif()
endforeach()
if(__module_IOUtils AND __module_Crypt)
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)

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)
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("${TARGET}" COMMAND ${CMAKE_COMMAND} -D COMPONENT=doc -P cmake_install.cmake)
add_dependencies("${TARGET}" "genereate.${TARGET}")

View File

@@ -86,17 +86,11 @@ macro(pip_resources RESULT INPUT)
set(RC_OUT ${CMAKE_CURRENT_BINARY_DIR}/${RC_FILE})
set(${RESULT} ${${RESULT}} ${RC_OUT})
set(CCM_FILES)
#if (ABS)
if(IS_ABSOLUTE "${INPUT}")
set(RC_FILES "${INPUT}")
else()
set(RC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${INPUT}")
endif()
#else()
# foreach(csrc ${CCM_SRC})
# list(APPEND CCM_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${csrc}")
# endforeach()
#endif()
#message(STATUS "CCM = ${RESULT}")
if(NOT DEFINED PIP_DLL_DIR)
set(PIP_DLL_DIR ${CMAKE_CURRENT_BINARY_DIR})

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = PIP
# could be handy for archiving the generated documentation or if some version
# 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
# 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
# Note: If this tag is empty the current directory is searched.
INPUT = src_main \
src_crypt \
src_fftw \
src_io_utils \
src_compress \
src_opencl \
src_usb
INPUT = ${DOXY_INPUT}
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -895,7 +889,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE =
EXCLUDE = ${DOXY_EXCLUDE}
# 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
@@ -928,7 +922,7 @@ EXCLUDE_SYMBOLS =
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH = doc/examples
EXAMPLE_PATH = ${DOXY_EXAMPLE_PATH}
# 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
@@ -948,7 +942,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \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
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -1459,14 +1453,14 @@ QHP_CUST_FILTER_NAME = PIP
# filters).
# 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
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS = PIP
QHP_SECT_FILTER_ATTRS = ${DOXY_QHP_SECT_FILTER_ATTRS}
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
@@ -2152,15 +2146,7 @@ SEARCH_INCLUDES = YES
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH = src_main/code \
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
INCLUDE_PATH = ${DOXY_INCLUDE_PATH}
# 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
@@ -2178,8 +2164,8 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = DOXYGEN \
PIP_EXPORT
PREDEFINED = ${DOXY_DEFINES}
# 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
@@ -2272,14 +2258,14 @@ CLASS_DIAGRAMS = YES
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# 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
# 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.
# 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
# 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.
# 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
# contain dot files that are included in the documentation (see the \dotfile

View File

@@ -211,6 +211,16 @@ piCout << s.find("3"); // 9
piCout << s.find("3", 4); // 9
piCout << s.find("3", 10); // -1
//! [PIString::findLast]
//! [PIString::findAny]
piCout << PIString("1.str").findAny(".,:"); // 1
piCout << PIString("1,str").findAny(".,:"); // 1
piCout << PIString("1:str").findAny(".,:"); // 1
//! [PIString::findAny]
//! [PIString::findAnyLast]
piCout << PIString("str.0").findAny(".,:"); // 3
piCout << PIString("str,0").findAny(".,:"); // 3
piCout << PIString("str:0").findAny(".,:"); // 3
//! [PIString::findAnyLast]
//! [PIString::findWord]
PIString s("this is <PIP>");
piCout << s.find("this"); // 0

View File

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

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
PICloud Client
Copyright (C) 2020 Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by
@@ -23,3 +23,18 @@
PICloudClient::PICloudClient() {
}
PICloudClient::~PICloudClient() {
}
bool PICloudClient::openDevice() {
}
bool PICloudClient::closeDevice() {
}

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
PICloud Server
Copyright (C) 2020 Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
PICloud TCP transport
Copyright (C) 2020 Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Cryptographic class using lib Sodium
Copyright (C) 2020 Andrey Bychkov work.a.b@yandex.ru
Compress class using zlib
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

View File

@@ -162,7 +162,6 @@ void PIScreen::SystemConsole::print() {
///cells[mouse_y][mouse_x].format.flags ^= Inverse;
}
#ifdef WINDOWS
//static int cnt = 0;
PRIVATE->srect = PRIVATE->sbi.srWindow;
int dx0 = -1, dx1 = -1, dy0 = -1, dy1 = -1;
for (int j = 0; j < height; ++j) {
@@ -189,11 +188,8 @@ void PIScreen::SystemConsole::print() {
Cell & c(cells[j + dy0][i + dx0]);
PRIVATE->chars[k].Char.UnicodeChar = 0;
PRIVATE->chars[k].Char.AsciiChar = c.symbol.toConsole1Byte();
//PRIVATE->chars[k].Char.UnicodeChar = c.symbol.toInt();
PRIVATE->chars[k].Attributes = attributes(c);
}
//PRIVATE->bc.X = dx0;
//PRIVATE->bc.Y = dy0;
//piCout << "draw" << dw << dh;
PRIVATE->bs.X = dw;
PRIVATE->bs.Y = dh;
@@ -235,10 +231,6 @@ void PIScreen::SystemConsole::print() {
printf("%s", s.data());
s.clear();
}
/*for (int i = 0; i < width; ++i) {
moveTo(i, j);
printf("%s", (formatString(cells[j][i]) + cells[j][i].symbol).data());
}*/
}
printf("\e[0m");
fflush(0);
@@ -420,9 +412,7 @@ PIScreen::~PIScreen() {
void PIScreen::setMouseEnabled(bool on) {
mouse_ = on;
//lock();
console.mouse_x = console.mouse_y = -1;
//unlock();
}
@@ -490,7 +480,7 @@ void PIScreen::mouse_event(PIKbdListener::MouseEvent me) {
PIVector<PIScreenTile * > tl = prepareMouse(&me);
if (tl.isEmpty()) return;
piForeachR (PIScreenTile * t, tl)
if (t->mouseEvent(me)) piBreak;
if (t->mouseEvent(me)) break;
}
@@ -498,7 +488,7 @@ void PIScreen::wheel_event(PIKbdListener::WheelEvent we) {
PIVector<PIScreenTile * > tl = prepareMouse(&we);
if (tl.isEmpty()) return;
piForeachR (PIScreenTile * t, tl)
if (t->wheelEvent(we)) piBreak;
if (t->wheelEvent(we)) break;
}

View File

@@ -0,0 +1,42 @@
/*
PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API
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 "piscreenconsole.h"
using namespace PIScreenTypes;
TileVars::TileVars(const PIString &n) : PIScreenTile(n) {
alignment = Left;
}
void TileVars::sizeHint(int &w, int &h) const {
}
void TileVars::drawEvent(PIScreenDrawer *d) {
}
PIScreenConsoleTile::PIScreenConsoleTile() {
}

View File

@@ -111,10 +111,7 @@ void PIScreenTile::setScreen(PIScreenBase * s) {
void PIScreenTile::deleteChildren() {
//piCout << this << "deleteChildren";
piForeach (PIScreenTile * t, tiles) {
//piCout << this << " child" << t;
//t->deleteChildren();
t->parent = 0;
delete t;
}
@@ -130,7 +127,6 @@ void PIScreenTile::setFocus() {
void PIScreenTile::drawEventInternal(PIScreenDrawer * d) {
if (!visible) {
//d->clearRect(x, y, x + width, y + height);
return;
}
d->fillRect(x_, y_, x_ + width_, y_ + height_, back_symbol, (Color)back_format.color_char, (Color)back_format.color_back, back_format.flags);
@@ -232,7 +228,7 @@ void PIScreenTile::layout() {
}
int cx = x_ + marginLeft, cy = y_ + marginTop;
for (int i = 0; i < tiles.size_s(); ++i) {
PIScreenTile * t(tiles[i]);
PIScreenTile * t = tiles[i];
if (!t->visible || !t->needLayout()) continue;
t->x_ = cx;
t->y_ = cy;

View File

@@ -154,7 +154,6 @@ void TileList::resizeEvent(int w, int h) {
void TileList::drawEvent(PIScreenDrawer * d) {
lhei = height_ - 2;
//int osp = piMini(3, lhei / 4);
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 (ie < content.size_s()) d->drawText(x_, y_ + height_ - 1, PIString(" \\/ ").repeat(width_ / 4), Green, Default, Bold);
@@ -182,11 +181,6 @@ void TileList::drawEvent(PIScreenDrawer * d) {
}
scroll->setMaximum(piMaxi(0, content.size_s() - 1));
scroll->setValue(cur);
/*int cx = x_ + width_ - 1;
d->drawLine(cx, y_ + 1, cx, y_ + height_ - 2, vert_line, Green);
if (content.size_s() > 1)
d->drawPixel(cx, y_ + piRound(float(cur) / (content.size_s() - 1) * (lhei - 1)) + 1, ' ', Green, Green);
if (ie < content.size_s()) d->drawText(x_, y_ + height_ - 1, PIString(" \\/ ").repeat(width_ / 4), Green, Default, Bold);*/
}
@@ -289,7 +283,6 @@ bool TileList::mouseEvent(PIKbdListener::MouseEvent me) {
break;
case PIKbdListener::MouseButtonDblClick:
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
//raiseEvent(TileEvent(RowPressed, cur));
return true;
default: break;
}

View File

@@ -805,7 +805,7 @@ bool PITerminal::initialize() {
if (e.startsWith("TERM=")) {
PRIVATE->term_type = termType(e.mid(5).trim().toLowerCase());
//piCout << PRIVATE->term_type;
piBreak;
break;
}
pid_t fr = forkpty(&(PRIVATE->fd), pty, 0, &ws);
//piCoutObj << fr << PRIVATE->fd << pty;

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
PIP Authentication API
Copyright (C) 2020 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
it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Cryptographic class using lib Sodium
Copyright (C) 2020 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
it under the terms of the GNU Lesser General Public License as published by

View File

@@ -24,7 +24,6 @@
#define PIFFT_P_H
#include "pivector.h"
#include "pimutex.h"
#include "picout.h"
#if defined(PIP_FFTW) || defined(PIP_FFTWf) || defined(PIP_FFTWl) || defined(PIP_FFTWq)
# include "fftw3.h"
@@ -37,7 +36,7 @@
template <typename T>
class PIP_EXPORT PIFFTW_Private
class PIFFTW_Private
{
public:
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) {
#ifdef PIP_CRYPT
_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) {
if (!_crypt) return data;
return

View File

@@ -17,8 +17,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wnonnull"
#endif
#include "pistreampacker.h"
#include "piiodevice.h"
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
/** \class PIStreamPacker
* \brief Simple packet wrap aroud any PIIODevice
@@ -107,7 +114,7 @@ void PIStreamPacker::received(uchar * readed, int size) {
void PIStreamPacker::received(const PIByteArray & data) {
stream.append(data);
//piCout << "rec" << data.size();
while (stream.size_s() >= 4) {
while (stream.size_s() >= 6) {
if (packet_size < 0) {
ushort sign(0);
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

@@ -4,7 +4,7 @@
/*
PIP - Platform Independent Primitives
PICloud Client
Copyright (C) 2020 Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by
@@ -23,16 +23,26 @@
#ifndef PICCLOUDCLIENT_H
#define PICCLOUDCLIENT_H
#include "pistring.h"
#include "pip_cloud_export.h"
#include "piiodevice.h"
class PIP_EXPORT PICloudClient {
class PIEthernet;
class PIP_CLOUD_EXPORT PICloudClient : public PIIODevice
{
PIIODEVICE(PICloudClient)
public:
//!
PICloudClient();
explicit PICloudClient();
virtual ~PICloudClient();
protected:
bool openDevice();
bool closeDevice();
private:
PIEthernet * eth;
};
#endif // PICCLOUDCLIENT_H

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Module includes
Copyright (C) 2020 Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by

View File

@@ -4,7 +4,7 @@
/*
PIP - Platform Independent Primitives
PICloud Server
Copyright (C) 2020 Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by
@@ -23,12 +23,14 @@
#ifndef PICCLOUDSERVER_H
#define PICCLOUDSERVER_H
#include "pistring.h"
#include "pip_cloud_export.h"
#include "piiodevice.h"
class PIP_EXPORT PICloudServer {
class PIP_CLOUD_EXPORT PICloudServer {
public:
//!
PICloudServer();
explicit PICloudServer();
private:

View File

@@ -4,7 +4,7 @@
/*
PIP - Platform Independent Primitives
PICloud TCP transport
Copyright (C) 2020 Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by
@@ -23,9 +23,10 @@
#ifndef PICCLOUDTCP_H
#define PICCLOUDTCP_H
#include "pip_cloud_export.h"
#include "pistring.h"
class PIP_EXPORT PICloudTCP {
class PIP_CLOUD_EXPORT PICloudTCP {
public:
//!
PICloudTCP();

View File

View File

@@ -24,13 +24,13 @@
#ifndef PICODEINFO_H
#define PICODEINFO_H
#include "pistring.h"
#include "pistringlist.h"
class PIVariant;
namespace PICodeInfo {
enum PIP_EXPORT TypeFlag {
enum TypeFlag {
NoFlag,
Const = 0x01,
Static = 0x02,
@@ -153,10 +153,10 @@ inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
return s;
}
extern PIMap<PIString, PICodeInfo::ClassInfo * > * classesInfo;
extern PIMap<PIString, PICodeInfo::EnumInfo * > * enumsInfo;
extern PIMap<PIString, PICodeInfo::AccessValueFunction> * accessValueFunctions;
extern PIMap<PIString, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
extern PIP_EXPORT PIMap<PIString, PICodeInfo::ClassInfo * > * classesInfo;
extern PIP_EXPORT PIMap<PIString, PICodeInfo::EnumInfo * > * enumsInfo;
extern PIP_EXPORT PIMap<PIString, PICodeInfo::AccessValueFunction> * accessValueFunctions;
extern PIP_EXPORT PIMap<PIString, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) {
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);
}
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:
__PICodeInfoInitializer__() {
if (_inited_) return;

View File

@@ -0,0 +1,26 @@
/*
PIP - Platform Independent Primitives
Module includes
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 PICODEMODULE_H
#define PICODEMODULE_H
#include "picodeinfo.h"
#include "picodeparser.h"
#endif // PICODEMODULE_H

View File

@@ -24,7 +24,7 @@
PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
PIStringList arg_vals;
while (!args_.isEmpty()) {
int ci = args_.find(","), bi = args_.find("(");
int ci = args_.find(','), bi = args_.find('(');
if (ci < 0) {
arg_vals << args_;
break;
@@ -33,7 +33,7 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
if (bi >= 0 && bi < ci) {
ca = args_.left(args_.takeLeft(bi).toInt());
ci -= ca.size_s(); bi -= ca.size_s();
ca += "(" + args_.takeRange("(", ")") + ")";
ca += '(' + args_.takeRange('(', ')') + ')';
} else {
ca = args_.takeLeft(ci);
}
@@ -41,7 +41,7 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
args_.trim(); args_.takeLeft(1); args_.trim();
}
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() << "!";
if (ok != 0) *ok = false;
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 (ppc != '#' && pc == '#' && !_isCChar(nc)) { // to chars
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;
continue;
}
@@ -66,7 +66,7 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
ind -= an.size_s() - av.size_s();
}
}
ret.replaceAll("##", "");
ret.replaceAll(PIStringAscii("##"), "");
if (ok != 0) *ok = true;
return ret;
}
@@ -99,20 +99,20 @@ void PICodeParser::parseFile(const PIString & file, bool follow_includes) {
}
piCout << "\n\nDefines:";
piForeachC (Define & m, defines)
piCout << "define" << m.first << m.second;
piCout << PIStringAscii("define") << m.first << m.second;
piCout << "\n\nMacros:";
piForeachC (Macro & m, macros)
piCout << "Macro:" << m.name << m.args << m.value;
piCout << "\n\nClasses:";
piCout << "\n\nEnums:";
piForeachC (Enum & c, enums) {
piCout << "enum" << c.name << c.meta;
piCout << PIStringAscii("enum") << c.name << c.meta;
piForeachC (EnumeratorInfo & e, c.members)
piCout << " " << e.name << "=" << e.value << e.meta;
piCout << " " << e.name << '=' << e.value << e.meta;
}
piCout << "\n\nTypedefs:";
piForeachC (Typedef & c, typedefs)
piCout << "typedef" << c;*/
piCout << PIStringAscii("typedef") << c;*/
}
@@ -122,19 +122,19 @@ void PICodeParser::parseFiles(const PIStringList & files, bool follow_includes)
parseFileInternal(f, follow_includes);
/*piCout << "\n\nDefines:";
piForeachC (Define & m, defines)
piCout << "define" << m.first << m.second;
piCout << PIStringAscii("define") << m.first << m.second;
piCout << "\n\nMacros:";
piForeachC (Macro & m, macros)
piCout << "Macro:" << m.name << m.args << m.value;
piCout << "\n\nClasses:";
piForeachC (Entity * c, entities)
piCout << "class" << c->name << c->parents;
piCout << PIStringAscii("class") << c->name << c->parents;
piCout << "\n\nEnums:";
piForeachC (Enum & c, enums)
piCout << "enum" << c.name << c.members;
piCout << PIStringAscii("enum") << c.name << c.members;
piCout << "\n\nTypedefs:";
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);
int ii = 0;
while (!f.isOpened() && ii < (includes.size_s() - 1)) {
f.setPath(includes[++ii] + "/" + file);
f.setPath(includes[++ii] + '/' + file);
//piCout << "try" << f.path();
f.open(PIIODevice::ReadOnly);
}
@@ -186,7 +186,10 @@ void PICodeParser::clear() {
evaluator.clearCustomVariables();
cur_def_vis = Global;
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;
PIMap<PIString, PIString> cchars;
/// Remove comments, join multiline "*" and replace "*" to $n (cchars)
fc.replaceAll("\r\n", "\n");
fc.replaceAll("\r", "\n");
/// Remove comments, join multiline '*' and replace '*' to $n (cchars)
fc.replaceAll("\r\n", '\n');
fc.replaceAll('\r', '\n');
for (int i = 0; i < fc.size_s() - 1; ++i) {
if (fc[i].unicode16Code() >= 255) continue;
if (i > 0) pc = c;
@@ -207,13 +210,6 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
if (c == '"' && !mlc && pc != '\'') {
if (i > 0) if (fc[i - 1] == '\\') continue;
cc = !cc;
/*if (cc) ccs = i;
if (!cc) {
ccmn = "$" + PIString::fromNumber(cchars.size());
cchars[ccmn] = fc.mid(ccs, i - ccs + 1);
fc.replace(ccs, i - ccs + 1, ccmn);
i = ccs - 1 + ccmn.size_s();
}*/
continue;
}
if (i > 0)
@@ -227,7 +223,6 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
if (fc.mid(i, 2) == "*/" && mlc) {mlc = false; fc.cutMid(mls, i - mls + 2); i = mls - 1; continue;}
if (fc.mid(i, 2) == "//" && !mlc) {ole = fc.find('\n', i); fc.cutMid(i, ole < 0 ? -1 : ole - i); --i; continue;}
}
//PICout(PICoutManipulators::DefaultControls) << fc;
pfc = procMacros(fc);
replaceMeta(pfc);
@@ -264,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 (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue;
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);
if (!ok) return false;
int rlen = pfc.find(range, ind + m.name.size_s()) + range.size_s() + 1 - ind;
@@ -282,46 +277,46 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
int nl = pfc.size_s();
if (pl == nl) break;
pl = nl;
if (pfc.left(9) == "namespace") {
pfc.cutLeft(pfc.find("{") + 1);
if (pfc.left(9) == PIStringAscii("namespace")) {
pfc.cutLeft(pfc.find('{') + 1);
continue;
}
if (pfc.left(8) == "template") {
if (pfc.left(8) == PIStringAscii("template")) {
pfc.cutLeft(8);
pfc.takeRange("<", ">");
pfc.takeRange('<', '>');
bool def = !isDeclaration(pfc, 0, &end);
pfc.cutLeft(end);
if (def) pfc.takeRange("{", "}");
if (def) pfc.takeRange('{', '}');
else pfc.takeSymbol();
continue;
}
if (pfc.left(5) == "class" || pfc.left(6) == "struct" || pfc.left(5) == "union") {
int dind = pfc.find("{", 0), find = pfc.find(";", 0);
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);
if (dind < 0 && find < 0) {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());
parseClass(0, ccmn);
continue;
}
if (pfc.left(4) == "enum") {
if (pfc.left(4) == PIStringAscii("enum")) {
pfc.cutLeft(4);
tmp = pfc.takeCWord();
pfc.trim();
MetaMap meta = maybeMeta(pfc);
parseEnum(0, cur_namespace + tmp, pfc.takeRange("{", "}"), meta);
parseEnum(0, cur_namespace + tmp, pfc.takeRange('{', '}'), meta);
pfc.takeSymbol();
continue;
}
if (pfc.left(7) == "typedef") {
if (pfc.left(7) == PIStringAscii("typedef")) {
pfc.cutLeft(7);
typedefs << parseTypedef(pfc.takeLeft(pfc.find(";")));
typedefs << parseTypedef(pfc.takeLeft(pfc.find(';')));
if (typedefs.back().first.isEmpty()) typedefs.pop_back();
else root_.typedefs << typedefs.back();
pfc.takeSymbol();
continue;
}
int sci = pfc.find(";", 0), obi = pfc.find("{", 0);
int sci = pfc.find(';', 0), obi = pfc.find('{', 0);
if (sci < 0 && obi < 0) {
pfc.takeLeft(1);
continue;
@@ -331,7 +326,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
str = pfc.takeLeft(sci + 1);
} else {
str = pfc.takeLeft(obi);
pfc.cutLeft(pfc.takeRange("{", "}").toInt());
pfc.cutLeft(pfc.takeRange('{', '}').toInt());
}
parseMember(&root_, str);
}
@@ -341,22 +336,22 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
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;
int ind = cd.find("$M");
int ind = cd.find(PIStringAscii("$M"));
if (ind >= 0) {
meta = tmp_meta.value(cd.takeMid(ind, 5));
cd.replaceAll(" ", " ");
cd.replaceAll(PIStringAscii(" "), ' ');
}
//piCout << "found class <****\n" << cd << "\n****>";
ind = cd.find(":");
ind = cd.find(':');
PIVector<Entity * > parents;
if (ind > 0) {
PIStringList pl = cd.takeMid(ind + 1).trim().split(",");
PIStringList pl = cd.takeMid(ind + 1).trim().split(',');
cd.cutRight(1);
Entity * pe = 0;
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;
pe = findEntityByName(pn);
if (pe == 0) ;//{piCout << "Error: can`t find" << pn;}
@@ -364,17 +359,17 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
}
}
PIString typename_ = cd.left(6).trim();
bool is_class = typename_ == "class";
bool is_class = typename_ == PIStringAscii("class");
cur_def_vis = (is_class ? Private : Public);
PIString cn = cd.mid(6).trim();
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;
if (cn.isEmpty()) return 0;
Entity * e = new Entity();
e->meta = meta;
e->name = cur_namespace + cn;
e->type = typename_;//(is_class ? "class" : "struct");
e->type = typename_;
e->has_name = has_name;
e->parents = parents;
e->file = cur_file;
@@ -385,7 +380,7 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
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 < dind) return fc.left(find);
//piCout << "parse class <****\n" << fc.left(20) << "\n****>";
@@ -398,43 +393,43 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
int ps = -1;
bool def = false;
PIString prev_namespace = cur_namespace, stmp;
cur_namespace = ce->name + "::";
cur_namespace = ce->name + PIStringAscii("::");
//piCout << "parse class" << ce->name << "namespace" << cur_namespace;
//piCout << "\nparse class" << ce->name << "namespace" << cur_namespace;
while (!fc.isEmpty()) {
PIString cw = fc.takeCWord(), tmp;
//piCout << "\ntaked word" << cw;
if (cw == "public") {cur_def_vis = Public; fc.cutLeft(1); continue;}
if (cw == "protected") {cur_def_vis = Protected; fc.cutLeft(1); continue;}
if (cw == "private") {cur_def_vis = Private; fc.cutLeft(1); continue;}
if (cw == "class" || cw == "struct" || cw == "union") {
if (cw == PIStringAscii("public" )) {cur_def_vis = Public; fc.cutLeft(1); continue;}
if (cw == PIStringAscii("protected")) {cur_def_vis = Protected; fc.cutLeft(1); continue;}
if (cw == PIStringAscii("private" )) {cur_def_vis = Private; fc.cutLeft(1); continue;}
if (cw == PIStringAscii("class") || cw == PIStringAscii("struct") || cw == PIStringAscii("union")) {
if (isDeclaration(fc, 0, &end)) {
fc.cutLeft(end);
fc.takeSymbol();
continue;
}
tmp = fc.takeLeft(fc.find("{"));
stmp = fc.takeRange("{", "}");
tmp = fc.takeLeft(fc.find('{'));
stmp = fc.takeRange('{', '}');
fc.takeSymbol();
stmp = cw + " " + tmp + "{" + stmp + "}";
stmp = cw + ' ' + tmp + '{' + stmp + '}';
parseClass(ce, stmp);
continue;
}
if (cw == "enum") {
if (cw == PIStringAscii("enum")) {
tmp = fc.takeCWord();
fc.trim();
MetaMap meta = maybeMeta(fc);
parseEnum(ce, cur_namespace + tmp, fc.takeRange("{", "}"), meta);
parseEnum(ce, cur_namespace + tmp, fc.takeRange('{', '}'), meta);
fc.takeSymbol();
continue;
}
if (cw == "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 == "template") {
fc.takeRange("<", ">");
if (cw == PIStringAscii("friend")) {fc.cutLeft(fc.find(';') + 1); 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 == PIStringAscii("template")) {
fc.takeRange('<', '>');
def = !isDeclaration(fc, 0, &end);
fc.cutLeft(end);
if (def) fc.takeRange("{", "}");
if (def) fc.takeRange('{', '}');
else fc.takeSymbol();
continue;
}
@@ -442,9 +437,9 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
tmp = (cw + fc.takeLeft(end)).trim();
if (!tmp.isEmpty())
parseMember(ce, tmp);
if (def) fc.takeRange("{", "}");
if (def) fc.takeRange('{', '}');
else fc.takeSymbol();
if (ps == fc.size_s()) {/*cur_namespace = prev_namespace;*/ fc.cutLeft(1);/*return false*/;}
if (ps == fc.size_s()) {fc.cutLeft(1);}
ps = fc.size_s();
}
cur_def_vis = prev_vis;
@@ -456,13 +451,13 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
PICodeParser::MetaMap PICodeParser::parseMeta(PIString & fc) {
PICodeParser::MetaMap ret;
if (fc.isEmpty()) return ret;
PIStringList ml = fc.split(",");
PIStringList ml = fc.split(',');
piForeachC (PIString & m, ml) {
int i = m.find("=");
int i = m.find('=');
if (i < 0) continue;
PIString mv = m.mid(i + 1).trim();
if (mv.startsWith("\"")) mv.cutLeft(1);
if (mv.endsWith("\"")) mv.cutRight(1);
if (mv.startsWith('\"')) mv.cutLeft(1);
if (mv.endsWith('\"')) mv.cutRight(1);
ret[m.left(i).trim()] = mv;
}
//piCout << ms << ret;
@@ -471,20 +466,22 @@ PICodeParser::MetaMap PICodeParser::parseMeta(PIString & fc) {
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);
e.meta = meta;
PIStringList vl(fc.split(","));
PIStringList vl(fc.split(','));
PIString vn;
int cv = -1, ind = 0;
piForeach (PIString & v, vl) {
MetaMap meta;
int mi = v.find("$M");
int mi = v.find(s_M);
if (mi >= 0) {
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;
e.members << EnumeratorInfo(vn.trim(), cv, meta);
@@ -500,15 +497,15 @@ bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc
PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) {
//piCout << "parse typedef" << fc;
Typedef td;
fc.replaceAll("\t", " ");
fc.replaceAll('\t', ' ');
if (fc.contains("(")) {
int start = fc.find("("), end = fc.find(")");
if (fc.contains('(')) {
int start = fc.find('('), end = fc.find(')');
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();
} else {
td.first = fc.takeMid(fc.findLast(" ")).trim();
td.first = fc.takeMid(fc.findLast(' ')).trim();
td.second = fc.trim();
}
//piCout << "found typedef" << td;
@@ -517,34 +514,53 @@ PICodeParser::Typedef PICodeParser::parseTypedef(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.find("operator") >= 0) return true;
if (fc.find(s_operator) >= 0) return true;
tmp_temp.clear();
//piCout << "parse member" << fc;
int ts = fc.find("<"), te = 0;
int ts = fc.find('<'), te = 0;
PIString ctemp, crepl;
while (ts >= 0) {
ctemp = fc.mid(ts).takeRange("<", ">");
if (ctemp.isEmpty()) {te = ts + 1; ts = fc.find("<", te); continue;}
crepl = "$T" + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, "0");
ctemp = fc.mid(ts).takeRange('<', '>');
if (ctemp.isEmpty()) {te = ts + 1; ts = fc.find('<', te); continue;}
crepl = s_T + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, '0');
fc.replace(ts, ctemp.size_s() + 2, crepl);
tmp_temp[crepl] = "<" + ctemp + ">";
ts = fc.find("<", te);
tmp_temp[crepl] = '<' + ctemp + '>';
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;
PIStringList tl, al;
Member me;
//piCout << fc;
if (fc.contains("(")) {
if (fc.contains('(')) {
MetaMap meta;
int ind = fc.find("$M");
int ind = fc.find(s_M);
if (ind >= 0) {
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);
te = fc.find("(");
fc.cutRight(fc.size_s() - fc.findLast(')') - 1);
te = fc.find('(');
//piCout << fc;
for (ts = te - 1; ts >= 0; --ts)
if (!_isCChar(fc[ts]) && !(fc[ts].isDigit())) break;
@@ -552,37 +568,37 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
me.meta = meta;
me.name = fc.takeMid(ts + 1, te - ts - 1);
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.visibility = cur_def_vis;
if (me.type.find("inline ") >= 0) {
if (me.type.find(s_inline_s) >= 0) {
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.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.type.removeAll("virtual ");
me.type.removeAll(s_virtual_s);
}
normalizeEntityNamespace(me.type);
int i = 0;
//piCout << 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();
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);
--j;
}
me.arguments_type = me.arguments_full;
piForeach (PIString & a, me.arguments_type) {
crepl.clear();
if (a.contains("["))
crepl = a.takeMid(a.find("["), a.findLast("]") - a.find("[") + 1);
if (a.contains('['))
crepl = a.takeMid(a.find('['), a.findLast(']') - a.find('[') + 1);
for (ts = a.size_s() - 1; ts >= 0; --ts)
if (!_isCChar(a[ts]) && !(a[ts].isDigit())) break;
a.cutRight(a.size_s() - ts - 1);
@@ -594,18 +610,18 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
//piCout << "func" << me.type << me.name << me.arguments_full << me.arguments_type;
parent->functions << me;
} else {
if (fc.endsWith(";")) fc.cutRight(1);
if (fc.startsWith("using") || !(fc.contains(' ') || fc.contains('\t') || fc.contains('\n'))) return true;
if (fc.endsWith(';')) fc.cutRight(1);
if (fc.startsWith(s_using) || !(fc.contains(' ') || fc.contains('\t') || fc.contains('\n'))) return true;
int bits = extractMemberBits(fc);
tl = fc.split(",");
tl = fc.split(',');
//piCout << "member" << fc << tl;
//piCout << "member after eb" << fc << ", bits =" << bits;
if (tl.isEmpty()) return true;
bool vn = true;
ctemp = tl.front().trim();
PIString meta_t;
if (ctemp.contains("$M"))
meta_t = ctemp.takeMid(ctemp.find("$M"));
if (ctemp.contains(s_M))
meta_t = ctemp.takeMid(ctemp.find(s_M));
for (ts = ctemp.size_s() - 1; ts > 0; --ts) {
if (vn) {if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;}
else {if (_isCChar(ctemp[ts]) || ctemp[ts].isDigit()) break;}
@@ -614,26 +630,26 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
me.visibility = cur_def_vis;
ctemp += meta_t;
restoreTmpTemp(&me);
PIString type = " " + me.type;
if (type.find(" const ") >= 0) {
PIString type = s_s5 + me.type;
if (type.find(s_s_const_s) >= 0) {
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;
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;
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;
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;
type.replaceAll(" extern ", " ");
type.replaceAll(s_s_extern_s, ' ');
}
type.trim();
normalizeEntityNamespace(type);
@@ -645,15 +661,15 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
me.type = type;
restoreTmpMeta(&me);
if (me.name.isEmpty()) continue;
if (me.name.contains("["))
crepl = me.name.takeMid(me.name.find("["), me.name.findLast("]") - me.name.find("[") + 1);
if (me.name.contains('['))
crepl = me.name.takeMid(me.name.find('['), me.name.findLast(']') - me.name.find('[') + 1);
while (!me.name.isEmpty()) {
if (me.name.front() == "*" || me.name.front() == "&") {
if (me.name.front() == PIChar('*') || me.name.front() == PIChar('&')) {
me.type += me.name.takeLeft(1);
me.name.trim();
} 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.bits = bits;
while (!crepl.isEmpty()) {
@@ -672,7 +688,7 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
int PICodeParser::extractMemberBits(PIString & fc) {
int i = fc.findLast(":");
int i = fc.findLast(':');
if (i <= 0) return -1;
if (fc[i - 1].toAscii() == ':') return -1;
PIString bs = fc.takeMid(i).mid(1).trim();
@@ -682,6 +698,14 @@ int PICodeParser::extractMemberBits(PIString & fc) {
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;
for (int i = n.size_s() - 1; i > 0; --i)
if (_isCChar(n[i]) || n[i].isDigit()) {
@@ -689,11 +713,11 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
n.cutRight(suff.size_s());
break;
}
n.push_front(" ");
if (n.find(" static ") >= 0) {n.replaceAll(" static ", ""); pref += "static ";}
if (n.find(" const ") >= 0) {n.replaceAll(" const ", ""); pref += "const ";}
if (n.find(" mutable ") >= 0) {n.replaceAll(" mutable ", ""); pref += "mutable ";}
if (n.find(" volatile ") >= 0) {n.replaceAll(" volatile ", ""); pref += "volatile ";}
n.push_front(' ');
if (n.find(s_s_const_s) >= 0) {n.replaceAll(s_s_const_s, ""); pref += s_const_s;}
if (n.find(s_s_static_s) >= 0) {n.replaceAll(s_s_static_s, ""); pref += s_static_s;}
if (n.find(s_s_mutable_s) >= 0) {n.replaceAll(s_s_mutable_s, ""); pref += s_mutable_s;}
if (n.find(s_s_volatile_s) >= 0) {n.replaceAll(s_s_volatile_s, ""); pref += s_volatile_s;}
n.trim();
int f = 0;
piForeachC (Entity * e, entities) {
@@ -702,28 +726,30 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
return;
}
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) {
n = pref + e->name + suff;
return;
}
}
piForeachC (Enum & e, enums)
piForeachC (Enum & e, enums) {
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) {
//piCout << "change" << n << "to" << e.name + suff;
n = pref + e.name + suff;
return;
}
piForeachC (Typedef & e, typedefs)
}
piForeachC (Typedef & e, typedefs) {
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) {
//piCout << "change" << n << "to" << e.name + suff;
n = pref + e.first + suff;
return;
}
}
n = (pref + n + suff).trim();
}
@@ -731,20 +757,20 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
void PICodeParser::restoreTmpTemp(Member * e) {
int i = 0;
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)]);
}
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)]);
}
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)]);
}
void PICodeParser::restoreTmpMeta(PICodeParser::Member * e) {
int i = e->name.find("$M");
int i = e->name.find(PIStringAscii("$M"));
if (i < 0) return;
e->meta = tmp_meta[e->name.takeMid(i, 5)];
}
@@ -752,7 +778,7 @@ void PICodeParser::restoreTmpMeta(PICodeParser::Member * e) {
PICodeParser::MetaMap PICodeParser::maybeMeta(PIString & fc) {
PICodeParser::MetaMap ret;
if (fc.left(2) == "$M") {
if (fc.left(2) == PIStringAscii("$M")) {
ret = tmp_meta.value(fc.takeLeft(5));
fc.trim();
}
@@ -762,10 +788,10 @@ PICodeParser::MetaMap PICodeParser::maybeMeta(PIString & fc) {
bool PICodeParser::macroCondition(const PIString & mif, PIString mifcond) {
//piCout << "macroCondition" << mif << mifcond;
if (mif == "ifdef") return isDefineExists(mifcond);
if (mif == "ifndef") return !isDefineExists(mifcond);
if (mif == "if" || mif == "elif") {
mifcond.removeAll(" ").removeAll("\t");
if (mif == PIStringAscii("ifdef")) return isDefineExists(mifcond);
if (mif == PIStringAscii("ifndef")) return !isDefineExists(mifcond);
if (mif == PIStringAscii("if") || mif == PIStringAscii("elif")) {
mifcond.removeAll(' ').removeAll('\t');
return procMacrosCond(mifcond) > 0.;
}
return false;
@@ -778,7 +804,7 @@ double PICodeParser::procMacrosCond(PIString fc) {
int oper = 0, ps = -1;
char cc, nc;
PIString ce;
fc.removeAll("defined");
fc.removeAll(PIStringAscii("defined"));
//piCout << "procMacrosCond" << fc;
while (!fc.isEmpty()) {
cc = fc[0].toAscii();
@@ -833,17 +859,17 @@ double PICodeParser::defineValue(const PIString & dn) {
void PICodeParser::replaceMeta(PIString & dn) {
tmp_meta.clear();
if (dn.isEmpty()) return;
int s = dn.find("PIMETA");
int s = dn.find(PIStringAscii("PIMETA"));
while (s >= 0) {
int ms = 0, ml = 0;
ms = dn.findRange('(', ')', '\\', s + 6, &ml);
if (ms < 0) return;
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);
//piCout << "FOUND META \"" << meta << "\"";
//piCout << "FOUND META \"" << meta << '\"';
tmp_meta[rm] = parseMeta(meta);
s = dn.find("PIMETA");
s = dn.find(PIStringAscii("PIMETA"));
}
}
@@ -857,7 +883,7 @@ PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) {
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);
if (dind < 0 && find < 0) {if (end) *end = -1; return true;}
if (dind < 0 || find < dind) {if (end) *end = find; return true;}
@@ -869,17 +895,17 @@ bool PICodeParser::isDeclaration(const PIString & fc, int start, int * end) {
bool PICodeParser::isMainFile(const PIString & fc) {
int si = 0;
while (si >= 0) {
int csi = fc.find(" main", si);
if (csi < 0) csi = fc.find("\tmain", si);
if (csi < 0) csi = fc.find("\nmain", si);
int csi = fc.find(PIStringAscii(" main"), si);
if (csi < 0) csi = fc.find(PIStringAscii("\tmain"), si);
if (csi < 0) csi = fc.find(PIStringAscii("\nmain"), si);
if (csi < 0) return false;
si = csi;
int fi = fc.find("(", si + 5);
int fi = fc.find('(', si + 5);
if (fi < 0) return false;
if (fi - si < 10) {
PIString ms(fc.mid(si, fi - si + 1));
ms.removeAll(" ").removeAll("\t").removeAll("\n");
if (ms == "main(") return true;
ms.removeAll(' ').removeAll('\t').removeAll('\n');
if (ms == PIStringAscii("main(")) return true;
}
si += 5;
}
@@ -893,17 +919,17 @@ PIString PICodeParser::procMacros(PIString fc) {
bool grab = false, skip = false, cond_ok = false;
PIString pfc, nfc, line, mif, mifcond;
//piCout << "procMacros\n<******" << fc << "\n******>";
fc += "\n";
fc += '\n';
while (!fc.isEmpty()) {
line = fc.takeLine().trimmed();
if (line.left(1) == "#") {
if (line.left(1) == PIChar('#')) {
mifcond = line.mid(1);
mif = mifcond.takeCWord();
//piCout << mif;
//piCout << "mif mifcond" << mif << mifcond << ifcnt;
if (skip || grab) {
if (mif.left(2) == "if") ifcnt++;
if (mif.left(5) == "endif") {
if (mif.left(2) == PIStringAscii("if")) ifcnt++;
if (mif.left(5) == PIStringAscii("endif")) {
if (ifcnt > 0) ifcnt--;
else {
//piCout << "main endif" << skip << grab;
@@ -912,7 +938,7 @@ PIString PICodeParser::procMacros(PIString fc) {
continue;
}
}
if (mif.left(4) == "elif" && ifcnt == 0) {
if (mif.left(4) == PIStringAscii("elif") && ifcnt == 0) {
//piCout << "main elif" << skip << grab << cond_ok;
if (cond_ok) {
if (grab) {
@@ -930,17 +956,17 @@ PIString PICodeParser::procMacros(PIString fc) {
}
continue;
}
if (mif.left(4) == "else" && ifcnt == 0) {
if (mif.left(4) == PIStringAscii("else") && ifcnt == 0) {
//piCout << "main else" << skip << grab;
if (grab) pfc << procMacros(nfc);
if (skip && !cond_ok) {skip = false; grab = true;}
else {skip = true; grab = false;}
continue;
}
if (grab) nfc << line << "\n";
if (grab) nfc << line << '\n';
continue;
}
if (mif.left(2) == "if") {
if (mif.left(2) == PIStringAscii("if")) {
//piCout << "main if";
skip = grab = cond_ok = false;
if (macroCondition(mif, mifcond.trimmed())) grab = cond_ok = true;
@@ -948,12 +974,12 @@ PIString PICodeParser::procMacros(PIString fc) {
ifcnt = 0;
nfc.clear();
} else {
/*if (!*/parseDirective(line.cutLeft(1).trim())/*)*/
;//return false; /// WARNING: now skip errors
parseDirective(line.cutLeft(1).trim());
//return false; /// WARNING: now skip errors
}
} else {
if (grab) nfc << line << "\n";
else if (!skip) pfc << line << "\n";
if (grab) nfc << line << '\n';
else if (!skip) pfc << line << '\n';
}
}
return pfc;
@@ -964,31 +990,30 @@ bool PICodeParser::parseDirective(PIString d) {
if (d.isEmpty()) return true;
PIString dname = d.takeCWord();
//piCout << "parseDirective" << d;
if (dname == "include") {
d.replaceAll("<", "\"").replaceAll(">", "\"");
PIString cf = cur_file, ifc = d.takeRange("\"", "\"");
if (dname == PIStringAscii("include")) {
d.replaceAll('<', '\"').replaceAll('>', '\"');
PIString cf = cur_file, ifc = d.takeRange('\"', '\"');
if (with_includes) {
bool ret = parseFileInternal(ifc, with_includes);
cur_file = cf;
return ret;
}
}
if (dname == "define") {
if (dname == PIStringAscii("define")) {
PIString mname = d.takeCWord();
//piCout << mname;
if (mname == "PIMETA") return true;
if (d.left(1) == "(") { // macro
PIStringList args = d.takeRange("(", ")").split(",").trim();
if (mname == PIStringAscii("PIMETA")) return true;
if (d.left(1) == PIChar('(')) { // macro
PIStringList args = d.takeRange('(', ')').split(',').trim();
macros << Macro(mname, d.trim(), args);
} else { // define
d.trim();
//if (mname == d) d.clear();
defines << Define(mname, d);
evaluator.setVariable(mname, complexd_1);
}
return true;
}
if (dname == "undef") {
if (dname == PIStringAscii("undef")) {
PIString mname = d.takeCWord();
for (int i = 0; i < defines.size_s(); ++i)
if (defines[i].first == mname) {defines.remove(i); --i;}

View File

@@ -33,8 +33,8 @@ class PIP_EXPORT PICodeParser {
public:
PICodeParser();
enum PIP_EXPORT Visibility {Global, Public, Protected, Private};
enum PIP_EXPORT Attribute {
enum Visibility {Global, Public, Protected, Private};
enum Attribute {
NoAttributes = 0x0,
Const = 0x01,
Static = 0x02,
@@ -170,7 +170,6 @@ private:
int macros_iter, anon_num;
bool with_includes;
PIEvaluator evaluator;
//PIVector<Entity * > tree;
PISet<PIString> proc_files;
PIString cur_file, main_file;
PIStringList includes;

View File

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

View File

@@ -0,0 +1,27 @@
/*
PIP - Platform Independent Primitives
Module includes
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 PICONSOLEMODULE_H
#define PICONSOLEMODULE_H
#include "pikbdlistener.h"
#include "piscreen.h"
#include "piscreentiles.h"
#endif // PICONSOLEMODULE_H

View File

@@ -267,10 +267,8 @@ void PIKbdListener::readKeyboard() {
case MOUSE_EVENT: {
MOUSE_EVENT_RECORD mer = ir.Event.MouseEvent;
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
//height = PRIVATE->sbi.srWindow.Bottom - ;
me.modifiers = getModifiers(mer.dwControlKeyState);
MouseButtons mb = getButtons(mer.dwButtonState);
//me.action = getButtons(mer.dwButtonState);
if (mer.dwEventFlags & MOUSE_WHEELED) {
memcpy((void*)(&we), (const void*)(&me), sizeof(me));
we.action = MouseWheel;
@@ -317,16 +315,6 @@ void PIKbdListener::readKeyboard() {
piMSleep(10);
return;
}
/*if (lc == 0) {
ReadConsole(hIn, &rc, 1, &(PRIVATE->ret), 0);
//cout << "read console" << endl;
lc = char(rc);
}*/
/*if (PRIVATE->ret < 0 || PRIVATE->ret > 3) return;
lc = char(((uchar * )&rc)[PRIVATE->ret - 1]);
for (int i = 0; i < PRIVATE->ret; ++i)
cout << std::hex << int(((uchar * )&rc)[i]) << ' ';
cout << endl << std::hex << rc << endl;*/
#else
tcsetattr(0, TCSANOW, &PRIVATE->tterm);
PRIVATE->ret = read(0, rc, 8);

View File

@@ -77,7 +77,7 @@ public:
typedef PIFlags<KeyModifier> KeyModifiers;
//! 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;}
//! Pressed key. It can be simple \b char or special key (see PIKbdListener::SpecialKey)
@@ -106,7 +106,7 @@ public:
typedef PIFlags<MouseButton> MouseButtons;
//! 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;}
//! Event X coordinate in view-space, from 0
@@ -126,18 +126,14 @@ public:
};
//! This struct contains information about mouse wheel action
struct WheelEvent: public MouseEvent {
struct PIP_EXPORT WheelEvent: public MouseEvent {
WheelEvent(): MouseEvent() {direction = false;}
//! Wheel direction, /b true - up, /b fasle - down
bool direction;
};
#ifdef PIP_CXX11_SUPPORT
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"
explicit PIKbdListener(KBFunc slot = 0, void * data = 0, bool startNow = true);
@@ -154,10 +150,8 @@ public:
//! Set external function to "slot"
void setSlot(KBFunc slot) {ret_func = slot;}
#ifdef PIP_CXX11_SUPPORT
//! Set external function to "slot"
void setSlot(std::function<void(KeyEvent)> slot) {ret_func = [slot](KeyEvent e, void *){slot(e);};}
#endif
//! Returns if exit key if awaiting
bool exitCaptured() const {return exit_enabled;}
@@ -213,7 +207,7 @@ private:
void end();
#ifndef WINDOWS
struct EscSeq {
struct PIP_EXPORT EscSeq {
const char * seq;
int key;
int mod;
@@ -234,7 +228,7 @@ private:
static const EscSeq esc_seq[];
#endif
PRIVATE_DECLARATION
PRIVATE_DECLARATION(PIP_EXPORT)
KBFunc ret_func;
int exit_key;
bool exit_enabled, is_active;

View File

@@ -23,11 +23,12 @@
#ifndef PISCREEN_H
#define PISCREEN_H
#include "pip_console_export.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;
@@ -100,7 +101,7 @@ public:
//! \}
private:
class SystemConsole {
class PIP_CONSOLE_EXPORT SystemConsole {
public:
SystemConsole();
~SystemConsole();
@@ -124,7 +125,7 @@ private:
#else
PIString formatString(const PIScreenTypes::Cell & c);
#endif
PRIVATE_DECLARATION
PRIVATE_DECLARATION(PIP_CONSOLE_EXPORT)
int width, height, pwidth, pheight;
int mouse_x, mouse_y;
PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells;

View File

@@ -25,16 +25,17 @@
#ifndef PISCREENCONSOLE_H
#define PISCREENCONSOLE_H
#include "pip_console_export.h"
#include "piscreentiles.h"
/// NOTE: incomplete class
/// TODO: write TileVars
class PIP_EXPORT TileVars: public PIScreenTile {
class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile {
public:
TileVars(const PIString & n = PIString());
protected:
struct Variable {
struct PIP_CONSOLE_EXPORT Variable {
Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = PIScreenTypes::CellFormat(); ptr = 0;}
bool isEmpty() const {return (ptr == 0);}
PIString name;
@@ -68,7 +69,7 @@ protected:
class PIP_EXPORT PIScreenConsoleTile : public PIScreenTile
class PIP_CONSOLE_EXPORT PIScreenConsoleTile : public PIScreenTile
{
public:
PIScreenConsoleTile();

View File

@@ -23,10 +23,11 @@
#ifndef PISCREENDRAWER_H
#define PISCREENDRAWER_H
#include "pip_console_export.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);

View File

@@ -23,12 +23,13 @@
#ifndef PISCREENTILE_H
#define PISCREENTILE_H
#include "pip_console_export.h"
#include "piscreentypes.h"
#include "pikbdlistener.h"
class PIScreenDrawer;
class PIP_EXPORT PIScreenTile: public PIObject {
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
friend class PIScreen;
PIOBJECT_SUBCLASS(PIScreenTile, PIObject)
public:

View File

@@ -23,10 +23,11 @@
#ifndef PISCREENTILES_H
#define PISCREENTILES_H
#include "pip_console_export.h"
#include "piscreentile.h"
class PIP_EXPORT TileSimple: public PIScreenTile {
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile)
public:
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
@@ -43,7 +44,7 @@ protected:
class TileList;
class PIP_EXPORT TileScrollBar: public PIScreenTile {
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile)
friend class TileList;
public:
@@ -66,7 +67,7 @@ protected:
};
class PIP_EXPORT TileList: public PIScreenTile {
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
PIOBJECT_SUBCLASS(TileList, PIScreenTile)
public:
TileList(const PIString & n = PIString());
@@ -98,7 +99,7 @@ protected:
};
class PIP_EXPORT TileButton: public PIScreenTile {
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButton, PIScreenTile)
public:
TileButton(const PIString & n = PIString());
@@ -118,7 +119,7 @@ protected:
class PIP_EXPORT TileButtons: public PIScreenTile {
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile)
public:
TileButtons(const PIString & n = PIString());
@@ -143,7 +144,7 @@ protected:
};
class PIP_EXPORT TileCheck: public PIScreenTile {
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile)
public:
TileCheck(const PIString & n = PIString());
@@ -162,7 +163,7 @@ protected:
};
class PIP_EXPORT TileProgress: public PIScreenTile {
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile)
public:
TileProgress(const PIString & n = PIString());
@@ -178,7 +179,7 @@ protected:
};
class PIP_EXPORT TilePICout: public TileList {
class PIP_CONSOLE_EXPORT TilePICout: public TileList {
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile)
public:
TilePICout(const PIString & n = PIString());
@@ -191,14 +192,11 @@ protected:
};
class PIP_EXPORT TileInput: public PIScreenTile {
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
PIOBJECT_SUBCLASS(TileInput, PIScreenTile)
public:
TileInput(const PIString & n = PIString());
virtual ~TileInput() {}
/*enum EventType {
EditFinished
};*/
PIScreenTypes::CellFormat format;
PIString text;
int max_length;
@@ -212,34 +210,5 @@ protected:
PITimeMeasurer tm_blink;
};
/*
class PIP_EXPORT TileTabs: public PIScreenTile {
PIOBJECT_SUBCLASS(TileTabs, PIScreenTile)
public:
TileTabs(const PIString & n = PIString());
enum EventType {
TabChanged
};
struct Tab {
Tab(const PIString & l = PIString(), int k = 0, PIScreenTile * t = 0) {
label = l;
key = k;
tile = t;
}
PIString label;
int key;
PIScreenTile * tile;
};
PIScreenTypes::CellFormat format_tab;
PIScreenTypes::CellFormat format_tab_selected;
PIDeque<Tab> tabs;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
void selectTab(int index);
int cur;
};
*/
#endif // PISCREENTILES_H

View File

@@ -23,6 +23,7 @@
#ifndef PISCREENTYPES_H
#define PISCREENTYPES_H
#include "pip_console_export.h"
#include "pivariant.h"
class PIScreenTile;
@@ -30,7 +31,7 @@ class PIScreenTile;
namespace PIScreenTypes {
//! Color for chars or background
enum PIP_EXPORT Color {
enum Color {
Default /** Default */,
Black /** Black */,
Red /** Red */,
@@ -44,7 +45,7 @@ namespace PIScreenTypes {
};
//! Flags for chars
enum PIP_EXPORT CharFlag {
enum CharFlag {
Bold /** Bold or bright */ = 0x1,
Blink /** Blink text */ = 0x2,
Underline /** Underline text */ = 0x4,
@@ -52,14 +53,14 @@ namespace PIScreenTypes {
};
//! Alignment
enum PIP_EXPORT Alignment {
enum Alignment {
Left /** Left */ ,
Center /** Center */ ,
Right /** Right */
};
//! Size policy
enum PIP_EXPORT SizePolicy {
enum SizePolicy {
Fixed /** Fixed size */ ,
Preferred /** Preferred size */ ,
Expanding /** Maximum available size */ ,
@@ -67,21 +68,13 @@ namespace PIScreenTypes {
};
//! Direction
enum PIP_EXPORT Direction {
enum Direction {
Horizontal /** Horizontal */ ,
Vertical /** Vertical */
};
//! Position
enum PIP_EXPORT Position {
//Left /** Left */ ,
//Right /** Right */ ,
//Top /** Top */ ,
//Bottom /** Bottom */
};
//! Focus flags
enum PIP_EXPORT FocusFlag {
enum FocusFlag {
CanHasFocus /** Tile can has focus */ = 0x1,
NextByTab /** Focus passed to next tile by tab key */ = 0x2,
NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4,
@@ -95,7 +88,7 @@ namespace PIScreenTypes {
typedef PIFlags<CharFlag> CharFlags;
typedef PIFlags<FocusFlag> FocusFlags;
union PIP_EXPORT CellFormat {
union PIP_CONSOLE_EXPORT CellFormat {
CellFormat(ushort f = 0) {raw_format = f;}
CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) {
color_char = col_char;
@@ -112,7 +105,7 @@ namespace PIScreenTypes {
bool operator !=(const CellFormat & c) const {return raw_format != c.raw_format;}
};
struct PIP_EXPORT Cell {
struct PIP_CONSOLE_EXPORT Cell {
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {symbol = c; format = f;}
CellFormat format;
PIChar symbol;
@@ -128,13 +121,13 @@ namespace PIScreenTypes {
}
};
struct PIP_EXPORT TileEvent {
struct PIP_CONSOLE_EXPORT TileEvent {
TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
int type;
PIVariant data;
};
class PIScreenBase {
class PIP_CONSOLE_EXPORT PIScreenBase {
public:
PIScreenBase() {}
virtual ~PIScreenBase() {}
@@ -150,8 +143,5 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v)
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
//__PICONTAINERS_SIMPLE_TYPE__(PIScreenTypes::Cell)
//__PIBYTEARRAY_SIMPLE_TYPE__(PIScreenTypes::Cell)
#endif // PISCREENTYPES_H

View File

@@ -23,11 +23,12 @@
#ifndef PITERMINAL_H
#define PITERMINAL_H
#include "pip_console_export.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:
@@ -63,7 +64,7 @@ private:
int termType(const PIString & t);
#endif
PRIVATE_DECLARATION
PRIVATE_DECLARATION(PIP_CONSOLE_EXPORT)
int dsize_x, dsize_y;
int size_x, size_y, cursor_x, cursor_y;
bool cursor_blink, cursor_visible;

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

@@ -0,0 +1,31 @@
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICONTAINERSMODULE_H
#define PICONTAINERSMODULE_H
#include "pivector.h"
#include "pideque.h"
#include "pimap.h"
#include "piqueue.h"
#include "piset.h"
#include "pistack.h"
#include "pivector2d.h"
#endif // PICONTAINERSMODULE_H

View File

@@ -6,7 +6,7 @@
/*
PIP - Platform Independent Primitives
Dynamic array of any type
Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by
@@ -28,14 +28,10 @@
#include "picontainers.h"
#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN)
template <typename T>
class PIDeque {
public:
inline PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
//piCout << "PIDeque";
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
}
inline PIDeque(const PIDeque<T> & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
@@ -52,8 +48,10 @@ public:
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
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() {
//piCout << "~PIDeque";
PIINTROSPECTION_CONTAINER_DELETE(T)
PIINTROSPECTION_CONTAINER_FREE(T, (pid_rsize))
deleteT(pid_data + pid_start, pid_size);
@@ -69,6 +67,11 @@ public:
return *this;
}
inline PIDeque<T> & operator =(PIDeque<T> && other) {
swap(other);
return *this;
}
typedef T value_type;
class iterator {
@@ -97,7 +100,6 @@ public:
size_t pos;
public:
inline const_iterator(): parent(0), pos(0) {}
//inline T & operator *() {return (*parent)[pos];}
inline const T & operator *() const {return (*parent)[pos];}
inline void operator ++() {++pos;}
inline void operator ++(int) {++pos;}
@@ -133,7 +135,6 @@ public:
size_t pos;
public:
inline const_reverse_iterator(): parent(0), pos(0) {}
//inline T & operator *() {return (*parent)[pos];}
inline const T & operator *() const {return (*parent)[pos];}
inline void operator ++() {--pos;}
inline void operator ++(int) {--pos;}
@@ -261,6 +262,23 @@ public:
elementNew(pid_data + pid_start + index, v);
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) {
if (other.isEmpty()) return *this;
assert(&other != this);
@@ -341,7 +359,14 @@ public:
elementNew(pid_data + pid_start + pid_size - 1, v);
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(T && v) {return push_back(std::move(v));}
inline PIDeque<T> & append(const PIDeque<T> & t) {
assert(&t != this);
size_t ps = pid_size;
@@ -350,10 +375,13 @@ public:
return *this;
}
inline PIDeque<T> & operator <<(const T & v) {return push_back(v);}
inline PIDeque<T> & operator <<(T && v) {return push_back(std::move(v));}
inline PIDeque<T> & operator <<(const PIDeque<T> & t) {return append(t);}
inline PIDeque<T> & push_front(const T & v) {insert(0, v); return *this;}
inline PIDeque<T> & push_front(T && v) {insert(0, std::move(v)); return *this;}
inline PIDeque<T> & prepend(const T & v) {return push_front(v);}
inline PIDeque<T> & prepend(T && v) {return push_front(std::move(v));}
inline PIDeque<T> & 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;}
@@ -369,7 +397,6 @@ public:
return ret;
}
#ifdef PIP_CXX11_SUPPORT
const PIDeque<T> & forEach(std::function<void(const T &)> f) const {
for (uint i = 0; i < pid_size; ++i)
f(pid_data[i + pid_start]);
@@ -393,7 +420,6 @@ public:
ret << f(pid_data[i + pid_start]);
return ret;
}
#endif
private:
inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;}
@@ -419,6 +445,7 @@ private:
}
}
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 dealloc() {
if ((uchar*)pid_data != 0) free((uchar*)pid_data);
@@ -492,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>::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, T && from) {(*to) = std::move(from);} \
template<> inline void PIDeque<T>::elementDelete(T &) {;} \
template<> inline PIDeque<T> & PIDeque<T>::_resizeRaw(size_t new_size) { \
if (new_size > pid_size) { \
@@ -507,33 +535,6 @@ private:
template<> inline PIDeque<T> & PIDeque<T>::assign(size_t new_size, const T & f) {_resizeRaw(new_size); return fill(f);}
#else
template<typename Type, typename Allocator = std::allocator<Type> >
class PIP_EXPORT PIDeque: public deque<Type, Allocator> {
typedef PIDeque<Type, Allocator> _CDeque;
typedef deque<Type, Allocator> _stlc;
public:
PIDeque() {piMonitor.containers++;}
PIDeque(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);}
PIDeque(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);}
PIDeque(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);}
PIDeque(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);}
~PIDeque() {piMonitor.containers--;}
int size_s() const {return static_cast<int>(_stlc::size());}
bool isEmpty() const {return _stlc::empty();}
bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;}
int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;}
_CDeque & operator <<(const Type & t) {_CDeque::push_back(t); return *this;}
PIDeque<Type> toVector() {PIDeque<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
};
#define __PIDEQUE_SIMPLE_FUNCTIONS__(T)
#endif
__PIDEQUE_SIMPLE_TYPE__(bool)
__PIDEQUE_SIMPLE_TYPE__(char)
__PIDEQUE_SIMPLE_TYPE__(uchar)
@@ -570,5 +571,7 @@ inline PICout operator <<(PICout s, const PIDeque<T> & v) {
return s;
}
template<typename T> inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {f.swap(s);}
#endif // PIDEQUE_H

View File

@@ -33,8 +33,6 @@ __PIDEQUE_SIMPLE_TYPE__(T)\
__PIVECTOR_SIMPLE_TYPE__(T)
#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN)
template<class T>
void piQuickSort(T * a, ssize_t N) {
if (N < 1) return;
@@ -59,7 +57,7 @@ void piQuickSort(T * a, ssize_t N) {
if (i <= j) {
if (i != j) {
//piCout << "swap" << i << j << a[i] << a[j];
piSwapBinary<T>(a[i], a[j]);
piSwap<T>(a[i], a[j]);
}
i++; j--;
}
@@ -69,13 +67,20 @@ void piQuickSort(T * a, ssize_t N) {
}
}
template <typename Key, typename T>
class PIMapIterator;
template <typename Key, typename T>
class PIMap {
template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIMap<Key1, T1> & v);
template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIMap<Key1, T1> & v);
template <typename Key1, typename T1> friend class PIMapIterator;
public:
PIMap() {;}
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() {;}
PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
@@ -86,6 +91,11 @@ public:
return *this;
}
PIMap<Key, T> & operator =(PIMap<Key, T> && other) {
swap(other);
return *this;
}
typedef T mapped_type;
typedef Key key_type;
typedef PIPair<Key, T> value_type;
@@ -179,6 +189,9 @@ public:
const_reverse_iterator constRbegin() const {return const_reverse_iterator(this, size() - 1);}
const_reverse_iterator constRend() const {return const_reverse_iterator(this, -1);}
PIMapIterator<Key, T> makeIterator() const {return PIMapIterator<Key, T>(*this);}
PIMapIterator<Key, T> makeReverseIterator() const {return PIMapIterator<Key, T>(*this, true);}
size_t size() const {return pim_content.size();}
int size_s() const {return pim_content.size_s();}
size_t length() const {return pim_content.size();}
@@ -197,14 +210,10 @@ public:
const T at(const Key & key) const {return (*this)[key];}
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
assert(&other != this);
if (other.isEmpty()) return *this;
if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;}
/*pim_content << other.pim_content;
size_t si = pim_index.size();
for (int i = 0; i < other.pim_index.size_s(); ++i)
pim_index << MapIndex(other.pim_index[i].key, other.pim_index[i].index + si);
_sort();*/
for (int i = 0; i < other.pim_index.size_s(); ++i)
insert(other.pim_index[i].key, other.pim_content[other.pim_index[i].index]);
return *this;
@@ -213,23 +222,20 @@ public:
bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content && pim_index == t.pim_index);}
bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content || pim_index != t.pim_index);}
bool contains(const Key & key) const {bool f(false); _find(key, f); return f;}
//int etries(const T & v) const {int ec = 0; for (size_t i = 0; i < pim_size; ++i) if (v == pim_data[i]) ++ec; return ec;}
PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size); pim_index.reserve(new_size); return *this;}
//PIMap<Key, T> & removeAll(const T & v) {for (llong i = 0; i < pim_size; ++i) if (pim_data[i] == v) {remove(i); --i;} return *this;}
PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;}
PIMap<Key, T> & remove(const Key & key) {return removeOne(key);}
PIMap<Key, T> & erase(const Key & key) {return removeOne(key);}
PIMap<Key, T> & clear() {pim_content.clear(); pim_index.clear(); return *this;}
void swap(PIMap<Key, T> & other) {
piSwapBinary<PIVector<T> >(pim_content, other.pim_content);
piSwapBinary<PIDeque<MapIndex> >(pim_index, other.pim_index);
pim_content.swap(other.pim_content);
pim_index.swap(other.pim_index);
}
PIMap<Key, T> & insert(const Key & key, const T & value) {
//MapIndex * i = _find(key);
bool f(false);
ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
@@ -238,11 +244,21 @@ public:
} else {
pim_content.push_back(value);
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
//_sort();
}
return *this;
}
//const T value(const Key & key, const T & default_ = T()) const {MapIndex * i = _find(key); if (i == 0) return default_; return pim_content[i->index];}
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];}
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_;}
@@ -288,12 +304,6 @@ protected:
}
void _sort() {piQuickSort<MapIndex>(pim_index.data(), pim_index.size_s() - 1);}
ssize_t _find(const Key & k, bool & found) const {
/*for (size_t i = 0; i < pim_index.size(); ++i)
if (pim_index[i].key == k) {
return (MapIndex * )&(pim_index[i]);
}
return 0;*/
//piCout << "find for" << k << pim_index.size_s();
if (pim_index.isEmpty()) {
found = false;
return 0;
@@ -309,7 +319,7 @@ protected:
pim_index[i].index = ci;
break;
}
piSwapBinary<T>(pim_content[ci], pim_content.back());
piSwap<T>(pim_content[ci], pim_content.back());
pim_content.resize(pim_index.size());
}
const value_type _pair(ssize_t index) const {
@@ -324,129 +334,43 @@ protected:
PIVector<T> pim_content;
PIDeque<MapIndex> pim_index;
};
//template <typename Key, typename T> bool operator <(const typename PIMap<Key, T>::MapIndex & f, const typename PIMap<Key, T>::MapIndex & s) {return f.key < s.key;}
//template <typename Key, typename T> bool operator >(const typename PIMap<Key, T>::MapIndex & f, const typename PIMap<Key, T>::MapIndex & s) {return f.key > s.key;}
/*#define __PIMAP_SIMPLE_FUNCTIONS__(T)
template<> inline PIMap<Key, T>::~PIMap() {dealloc(); _reset();} \
template<> inline PIMap<Key, T> & PIMap<Key, T>::push_back(const T & v) {alloc(pim_size + 1); pim_data[pim_size - 1] = v; return *this;} \
template<> inline PIMap<Key, T> & PIMap<Key, T>::fill(const T & f) { \
for (size_t i = 0; i < pim_size; ++i) \
pim_data[i] = f; \
return *this; \
} \
template<> inline PIMap<Key, T> & PIMap<Key, T>::resize(size_t new_size, const T & f) { \
if (new_size < pim_size) \
pim_size = new_size; \
if (new_size > pim_size) { \
size_t os = pim_size; \
alloc(new_size); \
for (size_t i = os; i < new_size; ++i) pim_data[i] = f; \
} \
return *this; \
} \
template<> inline PIMap<Key, T> & PIMap<Key, T>::insert(size_t index, const T & v) { \
alloc(pim_size + 1); \
if (index < pim_size - 1) { \
size_t os = pim_size - index - 1; \
memmove(&(pim_data[index + 1]), &(pim_data[index]), os * sizeof(T)); \
} \
pim_data[index] = v; \
return *this; \
} \
template<> inline PIMap<Key, T> & PIMap<Key, T>::remove(size_t index, size_t count) { \
if (index + count >= pim_size) { \
resize(index); \
return *this; \
} \
size_t os = pim_size - index - count; \
memmove(&(pim_data[index]), &(pim_data[index + count]), os * sizeof(T)); \
pim_size -= count; \
return *this; \
}
__PIMAP_SIMPLE_FUNCTIONS__(char)
__PIMAP_SIMPLE_FUNCTIONS__(uchar)
__PIMAP_SIMPLE_FUNCTIONS__(short)
__PIMAP_SIMPLE_FUNCTIONS__(ushort)
__PIMAP_SIMPLE_FUNCTIONS__(int)
__PIMAP_SIMPLE_FUNCTIONS__(uint)
__PIMAP_SIMPLE_FUNCTIONS__(long)
__PIMAP_SIMPLE_FUNCTIONS__(ulong)
__PIMAP_SIMPLE_FUNCTIONS__(llong)
__PIMAP_SIMPLE_FUNCTIONS__(ullong)
__PIMAP_SIMPLE_FUNCTIONS__(float)
__PIMAP_SIMPLE_FUNCTIONS__(double)
__PIMAP_SIMPLE_FUNCTIONS__(ldouble)*/
#else
template<typename Key, typename Type>
class PIP_EXPORT PIMap: public map<Key, Type> {
typedef PIMap<Key, Type> _CMap;
typedef map<Key, Type> _stlc;
typedef std::pair<Key, Type> _stlpair;
template <typename Key, typename T>
class PIMapIterator {
typedef PIMap<Key, T> MapType;
public:
PIMap() {;}
PIMap(const Key & key_, const Type & value_) {insert(key_, value_);}
bool isEmpty() const {return _stlc::empty();}
bool contains(const Key & key_) const {return _stlc::count(key_) > 0;}
int size_s() const {return static_cast<int>(_stlc::size());}
_CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;}
_CMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;}
Key key(Type value_, const Key & default_ = Key()) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return default_;}
PIVector<Key> keys() const {
PIVector<Key> ret;
for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++)
ret << i->first;
return ret;
PIMapIterator(const PIMap<Key, T> & map, bool reverse = false): m(map), pos(-1), rev(reverse) {
if (rev) pos = m.size_s();
}
Type & at(const Key & key_) {return _stlc::find(key_)->second;}
Type value(const Key & key_) const {typename _stlc::const_iterator it = _stlc::find(key_); if (it != _stlc::end()) return it->second; return Type();}
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;
};
template<typename Key, typename Type>
class PIP_EXPORT PIMultiMap: public multimap<Key, Type> {
typedef PIMultiMap<Key, Type> _CMultiMap;
typedef multimap<Key, Type> _stlc;
typedef std::pair<Key, Type> _stlpair;
public:
PIMultiMap() {;}
PIMultiMap(const Key & key_, const Type & value_) {insert(key_, value_);}
_CMultiMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;}
_CMultiMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;}
bool isEmpty() const {return _stlc::empty();}
bool contains(const Key & key_) const {return _stlc::count(key_) > 0;}
Key key(Type value_, const Key & default_ = Key()) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return default_;}
PIVector<Key> keys(Type value_) const {
PIVector<Key> ret;
for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++)
if (i->second == value_)
ret << i->first;
return ret;
}
Type & value(const Key & key_) {typename _stlc::iterator i = _stlc::find(key_); if (i == _stlc::end()) return Type(); return i->second;}
Type value(const Key & key_) const {typename _stlc::const_iterator i = _stlc::find(key_); if (i == _stlc::end()) return Type(); return i->second;}
PIVector<Type> values(const Key & key_) const {
std::pair<typename _stlc::const_iterator, typename _stlc::const_iterator> range = _stlc::equal_range(key_);
PIVector<Type> ret;
for (typename _stlc::const_iterator i = range.first; i != range.second; ++i)
ret << i->second;
return ret;
}
Type & operator [](const Key & key_) {if (!contains(key_)) return _stlc::insert(_stlpair(key_, Type()))->second; return _stlc::find(key_)->second;}
Type operator [](const Key & key_) const {return _stlc::find(key_)->second;}
};
#define __PIMAP_SIMPLE_FUNCTIONS__(T)
#endif
#ifdef PIP_STD_IOSTREAM
template<typename Key, typename Type>
inline std::ostream & operator <<(std::ostream & s, const PIMap<Key, Type> & v) {
@@ -480,5 +404,7 @@ inline PICout operator <<(PICout s, const PIMap<Key, Type> & v) {
return s;
}
template<typename Key, typename Type> inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {f.swap(s);}
#endif // PIMAP_H

View File

@@ -30,7 +30,7 @@
class PICout;
template<typename Type0, typename Type1>
class PIP_EXPORT PIPair {
class PIPair {
public:
PIPair() {first = Type0(); second = Type1();}
PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;}

View File

@@ -0,0 +1,51 @@
/*! \file pideque.h
* \brief Queue container
*
* This file declare PIQueue
*/
/*
PIP - Platform Independent Primitives
Queue container
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 PIQUEUE_H
#define PIQUEUE_H
#include "pideque.h"
#include "pivector.h"
template<typename T>
class PIQueue: public PIDeque<T> {
public:
PIQueue() {}
virtual ~PIQueue() {}
PIDeque<T> & enqueue(const T & v) {PIDeque<T>::push_front(v); return *this;}
PIDeque<T> & enqueue(T && v) {PIDeque<T>::push_front(std::move(v)); return *this;}
T dequeue() {return PIDeque<T>::take_back();}
T & head() {return PIDeque<T>::back();}
const T & head() const {return PIDeque<T>::back();}
PIVector<T> toVector() {
PIVector<T> v;
v.reserve(PIDeque<T>::size());
for (uint i = 0; i < PIDeque<T>::size(); ++i)
v.push_back(PIDeque<T>::at(i));
return v;
}
};
#endif // PIQUEUE_H

View File

@@ -35,7 +35,7 @@
* has logarithmic complexity.
*/
template <typename T>
class PIP_EXPORT PISet: public PIMap<T, uchar> {
class PISet: public PIMap<T, uchar> {
typedef PIMap<T, uchar> _CSet;
public:
@@ -59,32 +59,23 @@ public:
//! Contructs set from vector of elements
PISet(const PIVector<T> & values) {
if (values.isEmpty()) return;
//_CSet::pim_content.resize(values.size_s());
//_CSet::pim_index.resize(values.size_s());
for (int i = 0; i < values.size_s(); ++i) {
//_CSet::pim_index[i].index = i;
//_CSet::pim_index[i].key = values[i];
_CSet::insert(values[i], 0);
}
//_CSet::_sort();
}
//! Contructs set from deque of elements
PISet(const PIDeque<T> & values) {
if (values.isEmpty()) return;
//_CSet::pim_content.resize(values.size_s());
//_CSet::pim_index.resize(values.size_s());
for (int i = 0; i < values.size_s(); ++i) {
//_CSet::pim_index[i].index = i;
//_CSet::pim_index[i].key = values[i];
_CSet::insert(values[i], 0);
}
//_CSet::_sort();
}
typedef T key_type;
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;}
//! Returns if element "t" exists in this set

View File

@@ -0,0 +1,49 @@
/*! \file pistack.h
* \brief Stack container
*
* This file declare PIStack
*/
/*
PIP - Platform Independent Primitives
Stack container
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 PISTACK_H
#define PISTACK_H
#include "pivector.h"
template<typename T>
class PIStack: public PIVector<T> {
public:
PIStack() {;}
virtual ~PIStack() {;}
PIVector<T> & push(const T & v) {PIVector<T>::push_back(v); return *this;}
PIVector<T> & push(T && v) {PIVector<T>::push_back(std::move(v)); return *this;}
T pop() {return PIVector<T>::take_back();}
T & top() {return PIVector<T>::back();}
const T & top() const {return PIVector<T>::back();}
PIVector<T> toVector() {
PIVector<T> v;
v.reserve(PIVector<T>::size());
for (uint i = 0; i < PIVector<T>::size(); ++i)
v.push_back(PIVector<T>::at(i));
return v;
}
};
#endif // PISTACK_H

View File

@@ -6,7 +6,7 @@
/*
PIP - Platform Independent Primitives
Dynamic array of any type
Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by
@@ -28,9 +28,6 @@
#include "picontainers.h"
#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN)
template <typename T>
class PIVector {
public:
@@ -51,6 +48,9 @@ public:
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(piv_size, f);
}
inline PIVector(PIVector<T> && other): piv_data(other.piv_data), piv_size(other.piv_size), piv_rsize(other.piv_rsize) {
other._reset();
}
inline virtual ~PIVector() {
PIINTROSPECTION_CONTAINER_DELETE(T)
PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize))
@@ -68,6 +68,11 @@ public:
return *this;
}
inline PIVector<T> & operator =(PIVector<T> && other) {
swap(other);
return *this;
}
typedef T value_type;
class iterator {
@@ -256,6 +261,16 @@ public:
elementNew(piv_data + index, v);
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) {
if (other.isEmpty()) return *this;
assert(&other != this);
@@ -323,7 +338,14 @@ public:
elementNew(piv_data + piv_size - 1, v);
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(T && v) {return push_back(std::move(v));}
inline PIVector<T> & append(const PIVector<T> & other) {
assert(&other != this);
size_t ps = piv_size;
@@ -332,10 +354,13 @@ public:
return *this;
}
inline PIVector<T> & operator <<(const T & v) {return push_back(v);}
inline PIVector<T> & operator <<(T && v) {return push_back(std::move(v));}
inline PIVector<T> & operator <<(const PIVector<T> & other) {return append(other);}
inline PIVector<T> & push_front(const T & v) {insert(0, v); return *this;}
inline PIVector<T> & push_front(T && v) {insert(0, std::move(v)); return *this;}
inline PIVector<T> & prepend(const T & v) {return push_front(v);}
inline PIVector<T> & prepend(T && v) {return push_front(std::move(v));}
inline PIVector<T> & pop_back() {
if (piv_size == 0)
@@ -361,7 +386,6 @@ public:
return ret;
}
#ifdef PIP_CXX11_SUPPORT
const PIVector<T> & forEach(std::function<void(const T &)> f) const {
for (uint i = 0; i < piv_size; ++i)
f(piv_data[i]);
@@ -385,7 +409,6 @@ public:
ret << f(piv_data[i]);
return ret;
}
#endif
private:
inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;}
@@ -410,6 +433,7 @@ private:
}
}
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 dealloc() {
if ((uchar*)piv_data != 0) free((uchar*)piv_data);
@@ -439,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>::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, T && from) {(*to) = std::move(from);} \
template<> inline void PIVector<T>::elementDelete(T &) {;} \
template<> inline PIVector<T> & PIVector<T>::_resizeRaw(size_t new_size) { \
if (new_size > piv_size) { \
@@ -454,93 +479,6 @@ private:
template<> inline PIVector<T> & PIVector<T>::assign(size_t new_size, const T & f) {_resizeRaw(new_size); return fill(f);}
#else
template<typename T, typename Allocator = std::allocator<T> >
class PIP_EXPORT PIVector: public vector<T, Allocator> {
typedef PIVector<T, Allocator> _CVector;
typedef vector<T, Allocator> _stlc;
public:
PIVector() {}
PIVector(uint size, const T & value = T()) {_stlc::resize(size, value);}
~PIVector() {}
const T & at(uint index) const {return (*this)[index];}
T & at(uint index) {return (*this)[index];}
const T * data(uint index = 0) const {return &(*this)[index];}
T * data(uint index = 0) {return &(*this)[index];}
#ifdef DOXYGEN
uint size() const;
#endif
int size_s() const {return static_cast<int>(_stlc::size());}
bool isEmpty() const {return _stlc::empty();}
bool has(const T & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;}
int etries(const T & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;}
typedef int (*CompareFunc)(const T * , const T * );
static int compare_func(const T * t0, const T * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);}
#ifdef DOXYGEN
void resize(uint size, const T & new_type = T());
PIVector<T, Allocator> & enlarge(uint size);
void clear();
PIVector<T, Allocator> & sort(CompareFunc compare = compare_func) {piqsort(&at(0), _stlc::size(), sizeof(T), (int(*)(const void * , const void * ))compare); return *this;}
PIVector<T, Allocator> & fill(const T & t) {_stlc::assign(_stlc::size(), t); return *this;}
T & back();
const T & back() const;
T & front();
const T & front() const;
PIVector<T, Allocator> & push_back(const T & t);
PIVector<T, Allocator> & push_front(const T & t) {_stlc::insert(_stlc::begin(), t); return *this;}
PIVector<T, Allocator> & pop_back();
PIVector<T, Allocator> & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
T take_back() {T t(_stlc::back()); _stlc::pop_back(); return t;}
T take_front() {T t(_stlc::front()); pop_front(); return t;}
PIVector<T, Allocator> & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
PIVector<T, Allocator> & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
PIVector<T, Allocator> & removeOne(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
PIVector<T, Allocator> & removeAll(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
PIVector<T, Allocator> & insert(uint pos, const T & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
PIVector<T, Allocator> & insert(uint pos, const PIVector<T, Allocator> & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;}
T & operator [](uint index);
const T & operator [](uint index) const;
PIVector<T, Allocator> & operator <<(const T & t) {_stlc::push_back(t); return *this;}
PIVector<T, Allocator> & operator <<(const PIVector<T, Allocator> & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
bool operator ==(const PIVector<T, Allocator> & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
bool operator !=(const PIVector<T, Allocator> & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;}
bool contains(const T & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
#else
_CVector & enlarge(int size_) {int ns = size_s() + size_; if (ns <= 0) _stlc::clear(); else _stlc::resize(ns); return *this;}
_CVector & sort(CompareFunc compare = compare_func) {piqsort(&at(0), _stlc::size(), sizeof(T), (int(*)(const void * , const void * ))compare); return *this;}
_CVector & fill(const T & t) {_stlc::assign(_stlc::size(), t); return *this;}
_CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
_CVector & push_front(const T & t) {_stlc::insert(_stlc::begin(), t); return *this;}
T take_front() {T t(_stlc::front()); pop_front(); return t;}
T take_back() {T t(_stlc::back()); _stlc::pop_back(); return t;}
_CVector & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
_CVector & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
_CVector & removeOne(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
_CVector & removeAll(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
_CVector & insert(uint pos, const T & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
_CVector & insert(uint pos, const _CVector & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;}
_CVector & operator <<(const T & t) {_stlc::push_back(t); return *this;}
_CVector & operator <<(const _CVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
bool operator !=(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;}
bool contains(const T & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
#endif
};
#define __PIVECTOR_SIMPLE_TYPE__(T)
#endif
__PIVECTOR_SIMPLE_TYPE__(bool)
__PIVECTOR_SIMPLE_TYPE__(char)
__PIVECTOR_SIMPLE_TYPE__(uchar)
@@ -577,5 +515,7 @@ inline PICout operator <<(PICout s, const PIVector<T> & v) {
return s;
}
template<typename T> inline void piSwap(PIVector<T> & f, PIVector<T> & s) {f.swap(s);}
#endif // PIVECTOR_H

View File

@@ -44,10 +44,10 @@ public:
cols_ = cols;
mat.resize(rows*cols, f);
}
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v) {
mat = v;
rows_ = rows;
cols_ = cols;
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v) : rows_(rows), cols_(cols), mat(v) {
mat.resize(rows*cols);
}
inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v) : rows_(rows), cols_(cols), mat(std::move(v)) {
mat.resize(rows*cols);
}
inline PIVector2D(const PIVector<PIVector<T> > & v) {
@@ -212,8 +212,31 @@ public:
return *this;
}
inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) {
mat.resize(rows*cols_, f);
rows_ = rows;
int cs = (cols - cols_);
if (cs < 0) {
for (size_t r=0; r<rows; ++r) {
mat.remove(r*cols_ + cols_, -cs);
}
}
mat.resize(rows*cols, f);
if (!mat.isEmpty()) {
if (cs > 0) {
for (size_t r=0; r<rows_; ++r) {
for (int i=0; i<cs; ++i)
mat.insert(r*cols + cols_, mat.take_back());
}
}
}
cols_ = cols;
return *this;
}
PIVector<PIVector<T> > toVectors() const {
PIVector<PIVector<T> > ret;
ret.reserve(rows_);
for(size_t i = 0; i < rows_; ++i)
ret << PIVector<T>(mat.data(i*cols_), cols_);
return ret;

View File

@@ -94,14 +94,9 @@
//! Macro is defined when PIP can use "rt" library for "PITimer::ThreadRT" timers implementation
# define PIP_TIMER_RT
//! Define this macro to use STL implementation of containers, else PIP implementation will be used
# define PIP_CONTAINERS_STL
#endif
#ifdef PIP_CXX11_SUPPORT
#include <functional>
#endif
#include <cstddef>
#ifdef WINDOWS
@@ -197,10 +192,10 @@
// Private data macros
#define PRIVATE_DECLARATION \
#define PRIVATE_DECLARATION(e) \
struct __Private__; \
friend struct __Private__; \
struct __PrivateInitializer__ { \
struct e __PrivateInitializer__ { \
__PrivateInitializer__(); \
__PrivateInitializer__(const __PrivateInitializer__ & o); \
~__PrivateInitializer__(); \
@@ -215,16 +210,16 @@
#define PRIVATE_DEFINITION_END(c) \
}; \
c::__PrivateInitializer__::__PrivateInitializer__() {p = new c::__Private__();} \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ & o) {/*if (p) delete p;*/ p = new c::__Private__();} \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ & ) {/*if (p) delete p;*/ p = new c::__Private__();} \
c::__PrivateInitializer__::~__PrivateInitializer__() {delete p; p = 0;} \
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & o) {if (p) delete p; p = new c::__Private__(); return *this;}
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 NO_COPY_CLASS(name) \
explicit name(const name & ); \
void operator =(const name & );
name(const name&) = delete; \
name& operator=(const name&) = delete;
#ifdef FREERTOS
# define PIP_MIN_MSLEEP 10.
@@ -260,7 +255,7 @@ typedef long double ldouble;
/*! \brief Templated function for swap two values
* \details Example:\n \snippet piincludes.cpp swap */
template<typename T> inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;}
template<typename T> inline void piSwap(T & f, T & s) {T t(std::move(f)); f = std::move(s); s = std::move(t);}
/*! \brief Templated function for swap two values without "="
* \details Example:\n \snippet piincludes.cpp swapBinary */
@@ -297,6 +292,14 @@ template<> inline void piSwapBinary(const void *& f, const void *& s) {
}
}
template<> inline void piSwap(double & f, double & s) {piSwapBinary<double>(f, s);}
template<> inline void piSwap(ldouble & f, ldouble & s) {piSwapBinary<ldouble>(f, s);}
#ifdef ARCH_BITS_32
template<> inline void piSwap(float & f, float & s) {piSwapBinary<float>(f, s);}
template<> inline void piSwap(llong & f, llong & s) {piSwapBinary<llong>(f, s);}
template<> inline void piSwap(ullong & f, ullong & s) {piSwapBinary<ullong>(f, s);}
#endif
/*! \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) {

View File

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

View File

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Byte array
Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by
@@ -18,7 +18,7 @@
*/
#include "pibytearray.h"
#include "pistring.h"
#include "pistringlist.h"
#include <iostream>
/*! \class PIByteArray

View File

@@ -56,6 +56,10 @@ public:
//! Constructs an empty byte array
PIByteArray() {;}
PIByteArray(const PIByteArray & o): PIDeque<uchar>(o) {}
PIByteArray(PIByteArray && o): PIDeque<uchar>(std::move(o)) {}
//! Constructs 0-filled byte array with size "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());}
PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;}
PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;}
static PIByteArray fromUserInput(PIString str);
static PIByteArray fromHex(PIString str);
static PIByteArray fromBase64(const PIByteArray & base64);
@@ -138,7 +146,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
#endif
//! \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));
@@ -212,7 +220,7 @@ inline PIByteArray & operator >>(PIByteArray & s, ldouble & v) {assert(s.size()
//! \relatesalso PIByteArray \brief Restore operator
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
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
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;}
@@ -301,7 +309,6 @@ inline bool operator !=(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.s
__PIBYTEARRAY_SIMPLE_TYPE__(bool)
__PIBYTEARRAY_SIMPLE_TYPE__(char)
//__PIBYTEARRAY_SIMPLE_TYPE__(uchar)
__PIBYTEARRAY_SIMPLE_TYPE__(short)
__PIBYTEARRAY_SIMPLE_TYPE__(ushort)
__PIBYTEARRAY_SIMPLE_TYPE__(int)
@@ -317,6 +324,7 @@ __PIBYTEARRAY_SIMPLE_TYPE__(PIChar)
template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);}
#endif // PIBYTEARRAY_H

View File

@@ -4,7 +4,7 @@
/*
PIP - Platform Independent Primitives
Unicode char
Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by
@@ -75,7 +75,6 @@ ushort charFromCodepage(const char * c, int size, const char * codepage, int * t
if (ret <= 0) return 0;
if (taken) *taken = ret;
return buffer;
//printf("request %d\n", sz);
# else
wchar_t wc(0);
mbtowc(0, 0, 0); // reset mbtowc
@@ -378,10 +377,7 @@ PICout operator <<(PICout s, const PIChar & v) {
} else
#endif
#ifdef WINDOWS
//if (PICout::isBufferActive())
s << v.toSystem();
//else
// s << v.toConsole1Byte();
#else
{
char tc[8];

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

@@ -4,7 +4,7 @@
/*
PIP - Platform Independent Primitives
Unicode char
Ivan Pelipenko peri4ko@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
it under the terms of the GNU Lesser General Public License as published by
@@ -25,9 +25,9 @@
#include "piincludes.h"
extern char * __syslocname__;
extern char * __sysoemname__;
extern char * __utf8name__;
extern PIP_EXPORT char * __syslocname__;
extern PIP_EXPORT char * __sysoemname__;
extern PIP_EXPORT char * __utf8name__;
class PIP_EXPORT PIChar
{
@@ -57,37 +57,14 @@ public:
//! Contructs symbol from no more than 4 bytes of string
PIChar(const char * c, int * bytes = 0);
//inline operator const int() {return static_cast<const int>(ch);}
//inline operator const char() {return toAscii();}
//! Copy operator
PIChar & operator =(const char v) {ch = v; return *this;}
/*inline PIChar & operator =(const short v) {ch = v; return *this;}
inline PIChar & operator =(const int v) {ch = v; return *this;}
inline PIChar & operator =(const uchar v) {ch = v; return *this;}
inline PIChar & operator =(const ushort v) {ch = v; return *this;}
inline PIChar & operator =(const uint v) {ch = v; return *this;}*/
//! Compare operator
bool operator ==(const PIChar & o) const;
/*inline bool operator ==(const PIChar & o) const {if (o.isAscii() ^ isAscii()) return false;
if (isAscii()) return (o.toAscii() == toAscii());
return (o.toInt() == toInt());}
inline bool operator ==(const char o) const {return (PIChar(o) == *this);}
inline bool operator ==(const short o) const {return (PIChar(o) == *this);}
inline bool operator ==(const int o) const {return (PIChar(o) == *this);}
inline bool operator ==(const uchar o) const {return (PIChar(o) == *this);}
inline bool operator ==(const ushort o) const {return (PIChar(o) == *this);}
inline bool operator ==(const uint o) const {return (PIChar(o) == *this);}*/
//! Compare operator
bool operator !=(const PIChar & o) const {return !(o == *this);}
/*inline bool operator !=(const char o) const {return (PIChar(o) != *this);}
inline bool operator !=(const short o) const {return (PIChar(o) != *this);}
inline bool operator !=(const int o) const {return (PIChar(o) != *this);}
inline bool operator !=(const uchar o) const {return (PIChar(o) != *this);}
inline bool operator !=(const ushort o) const {return (PIChar(o) != *this);}
inline bool operator !=(const uint o) const {return (PIChar(o) != *this);}*/
//! Compare operator
bool operator >(const PIChar & o) const;

View File

@@ -1,3 +1,22 @@
/*
PIP - Platform Independent Primitives
Binary markup serializator
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pichunkstream.h"
/*! \class PIChunkStream
@@ -99,7 +118,6 @@ uint PIChunkStream::readVInt(PIByteArray & s) {
for (abc = 0; abc < 3; ++abc) {
uchar mask = (0x80 >> abc);
if ((bytes[0] & mask) == mask) {
//if (s.isEmpty()) return 0;
bytes[0] &= (mask - 1);
s >> bytes[abc + 1];
} else break;

View File

@@ -54,12 +54,18 @@ public:
int id;
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
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"
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(PIByteArray * data);
@@ -112,6 +118,7 @@ private:
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::ChunkConst<T> & c);
};
template <typename T>
@@ -133,5 +140,24 @@ PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c
}
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

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

@@ -1,3 +1,22 @@
/*
PIP - Platform Independent Primitives
Peer - named I/O ethernet node, forming self-organized peering network
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picollection.h"

View File

@@ -64,15 +64,14 @@ public:
static bool addToGroup(const PIString & group, const PIObject * element);
class CollectionAdder {
class PIP_EXPORT CollectionAdder {
public:
CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString(), bool own = false);
};
protected:
struct Group {
struct PIP_EXPORT Group {
Group(const PIString & name_ = PIString()) {name = name_;}
//~Group() {piCout << "delete group" << name << this; piForeach (const PIObject * o, elements) delete o; elements.clear();}
PIString name;
PIVector<const PIObject * > elements;
};

View File

@@ -0,0 +1,30 @@
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICOREMODULE_H
#define PICOREMODULE_H
#include "picollection.h"
#include "piobject.h"
#include "pitime.h"
#include "picli.h"
#include "pichunkstream.h"
#include "pipropertystorage.h"
#endif // PICOREMODULE_H

View File

@@ -18,9 +18,9 @@
*/
#include "piincludes_p.h"
#include "picout.h"
#include "piconsole.h"
#include "pibytearray.h"
#include "pistack.h"
#include "piobject.h"
#include "pistring_std.h"
#ifdef WINDOWS
# include <windows.h>
@@ -226,13 +226,6 @@ PICout PICout::operator <<(const PICoutAction v) {
if (isOutputDeviceActive(StdOut)) {
#ifdef WINDOWS
/// TODO : wondows ClearScreen !!!
/*GetConsoleCursorInfo(__Private__::hOut, &curinfo);
curinfo.bVisible = false;
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
SetConsoleCursorPosition(__Private__::hOut, ulcoord);
FillConsoleOutputAttribute(__Private__::hOut, __Private__::dattr, width * (height + 1), ulcoord, &written);
FillConsoleOutputCharacter(__Private__::hOut, ' ', width * (height + 1), ulcoord, &written);*/
#else
printf("\e[H\e[J");
#endif
@@ -262,14 +255,11 @@ PICout PICout::operator <<(const PICoutAction v) {
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
}\
}
//#define PICOUTTOTARGETS(v) {if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v); else printf("%s", (v).dataConsole());}
#define PINUMERICCOUT if (cnb_ == 10) PICOUTTOTARGET(v) else PICOUTTOTARGETS(PIString::fromNumber(v, cnb_))
PICout PICout::operator <<(const char * v) {if (!act_) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
//PICout PICout::operator <<(const std::string & v) {space(); quote(); if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << StdString2PIString(v); else std::cout << (v); quote(); return *this;}
PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;}
PICout PICout::operator <<(const char v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;}

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