diff --git a/CMakeLists.txt b/CMakeLists.txt index 1018551f..7e08b469 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 23) -set(_PIP_REVISION 0) -set(_PIP_SUFFIX ) +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,53 +41,94 @@ set(PIP_UTILS 1) if(LIBPROJECT) set(PIP_UTILS ${UTILS}) endif() +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_STANDARD 11) # 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 "lib/main") -set(PIP_SRC_CONSOLE "lib/console") -set(PIP_SRC_CRYPT "lib/crypt") -set(PIP_SRC_COMPRESS "lib/compress") -set(PIP_SRC_USB "lib/usb") -set(PIP_SRC_FFTW "lib/fftw") -set(PIP_SRC_OPENCL "lib/opencl") -set(PIP_SRC_IO_UTILS "lib/io_utils") -set(PIP_SRC_CONCURRENT "lib/concurrent") -set(PIP_SRC_CLOUD "lib/cloud") -set(PIP_SRC_DIRS ${PIP_SRC_MAIN} - ${PIP_SRC_CONSOLE} - ${PIP_SRC_CRYPT} - ${PIP_SRC_COMPRESS} - ${PIP_SRC_USB} - ${PIP_SRC_FFTW} - ${PIP_SRC_OPENCL} - ${PIP_SRC_IO_UTILS} - ${PIP_SRC_CONCURRENT} - ${PIP_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 "lib/concurrent/test") -endif() +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) @@ -94,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,17 +152,10 @@ set_version(PIP BUILD "${BUILD_NUMBER}" SUFFIX "${_PIP_SUFFIX}" OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/piversion.h") -set_deploy_property(pip ${PIP_LIB_TYPE} - LABEL "PIP main library" - FULLNAME "${_PIP_DOMAIN}.pip" - COMPANY "${_PIP_COMPANY}" - INFO "Platform-Independent Primitives") 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") -message(STATUS "Building PIP version ${PIP_VERSION} (${PIP_LIB_TYPE})") - if(MINGW) find_package(MinGW REQUIRED) @@ -172,48 +207,25 @@ endif() # Compiler get_filename_component(C_COMPILER "${CMAKE_C_COMPILER}" NAME) -#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") -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() -# Console lib -gather_src("${PIP_SRC_CONSOLE}" CPP_LIB_CONSOLE HDRS PHDRS) - -# 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) + add_subdirectory(tests) +endif() if(PIP_FREERTOS) add_definitions(-DPIP_FREERTOS) @@ -257,57 +269,47 @@ if((NOT DEFINED ENV{QNX_HOST}) AND (NOT APPLE) AND (NOT WIN32) AND (NOT DEFINED list(APPEND LIBS_MAIN rt) set(CMAKE_REQUIRED_LIBRARIES rt) endif() -CHECK_FUNCTION_EXISTS(timer_create PIP_TIMER_RT_0) +CHECK_FUNCTION_EXISTS(timer_create PIP_TIMER_RT_0) CHECK_FUNCTION_EXISTS(timer_settime PIP_TIMER_RT_1) -CHECK_FUNCTION_EXISTS(timer_delete PIP_TIMER_RT_2) +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 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) @@ -322,10 +324,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() @@ -361,19 +363,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() @@ -381,91 +376,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() - # Add console library - import_version(pip_console pip) - set_deploy_property(pip_console ${PIP_LIB_TYPE} - LABEL "PIP console support" - FULLNAME "${_PIP_DOMAIN}.pip_console" - COMPANY "${_PIP_COMPANY}" - INFO "Platform-Independent Primitives") - make_rc(pip_console _RC) - add_library(pip_console ${PIP_LIB_TYPE} ${CPP_LIB_CONSOLE} ${_RC}) - target_link_libraries(pip_console pip) - list(APPEND PIP_LIBS_TARGETS pip_console) - - - # 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() @@ -475,7 +416,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) @@ -483,171 +423,100 @@ 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 "${PIP_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() + # Test program 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) @@ -655,9 +524,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_MODULES} ARCHIVE DESTINATION ${MINGW_LIB}) endif() - install(TARGETS ${PIP_LIBS_TARGETS} RUNTIME DESTINATION ${MINGW_BIN}) + 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}") @@ -667,28 +540,31 @@ 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() endif() - install(TARGETS ${PIP_LIBS_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) + install(TARGETS ${PIP_MODULES} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) endif() - message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"") 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() @@ -696,7 +572,7 @@ if(NOT PIP_FREERTOS) # Auxiliary if (NOT CROSSTOOLS) - add_subdirectory("${PIP_SRC_MAIN}/auxiliary/piterminal") + add_subdirectory("utils/piterminal") endif() # Utils @@ -705,7 +581,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") @@ -718,20 +593,11 @@ 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 @@ -743,8 +609,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}\"") @@ -752,13 +619,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}") + 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("-----------------------") diff --git a/cmake/FindPIP.cmake b/cmake/FindPIP.cmake index 5b21dc6b..06292c0d 100644 --- a/cmake/FindPIP.cmake +++ b/cmake/FindPIP.cmake @@ -5,11 +5,12 @@ Also create imported targets: * 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 @@ -63,9 +64,10 @@ 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) get_filename_component(PIP_INCLUDES ${PIP_H_INCLUDE} PATH) set(__ext "") @@ -94,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) @@ -117,15 +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;Console;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 @@ -147,6 +163,9 @@ 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) diff --git a/cmake/PIPDocumentation.cmake b/cmake/PIPDocumentation.cmake index e034bad2..9e9a099a 100644 --- a/cmake/PIPDocumentation.cmake +++ b/cmake/PIPDocumentation.cmake @@ -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}") diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 462dd31b..cbc2f526 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -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 diff --git a/lib/cloud/piccloudclient.cpp b/lib/cloud/piccloudclient.cpp index 6b7507ab..98fec593 100644 --- a/lib/cloud/piccloudclient.cpp +++ b/lib/cloud/piccloudclient.cpp @@ -23,3 +23,18 @@ PICloudClient::PICloudClient() { } + +PICloudClient::~PICloudClient() { + +} + + +bool PICloudClient::openDevice() { + +} + + +bool PICloudClient::closeDevice() { + +} + diff --git a/lib/concurrent/piconditionlock.cpp b/lib/concurrent/piconditionlock.cpp deleted file mode 100644 index 35dee0c4..00000000 --- a/lib/concurrent/piconditionlock.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - PIP - Platform Independent Primitives - - Stephan Fomenko - - 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 . -*/ - -#include "piconditionlock.h" -#ifdef WINDOWS -# include -#else -# include -#endif - - -PRIVATE_DEFINITION_START(PIConditionLock) -#ifdef WINDOWS - CRITICAL_SECTION -#else - pthread_mutex_t -#endif - nativeHandle; -PRIVATE_DEFINITION_END(PIConditionLock) - - -PIConditionLock::PIConditionLock() { -#ifdef WINDOWS - InitializeCriticalSection(&PRIVATE->nativeHandle); -#else - pthread_mutexattr_t attr; - memset(&attr, 0, sizeof(attr)); - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); - pthread_mutex_init(&(PRIVATE->nativeHandle), &attr); - pthread_mutexattr_destroy(&attr); -#endif -} - - -PIConditionLock::~PIConditionLock() { -#ifdef WINDOWS - DeleteCriticalSection(&PRIVATE->nativeHandle); -#else - pthread_mutex_destroy(&(PRIVATE->nativeHandle)); -#endif -} - - -void PIConditionLock::lock() { -#ifdef WINDOWS - EnterCriticalSection(&PRIVATE->nativeHandle); -#else - pthread_mutex_lock(&(PRIVATE->nativeHandle)); -#endif -} - - -void PIConditionLock::unlock() { -#ifdef WINDOWS - LeaveCriticalSection(&PRIVATE->nativeHandle); -#else - pthread_mutex_unlock(&(PRIVATE->nativeHandle)); -#endif -} - - -void *PIConditionLock::handle() { -#ifdef WINDOWS - return &PRIVATE->nativeHandle; -#else - return &PRIVATE->nativeHandle; -#endif -} - - -bool PIConditionLock::tryLock() { -#ifdef WINDOWS - return TryEnterCriticalSection(&PRIVATE->nativeHandle) != 0; -#else - return (pthread_mutex_trylock(&(PRIVATE->nativeHandle)) == 0); -#endif -} diff --git a/lib/console/piconsole.cpp b/lib/console/piconsole.cpp deleted file mode 100644 index 8202826b..00000000 --- a/lib/console/piconsole.cpp +++ /dev/null @@ -1,1168 +0,0 @@ -/* - PIP - Platform Independent Primitives - Console output/input - 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 . -*/ -#include "piconsole.h" -#include "piincludes_p.h" -#include "pipeer.h" -#include "pidiagnostics.h" -#include "pisystemmonitor.h" -#ifndef WINDOWS -# include -# include -# include -#else -# include -# define COMMON_LVB_UNDERSCORE 0x8000 -#endif - - -/** \class PIConsole - * \brief Console output class - * \details - * \section PIConsole_sec0 Synopsis - * This class provides output to console with automatic alignment and update. - * It supports tabs, keyboard listening, formats and colors. - * - * \section PIConsole_sec1 Layout - * %PIConsole works with variable pointers. You should add your variables with - * functions \a addVariable() which receives label name, pointer to variable - * and optional column and format. Columns count is dynamically increased if - * new column used. E.g. if you add variable to empty tab to column 3, columns - * count will be increased to 3, but two firsts columns will be empty. Each column - * filled from top to bottom, but you can add just string with function - * \a addString() or add empty line with function \a addEmptyLine(). Layout scheme: - * \image html piconsole_layout.png - * - * \section PIConsole_sec2 Keyboard usage - * %PIConsole should to be single in application. %PIConsole aggregate PIKbdListener - * which grab keyboard and automatic switch tabs by theirs bind keys. If there is no - * tab binded to pressed key external function "slot" will be called - * - **/ - - -PRIVATE_DEFINITION_START(PIConsole) -#ifdef WINDOWS -void getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;} -COORD & getWinCoord(int dx = 0, int dy = 0) {getWinCurCoord(); ccoord.X += dx; ccoord.Y += dy; return ccoord;} -void * hOut; -CONSOLE_SCREEN_BUFFER_INFO sbi, csbi; -CONSOLE_CURSOR_INFO curinfo; -COORD ccoord, ulcoord; -WORD dattr; -DWORD smode, written; -#endif -PRIVATE_DEFINITION_END(PIConsole) - - -PIConsole::PIConsole(bool startNow, PIKbdListener::KBFunc slot): PIThread() { - setName("console"); - setPriority(piLow); - needLockRun(true); - ret_func = slot; - num_format = systime_format = 0; - vid = 0; - cur_tab = width = height = pwidth = pheight = max_y = 0; - def_align = Nothing; - tabs.reserve(16); -#ifdef WINDOWS - PRIVATE->ulcoord.X = 0; - PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE); - GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi); - PRIVATE->dattr = PRIVATE->sbi.wAttributes; - width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left; - height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top; - PRIVATE->ulcoord.Y = PRIVATE->sbi.srWindow.Top; - GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode); - GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); -#else -# ifdef FREERTOS - width = 80; - height = 24; -# else - winsize ws; - ioctl(0, TIOCGWINSZ, &ws); - width = ws.ws_col; - height = ws.ws_row; -# endif -#endif - addTab("main"); - listener = new PIKbdListener(key_event, this); - peer_timer = new PITimer(); - peer_timer->setName("__S__.PIConsole.peer_timer"); - peer = 0; - server_mode = pause_ = false; - state = Disconnected; - peer_timer->addDelimiter(20); - peer_timer->setName("__S__PIConsole::peer_timer"); - CONNECT2(void, void * , int, peer_timer, tickEvent, this, peerTimer); - if (startNow) start(); -} - - -PIConsole::~PIConsole() { - stopPeer(); - if (isRunning()) - stop(); - clearTabs(false); - delete listener; - delete peer_timer; -#ifdef WINDOWS - SetConsoleMode(PRIVATE->hOut, PRIVATE->smode); - SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr); -#endif -} - - -int PIConsole::addTab(const PIString & name, char bind_key) { - if (isRunning()) lock(); - tabs.push_back(Tab(name, bind_key)); - cur_tab = tabs.size() - 1; - if (isRunning()) unlock(); - return tabs.size(); -} - - -void PIConsole::removeTab(uint index) { - if (index >= tabs.size()) return; - if (isRunning()) lock(); - tabs.remove(index); - if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; - if (isRunning()) unlock(); -} - - -void PIConsole::removeTab(const PIString & name) { - uint index = tabs.size() + 1; - for (uint i = 0; i < tabs.size(); ++i) { - if (tabs[i].name == name) { - index = i; - break; - } - } - removeTab(index); -} - - -void PIConsole::clearTab(uint index) { - if (index >= tabs.size()) return; - lock(); - tabs[index].columns.clear(); - if (cur_tab == index) { - clearScreen(); - fillLabels(); - } - if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; - unlock(); -} - - -void PIConsole::clearTab(const PIString & name) { - uint index = tabs.size() + 1; - for (uint i = 0; i < tabs.size(); ++i) { - if (tabs[i].name == name) { - index = i; - break; - } - } - clearTab(index); -} - - -void PIConsole::update() { - lock(); - fillLabels(); - unlock(); -} - - -bool PIConsole::setTab(uint index) { - if (index >= tabs.size()) - return false; - if (!isRunning()) { - cur_tab = index; - return true; - } - lock(); - PICout::__mutex__().lock(); - cur_tab = index; - clearScreen(); - fillLabels(); - PICout::__mutex__().unlock(); - unlock(); - return true; -} - - -bool PIConsole::setTab(const PIString & name) { - uint index = tabs.size() + 1; - for (uint i = 0; i < tabs.size(); ++i) { - if (tabs[i].name == name) { - index = i; - break; - } - } - return setTab(index); -} - - -bool PIConsole::setTabBindKey(uint index, char bind_key) { - if (index >= tabs.size()) - return false; - tabs[index].key = bind_key; - return true; -} - - -bool PIConsole::setTabBindKey(const PIString & name, char bind_key) { - uint index =tabs.size() + 1; - for (uint i = 0; i < tabs.size(); ++i) { - if (tabs[i].name == name) { - index = i; - break; - } - } - return setTabBindKey(index, bind_key); -} - - -void PIConsole::key_event(PIKbdListener::KeyEvent key, void * t) { - PIConsole * p = (PIConsole * )t; - int ct = p->cur_tab; - if (key.key == PIKbdListener::LeftArrow) { - do { - ct--; - if (ct < 0) return; - } while (p->tabs[ct].key == 0); - p->setTab(ct); - return; - } - if (key.key == PIKbdListener::RightArrow) { - do { - ct++; - if (ct >= p->tabs.size_s()) return; - } while (p->tabs[ct].key == 0); - p->setTab(ct); - return; - } - for (uint i = 0; i < p->tabsCount(); ++i) { - if (p->tabs[i].key == key.key) { - p->setTab(i); - return; - } - } - if (p->ret_func != 0) p->ret_func(key, t); - p->keyPressed(key, t); -} - - -int PIConsole::couts(const PIString & v) { - return printf("%s", v.data()); -} - - -int PIConsole::couts(const char * v) { - return printf("%s", v); -} - - -void PIConsole::clearVariables(bool clearScreen) { - if (isRunning()) lock(); - if (clearScreen && isRunning()) { - toUpperLeft(); - clearScreenLower(); - } - columns().clear(); - if (isRunning()) unlock(); -} - - -void PIConsole::stop(bool clear) { - PIThread::stop(true); - if (clear) clearScreen(); - moveTo(0, max_y + 4); - showCursor(); - couts(fstr(Normal)); -#ifdef WINDOWS - SetConsoleMode(PRIVATE->hOut, PRIVATE->smode); - SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr); -#endif - fflush(0); -} - - -PIString PIConsole::fstr(FormatFlags f) { - num_format = systime_format = 0; - if (f[PIConsole::Dec]) num_format = 0; - if (f[PIConsole::Hex]) num_format = 1; - if (f[PIConsole::Oct]) num_format = 2; - if (f[PIConsole::Bin]) num_format = 4; - if (f[PIConsole::Scientific]) num_format = 3; - if (f[PIConsole::SystemTimeSplit]) systime_format = 0; - if (f[PIConsole::SystemTimeSeconds]) systime_format = 1; - -#ifdef WINDOWS - WORD attr = 0; - - if (f[PIConsole::Inverse]) { - if (f[PIConsole::Red]) attr |= BACKGROUND_RED; - if (f[PIConsole::Green]) attr |= BACKGROUND_GREEN; - if (f[PIConsole::Blue]) attr |= BACKGROUND_BLUE; - if (f[PIConsole::Yellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN); - if (f[PIConsole::Magenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE); - if (f[PIConsole::Cyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE); - if (f[PIConsole::White]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); - if (f[PIConsole::BackRed]) attr |= FOREGROUND_RED; - if (f[PIConsole::BackGreen]) attr |= FOREGROUND_GREEN; - if (f[PIConsole::BackBlue]) attr |= FOREGROUND_BLUE; - if (f[PIConsole::BackYellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN); - if (f[PIConsole::BackMagenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE); - if (f[PIConsole::BackCyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE); - if (f[PIConsole::BackWhite]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - if ((attr & BACKGROUND_RED) + (attr & BACKGROUND_GREEN) + (attr & BACKGROUND_BLUE) == 0) - attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - } else { - if (f[PIConsole::Red]) attr |= FOREGROUND_RED; - if (f[PIConsole::Green]) attr |= FOREGROUND_GREEN; - if (f[PIConsole::Blue]) attr |= FOREGROUND_BLUE; - if (f[PIConsole::Yellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN); - if (f[PIConsole::Magenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE); - if (f[PIConsole::Cyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE); - if (f[PIConsole::White]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - if (f[PIConsole::BackRed]) attr |= BACKGROUND_RED; - if (f[PIConsole::BackGreen]) attr |= BACKGROUND_GREEN; - if (f[PIConsole::BackBlue]) attr |= BACKGROUND_BLUE; - if (f[PIConsole::BackYellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN); - if (f[PIConsole::BackMagenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE); - if (f[PIConsole::BackCyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE); - if (f[PIConsole::BackWhite]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); - if ((attr & FOREGROUND_RED) + (attr & FOREGROUND_GREEN) + (attr & FOREGROUND_BLUE) == 0) - attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - } - if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY; - if (f[PIConsole::Underline]) attr |= COMMON_LVB_UNDERSCORE; - - SetConsoleTextAttribute(PRIVATE->hOut, attr); - return PIString(); -#else - PIString ts("\e[0"); - - if (f[PIConsole::Bold]) ts += ";1"; - if (f[PIConsole::Faint]) ts += ";2"; - if (f[PIConsole::Italic]) ts += ";3"; - if (f[PIConsole::Underline]) ts += ";4"; - if (f[PIConsole::Blink]) ts += ";5"; - if (f[PIConsole::Inverse]) ts += ";7"; - - if (f[PIConsole::Black]) ts += ";30"; - if (f[PIConsole::Red]) ts += ";31"; - if (f[PIConsole::Green]) ts += ";32"; - if (f[PIConsole::Yellow]) ts += ";33"; - if (f[PIConsole::Blue]) ts += ";34"; - if (f[PIConsole::Magenta]) ts += ";35"; - if (f[PIConsole::Cyan]) ts += ";36"; - if (f[PIConsole::White]) ts += ";37"; - - if (f[PIConsole::BackBlack]) ts += ";40"; - if (f[PIConsole::BackRed]) ts += ";41"; - if (f[PIConsole::BackGreen]) ts += ";42"; - if (f[PIConsole::BackYellow]) ts += ";43"; - if (f[PIConsole::BackBlue]) ts += ";44"; - if (f[PIConsole::BackMagenta]) ts += ";45"; - if (f[PIConsole::BackCyan]) ts += ";46"; - if (f[PIConsole::BackWhite]) ts += ";47"; - - return ts + "m"; -#endif -} - - -inline int PIConsole::couts(const bool v) {return (v ? printf("true") : printf("false"));} -inline int PIConsole::couts(const char v) {return printf("%c", v);} -inline int PIConsole::couts(const short v) { - switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hd", v); break;} -} -inline int PIConsole::couts(const int v) { - switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%d", v); break;} -} -inline int PIConsole::couts(const long v) { - switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%ld", v); break;} -} -inline int PIConsole::couts(const llong v) { - switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lld", v); break;} -} -inline int PIConsole::couts(const uchar v) { - switch (num_format) {case (1): return printf("0x%.2X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 1)); break; default: return printf("%u", v); break;} -} -inline int PIConsole::couts(const ushort v) { - switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hu", v); break;} -} -inline int PIConsole::couts(const uint v) { - switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%u", v); break;} -} -inline int PIConsole::couts(const ulong v) { - switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lu", v); break;} -} -inline int PIConsole::couts(const ullong v) { - switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%llu", v); break;} -} -inline int PIConsole::couts(const float v) { - switch (num_format) {case (3): return printf("%e", v); break; default: return printf("%.5g", v); break;} -} -inline int PIConsole::couts(const double v) { - switch (num_format) {case (3): return printf("%le", v); break; default: return printf("%.5lg", v); break;} -} -inline int PIConsole::couts(const PISystemTime & v) { - switch (systime_format) {case (1): return printf("%.6lg", v.toSeconds()); break; - default: return couts(v.seconds) + printf(" s, ") + couts(v.nanoseconds) + printf(" ns"); break;} -} - - -void PIConsole::toUpperLeft() { -#ifdef WINDOWS - SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ulcoord); -#else - printf("\e[H"); -#endif -} - -void PIConsole::moveRight(int n) { -#ifdef WINDOWS - SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->getWinCoord(n)); -#else - if (n > 0) printf("\e[%dC", n); -#endif -} - -void PIConsole::moveLeft(int n) { -#ifdef WINDOWS - SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->getWinCoord(-n)); -#else - if (n > 0) printf("\e[%dD", n); -#endif -} - -void PIConsole::moveTo(int x, int y) { -#ifdef WINDOWS - PRIVATE->ccoord.X = x; - PRIVATE->ccoord.Y = PRIVATE->ulcoord.Y + y; - SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord); -#else - printf("\e[%d;%dH", y, x); -#endif -} - -void PIConsole::clearScreen() { -#ifdef WINDOWS - couts(fstr(Normal)); - toUpperLeft(); - FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written); - FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written); -#else - couts(fstr(Normal)); printf("\e[H\e[J"); -#endif -} - -void PIConsole::clearScreenLower() { -#ifdef WINDOWS - couts(fstr(Normal)); - PRIVATE->getWinCurCoord(); - FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); - FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); -#else - couts(fstr(Normal)); printf("\e[J"); -#endif -} - -void PIConsole::clearLine() { -#ifdef WINDOWS - PRIVATE->getWinCurCoord(); - FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); - FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); -#else - printf("\e[K"); -#endif -} - -void PIConsole::newLine() { -#ifdef WINDOWS - PRIVATE->getWinCurCoord(); - PRIVATE->ccoord.X = 0; PRIVATE->ccoord.Y++; - SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord); -#else - printf("\eE"); -#endif -} - -void PIConsole::hideCursor() { -#ifdef WINDOWS - PRIVATE->curinfo.bVisible = false; - SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); -#else - printf("\e[?25l"); -#endif -} - -void PIConsole::showCursor() { -#ifdef WINDOWS - PRIVATE->curinfo.bVisible = true; SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); -#else - printf("\e[?25h"); -#endif -} - - -void PIConsole::begin() { -#ifdef WINDOWS - SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT); -#endif - max_y = 0; - PICout::__mutex__().lock(); - clearScreen(); - hideCursor(); - fillLabels(); - PICout::__mutex__().unlock(); -} - - -void PIConsole::run() { - if (pause_) return; - uint cx, clen = 0; - int j; -#ifdef WINDOWS - GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi); - width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left; - height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top; -#else -# ifdef FREERTOS - width = 80; - height = 24; -# else - winsize ws; - ioctl(0, TIOCGWINSZ, &ws); - width = ws.ws_col; - height = ws.ws_row; -# endif -#endif - //fflush(0); return; - PICout::__mutex__().lock(); - if (pwidth != width || pheight != height) { - clearScreen(); - fillLabels(); - } - pwidth = width; - pheight = height; - col_cnt = columns().size(); - col_wid = (col_cnt > 0) ? width / col_cnt : width; - for (uint i = 0; i < col_cnt; ++i) { - PIVector & cvars(tabs[cur_tab].columns[i].variables); - cx = col_wid * i; - toUpperLeft(); - if (max_y < cvars.size()) max_y = cvars.size(); - j = 0; - piForeachC (Variable & tv_, cvars) { - if (j > height - 3) continue; - j++; - moveRight(cx); - if (tv_.type == 15) { - newLine(); - continue; - } - moveRight(tv_.offset); - const void * ptr = 0; - if (tv_.remote) { - if (tv_.type == 0) { - rstr.clear(); - rba = tv_.rdata; - rba >> rstr; - rstr.trim(); - ptr = &rstr; - } else - ptr = tv_.rdata.data(); - } else - ptr = tv_.ptr; - switch (tv_.type) { - case 0: clen = printValue(ptr != 0 ? *(const PIString*)ptr : PIString(), tv_.format); break; - case 1: clen = printValue(ptr != 0 ? *(const bool*)ptr : false, tv_.format); break; - case 2: clen = printValue(ptr != 0 ? *(const int*)ptr : 0, tv_.format); break; - case 3: clen = printValue(ptr != 0 ? *(const long*)ptr : 0l, tv_.format); break; - case 4: clen = printValue(ptr != 0 ? *(const char*)ptr : char(0), tv_.format); break; - case 5: clen = printValue(ptr != 0 ? *(const float*)ptr : 0.f, tv_.format); break; - case 6: clen = printValue(ptr != 0 ? *(const double*)ptr : 0., tv_.format); break; - case 7: clen = printValue(ptr != 0 ? *(const short*)ptr : short(0), tv_.format); break; - case 8: clen = printValue(ptr != 0 ? *(const uint*)ptr : 0u, tv_.format); break; - case 9: clen = printValue(ptr != 0 ? *(const ulong*)ptr : 0ul, tv_.format); break; - case 10: clen = printValue(ptr != 0 ? *(const ushort*)ptr : ushort(0), tv_.format); break; - case 11: clen = printValue(ptr != 0 ? *(const uchar*)ptr : uchar(0), tv_.format); break; - case 12: clen = printValue(ptr != 0 ? *(const llong*)ptr : 0l, tv_.format); break; - case 13: clen = printValue(ptr != 0 ? *(const ullong*)ptr: 0ull, tv_.format); break; - case 20: clen = printValue(ptr != 0 ? *(const PISystemTime*)ptr: PISystemTime(), tv_.format); break; - case 14: clen = printValue(bitsValue(ptr, tv_.bitFrom, tv_.bitCount), tv_.format); break; - } - if (clen + tv_.offset < (uint)col_wid) { - PIString ts = PIString( - #if defined(QNX) || defined(FREE_BSD) - col_wid - clen - tv_.offset - 1, ' '); -#else - col_wid - clen - tv_.offset, ' '); -#endif - printf("%s", ts.data()); - } - newLine(); - } - } -#ifdef WINDOWS - moveTo(0, max_y + 1); -#else - moveTo(0, max_y + 2); -#endif - fflush(0); - PICout::__mutex__().unlock(); -} - - -void PIConsole::fillLabels() { - if (!isRunning()) return; - uint cx, cy, mx = 0, dx; -#ifdef WINDOWS - GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi); - width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left; - height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top; -#else -# ifdef FREERTOS - width = 80; - height = 24; -# else - winsize ws; - ioctl(0, TIOCGWINSZ, &ws); - width = ws.ws_col; - height = ws.ws_row; -# endif -#endif - max_y = 0; - col_cnt = columns().size(); - col_wid = (col_cnt > 0) ? width / col_cnt : width; - for (uint i = 0; i < col_cnt; ++i) { - Column & ccol(tabs[cur_tab].columns[i]); - PIVector & cvars(ccol.variables); - if (ccol.alignment != Nothing) { - mx = 0; - piForeachC (Variable & j, cvars) - if (!j.isEmpty()) - if (mx < j.name.size()) - mx = j.name.size(); - mx += 2; - } - cx = col_wid * i; - cy = 1; - toUpperLeft(); - for (uint j = 0; j < cvars.size(); ++j) { - if (int(j) > height - 3) continue; - if (max_y < j) max_y = j; - moveRight(cx); - Variable & tv_(cvars[j]); - cvars[j].nx = cx; - cvars[j].ny = cy; - if (tv_.name.isEmpty()) { - cvars[j].offset = 0; - clearLine(); - newLine(); - cy++; - continue; - } - clearLine(); - //piCout << tv_.name << tv_.type << tv_.ptr; - if (tv_.type == 15) { - cvars[j].offset = cvars[j].name.length(); - cvars[j].nx += cvars[j].offset; - printLine(tv_.name, cx, tv_.format); - newLine(); - cy++; - continue; - } - if (!tv_.isEmpty()) { - switch (ccol.alignment) { - case Nothing: - cvars[j].offset = (tv_.name + ": ").length(); - cvars[j].nx += cvars[j].offset; - printValue(tv_.name + ": ", tv_.format); - break; - case Left: - cvars[j].offset = mx; - cvars[j].nx += cvars[j].offset; - printValue(tv_.name + ": ", tv_.format); - break; - case Right: - cvars[j].offset = mx; - cvars[j].nx += cvars[j].offset; - dx = mx - (tv_.name + ": ").length(); - moveRight(dx); - printValue(tv_.name + ": ", tv_.format); - moveLeft(dx); - break; - } - } - newLine(); - cy++; - } - } -#ifdef WINDOWS - moveTo(0, max_y + 1); -#else - moveTo(0, max_y + 2); -#endif - if (!tabs[cur_tab].status.isEmpty()) { - printValue(tabs[cur_tab].status); - newLine(); - } - status(); -} - - -void PIConsole::status() { - Tab * ctab; - for (uint i = 0; i < tabsCount(); ++i) { - ctab = &tabs[i]; - if (ctab->key == 0) continue; - printValue(ctab->key, PIConsole::White | PIConsole::Bold); - if (i == cur_tab) - printValue(ctab->name + " ", PIConsole::BackYellow | PIConsole::Black); - else - printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse); - printValue(" "); - } - newLine(); -} - - -int PIConsole::bitsValue(const void * src, int offset, int count) const { - int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8; - char cbyte = reinterpret_cast(src)[stbyte]; - for (int i = 0; i < count; i++) { - ret |= ((cbyte >> cbit & 1) << i); - cbit++; - if (cbit == 8) { - cbit = 0; - stbyte++; - cbyte = reinterpret_cast(src)[stbyte]; - } - } - return ret; -} - - -const char * PIConsole::toBin(const void * d, int s) { - binstr.clear(); - uchar cc, b; - for (int i = 0; i < s; ++i) { - cc = ((const uchar *)d)[i]; - b = 1; - for (int j = 0; j < 8; ++j) { - binstr << (cc & b ? "1" : "0"); - b <<= 1; - } - if (i < s - 1) binstr << " "; - } - binstr.reverse(); - return binstr.data(); -} - - -#define ADD_VAR_BODY vid++; tv.id = vid; tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; tv.remote = false; checkColumn(col); - -void PIConsole::addString(const PIString & name, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 15; tv.size = 0; tv.ptr = 0; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const PIString * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 0; tv.size = 0; tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const bool * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 1; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const int * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 2; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const long * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 3; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const char * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 4; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const float * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 5; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const double * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 6; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const short * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 7; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const uint * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 8; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const ulong * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 9; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const ushort * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 10; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const uchar * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 11; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const llong * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 12; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const ullong * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 13; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const PISystemTime * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 20; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - * \details This function add to column "column" next lines: - * * " diagnostics" - * * "Received count": \a PIDiagnostics::receiveCount - * * "Invalid count": \a PIDiagnostics::wrongCount - * * "Sended count": \a PIDiagnostics::sendCount - * * "Immediate Frequency, Hz": \a PIDiagnostics::immediateFrequency - * * "Integral Frequency, Hz": \a PIDiagnostics::integralFrequency - * * "Receive speed": \a PIDiagnostics::receiveSpeed - * * "Send speed": \a PIDiagnostics::sendSpeed - * * "Quality": \a PIDiagnostics::quality - * */ -void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, FormatFlags format) { - addString(name + " diagnostics", col, format | PIConsole::Bold); -// addVariable("Received count", ptr->receiveCount_ptr(), col, format); -// addVariable("Invalid count", ptr->wrongCount_ptr(), col, format); -// addVariable("Sended count", ptr->sendCount_ptr(), col, format); -// addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); -// addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format); -// addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format); -// addVariable("Send speed", ptr->sendSpeed_ptr(), col, format); -// addVariable("Quality", ptr->quality_ptr(), col, format); -} -void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr, int col, FormatFlags format) { - addString("monitor " + name, col, format | PIConsole::Bold); - //addVariable("PID", &(ptr->statistic().ID), col, format); - //addVariable("state", &(ptr->statistic().state), col, format); - //addVariable("threads", &(ptr->statistic().threads), col, format); - //addVariable("priority", &(ptr->statistic().priority), col, format); - //addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format); - //addVariable("memory shared", &(ptr->statistic().share_memsize_readable), col, format); - //addVariable("cpu load kernel", &(ptr->statistic().cpu_load_system), col, format); - //addVariable("cpu load user", &(ptr->statistic().cpu_load_user), col, format); -} -void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, FormatFlags format) { - vid++; tv.id = vid; tv.size = sizeof(ullong); tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format; - checkColumn(col); column(col).push_back(tv);} -void PIConsole::addEmptyLine(int col, uint count) { - tv.id = 0; tv.size = 0; tv.name = ""; tv.type = 0; tv.ptr = 0; tv.format = Normal; - for (uint i = 0; i < count; ++i) { - checkColumn(col); - column(col).push_back(tv); - } -} - - -PIString PIConsole::getString(int x, int y) { - bool run = isRunning(); - if (run) PIThread::stop(true); - listener->setActive(false); - msleep(50); -#ifdef WINDOWS - moveTo(x - 1, y - 1); -#else - moveTo(x, y); -#endif - showCursor(); - PIByteArray ba(4096); -#ifdef CC_VC - int ret = scanf_s(" %s", ba.data()); -#else - int ret = scanf(" %s", ba.data()); -#endif - listener->setActive(true); - if (run) start(); - if (ret >= 1) return PIString(ba); - else return PIString(); -} - - -PIString PIConsole::getString(const PIString & name) { - piForeachC (Column & i, tabs[cur_tab].columns) - piForeachC (Variable & j, i.variables) - if (j.name == name) - return getString(j.nx + 1, j.ny); - return PIString(); -} - - -#define PRINT_VAR_BODY couts(fstr(format)); int ret = couts(value); couts(fstr(PIConsole::Dec)); return ret; - -inline void PIConsole::printLine(const PIString & value, int dx, FormatFlags format) { - int i = width - value.length() - dx; -#if defined(QNX) || defined(FREE_BSD) - --i; -#endif - PIString ts = fstr(format); - couts(ts); - if (i >= 0) ts = value + PIString(i, ' '); - else ts = value.left(value.size() + i); - couts(ts); - couts(fstr(Dec)); -} -inline int PIConsole::printValue(const PIString & value, FormatFlags format) { - couts(fstr(format)); - int ret = couts(value); - fstr(PIConsole::Dec); - return ret; -} -inline int PIConsole::printValue(const char * value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const bool value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const int value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const long value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const llong value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const float value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const double value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const char value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const short value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const uchar value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const ushort value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const uint value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const ulong value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const ullong value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const PISystemTime & value, FormatFlags format) {PRINT_VAR_BODY} - - - -void PIConsole::startServer(const PIString & name) { - stopPeer(); - server_mode = true; - peer = new PIPeer("_rcs_:" + name); - CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); - CONNECT1(void, const PIString & , peer, peerDisconnectedEvent, this, peerDisconnectedEvent); - peer_timer->start(50.); - serverSendInfo(); -} - - -void PIConsole::stopPeer() { - remote_clients.clear(); - peer_timer->stop(); - if (peer != 0) delete peer; - peer = 0; - state = Disconnected; -} - - -PIStringList PIConsole::clients() const { - PIStringList sl; - if (peer == 0) return sl; - piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { - if (i.name.left(6) != "_rcc_:") continue; - sl << i.name.right(i.name.length() - 6); - } - return sl; -} - - -void PIConsole::listenServers() { - stopPeer(); - server_mode = false; - server_name.clear(); - randomize(); - peer = new PIPeer("_rcc_:" + PIDateTime::current().toString("hhmmssddMMyy_") + PIString::fromNumber(randomi())); - CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); - peer_timer->start(100.); -} - - -PIStringList PIConsole::availableServers() const { - PIStringList sl; - if (peer == 0) return sl; - piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { - if (i.name.left(6) != "_rcs_:") continue; - sl << i.name.right(i.name.length() - 6); - } - return sl; -} - - -void PIConsole::connectToServer(const PIString & name) { - if (peer == 0) listenServers(); - server_name = name; -} - - -void PIConsole::disconnect() { - stopPeer(); -} - - -void PIConsole::serverSendInfo() { - if (peer == 0) return; - PIByteArray ba; - ba << int(0xAA); - peer->sendToAll(ba); -} - - -void PIConsole::serverSendData() { - if (peer == 0) return; - PIByteArray ba; - PIVector content; - piForeach (Tab & t, tabs) - piForeach (Column & c, t.columns) - piForeach (Variable & v, c.variables) - if (!v.isEmpty() && v.id > 0) { - VariableContent vc; - vc.id = v.id; - v.writeData(vc.rdata); - content << vc; - } - piForeach (RemoteClient & rc, remote_clients) { - ba.clear(); - switch (rc.state) { - case FetchingData: - ba << int(0xCC) << tabs; - //piCout << "server send const data" << rc.name << ba.size_s(); - break; - case Committing: - ba << int(0xDD); - break; - case Connected: - ba << int(0xEE) << content; - //piCout << "send data" << ba.size(); - break; - default: break; - } - if (!ba.isEmpty()) - peer->send(rc.name, ba); - } -} - - -PIConsole::RemoteClient & PIConsole::remoteClient(const PIString & fname) { - piForeach (RemoteClient & i, remote_clients) - if (i.name == fname) - return i; - remote_clients << RemoteClient(fname); - return remote_clients.back(); -} - - -void PIConsole::peerReceived(const PIString & from, const PIByteArray & data) { - int type; - PIByteArray ba(data); - ba >> type; - //piCout << "rec packet from" << from << "type" << PICoutManipulators::Hex << type; - if (server_mode) { - if (from.left(5) != "_rcc_") return; - //PIString rcn = from.right(from.length() - 6); - RemoteClient & rc(remoteClient(from)); - switch (type) { - case 0xBB: // fetch const data request - //piCout << "fetch data request from" << from << rc.state; - if (rc.state != Connected) - rc.state = FetchingData; - break; - case 0xCC: // const data commit - //piCout << "commit from" << from; - if (rc.state != Connected) - rc.state = Connected; - break; - default: break; - } - } else { - PIVector content; - PIMap vids; - if (from.left(5) != "_rcs_") return; - //PIString rcn = from.right(from.length() - 6); - switch (type) { - case 0xAA: // new server - //piCout << "new server" << rcn; - break; - case 0xCC: // const data - //piCout << "received const data"; - state = Committing; - ba >> tabs; - cur_tab = tabs.isEmpty() ? -1 : 0; - piForeach (Tab & t, tabs) - piForeach (Column & c, t.columns) - piForeach (Variable & v, c.variables) - v.remote = true; - break; - case 0xDD: // const data commit - //piCout << "received commit"; - state = Connected; - break; - case 0xEE: // dynamic data - //piCout << "received data" << ba.size_s(); - piForeach (Tab & t, tabs) - piForeach (Column & c, t.columns) - piForeach (Variable & v, c.variables) - if (!v.isEmpty() && v.id > 0) - vids[v.id] = &v; - ba >> content; - piForeach (VariableContent & vc, content) { - if (vc.id <= 0) continue; - Variable * v = vids.at(vc.id); - if (v == 0) continue; - //piCout << "read" << v->name << vc.rdata.size_s(); - v->rdata = vc.rdata; - } - break; - default: break; - } - } -} - - -void PIConsole::peerTimer(void * data, int delim) { - if (peer == 0) return; - //piCout << "timer" << delim; - if (server_mode) { - if (delim == 20) - serverSendInfo(); - else - serverSendData(); - } else { - if (delim != 1 || server_name.isEmpty()) return; - const PIPeer::PeerInfo * p = peer->getPeerByName("_rcs_:" + server_name); - if (p == 0) return; - PIByteArray ba; - switch (state) { - case Disconnected: - peer_tm.reset(); - ba << int(0xBB); - //piCout << "send to" << server_name << "fetch request disc"; - peer->send(p, ba); - state = FetchingData; - break; - case FetchingData: - if (peer_tm.elapsed_s() < 3.) - return; - peer_tm.reset(); - ba << int(0xBB); - //piCout << "send to" << server_name << "fetch request fd"; - peer->send(p, ba); - break; - case Committing: - peer_tm.reset(); - ba << int(0xCC); - //piCout << "send to" << server_name << "committing"; - state = Connected; - peer->send(p, ba); - break; - default: break; - }; - } -} - - -void PIConsole::peerDisconnectedEvent(const PIString & name) { - for (int i = 0; i < remote_clients.size_s(); ++i) - if (remote_clients[i].name == name) { - remote_clients.remove(i); - --i; - } -} diff --git a/lib/console/piscreen.cpp b/lib/console/piscreen.cpp index 60945d17..786c1b02 100644 --- a/lib/console/piscreen.cpp +++ b/lib/console/piscreen.cpp @@ -480,7 +480,7 @@ void PIScreen::mouse_event(PIKbdListener::MouseEvent me) { PIVector tl = prepareMouse(&me); if (tl.isEmpty()) return; piForeachR (PIScreenTile * t, tl) - if (t->mouseEvent(me)) piBreak; + if (t->mouseEvent(me)) break; } @@ -488,7 +488,7 @@ void PIScreen::wheel_event(PIKbdListener::WheelEvent we) { PIVector tl = prepareMouse(&we); if (tl.isEmpty()) return; piForeachR (PIScreenTile * t, tl) - if (t->wheelEvent(we)) piBreak; + if (t->wheelEvent(we)) break; } diff --git a/lib/console/piterminal.cpp b/lib/console/piterminal.cpp index 2c0da013..ce9623aa 100644 --- a/lib/console/piterminal.cpp +++ b/lib/console/piterminal.cpp @@ -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; diff --git a/lib/fftw/pifft_p.h b/lib/fftw/pifft_p.h index 92c7f378..04c61169 100644 --- a/lib/fftw/pifft_p.h +++ b/lib/fftw/pifft_p.h @@ -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 -class PIP_EXPORT PIFFTW_Private +class PIFFTW_Private { public: explicit PIFFTW_Private() { diff --git a/lib/lua/3rd/LuaBridge/List.h b/lib/lua/3rd/LuaBridge/List.h new file mode 100644 index 00000000..66e0d8fb --- /dev/null +++ b/lib/lua/3rd/LuaBridge/List.h @@ -0,0 +1,55 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + static void push (lua_State* L, std::list const& list) + { + lua_createtable (L, static_cast (list.size ()), 0); + typename std::list ::const_iterator item = list.begin (); + for (std::size_t i = 1; i <= list.size (); ++i) + { + lua_pushinteger (L, static_cast (i)); + Stack ::push (L, *item); + lua_settable (L, -3); + ++item; + } + } + + static std::list get (lua_State* L, int index) + { + if (!lua_istable (L, index)) + { + luaL_error (L, "#%d argument must be a table", index); + } + + std::list list; + + int const absindex = lua_absindex (L, index); + lua_pushnil (L); + while (lua_next (L, absindex) != 0) + { + list.push_back (Stack ::get (L, -1)); + lua_pop (L, 1); + } + return list; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_istable (L, index); + } +}; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/LuaBridge.h b/lib/lua/3rd/LuaBridge/LuaBridge.h new file mode 100644 index 00000000..866acc39 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/LuaBridge.h @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/lib/lua/3rd/LuaBridge/Map.h b/lib/lua/3rd/LuaBridge/Map.h new file mode 100644 index 00000000..a36d269a --- /dev/null +++ b/lib/lua/3rd/LuaBridge/Map.h @@ -0,0 +1,56 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + typedef std::map Map; + + static void push (lua_State* L, const Map& map) + { + lua_createtable (L, 0, static_cast (map.size ())); + typedef typename Map::const_iterator ConstIter; + for (ConstIter i = map.begin (); i != map.end (); ++i) + { + Stack ::push (L, i->first); + Stack ::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 ::get (L, -2), Stack ::get (L, -1)); + lua_pop (L, 1); + } + return map; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_istable (L, index); + } +}; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/RefCountedObject.h b/lib/lua/3rd/LuaBridge/RefCountedObject.h new file mode 100644 index 00000000..ebc749e3 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/RefCountedObject.h @@ -0,0 +1,356 @@ +//============================================================================== +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + 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 + +#include + +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 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 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 (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 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 MyClassPtr; + + @endcode +*/ +template +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 + inline RefCountedObjectPtr (const RefCountedObjectPtr& other) + : referencedObject (static_cast (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 + RefCountedObjectPtr& operator= (const RefCountedObjectPtr& other) + { + return operator= (static_cast (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 +bool operator== (const RefCountedObjectPtr& object1, ReferenceCountedObjectClass* const object2) +{ + return object1.getObject() == object2; +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (const RefCountedObjectPtr& object1, const RefCountedObjectPtr& object2) +{ + return object1.getObject() == object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (ReferenceCountedObjectClass* object1, RefCountedObjectPtr& object2) +{ + return object1 == object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (const RefCountedObjectPtr& object1, const ReferenceCountedObjectClass* object2) +{ + return object1.getObject() != object2; +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (const RefCountedObjectPtr& object1, RefCountedObjectPtr& object2) +{ + return object1.getObject() != object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (ReferenceCountedObjectClass* object1, RefCountedObjectPtr& object2) +{ + return object1 != object2.getObject(); +} + +//============================================================================== + +template +struct ContainerTraits > +{ + typedef T Type; + + static T* get (RefCountedObjectPtr const& c) + { + return c.getObject (); + } +}; + +//============================================================================== + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/RefCountedPtr.h b/lib/lua/3rd/LuaBridge/RefCountedPtr.h new file mode 100644 index 00000000..4db103f5 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/RefCountedPtr.h @@ -0,0 +1,244 @@ +//============================================================================== +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + 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 +#include "RefCountedObject.h" + +namespace luabridge { + +//============================================================================== +/** + Support for our RefCountedPtr. +*/ +struct RefCountedPtrBase +{ + // Declaration of container for the refcounts + typedef std::unordered_map 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 RefCountedPtr : private RefCountedPtrBase +{ +public: + template + struct rebind + { + typedef RefCountedPtr 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 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 + RefCountedPtr (RefCountedPtr const& rhs) : m_p (static_cast (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 & operator= (RefCountedPtr 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 + RefCountedPtr & operator= (RefCountedPtr const& rhs) + { + reset (); + m_p = static_cast (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 +bool operator== (const RefCountedPtr & lhs, const RefCountedPtr & rhs) +{ + return lhs.get () == rhs.get (); +} + +template +bool operator!= (const RefCountedPtr & lhs, const RefCountedPtr & rhs) +{ + return lhs.get() != rhs.get(); +} + +//============================================================================== + +// forward declaration +template +struct ContainerTraits; + +template +struct ContainerTraits > +{ + typedef T Type; + + static T* get (RefCountedPtr const& c) + { + return c.get (); + } +}; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/UnorderedMap.h b/lib/lua/3rd/LuaBridge/UnorderedMap.h new file mode 100644 index 00000000..78a7acee --- /dev/null +++ b/lib/lua/3rd/LuaBridge/UnorderedMap.h @@ -0,0 +1,55 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2019, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + typedef std::unordered_map Map; + + static void push (lua_State* L, const Map& map) + { + lua_createtable (L, 0, static_cast (map.size ())); + typedef typename Map::const_iterator ConstIter; + for (ConstIter i = map.begin (); i != map.end (); ++i) + { + Stack ::push (L, i->first); + Stack ::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 ::get (L, -2), Stack ::get (L, -1)); + lua_pop (L, 1); + } + return map; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_istable (L, index); + } +}; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/Vector.h b/lib/lua/3rd/LuaBridge/Vector.h new file mode 100644 index 00000000..cc803136 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/Vector.h @@ -0,0 +1,54 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + static void push (lua_State* L, std::vector const& vector) + { + lua_createtable (L, static_cast (vector.size ()), 0); + for (std::size_t i = 0; i < vector.size (); ++i) + { + lua_pushinteger (L, static_cast (i + 1)); + Stack ::push (L, vector [i]); + lua_settable (L, -3); + } + } + + static std::vector get (lua_State* L, int index) + { + if (!lua_istable (L, index)) + { + luaL_error (L, "#%d argument must be a table", index); + } + + std::vector vector; + vector.reserve (static_cast (get_length (L, index))); + + int const absindex = lua_absindex (L, index); + lua_pushnil (L); + while (lua_next (L, absindex) != 0) + { + vector.push_back (Stack ::get (L, -1)); + lua_pop (L, 1); + } + return vector; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_istable (L, index); + } +}; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/detail/CFunctions.h b/lib/lua/3rd/LuaBridge/detail/CFunctions.h new file mode 100644 index 00000000..d4ae0cca --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/CFunctions.h @@ -0,0 +1,495 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + 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 +#include + +#include + +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 + static int getVariable (lua_State* L) + { + assert (lua_islightuserdata (L, lua_upvalueindex (1))); + T const* ptr = static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (ptr != 0); + Stack ::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 + static int setVariable (lua_State* L) + { + assert (lua_islightuserdata (L, lua_upvalueindex (1))); + T* ptr = static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (ptr != 0); + *ptr = Stack ::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 + struct Call + { + typedef typename FuncTraits ::Params Params; + typedef typename FuncTraits ::ReturnType ReturnType; + + static int f (lua_State* L) + { + assert (lua_islightuserdata (L, lua_upvalueindex (1))); + FnPtr fnptr = reinterpret_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return Invoke ::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 + struct CallMember + { + typedef typename FuncTraits ::ClassType T; + typedef typename FuncTraits ::Params Params; + typedef typename FuncTraits ::ReturnType ReturnType; + + static int f (lua_State* L) + { + assert (isfulluserdata (L, lua_upvalueindex (1))); + T* const t = Userdata::get (L, 1, false); + MemFnPtr const& fnptr = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return Invoke ::run (L, t, fnptr); + } + }; + + template + struct CallConstMember + { + typedef typename FuncTraits ::ClassType T; + typedef typename FuncTraits ::Params Params; + typedef typename FuncTraits ::ReturnType ReturnType; + + static int f (lua_State* L) + { + assert (isfulluserdata (L, lua_upvalueindex (1))); + T const* const t = Userdata::get (L, 1, true); + MemFnPtr const& fnptr = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return Invoke ::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 + 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 (L, 1, false); + MFP const& fnptr = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return (t->*fnptr) (L); + } + }; + + template + 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 (L, 1, true); + MFP const& fnptr = *static_cast (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 + struct CallProxyFunction + { + using Params = typename FuncTraits ::Params; + using ReturnType = typename FuncTraits ::ReturnType; + + static int f (lua_State* L) + { + assert (lua_islightuserdata (L, lua_upvalueindex (1))); + auto fnptr = reinterpret_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return Invoke ::run (L, fnptr); + } + }; + + template + struct CallProxyFunctor + { + using Params = typename FuncTraits ::Params; + using ReturnType = typename FuncTraits ::ReturnType; + + static int f (lua_State* L) + { + assert (isfulluserdata (L, lua_upvalueindex (1))); + Functor& fn = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); + return Invoke ::run (L, fn); + } + }; + +#endif + + //-------------------------------------------------------------------------- + + // SFINAE Helpers + + template + 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 ::f, 1); + lua_pushvalue (L, -1); + rawsetfield (L, -5, name); // const table + rawsetfield (L, -3, name); // class table + } + }; + + template + struct CallMemberFunctionHelper + { + static void add (lua_State* L, char const* name, MemFnPtr mf) + { + new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf); + lua_pushcclosure (L, &CallMember ::f, 1); + rawsetfield (L, -3, name); // class table + } + }; + + //-------------------------------------------------------------------------- + /** + __gc metamethod for a class. + */ + template + static int gcMetaMethod (lua_State* L) + { + Userdata* const ud = Userdata::getExact (L, 1); + ud->~Userdata (); + return 0; + } + + /** + __gc metamethod for an arbitrary class. + */ + template + static int gcMetaMethodAny (lua_State* L) + { + assert (isfulluserdata (L, 1)); + T* t = static_cast (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 + static int getProperty (lua_State* L) + { + C* const c = Userdata::get (L, 1, true); + T C::** mp = static_cast (lua_touserdata (L, lua_upvalueindex (1))); + try + { + Stack ::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 + static int setProperty (lua_State* L) + { + C* const c = Userdata::get (L, 1, false); + T C::** mp = static_cast (lua_touserdata (L, lua_upvalueindex (1))); + try + { + c->**mp = Stack ::get (L, 2); + } + catch (const std::exception& e) + { + luaL_error (L, e.what ()); + } + return 0; + } +}; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/detail/ClassInfo.h b/lib/lua/3rd/LuaBridge/detail/ClassInfo.h new file mode 100644 index 00000000..ca83f93d --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/ClassInfo.h @@ -0,0 +1,169 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + + 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 (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 (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 (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 (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 (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 (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 (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 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 diff --git a/lib/lua/3rd/LuaBridge/detail/Config.h b/lib/lua/3rd/LuaBridge/detail/Config.h new file mode 100644 index 00000000..76b3d420 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/Config.h @@ -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 diff --git a/lib/lua/3rd/LuaBridge/detail/Constructor.h b/lib/lua/3rd/LuaBridge/detail/Constructor.h new file mode 100644 index 00000000..04b3dab0 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/Constructor.h @@ -0,0 +1,205 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + 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 +struct Constructor {}; + +template +struct Constructor +{ + static T* call (TypeListValues const&) + { + return new T; + } + static T* call (void* mem, TypeListValues const&) + { + return new (mem) T; + } +}; + +template +struct Constructor > +{ + static T* call (const TypeListValues > &tvl) + { + return new T(tvl.hd); + } + static T* call (void* mem, const TypeListValues > &tvl) + { + return new (mem) T(tvl.hd); + } +}; + +template +struct Constructor > > +{ + static T* call (const TypeListValues > > &tvl) + { + return new T(tvl.hd, tvl.tl.hd); + } + static T* call (void* mem, const TypeListValues > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd); + } +}; + +template +struct Constructor > > > +{ + static T* call (const TypeListValues > > > &tvl) + { + return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); + } + static T* call (void* mem, const TypeListValues > > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); + } +}; + +template +struct Constructor > > > > +{ + static T* call (const TypeListValues > > > > &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 > > > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); + } +}; + +template +struct Constructor > > > > > +{ + static T* call (const TypeListValues > > > > > &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 > > > > > &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 +struct Constructor > > > > > > +{ + static T* call (const TypeListValues > > > > > > &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 > > > > > > &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 +struct Constructor > > > > > > > +{ + static T* call (const TypeListValues > > > > > > > &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 > > > > > > > &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 +struct Constructor > > > > > > > > +{ + static T* call (const TypeListValues > > > > > > > > &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 > > > > > > > > &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 diff --git a/lib/lua/3rd/LuaBridge/detail/FuncTraits.h b/lib/lua/3rd/LuaBridge/detail/FuncTraits.h new file mode 100644 index 00000000..22b15863 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/FuncTraits.h @@ -0,0 +1,942 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2020, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + 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 + +#ifdef LUABRIDGE_CXX11 +#include +#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 +struct Caller; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & params) + { + return fn (); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues &) + { + return (obj->*fn) (); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & 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 +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & 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 + static ReturnType f (T* obj, MemFn& fn, TypeListValues & 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 +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & 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 + static ReturnType f (T* obj, MemFn& fn, TypeListValues & 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 +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & 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 + static ReturnType f (T* obj, MemFn& fn, TypeListValues & 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 +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & 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 + static ReturnType f (T* obj, MemFn& fn, TypeListValues & 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 +ReturnType doCall (Fn& fn, TypeListValues & tvl) +{ + return Caller ::value>::f (fn, tvl); +} + +template +static ReturnType doCall(T* obj, MemFn& fn, TypeListValues & tvl) +{ + return Caller ::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 +struct FuncTraits +{ +}; + +#ifndef LUABRIDGE_CXX11 + +/* Ordinary function pointers. */ + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef None Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */ + +#ifdef _M_IX86 // Windows 32bit only + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef None Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +#endif // _M_IX86 + +/* Non-const member function pointers. */ + +template +struct FuncTraits +{ + 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 & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +/* Const member function pointers. */ + +template +struct FuncTraits +{ + 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 & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > Params; + static R call (T const* obj, R (T::*fp) (P1, P2) const, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +#else // ifndef LUABRIDGE_CXX11 + +/* Ordinary function pointers. */ + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + using DeclType = R (*) (ParamList...); + using ReturnType = R; + using Params = typename MakeTypeList ::Result; + + static R call (const DeclType& fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */ + +#ifdef _M_IX86 // Windows 32bit only + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + using DeclType = R (__stdcall *) (ParamList...); + using ReturnType = R; + using Params = typename MakeTypeList ::Result; + + static R call (const DeclType& fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +#endif // _M_IX86 + +/* Non-const member function pointers. */ + +template +struct FuncTraits +{ + 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 ::Result; + + static R call (ClassType* obj, const DeclType& fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +/* Const member function pointers. */ + +template +struct FuncTraits +{ + 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 ::Result; + + static R call (const ClassType* obj, const DeclType& fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +/* std::function */ + +template +struct FuncTraits > +{ + static bool const isMemberFunction = false; + static bool const isConstMemberFunction = false; + using DeclType = std::function ; + using ReturnType = R; + using Params = typename MakeTypeList ::Result; + + static ReturnType call (DeclType& fn, TypeListValues & tvl) + { + return doCall (fn, tvl); + } +}; + +#endif // ifndef LUABRIDGE_CXX11 + +template +struct Invoke +{ + template + static int run (lua_State* L, Fn& fn) + { + try + { + ArgList args (L); + Stack ::push (L, FuncTraits ::call (fn, args)); + return 1; + } + catch (const std::exception& e) + { + return luaL_error (L, e.what ()); + } + } + + template + static int run (lua_State* L, T* object, const MemFn& fn) + { + try + { + ArgList args (L); + Stack ::push (L, FuncTraits ::call (object, fn, args)); + return 1; + } + catch (const std::exception& e) + { + return luaL_error (L, e.what ()); + } + } +}; + +template +struct Invoke +{ + template + static int run (lua_State* L, Fn& fn) + { + try + { + ArgList args (L); + FuncTraits ::call (fn, args); + return 0; + } + catch (const std::exception& e) + { + return luaL_error (L, e.what ()); + } + } + + template + static int run (lua_State* L, T* object, const MemFn& fn) + { + try + { + ArgList args (L); + FuncTraits ::call (object, fn, args); + return 0; + } + catch (const std::exception& e) + { + return luaL_error (L, e.what ()); + } + } +}; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/detail/Iterator.h b/lib/lua/3rd/LuaBridge/detail/Iterator.h new file mode 100644 index 00000000..6c176232 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/Iterator.h @@ -0,0 +1,154 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2018, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + 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 + +#include + + +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 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 diff --git a/lib/lua/3rd/LuaBridge/detail/LuaException.h b/lib/lua/3rd/LuaBridge/detail/LuaException.h new file mode 100644 index 00000000..836cb852 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/LuaException.h @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + Copyright 2008, Nigel Atkinson + + 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 +#include + +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 + 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 diff --git a/lib/lua/3rd/LuaBridge/detail/LuaHelpers.h b/lib/lua/3rd/LuaBridge/detail/LuaHelpers.h new file mode 100644 index 00000000..e336cf2b --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/LuaHelpers.h @@ -0,0 +1,151 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + 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 + +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 (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 (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 diff --git a/lib/lua/3rd/LuaBridge/detail/LuaRef.h b/lib/lua/3rd/LuaBridge/detail/LuaRef.h new file mode 100644 index 00000000..995c4650 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/LuaRef.h @@ -0,0 +1,1051 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2018, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + Copyright 2008, Nigel Atkinson + + 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 +#include + +#include +#include +#include +#include + +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 +{ + 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 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 + 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 ; + + //---------------------------------------------------------------------------- + /** + 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 (); + break; + + case LUA_TBOOLEAN: + os << (cast () ? "true" : "false"); + break; + + case LUA_TSTRING: + os << '"' << cast () << '"'; + 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 + T cast () const + { + StackPop p (m_L, 1); + impl ().push (); + return Stack ::get (m_L, -1); + } + + //---------------------------------------------------------------------------- + /** + Type check + */ + template + bool isInstance () const + { + StackPop p (m_L, 1); + impl ().push (); + return Stack ::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 operator T () const { return T (); } + }; + int main () { + S () || false; + return 0; + } + */ + template + operator T () const + { + return cast (); + } + + //---------------------------------------------------------------------------- + /** + Universal comparison operators. + */ + /** @{ */ + template + bool operator== (T rhs) const + { + StackPop p (m_L, 2); + impl ().push (); + Stack ::push (m_L, rhs); + return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1; + } + + template + bool operator< (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::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 + bool operator<= (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::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 + bool operator> (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::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 + bool operator>= (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::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 + bool rawequal (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::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 + void append (T v) const + { + impl ().push ();; + Stack ::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 + LuaRef operator() (P1 p1) const + { + impl ().push ();; + Stack ::push (m_L, p1); + LuaException::pcall (m_L, 1, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + LuaException::pcall (m_L, 2, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + LuaException::pcall (m_L, 3, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + LuaException::pcall (m_L, 4, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + LuaException::pcall (m_L, 5, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + Stack ::push (m_L, p6); + LuaException::pcall (m_L, 6, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + Stack ::push (m_L, p6); + Stack ::push (m_L, p7); + LuaException::pcall (m_L, 7, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const + { + impl ().push (); + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + Stack ::push (m_L, p6); + Stack ::push (m_L, p7); + Stack ::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 (*this); + } + + Impl& impl () + { + return static_cast (*this); + } +}; + +//------------------------------------------------------------------------------ +/** + Lightweight reference to a Lua object. + + The reference is maintained for the lifetime of the C++ object. +*/ +class LuaRef : public LuaRefBase +{ + //---------------------------------------------------------------------------- + /** + A proxy for representing table values. + */ + class Proxy : public LuaRefBase + { + 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 + 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 ::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 + 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 ::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 + 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 + LuaRef rawget (T key) const + { + return LuaRef (*this).rawget (key); + } + + private: + int m_tableRef; + int m_keyRef; + }; + + friend struct Stack ; + friend struct Stack ; + + //---------------------------------------------------------------------------- + /** + 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 + LuaRef (lua_State* L, T v) + : LuaRefBase (L) + , m_ref (LUA_NOREF) + { + Stack ::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 + 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 + Proxy operator[] (T key) const + { + Stack ::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 + LuaRef rawget (T key) const + { + StackPop (m_L, 1); + push (m_L); + Stack ::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 +{ + // 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 +{ + // 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 +T LuaRef_cast (LuaRef const& lr) +{ + return lr.cast (); +} + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/detail/Namespace.h b/lib/lua/3rd/LuaBridge/detail/Namespace.h new file mode 100644 index 00000000..68ae21fa --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/Namespace.h @@ -0,0 +1,1252 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + 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 +#include +#include +#include +#include + +#include +#include + +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 . + 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 + static int ctorContainerProxy (lua_State* L) + { + typedef typename ContainerTraits ::Type T; + ArgList args (L); + T* const p = Constructor ::call (args); + UserdataSharedHelper ::push (L, p); + return 1; + } + + //-------------------------------------------------------------------------- + /** + lua_CFunction to construct a class object in-place in the userdata. + */ + template + static int ctorPlacementProxy (lua_State* L) + { + ArgList args (L); + UserdataValue * value = UserdataValue ::place (L); + Constructor ::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 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 ); // 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 ); // 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 ::getStaticKey ()); // Stack: ns, co, cl, st + lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl + lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo ::getClassKey ()); // Stack: ns, co, cl, st + lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co + lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo ::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 ::getConstKey ()); // Stack: ns, st, co + lua_insert (L, -2); // Stack: ns, co, st + ++m_stackSize; + + lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::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 ); // 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 ); // 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 ::getStaticKey ()); // Stack: ns, co, cl, st + lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl + lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo ::getClassKey ()); // Stack: ns, co, cl, st + lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co + lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo ::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 & addStaticProperty (char const* name, U* pu, bool isWritable = true) + { + return addStaticData (name, pu, isWritable); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a static data member. + */ + template + Class & 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 , 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 , 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 & 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 (get)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // Stack: co, cl, st, getter + CFunc::addGetter (L, name, -2); // Stack: co, cl, st + + if (set != 0) + { + lua_pushlightuserdata (L, reinterpret_cast (set)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::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 & addStaticFunction (char const* name, FP const fp) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushlightuserdata (L, reinterpret_cast (fp)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // co, cl, st, function + rawsetfield (L, -2, name); // co, cl, st + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a lua_CFunction. + */ + Class & addStaticFunction (char const* name, int (*const fp) (lua_State*)) + { + return addStaticCFunction (name, fp); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a lua_CFunction. + */ + Class & 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 & addProperty (char const* name, U T::* mp, bool isWritable = true) + { + return addData (name, mp, isWritable); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a data member. + */ + template + Class & 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 , 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 , 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 & 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 ::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 ::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 & 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 ::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 ::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 & 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 (get)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::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 (set)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::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 & 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 & addProperty (char const* name, + std::function get, + std::function 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 ); // 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 ::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 ); // 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 ::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 & 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 ::isConstMemberFunction>::add (L, name, mf); + return *this; + } + +#else // ifndef LUABRIDGE_CXX11 + + //-------------------------------------------------------------------------- + /** + Add or replace a member function by std::function. + */ + template + Class & addFunction (char const* name, std::function 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 ); // 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 ::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 & addFunction (char const* name, std::function 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 ); // 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 ::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 & 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 ::add (L, name, mf); + return *this; + } + + template + Class & 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 ::add (L, name, mf); + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a proxy function. + */ + template + Class & 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 (proxyFn)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::CallProxyFunction ::f, 1); // Stack: co, cl, st, function + rawsetfield (L, -3, name); // Stack: co, cl, st + return *this; + } + + template + Class & 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 (proxyFn)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::CallProxyFunction ::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 & addFunction (char const* name, int (T::*mfp) (lua_State*)) + { + return addCFunction (name, mfp); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a member lua_CFunction. + */ + Class & 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 ::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 & addFunction (char const* name, int (T::*mfp) (lua_State*) const) + { + return addCFunction (name, mfp); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a const member lua_CFunction. + */ + Class & 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 ::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 & addConstructor () + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushcclosure (L, &ctorContainerProxy ::Params, C>, 0); + rawsetfield (L, -2, "__call"); + + return *this; + } + + template + Class & addConstructor () + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushcclosure (L, &ctorPlacementProxy ::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 + Namespace& addProperty (char const* name, T* pt, bool isWritable = true) + { + return addVariable (name, pt, isWritable); + } + + //---------------------------------------------------------------------------- + /** + Add or replace a variable. + */ + template + 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 , 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 , 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 + 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 (get)); // Stack: ns, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // Stack: ns, getter + CFunc::addGetter (L, name, -2); + + if (set != 0) + { + lua_pushlightuserdata(L, reinterpret_cast (set)); // Stack: ns, function ptr + lua_pushcclosure (L, &CFunc::Call ::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 + Namespace& addFunction (char const* name, FP const fp) + { + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + + lua_pushlightuserdata (L, reinterpret_cast (fp)); // Stack: ns, function ptr + lua_pushcclosure (L, &CFunc::Call ::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 beginClass (char const* name) + { + assertIsActive (); + return Class (name, *this); + } + + //---------------------------------------------------------------------------- + /** + Derive a new class for registrations. + + To continue registrations for the class later, use beginClass (). + Do not call deriveClass () again. + */ + template + Class deriveClass (char const* name) + { + assertIsActive (); + return Class (name, *this, ClassInfo ::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 diff --git a/lib/lua/3rd/LuaBridge/detail/Security.h b/lib/lua/3rd/LuaBridge/detail/Security.h new file mode 100644 index 00000000..51725456 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/Security.h @@ -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 +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 diff --git a/lib/lua/3rd/LuaBridge/detail/Stack.h b/lib/lua/3rd/LuaBridge/detail/Stack.h new file mode 100644 index 00000000..f00b9c9d --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/Stack.h @@ -0,0 +1,622 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + 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 +#include + +#include + +namespace luabridge { + +template +struct Stack; + +template <> +struct Stack +{ + static void push (lua_State* L) + { + } +}; + +//------------------------------------------------------------------------------ +/** + Receive the lua_State* as an argument. +*/ +template <> +struct Stack +{ + static lua_State* get (lua_State* L, int) + { + return L; + } +}; + +//------------------------------------------------------------------------------ +/** + Push a lua_CFunction. +*/ +template <> +struct Stack +{ + 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 +{ + static void push (lua_State* L, int value) + { + lua_pushinteger (L, static_cast (value)); + } + + static int get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, unsigned int value) + { + lua_pushinteger (L, static_cast (value)); + } + + static unsigned int get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, unsigned char value) + { + lua_pushinteger (L, static_cast (value)); + } + + static unsigned char get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, short value) + { + lua_pushinteger (L, static_cast (value)); + } + + static short get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, unsigned short value) + { + lua_pushinteger (L, static_cast (value)); + } + + static unsigned short get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, long value) + { + lua_pushinteger (L, static_cast (value)); + } + + static long get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, unsigned long value) + { + lua_pushinteger (L, static_cast (value)); + } + + static unsigned long get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, long long value) + { + lua_pushinteger (L, static_cast (value)); + } + + static long long get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, unsigned long long value) + { + lua_pushinteger (L, static_cast (value)); + } + static unsigned long long get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, float value) + { + lua_pushnumber (L, static_cast (value)); + } + + static float get (lua_State* L, int index) + { + return static_cast (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 +{ + static void push (lua_State* L, double value) + { + lua_pushnumber (L, static_cast (value)); + } + + static double get (lua_State* L, int index) + { + return static_cast (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 +{ + 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 +{ + 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 +{ + 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 +{ + 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 +struct StackOpSelector +{ + typedef T ReturnType; + + static void push (lua_State* L, T& value) + { + Stack ::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Stack ::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Stack ::isInstance (L, index); + } +}; + +template +struct StackOpSelector +{ + typedef T ReturnType; + + static void push (lua_State* L, const T& value) + { + Stack ::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Stack ::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Stack ::isInstance (L, index); + } +}; + +template +struct StackOpSelector +{ + typedef T ReturnType; + + static void push (lua_State* L, T* value) + { + Stack ::push (L, *value); + } + + static ReturnType get (lua_State* L, int index) + { + return Stack ::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Stack ::isInstance (L, index); + } +}; + +template +struct StackOpSelector +{ + typedef T ReturnType; + + static void push (lua_State* L, const T* value) + { + Stack ::push (L, *value); + } + + static ReturnType get (lua_State* L, int index) + { + return Stack ::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Stack ::isInstance (L, index); + } +}; + + +template +struct Stack +{ + typedef StackOpSelector ::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 +struct Stack +{ + typedef StackOpSelector ::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 +struct Stack +{ + typedef StackOpSelector ::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 +struct Stack +{ + typedef StackOpSelector ::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 +inline void push (lua_State* L, T t) +{ + Stack ::push (L, t); +} + +//------------------------------------------------------------------------------ +/** + * Check whether an object on the Lua stack is of type T. + */ +template +inline bool isInstance (lua_State* L, int index) +{ + return Stack ::isInstance (L, index); +} + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/detail/TypeList.h b/lib/lua/3rd/LuaBridge/detail/TypeList.h new file mode 100644 index 00000000..d142f6e1 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/TypeList.h @@ -0,0 +1,218 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + 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 +#include + +#include +#include + +namespace luabridge { + +/** + None type means void parameters or return value. +*/ +typedef void None; + +template +struct TypeList +{ + typedef Tail TailType; +}; + +template +struct TypeListSize +{ + static const size_t value = TypeListSize ::value + 1; +}; + +template <> +struct TypeListSize +{ + static const size_t value = 0; +}; + +#ifdef LUABRIDGE_CXX11 + +template +struct MakeTypeList; + +template +struct MakeTypeList +{ + using Result = TypeList ::Result>; +}; + +template <> +struct MakeTypeList <> +{ + using Result = None; +}; + +#endif + +/** + A TypeList with actual values. +*/ +template +struct TypeListValues +{ + static std::string const tostring (bool) + { + return ""; + } +}; + +/** + TypeListValues recursive template definition. +*/ +template +struct TypeListValues > +{ + Head hd; + TypeListValues tl; + + TypeListValues (Head hd_, TypeListValues 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 ::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 +struct TypeListValues > +{ + Head hd; + TypeListValues tl; + + TypeListValues (Head& hd_, TypeListValues 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 ::tostring (true); + } +}; + +template +struct TypeListValues > +{ + Head hd; + TypeListValues tl; + + TypeListValues (Head const& hd_, const TypeListValues & 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 ::tostring (true); + } +}; + +//============================================================================== +/** + Subclass of a TypeListValues constructable from the Lua stack. +*/ + +template +struct ArgList +{ +}; + +template +struct ArgList : public TypeListValues +{ + ArgList (lua_State*) + { + } +}; + +template +struct ArgList , Start> + : public TypeListValues > +{ + ArgList (lua_State* L) + : TypeListValues > (Stack ::get (L, Start), + ArgList (L)) + { + } +}; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/detail/TypeTraits.h b/lib/lua/3rd/LuaBridge/detail/TypeTraits.h new file mode 100644 index 00000000..5fad3756 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/TypeTraits.h @@ -0,0 +1,135 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + 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 + + +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 + struct ContainerTraits > + { + typedef typename T Type; + + static T* get (ContainerType const& c) + { + return c.get (); // Implementation-dependent on ContainerType + } + }; +*/ +template +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 + class isContainer + { + private: + typedef char yes[1]; // sizeof (yes) == 1 + typedef char no [2]; // sizeof (no) == 2 + + template + static no& test (typename C::isNotContainer*); + + template + static yes& test (...); + + public: + static const bool value = sizeof (test >(0)) == sizeof (yes); + }; + + /** Determine if T is const qualified. + */ + /** @{ */ + template + struct isConst + { + static bool const value = false; + }; + + template + struct isConst + { + static bool const value = true; + }; + /** @} */ + + /** Remove the const qualifier from T. + */ + /** @{ */ + template + struct removeConst + { + typedef T Type; + }; + + template + struct removeConst + { + typedef T Type; + }; + /**@}*/ +}; + + +template +struct Stack; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/detail/Userdata.h b/lib/lua/3rd/LuaBridge/detail/Userdata.h new file mode 100644 index 00000000..ef13d9fc --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/Userdata.h @@ -0,0 +1,829 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + 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 + +#include +#include + + +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 (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 (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 + static Userdata* getExact (lua_State* L, int index) + { + return getExactClass (L, index, ClassInfo ::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 + static T* get (lua_State* L, int index, bool canBeConst) + { + if (lua_isnil (L, index)) + return 0; + + return static_cast (getClass ( + L, index, ClassInfo ::getConstKey (), + ClassInfo ::getClassKey (), + canBeConst)->getPointer ()); + } + + template + static bool isInstance (lua_State* L, int index) + { + return isInstance (L, index, ClassInfo ::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 UserdataValue : public Userdata +{ +private: + UserdataValue (UserdataValue const&); + UserdataValue operator= (UserdataValue 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 * place (lua_State* const L) + { + UserdataValue * const ud = new ( + lua_newuserdata (L, sizeof (UserdataValue ))) UserdataValue (); + lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::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 + static inline void push (lua_State* const L, U const& u) + { + UserdataValue * 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 (&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 (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 + static void push (lua_State* const L, T* const p) + { + if (p) + push (L, p, ClassInfo ::getClassKey ()); + else + lua_pushnil (L); + } + + /** Push const pointer to object. + */ + template + static void push (lua_State* const L, T const* const p) + { + if (p) + push (L, p, ClassInfo ::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 UserdataShared : public Userdata +{ +private: + UserdataShared (UserdataShared const&); + UserdataShared & operator= (UserdataShared const&); + + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + C m_c; + +private: + ~UserdataShared () + { + } + +public: + /** + Construct from a container to the class or a derived class. + */ + template + explicit UserdataShared (U const& u) : m_c (u) + { + m_p = const_cast (reinterpret_cast ( + (ContainerTraits ::get (m_c)))); + } + + /** + Construct from a pointer to the class or a derived class. + */ + template + explicit UserdataShared (U* u) : m_c (u) + { + m_p = const_cast (reinterpret_cast ( + (ContainerTraits ::get (m_c)))); + } +}; + +//---------------------------------------------------------------------------- +// +// SFINAE helpers. +// + +// non-const objects +template +struct UserdataSharedHelper +{ + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + static void push (lua_State* L, C const& c) + { + if (ContainerTraits ::get (c) != 0) + { + new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (c); + lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::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 ))) UserdataShared (t); + lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::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 +struct UserdataSharedHelper +{ + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + static void push (lua_State* L, C const& c) + { + if (ContainerTraits ::get (c) != 0) + { + new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (c); + lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::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 ))) UserdataShared (t); + lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::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 +struct StackHelper +{ + static void push (lua_State* L, C const& c) + { + UserdataSharedHelper ::Type>::value>::push (L, c); + } + + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + static C get (lua_State* L, int index) + { + return Userdata::get (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 +struct StackHelper +{ + static inline void push (lua_State* L, T const& t) + { + UserdataValue ::push (L, t); + } + + static inline T const& get (lua_State* L, int index) + { + return *Userdata::get (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 +struct RefStackHelper +{ + typedef C return_type; + + static inline void push (lua_State* L, C const& t) + { + UserdataSharedHelper ::Type>::value>::push (L, t); + } + + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + static return_type get (lua_State* L, int index) + { + return Userdata::get (L, index, true); + } +}; + +template +struct RefStackHelper +{ + 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 (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 +struct Void +{ + typedef void Type; +}; + + +/** + * Trait class that selects whether to return a user registered + * class object by value or by reference. + */ + +template +struct UserdataGetter +{ + typedef T* ReturnType; + + static ReturnType get (lua_State* L, int index) + { + return Userdata::get (L, index, false); + } +}; + +template +struct UserdataGetter ::Type> +{ + typedef T ReturnType; + + static ReturnType get (lua_State* L, int index) + { + return StackHelper ::value>::get (L, index); + } +}; + +//============================================================================== + +/** + Lua stack conversions for class objects passed by value. +*/ +template +struct Stack +{ + typedef void IsUserdata; + + typedef UserdataGetter Getter; + typedef typename Getter::ReturnType ReturnType; + + static void push (lua_State* L, T const& value) + { + StackHelper ::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 (L, index); + } +}; + + +/** + * Trait class indicating whether the parameter type must be + * a user registered class. The trait checks the existence of + * member type Stack ::IsUserdata specialization for detection. + */ +template +struct IsUserdata +{ + static const bool value = false; +}; + +template +struct IsUserdata ::IsUserdata>::Type> +{ + static const bool value = true; +}; + + +/** + * Trait class that selects a specific push/get implemenation. + */ +template +struct StackOpSelector; + +// pointer +template +struct StackOpSelector +{ + 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 (L, index, false); + } + + static bool isInstance (lua_State* L, int index) + { + return Userdata::isInstance (L, index); + } +}; + +// pointer to const +template +struct StackOpSelector +{ + 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 (L, index, true); + } + + static bool isInstance (lua_State* L, int index) + { + return Userdata::isInstance (L, index); + } +}; + +// reference +template +struct StackOpSelector +{ + typedef RefStackHelper ::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 (L, index); + } +}; + +// reference to const +template +struct StackOpSelector +{ + typedef RefStackHelper ::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 (L, index); + } +}; + +} // namespace luabridge diff --git a/lib/lua/3rd/LuaBridge/detail/dump.h b/lib/lua/3rd/LuaBridge/detail/dump.h new file mode 100644 index 00000000..7e23f9f5 --- /dev/null +++ b/lib/lua/3rd/LuaBridge/detail/dump.h @@ -0,0 +1,143 @@ +//============================================================================== +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + 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 +#include + + +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 diff --git a/lib/lua/piluaprogram.cpp b/lib/lua/piluaprogram.cpp new file mode 100644 index 00000000..93603e86 --- /dev/null +++ b/lib/lua/piluaprogram.cpp @@ -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 . +*/ +#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); +} + diff --git a/lib/main/cloud/piccloudclient.h b/lib/main/cloud/piccloudclient.h index 30eea971..b54cd73c 100644 --- a/lib/main/cloud/piccloudclient.h +++ b/lib/main/cloud/piccloudclient.h @@ -23,16 +23,26 @@ #ifndef PICCLOUDCLIENT_H #define PICCLOUDCLIENT_H +#include "pip_cloud_export.h" #include "piiodevice.h" +class PIEthernet; -class PIP_EXPORT PICloudClient { + +class PIP_CLOUD_EXPORT PICloudClient : public PIIODevice +{ + PIIODEVICE(PICloudClient) public: //! explicit PICloudClient(); + virtual ~PICloudClient(); + +protected: + bool openDevice(); + bool closeDevice(); private: - + PIEthernet * eth; }; #endif // PICCLOUDCLIENT_H diff --git a/lib/main/cloud/piccloudserver.h b/lib/main/cloud/piccloudserver.h index eb65d1de..cf0e4e23 100644 --- a/lib/main/cloud/piccloudserver.h +++ b/lib/main/cloud/piccloudserver.h @@ -23,10 +23,11 @@ #ifndef PICCLOUDSERVER_H #define PICCLOUDSERVER_H +#include "pip_cloud_export.h" #include "piiodevice.h" -class PIP_EXPORT PICloudServer { +class PIP_CLOUD_EXPORT PICloudServer { public: //! explicit PICloudServer(); diff --git a/lib/main/cloud/piccloudtcp.h b/lib/main/cloud/piccloudtcp.h index 2d0c0703..ea0e4f5c 100644 --- a/lib/main/cloud/piccloudtcp.h +++ b/lib/main/cloud/piccloudtcp.h @@ -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(); diff --git a/lib/main/code/picodeinfo.h b/lib/main/code/picodeinfo.h index 5b182fc5..97506149 100644 --- a/lib/main/code/picodeinfo.h +++ b/lib/main/code/picodeinfo.h @@ -30,7 +30,7 @@ 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 * classesInfo; -extern PIMap * enumsInfo; -extern PIMap * accessValueFunctions; -extern PIMap * accessTypeFunctions; +extern PIP_EXPORT PIMap * classesInfo; +extern PIP_EXPORT PIMap * enumsInfo; +extern PIP_EXPORT PIMap * accessValueFunctions; +extern PIP_EXPORT PIMap * 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; diff --git a/lib/main/code/picodeparser.cpp b/lib/main/code/picodeparser.cpp index 8d26d1fe..9e7271d0 100644 --- a/lib/main/code/picodeparser.cpp +++ b/lib/main/code/picodeparser.cpp @@ -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,42 +99,42 @@ 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;*/ } void PICodeParser::parseFiles(const PIStringList & files, bool follow_includes) { clear(); piForeachC (PIString & f, files) - parseFileInternal(f, 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 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; @@ -256,7 +259,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) { if (ind + m.name.size_s() < pfc.size_s()) nc = pfc.mid(ind + m.name.size_s(),1)[0]; if (_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; @@ -274,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; @@ -323,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); } @@ -333,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 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;} @@ -356,11 +359,11 @@ 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 = ""; + if (cn.isEmpty()) cn = PIStringAscii("'; //piCout << "found " << typename_ << cn; if (cn.isEmpty()) return 0; Entity * e = new Entity(); @@ -377,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****>"; @@ -390,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; } @@ -434,7 +437,7 @@ 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()) {fc.cutLeft(1);} ps = fc.size_s(); @@ -448,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; @@ -463,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); @@ -492,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; @@ -509,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; @@ -544,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); @@ -586,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;} @@ -606,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); @@ -637,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()) { @@ -664,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(); @@ -674,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()) { @@ -681,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) { @@ -694,27 +726,29 @@ 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) - if ((f = e.name.find(n)) >= 0) - if (e.name.mid(f - 1, 1) == ":") - if (e.name.find(cur_namespace) >= 0) { - //piCout << "change" << n << "to" << e.name + suff; - n = pref + e.name + suff; - return; + piForeachC (Enum & e, enums) { + if ((f = e.name.find(n)) >= 0) + 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) - if ((f = e.first.find(n)) >= 0) - if (e.first.mid(f - 1, 1) == ":") - if (e.first.find(cur_namespace) >= 0) { - //piCout << "change" << n << "to" << e.name + suff; - n = pref + e.first + suff; - return; + piForeachC (Typedef & e, typedefs) { + if ((f = e.first.find(n)) >= 0) + 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(); } @@ -723,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)]; } @@ -744,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(); } @@ -754,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; @@ -770,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(); @@ -825,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")); } } @@ -849,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;} @@ -861,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; } @@ -885,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; @@ -904,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) { @@ -922,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; @@ -944,8 +978,8 @@ PIString PICodeParser::procMacros(PIString fc) { //return false; /// WARNING: now skip errors } } else { - if (grab) nfc << line << "\n"; - else if (!skip) pfc << line << "\n"; + if (grab) nfc << line << '\n'; + else if (!skip) pfc << line << '\n'; } } return pfc; @@ -956,21 +990,21 @@ 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(); @@ -979,7 +1013,7 @@ bool PICodeParser::parseDirective(PIString d) { } 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;} diff --git a/lib/main/code/picodeparser.h b/lib/main/code/picodeparser.h index 9eaf2821..716dda9a 100644 --- a/lib/main/code/picodeparser.h +++ b/lib/main/code/picodeparser.h @@ -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, diff --git a/lib/main/math/picompress.h b/lib/main/compress/picompress.h similarity index 82% rename from lib/main/math/picompress.h rename to lib/main/compress/picompress.h index 187b019e..e0ada4d0 100644 --- a/lib/main/math/picompress.h +++ b/lib/main/compress/picompress.h @@ -23,10 +23,11 @@ #ifndef PICOMPRESS_H #define PICOMPRESS_H +#include "pip_compress_export.h" #include "pibytearray.h" -PIByteArray piCompress(const PIByteArray & ba, int level = 6); +PIP_COMPRESS_EXPORT PIByteArray piCompress(const PIByteArray & ba, int level = 6); -PIByteArray piDecompress(const PIByteArray & zba); +PIP_COMPRESS_EXPORT PIByteArray piDecompress(const PIByteArray & zba); #endif // PICOMPRESS_H diff --git a/lib/main/console/piconsole.h b/lib/main/console/piconsole.h deleted file mode 100644 index 5e843d1d..00000000 --- a/lib/main/console/piconsole.h +++ /dev/null @@ -1,461 +0,0 @@ -/*! \file piconsole.h - * \brief Console output class -*/ -/* - PIP - Platform Independent Primitives - Console output/input - 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 . -*/ - -#ifndef PICONSOLE_H -#define PICONSOLE_H - -#include "pikbdlistener.h" - -class PIProtocol; -class PIDiagnostics; -class PISystemMonitor; -class PIPeer; -class PITimer; - -class PIP_EXPORT PIConsole: public PIThread -{ - PIOBJECT_SUBCLASS(PIConsole, PIThread) -public: - - //! Constructs %PIConsole with key handler "slot" and if "startNow" start it - explicit PIConsole(bool startNow = true, PIKbdListener::KBFunc slot = 0); - - ~PIConsole(); - - - //! Variables output format - enum Format { - Normal /** Default console format */ = 0x01, - Bold /** Bold text */ = 0x02, - Faint = 0x04, - Italic = 0x08, - Underline /** Underlined text */ = 0x10, - Blink /** Blinked text */ = 0x20, - Inverse /** Swap text and background colors */ = 0x40, - Black /** Black text */ = 0x100, - Red /** Red text */ = 0x200, - Green /** Green text */ = 0x400, - Yellow /** Yellow text */ = 0x800, - Blue /** Blue text */ = 0x1000, - Magenta /** Magenta text */ = 0x2000, - Cyan /** Cyan text */ = 0x4000, - White /** White text */ = 0x8000, - BackBlack /** Black background */ = 0x10000, - BackRed /** Red background */ = 0x20000, - BackGreen /** Green background */ = 0x40000, - BackYellow /** Yellow background */ = 0x80000, - BackBlue /** Blue background */ = 0x100000, - BackMagenta /** Magenta background */ = 0x200000, - BackCyan /** Cyan background */ = 0x400000, - BackWhite /** White background */ = 0x800000, - Dec /** Decimal base for integers */ = 0x1000000, - Hex /** Hexadecimal base for integers */ = 0x2000000, - Oct /** Octal base for integers */ = 0x4000000, - Bin /** Binary base for integers */ = 0x8000000, - Scientific /** Scientific representation of floats */ = 0x10000000, - SystemTimeSplit /** PISystemTime split representation (* s, * ns) */ = 0x20000000, - SystemTimeSeconds /** PISystemTime seconds representation (*.* s) */ = 0x40000000 - }; - - //! Column labels alignment - enum Alignment { - Nothing /** No alignment */ , - Left /** Labels align left and variables align left */ , - Right /** Labels align right and variables align left */ - }; - - typedef PIFlags FormatFlags; - - //! Add to current tab to column "column" string "name" with format "format" - void addString(const PIString & name, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const PIString * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const char * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const bool * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const short * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const int * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const long * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const llong * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const uchar * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const ushort * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const uint * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const ulong * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const ullong * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const float * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const double * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const PISystemTime * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - void addVariable(const PIString & name, const PIDiagnostics * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - void addVariable(const PIString & name, const PISystemMonitor * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" bits field with label "name", pointer "ptr" and format "format" - void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitsCount, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" "count" empty lines - void addEmptyLine(int column = 1, uint count = 1); - - PIString getString(int x, int y); - short getShort(int x, int y) {return getString(x, y).toShort();} - int getInt(int x, int y) {return getString(x, y).toInt();} - float getFloat(int x, int y) {return getString(x, y).toFloat();} - double getDouble(int x, int y) {return getString(x, y).toDouble();} - PIString getString(const PIString & name); - short getShort(const PIString & name) {return getString(name).toShort();} - int getInt(const PIString & name) {return getString(name).toInt();} - float getFloat(const PIString & name) {return getString(name).toFloat();} - double getDouble(const PIString & name) {return getString(name).toDouble();} - - - //! Returns tabs count - uint tabsCount() const {return tabs.size();} - - //! Returns current tab name - PIString currentTab() const {return tabs[cur_tab].name;} - - //! Returns current tab index - int currentTabIndex() const {return cur_tab;} - - //! Add new tab with name "name", bind key "bind_key" and returns this tab index - int addTab(const PIString & name, char bind_key = 0); - - //! Remove tab with index "index" - void removeTab(uint index); - - //! Remove tab with name "name" - void removeTab(const PIString & name); - - //! Clear content of tab with index "index" - void clearTab(uint index); - - //! Clear content of tab with name "name" - void clearTab(const PIString & name); - - //! Set current tab to tab with index "index", returns if tab exists - bool setTab(uint index); - - //! Set current tab to tab with name "name", returns if tab exists - bool setTab(const PIString & name); - - //! Set tab with index "index" bind key to "bind_key", returns if tab exists - bool setTabBindKey(uint index, char bind_key); - - //! Set tab with name "name" bind key to "bind_key", returns if tab exists - bool setTabBindKey(const PIString & name, char bind_key); - - //! Remove all tabs and if "clearScreen" clear the screen - void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();} - - - //! Set custom status text of current tab to "str" - void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;} - - //! Clear custom status text of current tab - void clearCustomStatus() {tabs[cur_tab].status.clear();} - - //! Returns default alignment - Alignment defaultAlignment() const {return def_align;} - - //! Set default alignment to "align" - void setDefaultAlignment(Alignment align) {def_align = align;} - - //! Set column "col" alignment to "align" - void setColumnAlignment(int col, Alignment align) {if (col < 0 || col >= columns().size_s()) return; column(col).alignment = align;} - - //! Set all columns of all tabs alignment to "align" - void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();} - - - //! Directly call function from \a PIKbdListener - void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);} - - //! Directly call function from \a PIKbdListener - void disableExitCapture() {listener->disableExitCapture();} - - //! Directly call function from \a PIKbdListener - bool exitCaptured() const {return listener->exitCaptured();} - - //! Directly call function from \a PIKbdListener - char exitKey() const {return listener->exitKey();} - - - int windowWidth() const {return width;} - int windowHeight() const {return height;} - - PIString fstr(FormatFlags f); - void update(); - void pause(bool yes) {pause_ = yes;} - - // Server functions - void startServer(const PIString & name); - void stopPeer(); - bool isServerStarted() const {return peer != 0;} - PIStringList clients() const; - - // Client functions - void listenServers(); - PIStringList availableServers() const; - PIString selectedServer() const {return server_name;} - void connectToServer(const PIString & name); - void disconnect(); - bool isConnected() const {return state == Connected;} - - void toUpperLeft(); - void moveRight(int n = 1); - void moveLeft(int n = 1); - void moveTo(int x = 0, int y = 0); - void clearScreen(); - void clearScreenLower(); - void clearLine(); - void newLine(); - void hideCursor(); - void showCursor(); - - EVENT_HANDLER0(void, clearVariables) {clearVariables(true);} - EVENT_HANDLER1(void, clearVariables, bool, clearScreen); - - EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT} - EVENT_HANDLER0(void, start) {start(false);} - EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();} - EVENT_HANDLER0(void, stop) {stop(false);} - EVENT_HANDLER1(void, stop, bool, clear); - - EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data) - - //! \handlers - //! \{ - - //! \fn void waitForFinish() - //! \brief block until finished (exit key will be pressed) - - //! \fn void clearVariables(bool clearScreen = true) - //! \brief Remove all columns at current tab and if "clearScreen" clear the screen - - //! \fn void start(bool wait = false) - //! \brief Start console output and if "wait" block until finished (exit key will be pressed) - - //! \fn void stop(bool clear = false) - //! \brief Stop console output and if "clear" clear the screen - - //! \} - //! \events - //! \{ - - //! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data) - //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object - - //! \} - - private: - void begin(); - void run(); - void fillLabels(); - void status(); - void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));} - int bitsValue(const void * src, int offset, int count) const; - const char * toBin(const void * d, int s); - inline void printLine(const PIString & str, int dx = 0, FormatFlags format = PIConsole::Normal); - inline int printValue(const PIString & str, FormatFlags format = PIConsole::Normal); - inline int printValue(const char * str, FormatFlags format = PIConsole::Normal); - inline int printValue(const bool value, FormatFlags format = PIConsole::Normal); - inline int printValue(const int value, FormatFlags format = PIConsole::Normal); - inline int printValue(const long value, FormatFlags format = PIConsole::Normal); - inline int printValue(const llong value, FormatFlags format = PIConsole::Normal); - inline int printValue(const float value, FormatFlags format = PIConsole::Normal); - inline int printValue(const double value, FormatFlags format = PIConsole::Normal); - inline int printValue(const char value, FormatFlags format = PIConsole::Normal); - inline int printValue(const short value, FormatFlags format = PIConsole::Normal); - inline int printValue(const uchar value, FormatFlags format = PIConsole::Normal); - inline int printValue(const ushort value, FormatFlags format = PIConsole::Normal); - inline int printValue(const uint value, FormatFlags format = PIConsole::Normal); - inline int printValue(const ulong value, FormatFlags format = PIConsole::Normal); - inline int printValue(const ullong value, FormatFlags format = PIConsole::Normal); - inline int printValue(const PISystemTime & value, FormatFlags format = PIConsole::Normal); - static void key_event(PIKbdListener::KeyEvent key, void * t); - - struct Variable { - Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = Normal; remote = false; ptr = 0; id = 1;} - Variable(const Variable & src) {remote = src.remote; name = src.name; format = src.format; type = src.type; offset = src.offset; size = src.size; - bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;} - bool isEmpty() const {return (remote ? false : ptr == 0);} - const void * data() {return (remote ? rdata.data() : ptr);} - void writeData(PIByteArray & ba) { - if (remote) ba << rdata; - else { - if (type == 0) ba << (*(PIString * )ptr); - else ba << PIByteArray::RawData(ptr, size); - } - } - PIString name; - FormatFlags format; - int nx; - int ny; - int type; - int offset; - int bitFrom; - int bitCount; - int size; - int id; - bool remote; - const void * ptr; - PIByteArray rdata; - void operator =(const Variable & src) {remote = src.remote; name = src.name; format = src.format; type = src.type; offset = src.offset; size = src.size; - bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;} - }; - - struct VariableContent { - int id; - PIByteArray rdata; - }; - - struct Column { - Column(Alignment align = PIConsole::Right) {variables.reserve(32); alignment = align;} - PIVector variables; - Alignment alignment; - uint size() const {return variables.size();} - Variable & operator [](int index) {return variables[index];} - const Variable & operator [](int index) const {return variables[index];} - void push_back(const Variable & v) {variables.push_back(v);} - void operator =(const Column & src) {variables = src.variables; alignment = src.alignment;} - }; - - struct Tab { - Tab(PIString n = "", char k = 0) {columns.reserve(8); name = n; key = k;} - PIVector columns; - PIString name; - PIString status; - char key; - }; - - enum ConnectedState {Disconnected, FetchingData, Committing, Connected}; - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v); - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v); - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v); - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v); - - PIVector & columns() {return tabs[cur_tab].columns;} - Column & column(int index) {return tabs[cur_tab].columns[index - 1];} - int couts(const PIString & v); - int couts(const char * v); - int couts(const bool v); - int couts(const char v); - int couts(const short v); - int couts(const int v); - int couts(const long v); - int couts(const llong v); - int couts(const uchar v); - int couts(const ushort v); - int couts(const uint v); - int couts(const ulong v); - int couts(const ullong v); - int couts(const float v); - int couts(const double v); - int couts(const PISystemTime & v); - - struct RemoteClient; - - void serverSendInfo(); - void serverSendData(); - RemoteClient & remoteClient(const PIString & fname); - EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data); - EVENT_HANDLER2(void, peerTimer, void * , data, int, delim); - EVENT_HANDLER1(void, peerDisconnectedEvent, const PIString &, name); - - PRIVATE_DECLARATION - PIVector tabs; - PIString binstr, rstr; - PIByteArray rba; - Variable tv; - PIKbdListener * listener; - Alignment def_align; - PIKbdListener::KBFunc ret_func; - int width, height, pwidth, pheight, col_wid, num_format, systime_format; - uint max_y; - int vid; - uint cur_tab, col_cnt; - - PIPeer * peer; - PITimer * peer_timer; - PITimeMeasurer peer_tm; - PIString server_name; - bool server_mode, pause_; - ConnectedState state; - - struct RemoteClient { - RemoteClient(const PIString & n = "") {name = n; state = Disconnected;} - PIString name; - ConnectedState state; - }; - - PIVector remote_clients; - -}; - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v) {ba << v.id << v.rdata; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v) {ba >> v.id; ba >> v.rdata; return ba;} - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v) {ba << v.name << v.id << (int)v.format << v.type << v.size << v.bitFrom << v.bitCount; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v) {ba >> v.name >> v.id >> (int & )v.format >> v.type >> v.size >> v.bitFrom >> v.bitCount; return ba;} - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v) {ba << (int)v.alignment << v.variables; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v) {int a; ba >> a >> v.variables; v.alignment = (PIConsole::Alignment)a; return ba;} - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v) {ba << v.name << v.status << (uchar)v.key << v.columns; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v) {ba >> v.name >> v.status >> (uchar&)v.key >> v.columns; return ba;} - -#endif // PICONSOLE_H diff --git a/lib/main/console/piconsolemodule.h b/lib/main/console/piconsolemodule.h index d6f24eab..a266884c 100644 --- a/lib/main/console/piconsolemodule.h +++ b/lib/main/console/piconsolemodule.h @@ -21,7 +21,6 @@ #define PICONSOLEMODULE_H #include "pikbdlistener.h" -#include "piconsole.h" #include "piscreen.h" #include "piscreentiles.h" diff --git a/lib/main/console/pikbdlistener.h b/lib/main/console/pikbdlistener.h index 8da6553c..c1bf9906 100644 --- a/lib/main/console/pikbdlistener.h +++ b/lib/main/console/pikbdlistener.h @@ -77,7 +77,7 @@ public: typedef PIFlags 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 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 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 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; diff --git a/lib/main/console/piscreen.h b/lib/main/console/piscreen.h index 493fc84e..34439e1b 100644 --- a/lib/main/console/piscreen.h +++ b/lib/main/console/piscreen.h @@ -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 > cells, pcells; diff --git a/lib/main/console/piscreenconsole.h b/lib/main/console/piscreenconsole.h index 4b745b1d..cd45ba73 100644 --- a/lib/main/console/piscreenconsole.h +++ b/lib/main/console/piscreenconsole.h @@ -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(); diff --git a/lib/main/console/piscreendrawer.h b/lib/main/console/piscreendrawer.h index 3efd48fd..6a118adb 100644 --- a/lib/main/console/piscreendrawer.h +++ b/lib/main/console/piscreendrawer.h @@ -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 > & c); diff --git a/lib/main/console/piscreentile.h b/lib/main/console/piscreentile.h index e9ab7b30..28e7dcd7 100644 --- a/lib/main/console/piscreentile.h +++ b/lib/main/console/piscreentile.h @@ -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: diff --git a/lib/main/console/piscreentiles.h b/lib/main/console/piscreentiles.h index b6c41a25..ee617156 100644 --- a/lib/main/console/piscreentiles.h +++ b/lib/main/console/piscreentiles.h @@ -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 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,7 +192,7 @@ protected: }; -class PIP_EXPORT TileInput: public PIScreenTile { +class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile { PIOBJECT_SUBCLASS(TileInput, PIScreenTile) public: TileInput(const PIString & n = PIString()); diff --git a/lib/main/console/piscreentypes.h b/lib/main/console/piscreentypes.h index 34c3349b..05335ed1 100644 --- a/lib/main/console/piscreentypes.h +++ b/lib/main/console/piscreentypes.h @@ -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,13 +68,13 @@ namespace PIScreenTypes { }; //! Direction - enum PIP_EXPORT Direction { + enum Direction { Horizontal /** Horizontal */ , Vertical /** Vertical */ }; //! 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, @@ -87,7 +88,7 @@ namespace PIScreenTypes { typedef PIFlags CharFlags; typedef PIFlags 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; @@ -104,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; @@ -120,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() {} diff --git a/lib/main/console/piterminal.h b/lib/main/console/piterminal.h index 040892dd..b519d6bd 100644 --- a/lib/main/console/piterminal.h +++ b/lib/main/console/piterminal.h @@ -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; diff --git a/lib/main/containers/picontainers.cpp b/lib/main/containers/picontainers.cpp index d4a356c8..41ba1fb2 100644 --- a/lib/main/containers/picontainers.cpp +++ b/lib/main/containers/picontainers.cpp @@ -28,147 +28,347 @@ * \fn PIVector::PIVector(); * Contructs an empty vector - * \fn PIVector::PIVector(ullong size, const Type & value = Type()); + * \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 Type & PIVector::at(ullong index) const; + * \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 Type & PIVector::at(ullong index); + * \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 Type * PIVector::data(ullong index = 0) const; + * \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 Type * PIVector::data(ullong index = 0); + * \fn T * PIVector::data(size_t index = 0); * \brief Pointer to element by index "index" * \details Example: \snippet picontainers.cpp PIVector::data - * \fn ullong PIVector::size() const; + * \fn size_t PIVector::size() const; * \brief Elements count - * \fn int PIVector::size_s() const; + * \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 Type & t) const; + * \fn bool PIVector::has(const T & t) const; - * \fn bool PIVector::contains(const Type & v) 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 Type & t) const; + * \fn int PIVector::etries(const T & t) const; * \brief Return how many times element "t" appears in vector - * \fn static int PIVector::compare_func(const Type * t0, const Type * t1); - * \brief Standard compare function for type "Type". Return 0 if t0 = t1, -1 if t0 < t1 and 1 if t0 > t1. + * \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 void PIVector::resize(ullong size, const Type & new_type = Type()); + * \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(ullong size); + * \fn PIVector & PIVector::enlarge(size_t size); * \brief Increase vector size with "size" elements * \fn void PIVector::clear(); * \brief Clear vector. Equivalent to call "resize(0)" - * \fn PIVector & PIVector::sort(CompareFunc compare = compare_func); + * \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 Type & t); + * \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 Type & PIVector::back(); + * \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 Type & PIVector::back() const; + * \fn const T & PIVector::back() const; * \brief Last element of the vector - * \fn Type & PIVector::front(); + * \fn T & PIVector::front(); * \brief First element of the vector - * \fn const Type & PIVector::front() const; + * \fn const T & PIVector::front() const; * \brief First element of the vector - * \fn PIVector & PIVector::push_back(const Type & t); + * \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 Type & t); + * \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(); + * \fn PIVector & PIVector::pop_back(); * \brief Remove one element from the end of vector and return reference to vector - * \fn PIVector & PIVector::pop_front(); + * \fn PIVector & PIVector::pop_front(); * \brief Remove one element from the beginning of vector and return reference to vector - * \fn Type PIVector::take_back(); + * \fn T PIVector::take_back(); * \brief Remove one element from the end of vector and return it - * \fn Type PIVector::take_front(); + * \fn T PIVector::take_front(); * \brief Remove one element from the beginning of vector and return it - * \fn PIVector & PIVector::remove(uint index); + * \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(uint index, uint count); + * \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 Type & v); + * \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 Type & v); + * \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(uint pos, const Type & t); + * \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(uint pos, const PIVector & t); + * \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 Type & PIVector::operator [](uint index); + * \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 Type & PIVector::operator [](uint index) const; + * \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 Type & t); + * \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); + * \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); + * \fn bool PIVector::operator ==(const PIVector & t); * \brief Compare with vector "t" - * \fn bool PIVector::operator !=(const PIVector & 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 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 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 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 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. + + * */ diff --git a/lib/main/containers/picontainers.h b/lib/main/containers/picontainers.h index 688388de..0487c892 100644 --- a/lib/main/containers/picontainers.h +++ b/lib/main/containers/picontainers.h @@ -97,141 +97,32 @@ */ # define piForeachCR(i,c) -/*!\brief Macro for break from any piForeach* loop - * \details \warning C++ ordinary "break" doesn`t work inside piForeach* - * loops! Always use "piBreak" instead! - */ -# define piBreak - #else -# define piBreak {_for._end = true; break;} + +template +struct _reverse_wrapper { + C & c_; + _reverse_wrapper(C & c): c_(c) {} + _reverse_wrapper(const C & c): c_(const_cast(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 _reverse_wrapper _reverse_wrap(C & c) {return _reverse_wrapper(c);} +template _reverse_wrapper _reverse_wrap(const C & c) {return _reverse_wrapper(c);} + # define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c) -#ifdef CC_GCC +# 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)) -template -class _PIForeach { -public: - _PIForeach(Type & t): _t(t), _break(false), _end(false) {_it = _t.begin();} - typename Type::value_type _var; - typename Type::iterator _it; - Type & _t; - bool _break, _end; - inline bool isEnd() {return _it == _t.end();} - inline void operator ++() {if (_end) _it = _t.end(); else _it++; _break = false;} -}; - -template -class _PIForeachR { -public: - _PIForeachR(Type & t): _t(t), _break(false), _end(false) {_rit = _t.rbegin();} - typename Type::value_type _var; - typename Type::reverse_iterator _rit; - Type & _t; - bool _break, _end; - inline bool isEnd() {return _rit == _t.rend();} - inline void operator ++() {if (_end) _rit = _t.rend(); else _rit++; _break = false;} -}; - -template -class _PIForeachC { -public: - _PIForeachC(const Type & t): _t(t), _break(false), _end(false) {_it = _t.begin();} - typename Type::value_type _var; - typename Type::const_iterator _it; - const Type & _t; - bool _break, _end; - inline bool isEnd() {return _it == _t.end();} - inline void operator ++() {if (_end) _it = _t.end(); else _it++; _break = false;} -}; - -template -class _PIForeachCR { -public: - _PIForeachCR(const Type & t): _t(t), _break(false), _end(false) {_rit = _t.rbegin();} - typename Type::value_type _var; - typename Type::const_reverse_iterator _rit; - const Type & _t; - bool _break, _end; - inline bool isEnd() {return _rit == _t.rend();} - inline void operator ++() {if (_end) _rit = _t.rend(); else _rit++; _break = false;} -}; - -#define piForeach(i,c) for(_PIForeach _for(c); !_for.isEnd(); ++_for) \ - for(i(*_for._it); !_for._break; _for._break = true) -#define piForeachR(i,c) for(_PIForeachR _for(c); !_for.isEnd(); ++_for) \ - for(i(*_for._rit); !_for._break; _for._break = true) -#define piForeachA(i,c) for(_PIForeach _for(c); !_for.isEnd(); ++_for) \ - for(typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true) -#define piForeachAR(i,c) for(_PIForeachR _for(c); !_for.isEnd(); ++_for) \ - for(typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true) -#define piForeachC(i,c) for(_PIForeachC _for(c); !_for.isEnd(); ++_for) \ - for(const i(*_for._it); !_for._break; _for._break = true) -#define piForeachCR(i,c) for(_PIForeachCR _for(c); !_for.isEnd(); ++_for) \ - for(const i(*_for._rit); !_for._break; _for._break = true) -#define piForeachCA(i,c) for(_PIForeachC _for(c); !_for.isEnd(); ++_for) \ - for(const typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true) -#define piForeachCAR(i,c) for(_PIForeachCR _for(c); !_for.isEnd(); ++_for) \ - for(const typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true) - -#define piForeachRA piForeachAR -#define piForeachAC piForeachCA -#define piForeachCRA piForeachCAR -#define piForeachARC piForeachCAR -#define piForeachACR piForeachCAR -#define piForeachRCA piForeachCAR -#define piForeachRAC piForeachCAR - -#else - -class _PIForeachBase {public: mutable bool _break, _end; }; - -template -class _PIForeach: public _PIForeachBase { -public: - _PIForeach(Type & t, bool i = false): _t(t), _inv(i) {_break = _end = false; if (_inv) _rit = _t.rbegin(); else _it = _t.begin();} - mutable typename Type::value_type _var; - mutable typename Type::iterator _it; - mutable typename Type::reverse_iterator _rit; - Type & _t; - bool _inv; - bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} - void operator ++() {if (_inv) {if (_end) _rit = _t.rend(); else _rit++;} else {if (_end) _it = _t.end(); else _it++;} _break = false;} -}; - -template -class _PIForeachC: public _PIForeachBase { -public: - _PIForeachC(const Type & t, bool i = false): _t(t), _inv(i) {_break = _end = false; if (_inv) _rit = _t.rbegin(); else _it = _t.begin();} - mutable typename Type::value_type _var; - mutable typename Type::const_iterator _it; - mutable typename Type::const_reverse_iterator _rit; - const Type & _t; - bool _inv; - bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} - void operator ++() {if (_inv) {if (_end) _rit = _t.rend(); else _rit++;} else {if (_end) _it = _t.end(); else _it++;} _break = false;} -}; - -template inline _PIForeach _PIForeachNew(T & t, bool i = false) {return _PIForeach(t, i);} -template inline _PIForeach * _PIForeachCast(_PIForeachBase & c, T & ) {return static_cast<_PIForeach * >(&c);} - -template inline _PIForeachC _PIForeachNewC(const T & t, bool i = false) {return _PIForeachC(t, i);} -template inline _PIForeachC * _PIForeachCastC(_PIForeachBase & c, const T & ) {return static_cast<_PIForeachC * >(&c);} - -#define piForeach(i,c) for(_PIForeachBase & _for = _PIForeachNew(c); !_PIForeachCast(_for, c)->isEnd(); ++(*_PIForeachCast(_for, c))) \ - for(i = *(_PIForeachCast(_for, c)->_it); !_for._break; _for._break = true) -#define piForeachR(i,c) for(_PIForeachBase & _for = _PIForeachNew(c, true); !_PIForeachCast(_for, c)->isEnd(); ++(*_PIForeachCast(_for, c))) \ - for(i = *(_PIForeachCast(_for, c)->_rit); !_for._break; _for._break = true) -#define piForeachC(i,c) for(_PIForeachBase & _for = _PIForeachNewC(c); !_PIForeachCastC(_for, c)->isEnd(); ++(*_PIForeachCastC(_for, c))) \ - for(const i = *(_PIForeachCastC(_for, c)->_it); !_for._break; _for._break = true) -#define piForeachCR(i,c) for(_PIForeachBase & _for = _PIForeachNewC(c, false); !_PIForeachCastC(_for, c)->isEnd(); ++(*_PIForeachCastC(_for, c))) \ - for(const i = *(_PIForeachCastC(_for, c)->_rit); !_for._break; _for._break = true) - -#endif - -#define piForeachRC piForeachCR +# define piForeachCR piForeachRC #endif // DOXYGEN diff --git a/lib/main/containers/pideque.h b/lib/main/containers/pideque.h index ff3ba8f8..6efead6f 100644 --- a/lib/main/containers/pideque.h +++ b/lib/main/containers/pideque.h @@ -32,7 +32,6 @@ template 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 & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { @@ -49,8 +48,10 @@ public: PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) resize(pid_size, f); } + inline PIDeque(PIDeque && 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); @@ -66,6 +67,11 @@ public: return *this; } + inline PIDeque & operator =(PIDeque && other) { + swap(other); + return *this; + } + typedef T value_type; class iterator { @@ -256,6 +262,23 @@ public: elementNew(pid_data + pid_start + index, v); return *this; } + inline PIDeque & 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 & insert(size_t index, const PIDeque & other) { if (other.isEmpty()) return *this; assert(&other != this); @@ -336,7 +359,14 @@ public: elementNew(pid_data + pid_start + pid_size - 1, v); return *this; } + inline PIDeque & 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 & append(const T & v) {return push_back(v);} + inline PIDeque & append(T && v) {return push_back(std::move(v));} inline PIDeque & append(const PIDeque & t) { assert(&t != this); size_t ps = pid_size; @@ -345,10 +375,13 @@ public: return *this; } inline PIDeque & operator <<(const T & v) {return push_back(v);} + inline PIDeque & operator <<(T && v) {return push_back(std::move(v));} inline PIDeque & operator <<(const PIDeque & t) {return append(t);} inline PIDeque & push_front(const T & v) {insert(0, v); return *this;} + inline PIDeque & push_front(T && v) {insert(0, std::move(v)); return *this;} inline PIDeque & prepend(const T & v) {return push_front(v);} + inline PIDeque & prepend(T && v) {return push_front(std::move(v));} inline PIDeque & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;} inline PIDeque & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;} @@ -364,7 +397,6 @@ public: return ret; } -#ifdef PIP_CXX11_SUPPORT const PIDeque & forEach(std::function f) const { for (uint i = 0; i < pid_size; ++i) f(pid_data[i + pid_start]); @@ -388,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;} @@ -414,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); @@ -487,6 +519,7 @@ private: template<> inline void PIDeque::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::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \ template<> inline void PIDeque::elementNew(T * to, const T & from) {(*to) = from;} \ + template<> inline void PIDeque::elementNew(T * to, T && from) {(*to) = std::move(from);} \ template<> inline void PIDeque::elementDelete(T &) {;} \ template<> inline PIDeque & PIDeque::_resizeRaw(size_t new_size) { \ if (new_size > pid_size) { \ @@ -538,5 +571,7 @@ inline PICout operator <<(PICout s, const PIDeque & v) { return s; } +template inline void piSwap(PIDeque & f, PIDeque & s) {f.swap(s);} + #endif // PIDEQUE_H diff --git a/lib/main/containers/pimap.h b/lib/main/containers/pimap.h index f176dab4..47f0d3b7 100644 --- a/lib/main/containers/pimap.h +++ b/lib/main/containers/pimap.h @@ -57,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(a[i], a[j]); + piSwap(a[i], a[j]); } i++; j--; } @@ -67,13 +67,20 @@ void piQuickSort(T * a, ssize_t N) { } } + +template +class PIMapIterator; + + template class PIMap { template friend PIByteArray & operator >>(PIByteArray & s, PIMap & v); template friend PIByteArray & operator <<(PIByteArray & s, const PIMap & v); + template friend class PIMapIterator; public: PIMap() {;} PIMap(const PIMap & other) {*this = other;} + PIMap(PIMap && other) : pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {} virtual ~PIMap() {;} PIMap & operator =(const PIMap & other) { @@ -84,6 +91,11 @@ public: return *this; } + PIMap & operator =(PIMap && other) { + swap(other); + return *this; + } + typedef T mapped_type; typedef Key key_type; typedef PIPair value_type; @@ -177,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 makeIterator() const {return PIMapIterator(*this);} + PIMapIterator makeReverseIterator() const {return PIMapIterator(*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();} @@ -216,8 +231,8 @@ public: PIMap & clear() {pim_content.clear(); pim_index.clear(); return *this;} void swap(PIMap & other) { - piSwapBinary >(pim_content, other.pim_content); - piSwapBinary >(pim_index, other.pim_index); + pim_content.swap(other.pim_content); + pim_index.swap(other.pim_index); } PIMap & insert(const Key & key, const T & value) { @@ -232,6 +247,18 @@ public: } return *this; } + PIMap & 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 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_;} @@ -292,7 +319,7 @@ protected: pim_index[i].index = ci; break; } - piSwapBinary(pim_content[ci], pim_content.back()); + piSwap(pim_content[ci], pim_content.back()); pim_content.resize(pim_index.size()); } const value_type _pair(ssize_t index) const { @@ -309,6 +336,41 @@ protected: }; +template +class PIMapIterator { + typedef PIMap MapType; +public: + PIMapIterator(const PIMap & map, bool reverse = false): m(map), pos(-1), rev(reverse) { + if (rev) pos = m.size_s(); + } + const Key & key() const {return const_cast(m)._key(pos);} + const T & value() const {return const_cast(m)._value(pos);} + T & valueRef() const {return const_cast(m)._value(pos);} + inline bool hasNext() const { + if (rev) { + return pos > 0; + } else { + return pos < (m.size_s() - 1); + } + return false; + } + inline bool next() { + if (rev) { + --pos; + return pos >= 0; + } else { + ++pos; + return pos < m.size_s(); + } + return false; + } +private: + const MapType & m; + ssize_t pos; + bool rev; +}; + + #ifdef PIP_STD_IOSTREAM template inline std::ostream & operator <<(std::ostream & s, const PIMap & v) { @@ -342,5 +404,7 @@ inline PICout operator <<(PICout s, const PIMap & v) { return s; } +template inline void piSwap(PIMap & f, PIMap & s) {f.swap(s);} + #endif // PIMAP_H diff --git a/lib/main/containers/pipair.h b/lib/main/containers/pipair.h index 670b240a..0e91ed31 100644 --- a/lib/main/containers/pipair.h +++ b/lib/main/containers/pipair.h @@ -30,7 +30,7 @@ class PICout; template -class PIP_EXPORT PIPair { +class PIPair { public: PIPair() {first = Type0(); second = Type1();} PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;} diff --git a/lib/main/containers/piqueue.h b/lib/main/containers/piqueue.h index 60612797..5c56b1b0 100644 --- a/lib/main/containers/piqueue.h +++ b/lib/main/containers/piqueue.h @@ -30,18 +30,20 @@ template -class PIP_EXPORT PIQueue: public PIDeque { +class PIQueue: public PIDeque { public: PIQueue() {} virtual ~PIQueue() {} PIDeque & enqueue(const T & v) {PIDeque::push_front(v); return *this;} + PIDeque & enqueue(T && v) {PIDeque::push_front(std::move(v)); return *this;} T dequeue() {return PIDeque::take_back();} T & head() {return PIDeque::back();} const T & head() const {return PIDeque::back();} PIVector toVector() { - PIVector v(PIDeque::size()); + PIVector v; + v.reserve(PIDeque::size()); for (uint i = 0; i < PIDeque::size(); ++i) - v[i] = PIDeque::at(i); + v.push_back(PIDeque::at(i)); return v; } }; diff --git a/lib/main/containers/piset.h b/lib/main/containers/piset.h index 795124ac..50603403 100644 --- a/lib/main/containers/piset.h +++ b/lib/main/containers/piset.h @@ -35,7 +35,7 @@ * has logarithmic complexity. */ template -class PIP_EXPORT PISet: public PIMap { +class PISet: public PIMap { typedef PIMap _CSet; public: @@ -75,6 +75,7 @@ public: typedef T key_type; PISet & operator <<(const T & t) {_CSet::insert(t, 0); return *this;} + PISet & operator <<(T && t) {_CSet::insert(std::move(t), 0); return *this;} PISet & operator <<(const PISet & other) {(*(_CSet*)this) << *((_CSet*)&other); return *this;} //! Returns if element "t" exists in this set diff --git a/lib/main/containers/pistack.h b/lib/main/containers/pistack.h index 9cbd072b..5b65fa90 100644 --- a/lib/main/containers/pistack.h +++ b/lib/main/containers/pistack.h @@ -28,15 +28,22 @@ #include "pivector.h" template -class PIP_EXPORT PIStack: public PIVector { +class PIStack: public PIVector { public: PIStack() {;} virtual ~PIStack() {;} PIVector & push(const T & v) {PIVector::push_back(v); return *this;} + PIVector & push(T && v) {PIVector::push_back(std::move(v)); return *this;} T pop() {return PIVector::take_back();} T & top() {return PIVector::back();} const T & top() const {return PIVector::back();} - PIVector toVector() {PIVector v(PIVector::size()); for (uint i = 0; i < PIVector::size(); ++i) v[i] = PIVector::at(i); return v;} + PIVector toVector() { + PIVector v; + v.reserve(PIVector::size()); + for (uint i = 0; i < PIVector::size(); ++i) + v.push_back(PIVector::at(i)); + return v; + } }; #endif // PISTACK_H diff --git a/lib/main/containers/pivector.h b/lib/main/containers/pivector.h index a389f05f..e41aeaea 100644 --- a/lib/main/containers/pivector.h +++ b/lib/main/containers/pivector.h @@ -48,6 +48,9 @@ public: PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) resize(piv_size, f); } + inline PIVector(PIVector && 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)) @@ -65,6 +68,11 @@ public: return *this; } + inline PIVector & operator =(PIVector && other) { + swap(other); + return *this; + } + typedef T value_type; class iterator { @@ -253,6 +261,16 @@ public: elementNew(piv_data + index, v); return *this; } + inline PIVector & 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 & insert(size_t index, const PIVector & other) { if (other.isEmpty()) return *this; assert(&other != this); @@ -320,7 +338,14 @@ public: elementNew(piv_data + piv_size - 1, v); return *this; } + inline PIVector & 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 & append(const T & v) {return push_back(v);} + inline PIVector & append(T && v) {return push_back(std::move(v));} inline PIVector & append(const PIVector & other) { assert(&other != this); size_t ps = piv_size; @@ -329,10 +354,13 @@ public: return *this; } inline PIVector & operator <<(const T & v) {return push_back(v);} + inline PIVector & operator <<(T && v) {return push_back(std::move(v));} inline PIVector & operator <<(const PIVector & other) {return append(other);} inline PIVector & push_front(const T & v) {insert(0, v); return *this;} + inline PIVector & push_front(T && v) {insert(0, std::move(v)); return *this;} inline PIVector & prepend(const T & v) {return push_front(v);} + inline PIVector & prepend(T && v) {return push_front(std::move(v));} inline PIVector & pop_back() { if (piv_size == 0) @@ -358,7 +386,6 @@ public: return ret; } -#ifdef PIP_CXX11_SUPPORT const PIVector & forEach(std::function f) const { for (uint i = 0; i < piv_size; ++i) f(piv_data[i]); @@ -382,7 +409,6 @@ public: ret << f(piv_data[i]); return ret; } -#endif private: inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;} @@ -407,6 +433,7 @@ private: } } inline void elementNew(T * to, const T & from) {new(to)T(from);} + inline void elementNew(T * to, 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); @@ -436,6 +463,7 @@ private: template<> inline void PIVector::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::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \ template<> inline void PIVector::elementNew(T * to, const T & from) {(*to) = from;} \ + template<> inline void PIVector::elementNew(T * to, T && from) {(*to) = std::move(from);} \ template<> inline void PIVector::elementDelete(T &) {;} \ template<> inline PIVector & PIVector::_resizeRaw(size_t new_size) { \ if (new_size > piv_size) { \ @@ -487,5 +515,7 @@ inline PICout operator <<(PICout s, const PIVector & v) { return s; } +template inline void piSwap(PIVector & f, PIVector & s) {f.swap(s);} + #endif // PIVECTOR_H diff --git a/lib/main/containers/pivector2d.h b/lib/main/containers/pivector2d.h index 744316af..f573439f 100644 --- a/lib/main/containers/pivector2d.h +++ b/lib/main/containers/pivector2d.h @@ -44,10 +44,10 @@ public: cols_ = cols; mat.resize(rows*cols, f); } - inline PIVector2D(size_t rows, size_t cols, const PIVector & v) { - mat = v; - rows_ = rows; - cols_ = cols; + inline PIVector2D(size_t rows, size_t cols, const PIVector & v) : rows_(rows), cols_(cols), mat(v) { + mat.resize(rows*cols); + } + inline PIVector2D(size_t rows, size_t cols, PIVector && v) : rows_(rows), cols_(cols), mat(std::move(v)) { mat.resize(rows*cols); } inline PIVector2D(const PIVector > & v) { @@ -236,6 +236,7 @@ public: PIVector > toVectors() const { PIVector > ret; + ret.reserve(rows_); for(size_t i = 0; i < rows_; ++i) ret << PIVector(mat.data(i*cols_), cols_); return ret; diff --git a/lib/main/core/pibase.h b/lib/main/core/pibase.h index e55bb696..e0b1dd0a 100644 --- a/lib/main/core/pibase.h +++ b/lib/main/core/pibase.h @@ -96,9 +96,7 @@ #endif -#ifdef PIP_CXX11_SUPPORT -# include -#endif +#include #include #ifdef WINDOWS @@ -194,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__(); \ @@ -220,8 +218,8 @@ #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. @@ -257,7 +255,7 @@ typedef long double ldouble; /*! \brief Templated function for swap two values * \details Example:\n \snippet piincludes.cpp swap */ -template inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;} +template 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 */ @@ -294,6 +292,14 @@ template<> inline void piSwapBinary(const void *& f, const void *& s) { } } +template<> inline void piSwap(double & f, double & s) {piSwapBinary(f, s);} +template<> inline void piSwap(ldouble & f, ldouble & s) {piSwapBinary(f, s);} +#ifdef ARCH_BITS_32 +template<> inline void piSwap(float & f, float & s) {piSwapBinary(f, s);} +template<> inline void piSwap(llong & f, llong & s) {piSwapBinary(f, s);} +template<> inline void piSwap(ullong & f, ullong & s) {piSwapBinary(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) { diff --git a/lib/main/core/pibytearray.h b/lib/main/core/pibytearray.h index cee46ce1..d3d532b4 100644 --- a/lib/main/core/pibytearray.h +++ b/lib/main/core/pibytearray.h @@ -56,6 +56,10 @@ public: //! Constructs an empty byte array PIByteArray() {;} + PIByteArray(const PIByteArray & o): PIDeque(o) {} + + PIByteArray(PIByteArray && o): PIDeque(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 & 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 inline PIByteArray & operator >>(PIByteArray & s, PIFlags & 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;} @@ -316,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 diff --git a/lib/main/core/pichar.h b/lib/main/core/pichar.h index cf7dbe0f..5b18db41 100644 --- a/lib/main/core/pichar.h +++ b/lib/main/core/pichar.h @@ -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 { diff --git a/lib/main/core/pichunkstream.h b/lib/main/core/pichunkstream.h index ef4f9e25..4dec6789 100644 --- a/lib/main/core/pichunkstream.h +++ b/lib/main/core/pichunkstream.h @@ -54,12 +54,18 @@ public: int id; T data; }; + template + 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 static Chunk chunk(int id, const T & data) {return Chunk(id, data);} + template static ChunkConst chunk(int id, const T & data) {return ChunkConst(id, data);} //! Add data to this chunk strean with ID "id" and value "data" - template PIChunkStream & add(int id, const T & data) {*this << Chunk(id, data); return *this;} + template PIChunkStream & add(int id, const T & data) {*this << ChunkConst(id, data); return *this;} void setSource(const PIByteArray & data); void setSource(PIByteArray * data); @@ -112,6 +118,7 @@ private: PIMap data_map; template friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk & c); + template friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::ChunkConst & c); }; template @@ -133,5 +140,24 @@ PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk & c } return s; } +template +PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::ChunkConst & 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 diff --git a/lib/main/core/picollection.h b/lib/main/core/picollection.h index ac8d3017..93e58a6c 100644 --- a/lib/main/core/picollection.h +++ b/lib/main/core/picollection.h @@ -64,13 +64,13 @@ 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_;} PIString name; PIVector elements; diff --git a/lib/main/core/picout.cpp b/lib/main/core/picout.cpp index c20cf82f..ff37a625 100644 --- a/lib/main/core/picout.cpp +++ b/lib/main/core/picout.cpp @@ -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 diff --git a/lib/main/core/picout.h b/lib/main/core/picout.h index 19eab8ec..6e4b39d6 100644 --- a/lib/main/core/picout.h +++ b/lib/main/core/picout.h @@ -46,7 +46,7 @@ class PIObject; namespace PICoutManipulators { //! \brief Enum contains special characters - enum PIP_EXPORT PICoutSpecialChar { + enum PICoutSpecialChar { Null /*! Null-character, '\\0' */, NewLine /*! New line character, '\\n' */, Tab /*! Tab character, '\\t' */, @@ -55,7 +55,7 @@ namespace PICoutManipulators { }; //! \brief Enum contains immediate action - enum PIP_EXPORT PICoutAction { + enum PICoutAction { Flush /*! Flush the output */, Backspace /*! Remove last symbol */, ShowCursor /*! Show cursor */, @@ -67,7 +67,7 @@ namespace PICoutManipulators { }; //! \brief Enum contains control of PICout - enum PIP_EXPORT PICoutControl { + enum PICoutControl { AddNone /*! No controls */ = 0x0, AddSpaces /*! Spaces will be appear after each output */ = 0x1, AddNewLine /*! New line will be appear after all output */ = 0x2, @@ -78,7 +78,7 @@ namespace PICoutManipulators { }; //! \brief Enum contains output format - enum PIP_EXPORT PICoutFormat { + enum PICoutFormat { Bin /*! Binary representation of integers */ = 0x01, Oct /*! Octal representation of integers */ = 0x02, Dec /*! Decimal representation of integers */ = 0x04, @@ -128,7 +128,7 @@ public: ~PICout(); - class Notifier { + class PIP_EXPORT Notifier { public: static Notifier * instance(); static PIObject * object(); @@ -291,7 +291,7 @@ private: void applyFormat(PICoutManipulators::PICoutFormat f); static OutputDevices devs; - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) bool fo_, cc_, fc_, act_; int cnb_, attr_, id_; PIString * buffer_; diff --git a/lib/main/core/piflags.h b/lib/main/core/piflags.h index 202027f9..d7584dd5 100644 --- a/lib/main/core/piflags.h +++ b/lib/main/core/piflags.h @@ -32,7 +32,7 @@ * \snippet piincludes.cpp flags */ template -class PIP_EXPORT PIFlags { +class PIFlags { public: //! Constructor with flags = 0 PIFlags(): flags(0) {;} diff --git a/lib/main/core/piincludes.cpp b/lib/main/core/piincludes.cpp index 5600257c..6b480a21 100644 --- a/lib/main/core/piincludes.cpp +++ b/lib/main/core/piincludes.cpp @@ -19,7 +19,6 @@ #include "piincludes.h" #include "piincludes_p.h" -#include "piconsole.h" #include "pitime.h" #ifndef QNX # include diff --git a/lib/main/core/piincludes.h b/lib/main/core/piincludes.h index 14a45a27..ba158476 100644 --- a/lib/main/core/piincludes.h +++ b/lib/main/core/piincludes.h @@ -26,9 +26,11 @@ #ifdef PIP_STD_IOSTREAM # include #endif +#include -class PIObject; class PIMutex; +class PIMutexLocker; +class PIObject; class PIString; class PIByteArray; class PIInit; @@ -37,7 +39,7 @@ class PICout; struct lconv; -extern lconv * currentLocale; +extern PIP_EXPORT lconv * currentLocale; /*! \fn errorString() * \brief Return readable error description in format "code - " */ diff --git a/lib/main/core/piinit.cpp b/lib/main/core/piinit.cpp index 6063a2c5..90eacfa1 100644 --- a/lib/main/core/piinit.cpp +++ b/lib/main/core/piinit.cpp @@ -125,7 +125,7 @@ PIInit::PIInit() { piForeachC (PIString & i, ifpathes) { if (fileExists(i)) { sinfo->ifconfigPath = i; - piBreak; + break; } } # else diff --git a/lib/main/core/piinit.h b/lib/main/core/piinit.h index d72d7b1f..e0dad2c8 100644 --- a/lib/main/core/piinit.h +++ b/lib/main/core/piinit.h @@ -63,7 +63,7 @@ private: explicit PIInit(); void setFileCharset(const char *charset); bool fileExists(const PIString & p); - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) char * file_charset; }; diff --git a/lib/main/core/piobject.cpp b/lib/main/core/piobject.cpp index 5d190f99..42af0a01 100644 --- a/lib/main/core/piobject.cpp +++ b/lib/main/core/piobject.cpp @@ -190,39 +190,42 @@ PIStringList PIObject::scopeList() const { PIStringList PIObject::methodsEH() const { PIMutexLocker ml(__meta_mutex()); PIStringList ret; - __MetaData & ehd(__meta_data()[classNameID()]); - piForeachC (__EHPair & eh, ehd.eh_func) - ret << eh.second.fullFormat(); + const __MetaData & ehd(__meta_data()[classNameID()]); + for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) + ret << eh.value().fullFormat(); return ret; } bool PIObject::isMethodEHContains(const PIString & name) const { PIMutexLocker ml(__meta_mutex()); - __MetaData & ehd(__meta_data()[classNameID()]); - piForeachC (__EHPair & eh, ehd.eh_func) - if (eh.second.func_name == name) + const __MetaData & ehd(__meta_data()[classNameID()]); + for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { + if (eh.value().func_name == name) return true; + } return false; } PIString PIObject::methodEHArguments(const PIString & name) const { PIMutexLocker ml(__meta_mutex()); - __MetaData & ehd(__meta_data()[classNameID()]); - piForeachC (__EHPair & eh, ehd.eh_func) - if (eh.second.func_name == name) - return eh.second.arguments(); + const __MetaData & ehd(__meta_data()[classNameID()]); + for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { + if (eh.value().func_name == name) + return eh.value().arguments(); + } return PIString(); } PIString PIObject::methodEHFullFormat(const PIString & name) const { PIMutexLocker ml(__meta_mutex()); - __MetaData & ehd(__meta_data()[classNameID()]); - piForeachC (__EHPair & eh, ehd.eh_func) - if (eh.second.func_name == name) - return eh.second.fullFormat(); + const __MetaData & ehd(__meta_data()[classNameID()]); + for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { + if (eh.value().func_name == name) + return eh.value().fullFormat(); + } return PIString(); } @@ -234,10 +237,11 @@ PIString PIObject::methodEHFromAddr(const void * addr) const { PIVector PIObject::findEH(const PIString & name) const { PIVector<__MetaFunc> ret; - __MetaData & ehd(__meta_data()[classNameID()]); - piForeachC (__EHPair & eh, ehd.eh_func) - if (eh.second.func_name == name) - ret << eh.second; + const __MetaData & ehd(__meta_data()[classNameID()]); + for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { + if (eh.value().func_name == name) + ret << eh.value(); + } return ret; } @@ -313,7 +317,6 @@ bool PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_ } -#ifdef PIP_CXX11_SUPPORT bool PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function * f, const char * loc) { if (src == 0) { delete f; @@ -345,7 +348,6 @@ bool PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function__stat_eh_##event##__, functor), LOCATION); -#endif +#define CONNECTL(src, event, functor) PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION); #define CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__), 0, LOCATION); #define CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__), 1, LOCATION); @@ -499,18 +497,16 @@ class PIP_EXPORT PIObject { typedef void __Parent__; friend class PIIntrospection; public: - + NO_COPY_CLASS(PIObject) + //! Contructs PIObject with name "name" explicit PIObject(const PIString & name = PIString()); virtual ~PIObject(); - -private: - explicit PIObject(const PIObject & ); - void operator =(const PIObject & ); +private: uint _signature_; - + public: //! Returns object name @@ -601,13 +597,11 @@ public: // / Direct connect static void piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc); static bool piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0); -#ifdef PIP_CXX11_SUPPORT static bool piConnectLS(PIObject * src, const PIString & sig, std::function * f, const char * loc); template static std::function * __newFunctor(void(*stat_handler)(void*,TYPES...), INPUT functor) { return (std::function*)(new std::function(functor)); } -#endif // / Through names and mixed static void piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h); @@ -629,11 +623,9 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection i(sender->connections[j]); if (i.eventID != eventID) continue; -#ifdef PIP_CXX11_SUPPORT if (i.functor) { (*(i.functor))(); } else { -#endif if (i.performer) { i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender)); } else { @@ -646,9 +638,7 @@ public: if (ts) i.dest_o->mutex_.unlock(); } } -#ifdef PIP_CXX11_SUPPORT } -#endif if (!sender->isPIObject()) break; } } @@ -658,11 +648,9 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection i(sender->connections[j]); if (i.eventID != eventID) continue; -#ifdef PIP_CXX11_SUPPORT if (i.functor) { (*((std::function*)i.functor))(v0); } else { -#endif if (i.performer) { PIVector vl; if (i.args_count > 0) vl << PIVariant::fromValue(v0); @@ -678,9 +666,7 @@ public: if (ts) i.dest_o->mutex_.unlock(); } } -#ifdef PIP_CXX11_SUPPORT } -#endif if (!sender->isPIObject()) break; } } @@ -689,11 +675,9 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection i(sender->connections[j]); if (i.eventID != eventID) continue; -#ifdef PIP_CXX11_SUPPORT if (i.functor) { (*((std::function*)i.functor))(v0, v1); } else { -#endif if (i.performer) { PIVector vl; if (i.args_count > 0) vl << PIVariant::fromValue(v0); @@ -713,9 +697,7 @@ public: if (ts) i.dest_o->mutex_.unlock(); } } -#ifdef PIP_CXX11_SUPPORT } -#endif if (!sender->isPIObject()) break; } } @@ -724,11 +706,9 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection i(sender->connections[j]); if (i.eventID != eventID) continue; -#ifdef PIP_CXX11_SUPPORT if (i.functor) { (*((std::function*)i.functor))(v0, v1, v2); } else { -#endif if (i.performer) { PIVector vl; if (i.args_count > 0) vl << PIVariant::fromValue(v0); @@ -750,9 +730,7 @@ public: if (ts) i.dest_o->mutex_.unlock(); } } -#ifdef PIP_CXX11_SUPPORT } -#endif if (!sender->isPIObject()) break; } } @@ -761,11 +739,9 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection i(sender->connections[j]); if (i.eventID != eventID) continue; -#ifdef PIP_CXX11_SUPPORT if (i.functor) { (*((std::function*)i.functor))(v0, v1, v2, v3); } else { -#endif if (i.performer) { PIVector vl; if (i.args_count > 0) vl << PIVariant::fromValue(v0); @@ -789,9 +765,7 @@ public: if (ts) i.dest_o->mutex_.unlock(); } } -#ifdef PIP_CXX11_SUPPORT } -#endif if (!sender->isPIObject()) break; } } @@ -826,7 +800,7 @@ public: static bool isTypeOf(const void * o) {return isTypeOf((PIObject*)o);} static PIString simplifyType(const char * a); - struct __MetaFunc { + struct PIP_EXPORT __MetaFunc { __MetaFunc(): addr(0), addrV(0) {;} bool isNull() const {return addr == 0;} PIString arguments() const; @@ -839,7 +813,7 @@ public: PIStringList types; PIStringList names; }; - struct __MetaData { + struct PIP_EXPORT __MetaData { __MetaData() {scope_list << PIStringAscii("PIObject"); scope_id << PIStringAscii("PIObject").hash();} void addScope(const PIString & s, uint shash); PIStringList scope_list; @@ -891,16 +865,12 @@ private: dest = d; args_count = ac; performer = p; -#ifdef PIP_CXX11_SUPPORT functor = 0; -#endif } void destroy(); void * slot; void * signal; -#ifdef PIP_CXX11_SUPPORT std::function * functor; -#endif PIString event; uint eventID; PIObject * dest_o; @@ -949,7 +919,7 @@ private: }; -void dumpApplication(); -bool dumpApplicationToFile(const PIString & path); +PIP_EXPORT void dumpApplication(); +PIP_EXPORT bool dumpApplicationToFile(const PIString & path); #endif // PIOBJECT_H diff --git a/lib/main/core/pipropertystorage.h b/lib/main/core/pipropertystorage.h index 56c09a51..a4a8ad15 100644 --- a/lib/main/core/pipropertystorage.h +++ b/lib/main/core/pipropertystorage.h @@ -32,14 +32,14 @@ * contains unique name and you can identify property by name with propertyValueByName(), propertyByName(). * You can add property using addProperty(const Property&), addProperty(const PIString&, const PIVariant&, const PIString&, int). */ -class PIPropertyStorage { +class PIP_EXPORT PIPropertyStorage { public: PIPropertyStorage() {} /** * @brief PIPropertyStorage element. */ - struct Property { + struct PIP_EXPORT Property { Property(const PIString & n = PIString(), const PIString & c = PIString(), const PIVariant & v = PIVariant(), int f = 0): name(n), comment(c), value(v), flags(f) {} diff --git a/lib/main/core/pistring.cpp b/lib/main/core/pistring.cpp index 4cd27fab..f2f454e8 100644 --- a/lib/main/core/pistring.cpp +++ b/lib/main/core/pistring.cpp @@ -173,7 +173,7 @@ PIString PIString::dtos(const double num, char format, int precision) { PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) { - if (value == 0LL) return PIString("0"); + if (value == 0LL) return PIString('0'); if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();} if (ok != 0) *ok = true; if (base == 10) return lltos(value); @@ -192,7 +192,7 @@ PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) { } PIString PIString::fromNumberBaseU(const ullong value, int base, bool * ok) { - if (value == 0ULL) return PIString("0"); + if (value == 0ULL) return PIString('0'); if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();} if (ok != 0) *ok = true; if (base == 10) return ulltos(value); @@ -211,9 +211,10 @@ PIString PIString::fromNumberBaseU(const ullong value, int base, bool * ok) { llong PIString::toNumberBase(const PIString & value, int base, bool * ok) { + static const PIString s_0x = PIStringAscii("0x"); PIString v = value.trimmed(); if (base < 0) { - int ind = v.find("0x"); + int ind = v.find(s_0x); if (ind == 0 || ind == 1) {v.remove(ind, 2); base = 16;} else base = 10; } else @@ -254,6 +255,7 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) { int sz = ucnv_toUChars(cc, ucs, s, c, s, &e); //printf("appendFromChars %d -> %d\n", s, sz); //printf("PIString %d -> %d\n", c[0], ucs[0]); + reserve(size_s() + sz); for (int i = 0; i < sz; ++i) push_back(PIChar(ucs[i])); delete[] ucs; @@ -264,11 +266,9 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) { # ifdef WINDOWS sz = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, 0, 0); if (sz <= 0) return; - wchar_t * buffer = new wchar_t[sz]; - MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, buffer, sz); - for (int i = 0; i < sz; ++i) - push_back(PIChar((ushort)buffer[i])); - delete[] buffer; + int old_sz = size_s(); + enlarge(sz); + MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, (LPWSTR)PIDeque::data(old_sz), sz); return; //printf("request %d\n", sz); # else @@ -330,9 +330,14 @@ PIString PIString::fromAscii(const char * s) { PIString ret; int l = 0; while (s[l] != '\0') { - ret.push_back(PIChar(short(s[l]))); + ret.push_back(PIChar(s[l])); ++l; } + /*while (s[l] != '\0') ++l; + PIString ret; + ret.resize(l); + for (int i = 0; i < l; ++i) + ret[i] = s[i];*/ return ret; } @@ -369,6 +374,7 @@ void PIString::buildData(const char * cp) const { UConverter * cc = ucnv_open(cp, &e); if (cc) { char uc[8]; + data_.reserve(size_s()); for (int i = 0; i < size_s(); ++i) { if (at(i).isAscii()) data_.push_back(uchar(at(i).unicode16Code())); @@ -605,16 +611,18 @@ PIString PIString::trimmed() const { PIString & PIString::replace(int from, int count, const PIString & with) { - if (count < length() - from) remove(from, count); - else remove(from, length() - from); - uint c = with.length(); - for (uint i = 0; i < c; ++i) insert(from + i, with[i]); + count = piMini(count, length() - from); + if (count == with.size_s()) + memcpy(&(at(from)), &(with.at(0)), count * sizeof(PIChar)); + else { + remove(from, count); + PIDeque::insert(from, with); + } return *this; } PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) { - //piCout << "replace" << what << with; if (what.isEmpty()) { if (ok != 0) *ok = false; return *this; @@ -628,8 +636,73 @@ PIString & PIString::replace(const PIString & what, const PIString & with, bool PIString & PIString::replaceAll(const PIString & what, const PIString & with) { if (what.isEmpty() || what == with) return *this; - bool ok = true; - while (ok) replace(what, with, &ok); + if (with.isEmpty()) removeAll(what); + else { + int l = what.length(), dl = with.length() - what.length(); + for (int i = 0; i < length() - l + 1; ++i) { + bool match = true; + for (int j = 0; j < l; ++j) { + if (at(j + i) != what[j]) { + match = false; + break; + } + } + if (!match) continue; + if (dl > 0) PIDeque::insert(i, PIDeque((size_t)dl)); + if (dl < 0) PIDeque::remove(i, -dl); + memcpy(PIDeque::data(i), &(with.at(0)), with.length() * sizeof(PIChar)); + //i -= l; + } + } + return *this; +} + + +PIString & PIString::replaceAll(const PIString & what, const char with) { + if (what.isEmpty()) return *this; + int l = what.length(), dl = what.length() - 1; + for (int i = 0; i < length() - l + 1; ++i) { + bool match = true; + for (int j = 0; j < l; ++j) { + if (at(j + i) != what[j]) { + match = false; + break; + } + } + if (!match) continue; + if (dl > 0) PIDeque::remove(i, dl); + at(i) = PIChar(with); + //i -= l; + } + return *this; +} + + +PIString & PIString::replaceAll(const char what, const char with) { + int l = length(); + for (int i = 0; i < l; ++i) { + if (at(i) == what) + at(i) = with; + } + return *this; +} + + +PIString & PIString::removeAll(const PIString & str) { + if (str.isEmpty()) return *this; + int l = str.length(); + for (int i = 0; i < length() - l + 1; ++i) { + bool match = true; + for (int j = 0; j < l; ++j) { + if (at(j + i) != str[j]) { + match = false; + break; + } + } + if (!match) continue; + PIDeque::remove(i, l); + i -= l; + } return *this; } @@ -641,16 +714,17 @@ PIString & PIString::insert(int index, const PIString & str) { PIString & PIString::elide(int size, float pos) { + static const PIString s_dotdot = PIStringAscii(".."); if (length() <= size) return *this; if (length() <= 2) { - fill("."); + fill('.'); return *this; } pos = piClampf(pos, 0.f, 1.f); int ns = size - 2; int ls = piRoundf(ns * pos); remove(ls, length() - ns); - insert(ls, ".."); + insert(ls, s_dotdot); return *this; } @@ -670,9 +744,9 @@ PIStringList PIString::split(const PIString & delim) const { } -int PIString::find(const char str, const int start) const { +int PIString::find(const char c, const int start) const { for (int i = start; i < length(); ++i) - if (at(i) == str) + if (at(i) == c) return i; return -1; } @@ -687,9 +761,9 @@ int PIString::find(const PIString & str, const int start) const { } -int PIString::findLast(const char str, const int start) const { +int PIString::findLast(const char c, const int start) const { for (int i = length() - 1; i >= start; --i) - if (at(i) == str) + if (at(i) == c) return i; return -1; } @@ -730,7 +804,7 @@ int PIString::findCWord(const PIString & word, const int start) const { } -int PIString::findRange(const PIChar & start, const PIChar & end, const PIChar & shield, const int start_index, int * len) const { +int PIString::findRange(const PIChar start, const PIChar end, const PIChar shield, const int start_index, int * len) const { if (len) *len = 0; bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end); int sz = size_s(), ls = -1, le = -1, cnt = 0; @@ -783,7 +857,7 @@ int PIString::findAnyLast(const PIString & str, const int start) const { } -int PIString::entries(const PIChar & c) const { +int PIString::entries(const PIChar c) const { int sz = size_s(), ret = 0; for (int i = 0; i < sz; ++i) if (at(i) == c) ++ret; @@ -804,9 +878,14 @@ bool PIString::endsWith(const PIString & str) const { bool PIString::toBool() const { + static const PIString s_true = PIStringAscii("true"); + static const PIString s_yes = PIStringAscii("yes" ); + static const PIString s_on = PIStringAscii("on" ); + static const PIString s_ok = PIStringAscii("ok" ); PIString s(*this); s = s.trimmed().toLowerCase(); - if ( atof(s.toNativeDecimalPoints().data()) > 0. || s == "true" || s == "yes" || s == "on" || s == "ok") return true; + if (s == s_true || s == s_yes || s == s_on || s == s_ok) return true; + if (atof(s.toNativeDecimalPoints().data()) > 0.) return true; return false; } @@ -953,7 +1032,7 @@ PIString PIString::takeNumber() { } -PIString PIString::takeRange(const PIChar & start, const PIChar & end, const PIChar & shield) { +PIString PIString::takeRange(const PIChar start, const PIChar end, const PIChar shield) { PIString ret; bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end); int sz = size_s(), ls = -1, le = -1, cnt = 0; @@ -991,7 +1070,7 @@ PIString PIString::takeRange(const PIChar & start, const PIChar & end, const PIC } -PIString PIString::inBrackets(const PIChar &start, const PIChar &end) const { +PIString PIString::inBrackets(const PIChar start, const PIChar end) const { int slen = length(); int st = -1, bcnt = 0; PIChar cc; @@ -1030,9 +1109,9 @@ PIString PIString::toNativeDecimalPoints() const { #ifdef HAS_LOCALE PIString s(*this); if (currentLocale == 0) return s; - return s.replaceAll(".", currentLocale->decimal_point).replaceAll(",", currentLocale->decimal_point); + return s.replaceAll('.', currentLocale->decimal_point).replaceAll(',', currentLocale->decimal_point); #else - return PIString(*this).replaceAll(",", "."); + return PIString(*this).replaceAll(',', '.'); #endif } @@ -1062,27 +1141,27 @@ ldouble PIString::toLDouble() const { PIString & PIString::setReadableSize(llong bytes) { clear(); - if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + " B"); return *this;} + if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + PIStringAscii(" B")); return *this;} double fres = bytes / 1024.; llong res = bytes / 1024; fres -= res; - if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " kB"); return *this;} + if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" kB")); return *this;} fres = res / 1024.; res /= 1024; fres -= res; - if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " MB"); return *this;} + if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" MB")); return *this;} fres = res / 1024.; res /= 1024; fres -= res; - if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " GB"); return *this;} + if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" GB")); return *this;} fres = res / 1024.; res /= 1024; fres -= res; - if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " TB"); return *this;} + if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" TB")); return *this;} fres = res / 1024.; res /= 1024; fres -= res; - *this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " PB"); + *this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" PB")); return *this; } @@ -1110,14 +1189,14 @@ void parseVersion(PIString s, PIVector & codes, PIStringList & strs) { } int mccnt = 2 - s.entries('.'); if (mccnt > 0) { - int ind = s.findLast(".") + 1; + int ind = s.findLast('.') + 1; while (!_versionDelims_.contains(s[ind])) { ++ind; if (ind > s.size_s() - 1) break; } for (int i = 0; i < mccnt; ++i) - s.insert(ind, ".0"); + s.insert(ind, PIStringAscii(".0")); } PIStringList comps; while (!s.isEmpty()) { @@ -1132,7 +1211,7 @@ void parseVersion(PIString s, PIVector & codes, PIStringList & strs) { } for (int i = 0; i < comps.size_s(); ++i) { if (comps[i].isEmpty()) - comps[i] = "0"; + comps[i] = '0'; bool ok = false; int val = comps[i].toInt(-1, &ok); if (ok) { @@ -1148,20 +1227,20 @@ void parseVersion(PIString s, PIVector & codes, PIStringList & strs) { int versionLabelValue(PIString s) { int ret = -10000; if (s.isEmpty()) return 0; - if (s.startsWith("pre")) { + if (s.startsWith(PIStringAscii("pre"))) { s.cutLeft(3); ret -= 1; } - if (s.startsWith("rc")) { + if (s.startsWith(PIStringAscii("rc"))) { s.cutLeft(2); ret += s.toInt(); } - if (s.startsWith("r")) { + if (s.startsWith(PIStringAscii("r"))) { s.cutLeft(1); ret += 10000 + s.toInt(); } - if (s == "alpha") ret -= 4; - if (s == "beta" ) ret -= 2; + if (s == PIStringAscii("alpha")) ret -= 4; + if (s == PIStringAscii("beta" )) ret -= 2; return ret; } @@ -1200,13 +1279,13 @@ PIString versionNormalize(const PIString & v) { PIString ret; for (int i = 0; i < codes.size_s(); ++i) { if (i > 0) { - if (i < 3) ret += "."; - else ret += "-"; + if (i < 3) ret += '.'; + else ret += '-'; } ret += PIString::fromNumber(codes[i]); } for (int i = 0; i < strs.size_s(); ++i) { - ret += "_"; + ret += '_'; ret += strs[i]; } return ret; diff --git a/lib/main/core/pistring.h b/lib/main/core/pistring.h index 5afe1173..9268f759 100644 --- a/lib/main/core/pistring.h +++ b/lib/main/core/pistring.h @@ -43,17 +43,20 @@ public: static const float ElideCenter; static const float ElideRight ; - PIString & operator +=(const PIChar & c) {push_back(c); return *this;} + PIString & operator +=(const PIChar c) {push_back(c); return *this;} + PIString & operator +=(const char c) {push_back(PIChar(c)); return *this;} PIString & operator +=(const char * str); PIString & operator +=(const wchar_t * str); PIString & operator +=(const PIByteArray & ba) {appendFromChars((const char * )ba.data(), ba.size_s(), __utf8name__); return *this;} PIString & operator +=(const PIString & str); - PIString(const PIString & o): PIDeque() {*this += o;} + PIString(const PIString & o): PIDeque(o) {} + + PIString(PIString && o): PIDeque(std::move(o)) {} //! Contructs string with single symbol "c" - PIString(const PIChar & c): PIDeque() {*this += c;} + PIString(const PIChar c): PIDeque() {*this += c;} PIString(const char c): PIDeque() {*this += PIChar(c);} /*! \brief Contructs string from c-string "str" @@ -82,13 +85,15 @@ public: /*! \brief Contructs string as sequence of symbols "c" of buffer with length "len" * \details Example: \snippet pistring.cpp PIString(int, PIChar) */ - PIString(const int len, const PIChar & c): PIDeque() {for (int i = 0; i < len; ++i) push_back(c);} + PIString(const int len, const PIChar c): PIDeque() {for (int i = 0; i < len; ++i) push_back(c);} ~PIString() {} PIString & operator =(const PIString & o) {if (this == &o) return *this; clear(); *this += o; return *this;} + PIString & operator =(PIString && o) {swap(o); return *this;} + /*! \brief Return c-string representation of string * \details Converts content of string to c-string and return * pointer to first char. This buffer is valid until new convertion @@ -106,7 +111,7 @@ public: bool operator ==(const PIString & str) const; //! Compare operator - bool operator ==(const PIChar c) const {return *this == PIString(c);} + bool operator ==(const PIChar c) const {if (size_s() != 1) return false; return at(0) == c;} //! Compare operator bool operator ==(const char * str) const {return *this == PIString(str);} @@ -115,7 +120,7 @@ public: bool operator !=(const PIString & str) const; //! Compare operator - bool operator !=(const PIChar c) const {return *this != PIString(c);} + bool operator !=(const PIChar c) const {if (size_s() != 1) return true; return at(0) != c;} //! Compare operator bool operator !=(const char * str) const {return *this != PIString(str);} @@ -124,7 +129,7 @@ public: bool operator <(const PIString & str) const; //! Compare operator - bool operator <(const PIChar c) const {return *this < PIString(c);} + bool operator <(const PIChar c) const {if (size_s() != 1) return size_s() < 1; return at(0) < c;} //! Compare operator bool operator <(const char * str) const {return *this < PIString(str);} @@ -133,7 +138,7 @@ public: bool operator >(const PIString & str) const; //! Compare operator - bool operator >(const PIChar c) const {return *this > PIString(c);} + bool operator >(const PIChar c) const {if (size_s() != 1) return size_s() > 1; return at(0) > c;} //! Compare operator bool operator >(const char * str) const {return *this > PIString(str);} @@ -142,7 +147,7 @@ public: bool operator <=(const PIString & str) const {return !(*this > str);} //! Compare operator - bool operator <=(const PIChar c) const {return *this <= PIString(c);} + bool operator <=(const PIChar c) const {return !(*this > c);} //! Compare operator bool operator <=(const char * str) const {return *this <= PIString(str);} @@ -151,7 +156,7 @@ public: bool operator >=(const PIString & str) const {return !(*this < str);} //! Compare operator - bool operator >=(const PIChar c) const {return *this >= PIString(c);} + bool operator >=(const PIChar c) const {return !(*this < c);} //! Compare operator bool operator >=(const char * str) const {return *this >= PIString(str);} @@ -162,7 +167,11 @@ public: /*! \brief Append symbol "c" at the end of string * \details Example: \snippet pistring.cpp PIString::<<(PIChar) */ - PIString & operator <<(const PIChar & c) {*this += c; return *this;} + PIString & operator <<(const PIChar c) {*this += c; return *this;} + + /*! \brief Append symbol "c" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(PIChar) */ + PIString & operator <<(const char c) {*this += PIChar(c); return *this;} /*! \brief Append c-string "str" at the end of string * \details Example: \snippet pistring.cpp PIString::<<(char * ) */ @@ -177,11 +186,6 @@ public: PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const uint & num) {*this += PIString::fromNumber(num); return *this;} - /*! \brief Append string representation of "num" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(int) */ - PIString & operator <<(const short & num) {*this += PIString::fromNumber(num); return *this;} - PIString & operator <<(const ushort & num) {*this += PIString::fromNumber(num); return *this;} - /*! \brief Append string representation of "num" at the end of string * \details Example: \snippet pistring.cpp PIString::<<(int) */ PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;} @@ -278,8 +282,25 @@ public: * \details Example: \snippet pistring.cpp PIString::replaceAll * \sa \a replace(), \a replaced() */ PIString & replaceAll(const PIString & what, const PIString & with); - PIString replaceAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;} - + + /*! \brief Replace all founded substrings "what" with symbol "with" and return this string + * \details Example: \snippet pistring.cpp PIString::replaceAll + * \sa \a replace(), \a replaced() */ + PIString & replaceAll(const PIString & what, const char with); + + /*! \brief Replace all founded symbols "what" with symbol "with" and return this string + * \details Example: \snippet pistring.cpp PIString::replaceAll + * \sa \a replace(), \a replaced() */ + PIString & replaceAll(const char what, const char with); + + PIString replacedAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;} + + PIString replacedAll(const char what, const char with) const {PIString str(*this); str.replaceAll(what, with); return str;} + + PIString & removeAll(const PIString & str); + + PIString & removeAll(char c) {PIDeque::removeAll(PIChar(c)); return *this;} + /*! \brief Repeat content of string "times" times and return this string * \details Example: \snippet pistring.cpp PIString::repeat */ PIString & repeat(int times) {PIString ss(*this); times--; piForTimes (times) *this += ss; return *this;} @@ -290,11 +311,11 @@ public: /*! \brief Insert symbol "c" after index "index" and return this string * \details Example: \snippet pistring.cpp PIString::insert_0 */ - PIString & insert(const int index, const PIChar & c) {PIDeque::insert(index, c); return *this;} + PIString & insert(const int index, const PIChar c) {PIDeque::insert(index, c); return *this;} /*! \brief Insert symbol "c" after index "index" and return this string * \details Example: \snippet pistring.cpp PIString::insert_1 */ - PIString & insert(const int index, const char & c) {return insert(index, PIChar(c));} + PIString & insert(const int index, const char c) {return insert(index, PIChar(c));} /*! \brief Insert string "str" after index "index" and return this string * \details Example: \snippet pistring.cpp PIString::insert_2 */ @@ -308,13 +329,13 @@ public: * "c" at the end of string, and return this string * \details Example: \snippet pistring.cpp PIString::expandRightTo * \sa \a expandLeftTo() */ - PIString & expandRightTo(const int len, const PIChar & c) {if (len > length()) resize(len, c); return *this;} + PIString & expandRightTo(const int len, const PIChar c) {if (len > length()) resize(len, c); return *this;} /*! \brief Enlarge string to length "len" by addition sequence of symbols * "c" at the beginning of string, and return this string * \details Example: \snippet pistring.cpp PIString::expandLeftTo * \sa \a expandRightTo() */ - PIString & expandLeftTo(const int len, const PIChar & c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;} + PIString & expandLeftTo(const int len, const PIChar c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;} /*! \brief Add "c" symbols at the beginning and end of the string, and return this string * \sa \a quoted() */ @@ -327,7 +348,7 @@ public: /*! \brief Reverse string and return this string * \details Example: \snippet pistring.cpp PIString::reverse * \sa \a reversed() */ - PIString & reverse() {PIString str(*this); clear(); piForeachR (const PIChar & c, str) push_back(c); return *this;} + PIString & reverse() {PIString str(*this); clear(); piForeachCR (PIChar c, str) push_back(c); return *this;} /*! \brief Reverse copy of this string and return it * \details Example: \snippet pistring.cpp PIString::reversed @@ -390,13 +411,13 @@ public: * \details "Shield" symbol prevent analysis of the next symbol. * Example: \snippet pistring.cpp PIString::takeRange * \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber() */ - PIString takeRange(const PIChar & start, const PIChar & end, const PIChar & shield = '\\'); + PIString takeRange(const PIChar start, const PIChar end, const PIChar shield = '\\'); /*! \brief Return a string in brackets "start" and "end" symbols from the begin of this * string and return it. * \details Example: string = "a(b(c)d)e"; inBrackets('(', ')') = "b(c)d"; */ - PIString inBrackets(const PIChar & start, const PIChar & end) const; + PIString inBrackets(const PIChar start, const PIChar end) const; /*! \brief Return real bytes count of this string * \details It`s equivalent length of char sequence @@ -463,11 +484,8 @@ public: PIString toNativeDecimalPoints() const; - //! \brief Returns if string contains "str" - bool contains(const char str) const {return contains(PIString(str));} - - //! \brief Returns if string contains "str" - bool contains(const PIChar str) const {return contains(PIString(str));} + //! \brief Returns if string contains "c" + bool contains(const char c) const {return PIDeque::contains(PIChar(c));} //! \brief Returns if string contains "str" bool contains(const char * str) const {return contains(PIString(str));} @@ -476,9 +494,9 @@ public: bool contains(const PIString & str) const {return find(str) >= 0;} - //! \brief Search substring "str" from symbol at index "start" and return first occur position + //! \brief Search symbol "c" from symbol at index "start" and return first occur position //! \details Example: \snippet pistring.cpp PIString::find - int find(const char str, const int start = 0) const; + int find(const char c, const int start = 0) const; //! \brief Search substring "str" from symbol at index "start" and return first occur position //! \details Example: \snippet pistring.cpp PIString::find @@ -488,9 +506,9 @@ public: //! \details Example: \snippet pistring.cpp PIString::find int find(const char * str, const int start = 0) const {return find(PIString(str), start);} - //! \brief Search substring "str" from symbol at index "start" and return last occur position + //! \brief Search symbol "c" from symbol at index "start" and return last occur position //! \details Example: \snippet pistring.cpp PIString::findLast - int findLast(const char str, const int start = 0) const; + int findLast(const char c, const int start = 0) const; //! \brief Search substring "str" from symbol at index "start" and return last occur position //! \details Example: \snippet pistring.cpp PIString::findLast @@ -510,7 +528,7 @@ public: //! \brief Search range between "start" and "end" symbols at index "start_index" and return first occur position. //! \details Example: \snippet pistring.cpp PIString::findRange - int findRange(const PIChar & start, const PIChar & end, const PIChar & shield = '\\', const int start_index = 0, int * len = 0) const; + int findRange(const PIChar start, const PIChar end, const PIChar shield = '\\', const int start_index = 0, int * len = 0) const; //! \brief Search any symbol of "str" from symbol at index "start" and return first occur position //! \details Example: \snippet pistring.cpp PIString::findAny @@ -529,7 +547,7 @@ public: int findAnyLast(const char * str, const int start = 0) const {return findAnyLast(PIString(str), start);} //! \brief Returns number of occurrences of symbol "c" - int entries(const PIChar & c) const; + int entries(const PIChar c) const; //! \brief Returns number of occurrences of symbol "c" int entries(char c) const {return entries(PIChar(c));} @@ -714,9 +732,6 @@ public: //! \details Example: \snippet pistring.cpp PIString::readableSize static PIString readableSize(llong bytes); - PIString & removeAll(char v) {replaceAll(v, ""); return *this;} - PIString & removeAll(const PIString & v) {replaceAll(v, ""); return *this;} - private: static const char toBaseN[]; static const int fromBaseN[]; @@ -759,6 +774,12 @@ inline PIString operator +(const PIString & f, const char * str) {PIString s(f); //! \relatesalso PIString \brief Return concatenated string inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;} +//! \relatesalso PIString \brief Return concatenated string +inline PIString operator +(const char c, const PIString & f) {return PIChar(c) + f;} + +//! \relatesalso PIString \brief Return concatenated string +inline PIString operator +(const PIString & f, const char c) {return f + PIChar(c);} + inline char chrUpr(char c); inline char chrLwr(char c); @@ -770,5 +791,6 @@ PIString versionNormalize(const PIString & v); template<> inline uint piHash(const PIString & s) {return s.hash();} +template<> inline void piSwap(PIString & f, PIString & s) {f.swap(s);} #endif // PISTRING_H diff --git a/lib/main/core/pistringlist.h b/lib/main/core/pistringlist.h index 0a9669f0..e5a9210e 100644 --- a/lib/main/core/pistringlist.h +++ b/lib/main/core/pistringlist.h @@ -37,17 +37,22 @@ public: //! Contructs strings list with one string "str" PIStringList(const PIString & str) {push_back(str);} + PIStringList(PIString && str) {push_back(std::move(str));} //! Contructs empty strings list with strings "s0" and "s1" PIStringList(const PIString & s0, const PIString & s1) {push_back(s0); push_back(s1);} + PIStringList(PIString && s0, PIString && s1) {push_back(std::move(s0)); push_back(std::move(s1));} //! Contructs empty strings list with strings "s0", "s1" and "s2" PIStringList(const PIString & s0, const PIString & s1, const PIString & s2) {push_back(s0); push_back(s1); push_back(s2);} + PIStringList(PIString && s0, PIString && s1, PIString && s2) {push_back(std::move(s0)); push_back(std::move(s1)); push_back(std::move(s2));} //! Contructs empty strings list with strings "s0", "s1", "s2" and "s3" PIStringList(const PIString & s0, const PIString & s1, const PIString & s2, const PIString & s3) {push_back(s0); push_back(s1); push_back(s2); push_back(s3);} + PIStringList(PIString && s0, PIString && s1, PIString && s2, PIString && s3) {push_back(std::move(s0)); push_back(std::move(s1)); push_back(std::move(s2)); push_back(std::move(s3));} - PIStringList(const PIStringList & o): PIDeque() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];} + PIStringList(const PIStringList & o): PIDeque(o) {} + PIStringList(PIStringList && o): PIDeque(std::move(o)) {} PIStringList(const PIVector & o): PIDeque() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];} PIStringList(const PIDeque & o): PIDeque() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];} @@ -83,6 +88,7 @@ public: PIStringList & operator =(const PIStringList & o) {PIDeque::operator=(o); return *this;} PIStringList & operator <<(const PIString & str) {append(str); return *this;} + PIStringList & operator <<(PIString && str) {append(std::move(str)); return *this;} PIStringList & operator <<(const PIStringList & sl) {append(sl); return *this;} }; diff --git a/lib/main/core/pivariant.h b/lib/main/core/pivariant.h index d40fa561..f5da7ce1 100644 --- a/lib/main/core/pivariant.h +++ b/lib/main/core/pivariant.h @@ -39,7 +39,7 @@ template -class PIP_EXPORT __PIVariantFunctions__ { +class __PIVariantFunctions__ { public: static PIString typeNameHelper() {return PIStringAscii("");} @@ -59,7 +59,7 @@ struct PIP_EXPORT __PIVariantInfo__ { }; template -struct PIP_EXPORT __PIVariantTypeInfo__ { +struct __PIVariantTypeInfo__ { typedef T PureType; typedef const T ConstPureType; typedef T * PointerType; @@ -102,7 +102,7 @@ REGISTER_VARIANT_TYPEINFO(ns::classname) #define REGISTER_VARIANT_CPP(classname) \ template \ -class PIP_EXPORT __##classname##_PIVariantInitializer__ { \ +class __##classname##_PIVariantInitializer__ { \ public: \ __##classname##_PIVariantInitializer__(const PIString & name) { \ if (__PIVariantInfoStorage__::get()->map->contains(name)) \ @@ -115,7 +115,7 @@ public: \ #define REGISTER_NS_VARIANT_CPP(ns, classname) \ template \ -class PIP_EXPORT __##ns##classname##_PIVariantInitializer__ { \ +class __##ns##classname##_PIVariantInitializer__ { \ public: \ __##ns##classname##_PIVariantInitializer__(const PIString & name) { \ if (__PIVariantInfoStorage__::get()->map->contains(name)) \ @@ -155,7 +155,7 @@ PIByteArray __PIVariantFunctions__::castHelper(PIB PIByteArray ret; ret << t; \ return ret;} \ template \ -class PIP_EXPORT __##classname_from##_##classname_to##_PIVariantCastInitializer__ { \ +class __##classname_from##_##classname_to##_PIVariantCastInitializer__ { \ public: \ __##classname_from##_##classname_to##_PIVariantCastInitializer__(const PIString & name, const PIString & cname) { \ __PIVariantInfo__ * vi(__PIVariantInfoStorage__::get()->map->value(name, 0)); \ @@ -206,7 +206,7 @@ class PIP_EXPORT PIVariant { public: //! Type of %PIVariant content - enum PIP_EXPORT Type { + enum Type { pivInvalid /** Invalid type , default type of empty contructor */ = 0 , pivBool /** bool */ , pivChar /** char */ , diff --git a/lib/main/crypt/piauth.h b/lib/main/crypt/piauth.h index 55559484..947d7e77 100644 --- a/lib/main/crypt/piauth.h +++ b/lib/main/crypt/piauth.h @@ -23,11 +23,12 @@ #ifndef PIAUTH_H #define PIAUTH_H +#include "pip_crypt_export.h" #include "piobject.h" #include "picrypt.h" -class PIP_EXPORT PIAuth : public PIObject +class PIP_CRYPT_EXPORT PIAuth : public PIObject { PIOBJECT(PIAuth) public: diff --git a/lib/main/crypt/picrypt.h b/lib/main/crypt/picrypt.h index e9eea9cd..67fe3a6b 100644 --- a/lib/main/crypt/picrypt.h +++ b/lib/main/crypt/picrypt.h @@ -23,9 +23,10 @@ #ifndef PICRYPT_H #define PICRYPT_H +#include "pip_crypt_export.h" #include "pistring.h" -class PIP_EXPORT PICrypt { +class PIP_CRYPT_EXPORT PICrypt { public: //! Construct and generate random key PICrypt(); diff --git a/lib/main/geo/pigeoposition.h b/lib/main/geo/pigeoposition.h index ef6ead1e..bb301198 100644 --- a/lib/main/geo/pigeoposition.h +++ b/lib/main/geo/pigeoposition.h @@ -30,8 +30,7 @@ class PIP_EXPORT PIGeoPosition : public PIMathVectorT3d { public: - enum CoordinateSystem - { + enum CoordinateSystem { Unknown=0, /// Unknown coordinate system Geodetic, /// Geodetic latitude, longitude, and height above ellipsoid Geocentric, /// Geocentric (regular spherical coordinates) diff --git a/lib/main/introspection/piintrospection_base.h b/lib/main/introspection/piintrospection_base.h index 6b86771d..e21f9830 100644 --- a/lib/main/introspection/piintrospection_base.h +++ b/lib/main/introspection/piintrospection_base.h @@ -23,7 +23,6 @@ #include "pibase.h" class PIString; -class PIMutex; class PIThread; class PITimer; class PIPeer; diff --git a/lib/main/introspection/piintrospection_containers_p.h b/lib/main/introspection/piintrospection_containers_p.h index f9d24a71..7ace0e6d 100644 --- a/lib/main/introspection/piintrospection_containers_p.h +++ b/lib/main/introspection/piintrospection_containers_p.h @@ -44,7 +44,7 @@ public: PIVector getInfo() const; #pragma pack(push, 1) - struct _Type { + struct PIP_EXPORT _Type { _Type(); uint id; uint count; @@ -54,7 +54,7 @@ public: }; #pragma pack(pop) - struct TypeInfo: _Type { + struct PIP_EXPORT TypeInfo: _Type { PIString name; }; @@ -63,7 +63,7 @@ public: mutable PIMutex mutex; }; -PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v); -PIByteArray & operator >>(PIByteArray & s, PIIntrospectionContainers::TypeInfo & v); +PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v); +PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIIntrospectionContainers::TypeInfo & v); #endif // PIINTROSPECTION_CONTAINERS_P_H diff --git a/lib/main/introspection/piintrospection_server_p.cpp b/lib/main/introspection/piintrospection_server_p.cpp index e5935f10..f0aee35c 100644 --- a/lib/main/introspection/piintrospection_server_p.cpp +++ b/lib/main/introspection/piintrospection_server_p.cpp @@ -214,9 +214,10 @@ PIByteArray PIIntrospection::packThreads() { if (p) { p->mutex.lock(); PIMap & tm(p->threads); - for (PIMap::iterator i = tm.begin(); i != tm.end(); ++i) { - i.value().classname = PIStringAscii(i.key()->className()); - i.value().name = i.key()->name(); + auto it = tm.makeIterator(); + while (it.next()) { + it.valueRef().classname = PIStringAscii(it.key()->className()); + it.valueRef().name = it.key()->name(); } ret << tm.values(); p->mutex.unlock(); diff --git a/lib/main/introspection/piintrospection_server_p.h b/lib/main/introspection/piintrospection_server_p.h index d47b83da..549dd044 100644 --- a/lib/main/introspection/piintrospection_server_p.h +++ b/lib/main/introspection/piintrospection_server_p.h @@ -27,7 +27,7 @@ #include "pisystemmonitor.h" -class PIIntrospection { +class PIP_EXPORT PIIntrospection { public: enum InfoTypes { @@ -38,12 +38,12 @@ public: itThreads = 0x10, }; - struct RequiredInfo { + struct PIP_EXPORT RequiredInfo { RequiredInfo(); PIFlags types; }; - struct ProcessInfo { + struct PIP_EXPORT ProcessInfo { ProcessInfo(); PIString execCommand, hostname, user, OS_name, OS_version, architecture; @@ -53,14 +53,14 @@ public: PIStringList build_options; }; - struct ProcessStat { + struct PIP_EXPORT ProcessStat { ProcessStat() {} PISystemMonitor::ProcessStats proc; PIVector threads; }; - struct ObjectInfo { + struct PIP_EXPORT ObjectInfo { ObjectInfo(); PIString classname, name; @@ -91,13 +91,13 @@ public: }; -PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v); -PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v); +PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v); +PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v); -PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v); -PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v); +PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v); +PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v); -PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v); -PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v); +PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v); +PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v); #endif // PIINTROSPECTION_SERVER_P_H diff --git a/lib/main/introspection/piintrospection_threads_p.h b/lib/main/introspection/piintrospection_threads_p.h index b9f12461..3318a4d2 100644 --- a/lib/main/introspection/piintrospection_threads_p.h +++ b/lib/main/introspection/piintrospection_threads_p.h @@ -35,7 +35,7 @@ public: sWaiting, }; - struct ThreadInfo { + struct PIP_EXPORT ThreadInfo { ThreadInfo(); PIString classname, name; int id, delay; @@ -57,7 +57,7 @@ public: }; -PIByteArray & operator <<(PIByteArray & b, const PIIntrospectionThreads::ThreadInfo & v); -PIByteArray & operator >>(PIByteArray & b, PIIntrospectionThreads::ThreadInfo & v); +PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospectionThreads::ThreadInfo & v); +PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospectionThreads::ThreadInfo & v); #endif // PIINTROSPECTION_THREADS_P_H diff --git a/lib/main/io_devices/pibinarylog.cpp b/lib/main/io_devices/pibinarylog.cpp index 51b33dc6..c1e46d4d 100644 --- a/lib/main/io_devices/pibinarylog.cpp +++ b/lib/main/io_devices/pibinarylog.cpp @@ -96,7 +96,7 @@ bool PIBinaryLog::openDevice() { piForeachC(PIFile::FileInfo &i, es) { if (i.extension() == "binlog" && i.isFile() && i.baseName().startsWith(filePrefix())) { setPath(i.path); - piBreak; + break; } } } diff --git a/lib/main/io_devices/pibinarylog.h b/lib/main/io_devices/pibinarylog.h index c41401f0..6703dcf0 100644 --- a/lib/main/io_devices/pibinarylog.h +++ b/lib/main/io_devices/pibinarylog.h @@ -56,7 +56,7 @@ public: }; //! \brief Struct contains information about all records with same ID - struct BinLogRecordInfo { + struct PIP_EXPORT BinLogRecordInfo { BinLogRecordInfo() { id = count = 0; minimum_size = maximum_size = 0; @@ -70,7 +70,7 @@ public: }; //! \brief Struct contains full information about Binary Log file and about all Records using map of \a BinLogRecordInfo - struct BinLogInfo { + struct PIP_EXPORT BinLogInfo { PIString path; int records_count; llong log_size; @@ -80,7 +80,7 @@ public: }; //! \brief Struct contains position, ID and timestamp of record in file - struct BinLogIndex { + struct PIP_EXPORT BinLogIndex { int id; llong pos; PISystemTime timestamp; @@ -293,7 +293,7 @@ protected: DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;} private: - struct BinLogRecord { + struct PIP_EXPORT BinLogRecord { int id; int size; PISystemTime timestamp; diff --git a/lib/main/io_devices/piconfig.h b/lib/main/io_devices/piconfig.h index cb3ddb6e..c6027ffc 100644 --- a/lib/main/io_devices/piconfig.h +++ b/lib/main/io_devices/piconfig.h @@ -505,8 +505,8 @@ private: #ifdef PIP_STD_IOSTREAM -std::ostream & operator <<(std::ostream & s, const PIConfig::Branch & v); -std::ostream & operator <<(std::ostream & s, const PIConfig::Entry & v); +PIP_EXPORT std::ostream & operator <<(std::ostream & s, const PIConfig::Branch & v); +PIP_EXPORT std::ostream & operator <<(std::ostream & s, const PIConfig::Entry & v); #endif inline PICout operator <<(PICout s, const PIConfig::Branch & v) {s.setControl(0, true); v.piCoutt(s, ""); s.restoreControl(); return s;} diff --git a/lib/main/io_devices/piethernet.h b/lib/main/io_devices/piethernet.h index 574f9fab..bb9f988e 100644 --- a/lib/main/io_devices/piethernet.h +++ b/lib/main/io_devices/piethernet.h @@ -43,7 +43,7 @@ public: explicit PIEthernet(); //! \brief Type of %PIEthernet - enum PIP_EXPORT Type { + enum Type { UDP /** UDP - User Datagram Protocol */ , TCP_Client /** TCP client - allow connection to TCP server */ , TCP_Server /** TCP server - receive connections from TCP clients */ , @@ -51,7 +51,7 @@ public: }; //! \brief Parameters of %PIEthernet - enum PIP_EXPORT Parameters { + enum Parameters { ReuseAddress /** Rebind address if there is already binded. Enabled by default */ = 0x1, Broadcast /** Broadcast send. Disabled by default */ = 0x2, SeparateSockets /** If this parameter is set, %PIEthernet will initialize two different sockets, @@ -63,7 +63,7 @@ public: //! \brief IPv4 network address, IP and port - class Address { + class PIP_EXPORT Address { friend class PIEthernet; friend inline PIByteArray & operator <<(PIByteArray & s, const PIEthernet::Address & v); friend inline PIByteArray & operator >>(PIByteArray & s, PIEthernet::Address & v); @@ -322,7 +322,7 @@ public: //! Flags of network interface - enum PIP_EXPORT InterfaceFlag { + enum InterfaceFlag { ifActive /** Is active */ = 0x1, ifRunning /** Is running */ = 0x2, ifBroadcast /** Support broadcast */ = 0x4, @@ -485,7 +485,7 @@ protected: void applyTimeout(int fd, int opt, double ms); void applyOptInt(int level, int opt, int val); - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) int sock, sock_s; bool connected_, connecting_, listen_threaded, server_bounded; mutable Address addr_r, addr_s, addr_lr; diff --git a/lib/main/io_devices/pifile.cpp b/lib/main/io_devices/pifile.cpp index cc9d0d9c..8984253b 100644 --- a/lib/main/io_devices/pifile.cpp +++ b/lib/main/io_devices/pifile.cpp @@ -235,7 +235,7 @@ PIByteArray PIFile::readAll(bool forceRead) { llong s = size(); if (s < 0) return a; a.resize(s); - s = readAll(a.data()); + fread(a.data(), 1, s, PRIVATE->fd); seek(cp); if (s >= 0) a.resize(s); return a; @@ -593,7 +593,7 @@ void PIFile::setDefaultCharset(const char * c) { PIFile::FileInfo PIFile::fileInfo(const PIString & path) { FileInfo ret; if (path.isEmpty()) return ret; - ret.path = path.replaceAll("\\", PIDir::separator); + ret.path = path.replacedAll("\\", PIDir::separator); PIString n = ret.name(); //piCout << "open" << path; #ifdef WINDOWS diff --git a/lib/main/io_devices/pifile.h b/lib/main/io_devices/pifile.h index e8af7626..1f94625b 100644 --- a/lib/main/io_devices/pifile.h +++ b/lib/main/io_devices/pifile.h @@ -38,7 +38,7 @@ public: struct PIP_EXPORT FileInfo { FileInfo() {size = 0; id_group = id_user = 0;} - enum PIP_EXPORT Flag { + enum Flag { File = 0x01, Dir = 0x02, Dot = 0x04, @@ -292,7 +292,7 @@ protected: private: PIString strType(const PIIODevice::DeviceMode type); - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) int ret, prec_, fdi; PIString prec_str; diff --git a/lib/main/io_devices/pigpio.h b/lib/main/io_devices/pigpio.h index cd2b91e7..ed566206 100644 --- a/lib/main/io_devices/pigpio.h +++ b/lib/main/io_devices/pigpio.h @@ -26,7 +26,7 @@ #include "pithread.h" -class PIGPIO: public PIThread +class PIP_EXPORT PIGPIO: public PIThread { PIOBJECT_SUBCLASS(PIGPIO, PIThread) public: @@ -85,7 +85,7 @@ public: //! \} private: - struct GPIOData { + struct PIP_EXPORT GPIOData { GPIOData() {dir = PIGPIO::In; num = fd = -1;} PIString name; int dir; diff --git a/lib/main/io_devices/piiodevice.cpp b/lib/main/io_devices/piiodevice.cpp index f4919052..ec54085b 100644 --- a/lib/main/io_devices/piiodevice.cpp +++ b/lib/main/io_devices/piiodevice.cpp @@ -382,7 +382,7 @@ void PIIODevice::splitFullPath(PIString fpwm, PIString * full_path, DeviceMode * int dm = 0; DeviceOptions op = 0; if (fpwm.find("(") > 0 && fpwm.find(")") > 0) { - PIString dms(fpwm.right(fpwm.length() - fpwm.findLast("(")).takeRange("(", ")").trim().toLowerCase().removeAll(" ")); + PIString dms(fpwm.right(fpwm.length() - fpwm.findLast("(")).takeRange("(", ")").trim().toLowerCase().removeAll(' ')); PIStringList opts(dms.split(",")); piForeachC (PIString & o, opts) { //piCout << dms; diff --git a/lib/main/io_devices/piiodevice.h b/lib/main/io_devices/piiodevice.h index 74a6e8b7..a9d1d227 100644 --- a/lib/main/io_devices/piiodevice.h +++ b/lib/main/io_devices/piiodevice.h @@ -54,6 +54,7 @@ class PIP_EXPORT PIIODevice: public PIThread PIOBJECT_SUBCLASS(PIIODevice, PIThread) friend void __DevicePool_threadReadDP(void * ddp); public: + NO_COPY_CLASS(PIIODevice) //! Constructs a empty PIIODevice explicit PIIODevice(); @@ -388,8 +389,6 @@ protected: void * ret_data_; private: - NO_COPY_CLASS(PIIODevice) - EVENT_HANDLER2(void, check_start, void * , data, int, delim); EVENT_HANDLER(void, write_func); diff --git a/lib/main/io_devices/pipeer.cpp b/lib/main/io_devices/pipeer.cpp index 260812f6..85cc0bc3 100644 --- a/lib/main/io_devices/pipeer.cpp +++ b/lib/main/io_devices/pipeer.cpp @@ -491,7 +491,7 @@ bool PIPeer::dataRead(uchar * readed, int size) { if (p.name != from) continue; piForeach (PeerInfo::PeerAddress & a, p.addresses) { if (a.address != addr) continue; - if (a.last_ping >= time) piBreak; + if (a.last_ping >= time) break; ptime = ctime - time; a.last_ping = time; a.wait_ping = false; @@ -677,7 +677,7 @@ bool PIPeer::mbcastRead(uchar * data, int size) { if (peer.name == pi.name) peer.sync = 0; ch = true; } - piBreak; + break; } } if (exist || isRemoved(rpeer)) continue; diff --git a/lib/main/io_devices/pipeer.h b/lib/main/io_devices/pipeer.h index c142b81b..41862623 100644 --- a/lib/main/io_devices/pipeer.h +++ b/lib/main/io_devices/pipeer.h @@ -36,7 +36,7 @@ public: explicit PIPeer(const PIString & name = PIString()); virtual ~PIPeer(); - class PeerInfo { + class PIP_EXPORT PeerInfo { friend class PIPeer; friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v); friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v); @@ -44,7 +44,7 @@ public: PeerInfo() {dist = sync = cnt = 0; trace = -1; was_update = false; _data = 0;} ~PeerInfo() {} - struct PeerAddress { + struct PIP_EXPORT PeerAddress { PeerAddress(const PIEthernet::Address & a = PIEthernet::Address(), const PIEthernet::Address & m = PIEthernet::Address("255.255.255.0")); bool isAvailable() const {return ping > 0;} PIEthernet::Address address; @@ -120,11 +120,11 @@ public: EVENT1(peerConnectedEvent, const PIString &, name) EVENT1(peerDisconnectedEvent, const PIString &, name) - bool lockedEth() const {return eth_mutex.isLocked();} - bool lockedPeers() const {return peers_mutex.isLocked();} - bool lockedMBcasts() const {return mc_mutex.isLocked();} - bool lockedSends() const {return send_mutex.isLocked();} - bool lockedMCSends() const {return send_mc_mutex.isLocked();} +// bool lockedEth() const {return eth_mutex.isLocked();} +// bool lockedPeers() const {return peers_mutex.isLocked();} +// bool lockedMBcasts() const {return mc_mutex.isLocked();} +// bool lockedSends() const {return send_mutex.isLocked();} +// bool lockedMCSends() const {return send_mc_mutex.isLocked();} protected: virtual void dataReceived(const PIString & from, const PIByteArray & data) {;} diff --git a/lib/main/io_devices/piserial.cpp b/lib/main/io_devices/piserial.cpp index b39fad68..4c526a62 100644 --- a/lib/main/io_devices/piserial.cpp +++ b/lib/main/io_devices/piserial.cpp @@ -544,7 +544,7 @@ bool PISerial::openDevice() { piForeachC (DeviceInfo & d, devs) { if (d.id() == pl) { p = d.path; - piBreak; + break; } } if (p.isEmpty()) { diff --git a/lib/main/io_devices/piserial.h b/lib/main/io_devices/piserial.h index 8ef9e9d7..4b8cae4e 100644 --- a/lib/main/io_devices/piserial.h +++ b/lib/main/io_devices/piserial.h @@ -72,7 +72,7 @@ public: }; //! \brief Information about serial device - struct DeviceInfo { + struct PIP_EXPORT DeviceInfo { DeviceInfo(); //! \brief String representation of USB ID in format \"xxxx:xxxx\" @@ -246,7 +246,7 @@ protected: bool openDevice(); bool closeDevice(); - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) int fd, vtime; bool sending; PITimeMeasurer tm_; diff --git a/lib/main/io_devices/pisharedmemory.h b/lib/main/io_devices/pisharedmemory.h index f00046e8..36bd8c3f 100644 --- a/lib/main/io_devices/pisharedmemory.h +++ b/lib/main/io_devices/pisharedmemory.h @@ -86,7 +86,7 @@ private: void initPrivate(); int dsize; - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) }; diff --git a/lib/main/io_devices/pispi.h b/lib/main/io_devices/pispi.h index f6705f81..7c30a59f 100644 --- a/lib/main/io_devices/pispi.h +++ b/lib/main/io_devices/pispi.h @@ -77,7 +77,7 @@ private: uchar spi_bits; PIByteArray tx_buf, rx_buf; PIByteArray recv_buf; - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) }; #endif // PISPI_H diff --git a/lib/main/io_devices/piusb.h b/lib/main/io_devices/piusb.h index ce729734..2b17d382 100644 --- a/lib/main/io_devices/piusb.h +++ b/lib/main/io_devices/piusb.h @@ -34,7 +34,7 @@ public: explicit PIUSB(ushort vid = 0, ushort pid = 0); ~PIUSB() {closeDevice();} - struct Endpoint { + struct PIP_EXPORT Endpoint { Endpoint(uchar a = 0, uchar at = 0, ushort mps = 0) {address = a; attributes = at; max_packet_size = mps; parse();} enum Direction {Write = 0, Read = 1}; @@ -54,7 +54,7 @@ public: UsageType usage_type; }; - struct Interface { + struct PIP_EXPORT Interface { Interface() {index = value_to_select = class_code = subclass_code = protocol_code = 0;} uchar index; uchar value_to_select; @@ -64,7 +64,7 @@ public: PIVector endpoints; }; - struct Configuration { + struct PIP_EXPORT Configuration { Configuration() {index = value_to_select = attributes = max_power = 0; self_powered = remote_wakeup = false;} uchar index; uchar value_to_select; @@ -75,7 +75,7 @@ public: PIVector interfaces; }; - struct Descriptor { + struct PIP_EXPORT Descriptor { Descriptor() {usb_spec_number = 0; device_class = device_subclass = device_protocol = max_packet_size = 0; id_vendor = id_product = id_device_release = 0; index_manufacturer = index_product = index_serial = 0;} ushort usb_spec_number; uchar device_class; @@ -148,6 +148,6 @@ protected: }; -PICout operator <<(PICout s, const PIUSB::Endpoint & v); +PIP_EXPORT PICout operator <<(PICout s, const PIUSB::Endpoint & v); #endif // PIUSB_H diff --git a/lib/main/io_utils/pibasetransfer.h b/lib/main/io_utils/pibasetransfer.h index a11909da..d5f54ac2 100644 --- a/lib/main/io_utils/pibasetransfer.h +++ b/lib/main/io_utils/pibasetransfer.h @@ -102,7 +102,7 @@ protected: llong bytes_all, bytes_cur; private: - enum PIP_EXPORT PacketType {pt_Unknown, pt_Data, pt_ReplySuccess, pt_ReplyInvalid, pt_Break, pt_Start, pt_Pause}; + enum PacketType {pt_Unknown, pt_Data, pt_ReplySuccess, pt_ReplyInvalid, pt_Break, pt_Start, pt_Pause}; # pragma pack(push,1) struct PIP_EXPORT StartRequest { diff --git a/lib/main/io_utils/pibroadcast.h b/lib/main/io_utils/pibroadcast.h index b099e43e..67008007 100644 --- a/lib/main/io_utils/pibroadcast.h +++ b/lib/main/io_utils/pibroadcast.h @@ -23,11 +23,12 @@ #ifndef PIBROADCAST_H #define PIBROADCAST_H +#include "pip_io_utils_export.h" #include "piethutilbase.h" #include "piethernet.h" -class PIBroadcast: public PIThread, public PIEthUtilBase { +class PIP_IO_UTILS_EXPORT PIBroadcast: public PIThread, public PIEthUtilBase { PIOBJECT_SUBCLASS(PIBroadcast, PIThread) public: diff --git a/lib/main/io_utils/piconnection.cpp b/lib/main/io_utils/piconnection.cpp index ddafa147..c82d8c7c 100644 --- a/lib/main/io_utils/piconnection.cpp +++ b/lib/main/io_utils/piconnection.cpp @@ -375,21 +375,22 @@ bool PIConnection::removeDevice(const PIString & full_path) { PIStringList dntd(deviceNames(dev)); piForeachC (PIString & n, dntd) device_names.removeOne(n); - piForeachC (SPair & s, senders) { - if (s.second == 0) continue; - s.second->lock(); - s.second->devices.removeAll(dev); - s.second->unlock(); + for (auto s = senders.constBegin(); s != senders.constEnd(); s++) { + if (s.value() == 0) continue; + s.value()->lock(); + s.value()->devices.removeAll(dev); + s.value()->unlock(); } device_modes.remove(dev); - piForeachC (PEPair & i, extractors) { - if (i.second == 0) continue; - i.second->devices.removeAll(dev); + for (auto i = extractors.constBegin(); i != extractors.constEnd(); i++) { + if (i.value() == 0) continue; + i.value()->devices.removeAll(dev); } bounded_extractors.remove(dev); channels_.remove(dev); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(dev); + auto it = channels_.makeIterator(); + while (it.next()) + it.valueRef().removeAll(dev); __device_pool__->lock(); if (diags_.value(dev, 0) != 0) delete diags_.value(dev); @@ -404,15 +405,16 @@ void PIConnection::removeAllDevices() { PIVector bdevs(__device_pool__->boundedDevices(this)); __device_pool__->lock(); piForeach (PIIODevice * d, bdevs) { - piForeachC (SPair & s, senders) { - if (s.second == 0) continue; - s.second->lock(); - s.second->devices.removeAll(d); - s.second->unlock(); + for (auto s = senders.constBegin(); s != senders.constEnd(); s++) { + if (s.value() == 0) continue; + s.value()->lock(); + s.value()->devices.removeAll(d); + s.value()->unlock(); } channels_.remove(d); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(d); + auto it = channels_.makeIterator(); + while (it.next()) + it.valueRef().removeAll(d); if (diags_.value(d, 0) != 0) delete diags_.value(d); diags_.remove(d); @@ -421,9 +423,9 @@ void PIConnection::removeAllDevices() { __device_pool__->unlock(); device_modes.clear(); bounded_extractors.clear(); - piForeachC (PEPair & i, extractors) { - if (i.second == 0) continue; - i.second->devices.clear(); + for (auto i = extractors.constBegin(); i != extractors.constEnd(); i++) { + if (i.value() == 0) continue; + i.value()->devices.clear(); } } @@ -563,15 +565,16 @@ bool PIConnection::removeFilter(const PIString & name_) { void PIConnection::removeAllFilters() { __device_pool__->lock(); - piForeachC (PEPair & i, extractors) { - if (i.second == 0) continue; - channels_.remove(i.second->extractor); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(i.second->extractor); - if (diags_.value(i.second->extractor, 0) != 0) - delete diags_.value(i.second->extractor); - diags_.remove(i.second->extractor); - delete i.second; + for (auto i = extractors.constBegin(); i != extractors.constEnd(); i++) { + if (i.value() == 0) continue; + channels_.remove(i.value()->extractor); + auto it = channels_.makeIterator(); + while (it.next()) + it.valueRef().removeAll(i.value()->extractor); + if (diags_.value(i.value()->extractor, 0) != 0) + delete diags_.value(i.value()->extractor); + diags_.remove(i.value()->extractor); + delete i.value(); } extractors.clear(); bounded_extractors.clear(); @@ -581,28 +584,31 @@ void PIConnection::removeAllFilters() { PIVector PIConnection::filters() const { PIVector ret; - piForeachC (PEPair & i, extractors) - if (i.second != 0) - if (i.second->extractor != 0) ret << i.second->extractor; + for (auto i = extractors.constBegin(); i != extractors.constEnd(); i++) { + if (i.value() != 0) + if (i.value()->extractor != 0) ret << i.value()->extractor; + } return ret; } PIStringList PIConnection::filterNames() const { PIStringList ret; - piForeachC (PEPair & i, extractors) - if (i.second != 0) - if (i.second->extractor != 0) ret << i.first; + for (auto i = extractors.constBegin(); i != extractors.constEnd(); i++) { + if (i.value() != 0) + if (i.value()->extractor != 0) ret << i.key(); + } return ret; } PIPacketExtractor * PIConnection::filter(const PIString & name_) const { PIString fname_ = name_.trimmed(); - piForeachC (PEPair & i, extractors) - if (i.second != 0) - if (i.second->extractor != 0 && i.first == fname_) - return i.second->extractor; + for (auto i = extractors.constBegin(); i != extractors.constEnd(); i++) { + if (i.value() != 0) + if (i.value()->extractor != 0 && i.key() == fname_) + return i.value()->extractor; + } return 0; } @@ -655,8 +661,9 @@ bool PIConnection::removeChannel(const PIString & name0) { if (pe0 != 0) dev0 = pe0; if (dev0 == 0) return false; channels_.remove(dev0); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(dev0); + auto it = channels_.makeIterator(); + while (it.next()) + it.valueRef().removeAll(dev0); return true; } @@ -784,9 +791,10 @@ float PIConnection::senderFrequency(const PIString & name) const { void PIConnection::removeAllSenders() { - piForeachC (SPair & s, senders) - if (s.second != 0) - delete s.second; + for (auto s = senders.constBegin(); s != senders.constEnd(); s++) { + if (s.value() != 0) + delete s.value(); + } senders.clear(); } @@ -802,8 +810,8 @@ void PIConnection::startThreadedRead(const PIString & full_path_name) { void PIConnection::startAllThreadedReads() { - piForeachC (DevicePool::DDPair & d, __device_pool__->devices) - startThreadedRead(d.first); + for (auto d = __device_pool__->devices.constBegin(); d != __device_pool__->devices.constEnd(); d++) + startThreadedRead(d.key()); } @@ -816,10 +824,10 @@ void PIConnection::startSender(const PIString & name) { void PIConnection::startAllSenders() { - piForeachC (SPair & s, senders) { - if (s.second == 0) continue; - if (!s.second->isRunning() && !__device_pool__->fake) - s.second->start(s.second->int_); + for (auto s = senders.constBegin(); s != senders.constEnd(); s++) { + if (s.value() == 0) continue; + if (!s.value()->isRunning() && !__device_pool__->fake) + s.value()->start(s.value()->int_); } } @@ -835,8 +843,8 @@ void PIConnection::stopThreadedRead(const PIString & full_path_name) { void PIConnection::stopAllThreadedReads() { - piForeachC (DevicePool::DDPair & d, __device_pool__->devices) - stopThreadedRead(d.first); + for (auto d = __device_pool__->devices.constBegin(); d != __device_pool__->devices.constEnd(); d++) + stopThreadedRead(d.key()); } @@ -848,10 +856,10 @@ void PIConnection::stopSender(const PIString & name) { void PIConnection::stopAllSenders() { - piForeachC (SPair & s, senders) { - if (s.second == 0) continue; - if (s.second->isRunning()) - s.second->stop(); + for (auto s = senders.constBegin(); s != senders.constEnd(); s++) { + if (s.value() == 0) continue; + if (s.value()->isRunning()) + s.value()->stop(); } } @@ -1012,14 +1020,14 @@ bool PIConnection::DevicePool::removeDevice(PIConnection * parent, const PIStrin void PIConnection::DevicePool::unboundConnection(PIConnection * parent) { PIStringList rem; - piForeachC (DDPair & i, devices) { - if (i.second == 0) { - rem << i.first; + for (auto i = devices.constBegin(); i != devices.constEnd(); i++) { + if (i.value() == 0) { + rem << i.key(); continue; } - i.second->listeners.removeAll(parent); - if (i.second->listeners.isEmpty()) - rem << i.first; + i.value()->listeners.removeAll(parent); + if (i.value()->listeners.isEmpty()) + rem << i.key(); } piForeachC (PIString & i, rem) { DeviceData * dd = devices.value(i); @@ -1105,9 +1113,9 @@ PIConnection::DevicePool::DeviceData::~DeviceData() { void PIConnection::DevicePool::run() { PIVector conns(PIConnection::allConnections()); piForeach (PIConnection * c, conns) { - piForeachC (PIConnection::DPair & d, c->diags_) { - if (d.second == 0) continue; - d.second->tick(0, 1); + for (auto d = c->diags_.constBegin(); d != c->diags_.constEnd(); d++) { + if (d.value() == 0) continue; + d.value()->tick(0, 1); } } } @@ -1236,8 +1244,9 @@ void PIConnection::Sender::tick(void * , int) { void PIConnection::unboundExtractor(PIPacketExtractor * pe) { if (pe == 0) return; channels_.remove(pe); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(pe); + auto it = channels_.makeIterator(); + while (it.next()) + it.valueRef().removeAll(pe); bounded_extractors.remove(pe); PIVector k = bounded_extractors.keys(); piForeach (PIIODevice * i, k) { diff --git a/lib/main/io_utils/piconnection.h b/lib/main/io_utils/piconnection.h index 5af11b52..f6be10bd 100644 --- a/lib/main/io_utils/piconnection.h +++ b/lib/main/io_utils/piconnection.h @@ -404,7 +404,7 @@ private: void __DevicePool_threadReadDP(void * ddp); -extern PIConnection::DevicePool * __device_pool__; +extern PIP_EXPORT PIConnection::DevicePool * __device_pool__; class PIP_EXPORT __DevicePoolContainer__ { public: diff --git a/lib/main/io_utils/pidiagnostics.h b/lib/main/io_utils/pidiagnostics.h index 74a69348..71da060a 100644 --- a/lib/main/io_utils/pidiagnostics.h +++ b/lib/main/io_utils/pidiagnostics.h @@ -32,12 +32,13 @@ class PIP_EXPORT PIDiagnostics: public PITimer PIOBJECT_SUBCLASS(PIDiagnostics, PITimer) friend class PIConnection; public: + NO_COPY_CLASS(PIDiagnostics) //! Constructs an empty diagnostics and if "start_" start it PIDiagnostics(bool start_ = true); virtual ~PIDiagnostics(); - + //! Connection quality enum Quality { Unknown /** Unknown, no one packet received yet */ = 1, @@ -48,7 +49,7 @@ public: }; //! Information about current diagnostics state - struct State { + struct PIP_EXPORT State { State(); float immediate_freq; float integral_freq; @@ -122,9 +123,7 @@ public: //! \} private: - NO_COPY_CLASS(PIDiagnostics) - - struct Entry { + struct PIP_EXPORT Entry { Entry() {bytes_ok = bytes_fail = 0; cnt_ok = cnt_fail = 0; empty = true;} ullong bytes_ok; ullong bytes_fail; diff --git a/lib/main/io_utils/piethutilbase.h b/lib/main/io_utils/piethutilbase.h index 8542ef36..fc564004 100644 --- a/lib/main/io_utils/piethutilbase.h +++ b/lib/main/io_utils/piethutilbase.h @@ -23,9 +23,10 @@ #ifndef PIETHUTILBASE_H #define PIETHUTILBASE_H +#include "pip_io_utils_export.h" #include "pibytearray.h" -class PIEthUtilBase { +class PIP_IO_UTILS_EXPORT PIEthUtilBase { public: PIEthUtilBase(); ~PIEthUtilBase(); diff --git a/lib/main/io_utils/pifiletransfer.h b/lib/main/io_utils/pifiletransfer.h index 241b499c..b74b9eef 100644 --- a/lib/main/io_utils/pifiletransfer.h +++ b/lib/main/io_utils/pifiletransfer.h @@ -35,7 +35,7 @@ public: PIFileTransfer(); ~PIFileTransfer(); - enum PIP_EXPORT StepType {pft_None, pft_Description, pft_Data}; + enum StepType {pft_None, pft_Description, pft_Data}; struct PIP_EXPORT PFTFileInfo: public PIFile::FileInfo { PFTFileInfo(const PIFile::FileInfo &fi = PIFile::FileInfo()): PIFile::FileInfo(fi) {} diff --git a/lib/main/io_utils/pistreampacker.h b/lib/main/io_utils/pistreampacker.h index 361e647c..f9777ee4 100644 --- a/lib/main/io_utils/pistreampacker.h +++ b/lib/main/io_utils/pistreampacker.h @@ -23,20 +23,21 @@ #ifndef PISTREAMPACKER_H #define PISTREAMPACKER_H +#include "pip_io_utils_export.h" #include "piobject.h" #include "piethutilbase.h" class PIIODevice; -class PIP_EXPORT PIStreamPacker: public PIObject, public PIEthUtilBase { +class PIP_IO_UTILS_EXPORT PIStreamPacker: public PIObject, public PIEthUtilBase { PIOBJECT(PIStreamPacker) public: //! Contructs packer and try to assign \"dev\" PIStreamPacker(PIIODevice * dev = 0); //! Progress info - struct Progress { + struct PIP_IO_UTILS_EXPORT Progress { Progress(); //! Is send/receive in progress diff --git a/lib/main/concurrent/piconditionlock.h b/lib/main/lua/piluaprogram.h similarity index 52% rename from lib/main/concurrent/piconditionlock.h rename to lib/main/lua/piluaprogram.h index b44e4633..3b2cf5da 100644 --- a/lib/main/concurrent/piconditionlock.h +++ b/lib/main/lua/piluaprogram.h @@ -1,7 +1,10 @@ +/*! \file piluaprogram.h + * \brief Lua Program +*/ /* PIP - Platform Independent Primitives - - Stephan Fomenko + 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 @@ -17,35 +20,32 @@ along with this program. If not, see . */ -#ifndef PICONDITIONLOCK_H -#define PICONDITIONLOCK_H +#ifndef PILUAPROGRAM_H +#define PILUAPROGRAM_H -#include "pimutex.h" +#include "pip_lua_export.h" +#include "pip_lua.h" - -/** - * @brief Continued - */ -class PIP_EXPORT PIConditionLock { +class PIP_LUA_EXPORT PILuaProgram +{ public: - explicit PIConditionLock(); - ~PIConditionLock(); + //! Constructs an empty PILuaProgram, initialize Lua context + PILuaProgram(); - //! \brief lock - void lock(); + //! Load Lua script from PIString + bool load(const PIString & script); - //! \brief unlock - void unlock(); + //! Execute script + bool prepare(); - //! \brief tryLock - bool tryLock(); + //! Get Lua Object or Function + luabridge::LuaRef getGlobal(const PIString & name); - void * handle(); + //! Return Lua global namespace + luabridge::Namespace getGlobalNamespace(); private: - NO_COPY_CLASS(PIConditionLock) - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_LUA_EXPORT) }; - -#endif // PICONDITIONLOCK_H +#endif // PILUAPROGRAM_H diff --git a/lib/main/lua/pip_lua.h b/lib/main/lua/pip_lua.h new file mode 100644 index 00000000..a9b94167 --- /dev/null +++ b/lib/main/lua/pip_lua.h @@ -0,0 +1,58 @@ +/*! \file pip_lua.h + * \brief PIP Lua bindings + * + * This file declare conversions for PIP types via LuaBridge +*/ +/* + PIP - Platform Independent Primitives + PIP Lua bindings + 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 . +*/ +#ifndef PIP_LUA_H +#define PIP_LUA_H + +#include "lua.hpp" +#include +#include "pistring.h" + +namespace luabridge { + +template <> +struct Stack { + static void push (lua_State* L, PIString const& str) { + lua_pushstring(L, str.dataUTF8()); + } + + static PIString get (lua_State* L, int index) { + if (lua_type(L, index) == LUA_TSTRING) { + const char* str = lua_tostring(L, index); + return PIString::fromUTF8(str); + } + + lua_pushvalue(L, index); + const char* str = lua_tostring(L, -1); + PIString string = PIString::fromUTF8(str); + lua_pop(L, 1); + return string; + } + + static bool isInstance (lua_State* L, int index) { + return lua_type(L, index) == LUA_TSTRING; + } +}; + +} +#endif // PIP_LUA_H diff --git a/lib/main/math/pievaluator.h b/lib/main/math/pievaluator.h index fa4095a2..94ff6250 100644 --- a/lib/main/math/pievaluator.h +++ b/lib/main/math/pievaluator.h @@ -30,12 +30,12 @@ typedef complexd (*FuncFunc)(void * , int, complexd * ); namespace PIEvaluatorTypes { - enum PIP_EXPORT eType {etNumber, etOperator, etVariable, etFunction}; - enum PIP_EXPORT Operation {oNone, oAdd, oSubtract, oMultiply, oDivide, oResidue, oPower, + enum eType {etNumber, etOperator, etVariable, etFunction}; + enum Operation {oNone, oAdd, oSubtract, oMultiply, oDivide, oResidue, oPower, oEqual, oNotEqual, oGreater, oSmaller, oGreaterEqual, oSmallerEqual, oAnd, oOr, oFunction }; - enum PIP_EXPORT BaseFunctions {bfUnknown, bfSin, bfCos, bfTg, bfCtg, + enum BaseFunctions {bfUnknown, bfSin, bfCos, bfTg, bfCtg, bfArcsin, bfArccos, bfArctg, bfArcctg, bfExp, bfRandom, bfRandomn, bfSh, bfCh, bfTh, bfCth, diff --git a/lib/main/math/pifft.h b/lib/main/math/pifft.h index 06250e32..628f3979 100644 --- a/lib/main/math/pifft.h +++ b/lib/main/math/pifft.h @@ -23,6 +23,7 @@ #ifndef PIFFT_H #define PIFFT_H +#include "pip_fftw_export.h" #include "pimathcomplex.h" class PIP_EXPORT PIFFT_double @@ -123,7 +124,7 @@ typedef PIFFT_float PIFFTf; #ifndef CC_VC -#define _PIFFTW_H(type) class _PIFFTW_P_##type##_ { \ +#define _PIFFTW_H(type) class PIP_FFTW_EXPORT _PIFFTW_P_##type##_ { \ public: \ _PIFFTW_P_##type##_(); \ ~_PIFFTW_P_##type##_(); \ @@ -138,7 +139,7 @@ _PIFFTW_H(double) _PIFFTW_H(ldouble) template -class PIP_EXPORT PIFFTW +class PIFFTW { public: explicit PIFFTW() {p = 0; newP(p);} diff --git a/lib/main/math/pimathbase.h b/lib/main/math/pimathbase.h index 740514b7..d33482b7 100644 --- a/lib/main/math/pimathbase.h +++ b/lib/main/math/pimathbase.h @@ -103,21 +103,21 @@ inline float sqr(const float & v) {return v * v;} inline double sqr(const double & v) {return v * v;} inline double sinc(const double & v) {if (v == 0.) return 1.; double t = M_PI * v; return sin(t) / t;} -double piJ0(const double & v); -double piJ1(const double & v); -double piJn(int n, const double & v); -double piY0(const double & v); -double piY1(const double & v); -double piYn(int n, const double & v); +PIP_EXPORT double piJ0(const double & v); +PIP_EXPORT double piJ1(const double & v); +PIP_EXPORT double piJn(int n, const double & v); +PIP_EXPORT double piY0(const double & v); +PIP_EXPORT double piY1(const double & v); +PIP_EXPORT double piYn(int n, const double & v); inline double toDb(double val) {return 10. * log10(val);} inline double fromDb(double val) {return pow(10., val / 10.);} inline double toRad(double deg) {return deg * M_PI_180;} inline double toDeg(double rad) {return rad * M_180_PI;} // [-1 ; 1] -double randomd(); +PIP_EXPORT double randomd(); // [-1 ; 1] normal -double randomn(double dv = 0., double sv = 1.); +PIP_EXPORT double randomn(double dv = 0., double sv = 1.); inline PIVector abs(const PIVector & v) { diff --git a/lib/main/math/pimathcomplex.h b/lib/main/math/pimathcomplex.h index 4c1ffe1b..2bcc7fea 100644 --- a/lib/main/math/pimathcomplex.h +++ b/lib/main/math/pimathcomplex.h @@ -68,15 +68,10 @@ inline complexd sign(const complexd & x) {return complexd(sign(x.real()), sign(x inline complexd round(const complexd & c) {return complexd(piRound(c.real()), piRound(c.imag()));} inline complexd floor(const complexd & c) {return complexd(floor(c.real()), floor(c.imag()));} inline complexd ceil (const complexd & c) {return complexd(ceil(c.real()), ceil(c.imag()));} -#ifdef PIP_CXX11_SUPPORT -# define acosc acos -# define asinc asin -# define atanc atan -#else -inline complexd atanc(const complexd & c) {return complexd(0., 0.5) * log((complexd_1 - complexd_i * c) / (complexd_1 + complexd_i * c));} -inline complexd asinc(const complexd & c) {return -complexd_i * log(complexd_i * c + sqrt(complexd_1 - c * c));} -inline complexd acosc(const complexd & c) {return -complexd_i * log(c + complexd_i * sqrt(complexd_1 - c * c));} -#endif + +#define acosc acos +#define asinc asin +#define atanc atan #ifdef CC_GCC # if CC_GCC_VERSION <= 0x025F diff --git a/lib/main/math/pimathsolver.h b/lib/main/math/pimathsolver.h index 23bbd249..5d030c20 100644 --- a/lib/main/math/pimathsolver.h +++ b/lib/main/math/pimathsolver.h @@ -27,7 +27,7 @@ /// Differential evaluations -struct TransferFunction { +struct PIP_EXPORT TransferFunction { PIVector vector_Bm, vector_An; }; diff --git a/lib/main/math/piquaternion.h b/lib/main/math/piquaternion.h index 475da1b6..e9b79e92 100644 --- a/lib/main/math/piquaternion.h +++ b/lib/main/math/piquaternion.h @@ -25,7 +25,7 @@ #include "pimathmatrix.h" -class PIQuaternion +class PIP_EXPORT PIQuaternion { friend PIQuaternion operator*(const PIQuaternion & q0, const PIQuaternion & q1); friend PIQuaternion operator*(const double & a, const PIQuaternion & q); @@ -57,8 +57,8 @@ protected: }; -PIQuaternion operator *(const double & a, const PIQuaternion & q); -PIQuaternion operator *(const PIQuaternion & q0, const PIQuaternion & q1); +PIP_EXPORT PIQuaternion operator *(const double & a, const PIQuaternion & q); +PIP_EXPORT PIQuaternion operator *(const PIQuaternion & q0, const PIQuaternion & q1); inline PIQuaternion operator +(const PIQuaternion & q0, const PIQuaternion & q1) {return PIQuaternion(q0.vector() + q1.vector(), q0.scalar() + q1.scalar());} inline PIQuaternion operator -(const PIQuaternion & q0, const PIQuaternion & q1) {return PIQuaternion(q0.vector() - q1.vector(), q0.scalar() - q1.scalar());} inline PIQuaternion operator -(const PIQuaternion & q0) {return PIQuaternion(-q0.vector(), -q0.scalar());} diff --git a/lib/main/math/pistatistic.h b/lib/main/math/pistatistic.h index f5f66f30..d4e70997 100644 --- a/lib/main/math/pistatistic.h +++ b/lib/main/math/pistatistic.h @@ -26,7 +26,7 @@ #include "pimathbase.h" template -class PIP_EXPORT PIStatistic { +class PIStatistic { public: PIStatistic() {mean = variance = skewness = kurtosis = T();} diff --git a/lib/main/opencl/piopencl.h b/lib/main/opencl/piopencl.h index ac00f160..51be9a6a 100644 --- a/lib/main/opencl/piopencl.h +++ b/lib/main/opencl/piopencl.h @@ -20,10 +20,11 @@ #ifndef PIOPENCL_H #define PIOPENCL_H +#include "pip_opencl_export.h" #include "pivariant.h" -class PIOpenCL { +class PIP_OPENCL_EXPORT PIOpenCL { public: struct KernelArg; @@ -69,7 +70,7 @@ public: Double, }; - struct KernelArg { + struct PIP_OPENCL_EXPORT KernelArg { KernelArg(); AddressQualifier address_qualifier; AccessQualifier access_qualifier; @@ -85,7 +86,7 @@ public: void init(void * _k, uint index); }; - struct Device { + struct PIP_OPENCL_EXPORT Device { Device() {id = platform_id = 0; max_compute_units = max_clock_frequency = 0; max_memory_size = 0;} bool isValid() const {return id != 0;} PIString displayText() const {return name.trimmed() + " (" + device_version.trimmed() + ")";} @@ -100,7 +101,7 @@ public: ullong max_memory_size; }; - struct Platform { + struct PIP_OPENCL_EXPORT Platform { Platform() {id = 0;} bool isValid() const {return id != 0;} PIString displayText() const {return name.trimmed() + " (" + version.trimmed() + ", " + profile.trimmed() + ")";} @@ -113,7 +114,7 @@ public: PIVector devices; }; - class Context { + class PIP_OPENCL_EXPORT Context { friend class Program; public: ~Context(); @@ -125,10 +126,10 @@ public: void zero(); void deletePrograms(); PIVector programs_; - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_OPENCL_EXPORT) }; - class Program { + class PIP_OPENCL_EXPORT Program { friend class Context; friend class Kernel; public: @@ -143,10 +144,10 @@ public: Context * context_; PIString source_; PIVector kernels_; - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_OPENCL_EXPORT) }; - class Kernel { + class PIP_OPENCL_EXPORT Kernel { friend class Program; public: const PIString & name() const {return name_;} @@ -165,7 +166,7 @@ public: Program * program_; PIString name_; PIVector args_; - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_OPENCL_EXPORT) }; static void init(); @@ -177,7 +178,7 @@ public: private: static PIString prog_header; PIOpenCL() {;} - class Initializer { + class PIP_OPENCL_EXPORT Initializer { public: Initializer(); static Initializer * instance(); diff --git a/lib/main/piplatform.h b/lib/main/piplatform.h index 8fc0331d..cb46423d 100644 --- a/lib/main/piplatform.h +++ b/lib/main/piplatform.h @@ -20,17 +20,16 @@ #ifndef PIPLATFORM_H #define PIPLATFORM_H -#if (__cplusplus >= 201103L) // стандарт C++ 11 или выше - #define PIP_CXX11_SUPPORT -#endif +#include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# define WINDOWS -# define ARCH_BITS_32 -#endif #if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) # define WINDOWS # define ARCH_BITS_64 +#else +# if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# define WINDOWS +# define ARCH_BITS_32 +# endif #endif #if defined(__QNX__) || defined(__QNXNTO__) # define QNX @@ -93,11 +92,5 @@ # define typeof __typeof__ #endif -#if defined(DOXYGEN) || defined(CC_GCC) || defined(PICODE) -# undef PIP_EXPORT -# define PIP_EXPORT -# undef DEPRECATED -# define DEPRECATED -#endif #endif // PIPLATFORM_H diff --git a/lib/main/resources/piresources.cpp b/lib/main/resources/piresources.cpp index e3a691d6..035d4d8f 100644 --- a/lib/main/resources/piresources.cpp +++ b/lib/main/resources/piresources.cpp @@ -36,13 +36,12 @@ PIByteArray PIResources::get(const PIString & name) { void PIResources::dump() { - PIMap & sm(PIResourcesStorage::instance()->sections); - PIMap::iterator si; - for (si = sm.begin(); si != sm.end(); ++si) { + auto si = PIResourcesStorage::instance()->sections.makeIterator(); + while (si.next()) { piCout << "Section [" << si.key() << "]"; if (!si.value()) continue; - PIMap::iterator fi; - for (fi = si.value()->entries.begin(); fi != si.value()->entries.end(); ++fi) { + auto fi = si.value()->entries.makeIterator(); + while (fi.next()) { PIString s = fi.key() + ": "; s << (fi.value() ? fi.value()->size_s() : 0) << " b"; piCout << " " << s; diff --git a/lib/main/resources/piresourcesstorage.cpp b/lib/main/resources/piresourcesstorage.cpp index b08dba70..fd6e20eb 100644 --- a/lib/main/resources/piresourcesstorage.cpp +++ b/lib/main/resources/piresourcesstorage.cpp @@ -31,8 +31,8 @@ PIResourcesStorage::Section::~Section() { void PIResourcesStorage::Section::add(const PIResourcesStorage::Section & s) { - PIMap::const_iterator i; - for (i = s.entries.begin(); i != s.entries.end(); ++i) { + auto i = s.entries.makeIterator(); + while (i.next()) { if (!i.value()) continue; if (entries.value(i.key(), 0)) continue; entries[i.key()] = i.value(); @@ -83,10 +83,10 @@ void PIResourcesStorage::registerSection(const uchar * rc_data, const uchar * rc piForeachC (PIResourcesStorage::__RCEntry & e, el) { ebs[e.section] << e; } - PIMap >::iterator it; - for (it = ebs.begin(); it != ebs.end(); ++it) { + auto it = ebs.makeIterator(); + while (it.next()) { PIResourcesStorage::Section s; - PIVector & itv(it.value()); + const PIVector & itv(it.value()); piForeachC (PIResourcesStorage::__RCEntry & e, itv) { //piCout << "add" << e.name << e.alias << PIString::readableSize(e.size); PIByteArray * eba = new PIByteArray(&(rc_data[e.offset]), e.size); @@ -114,8 +114,8 @@ PIByteArray PIResourcesStorage::get(const PIString & section_name, const PIStrin PIByteArray PIResourcesStorage::get(const PIString & entry_name) const { - PIMap::const_iterator i; - for (i = sections.begin(); i != sections.end(); ++i) { + auto i = sections.makeIterator(); + while (i.next()) { if (!i.value()) continue; PIByteArray * ba = i.value()->entries.value(entry_name, 0); if (!ba) continue; diff --git a/lib/main/system/picodec.cpp b/lib/main/system/picodec.cpp deleted file mode 100644 index 235d2ad6..00000000 --- a/lib/main/system/picodec.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - PIP - Platform Independent Primitives - Text codings coder, based on "iconv" - 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 . -*/ - -#ifndef PIP_FREERTOS - -#include "picodec.h" - - -PIStringList PICodec::availableCodecs() { - exec("/usr/bin/iconv", "-l"); - waitForFinish(); - PIString str(readOutput()); - str.cutLeft(str.find("\n ")); - str.replaceAll("\n", ""); - return str.split("//"); -} - - -PIByteArray PICodec::exec_iconv(const PIString & from, const PIString & to, const PIByteArray & str) { - tf.openTemporary(PIIODevice::ReadWrite); - tf.clear(); - tf << str; - tf.close(); - exec("/usr/bin/iconv", PIStringList() << ("-f=" + from) << ("-t=" + to) << tf.path()); - waitForFinish(); - return readOutput(); -} - -#endif // PIP_FREERTOS diff --git a/lib/main/system/picodec.h b/lib/main/system/picodec.h deleted file mode 100644 index 67a88941..00000000 --- a/lib/main/system/picodec.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - PIP - Platform Independent Primitives - Text codings coder, based on "iconv" - 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 . -*/ - -#ifndef PICODEC_H -#define PICODEC_H - -#ifndef PIP_FREERTOS - -#include "piprocess.h" - -class PIP_EXPORT PICodec: protected PIProcess -{ - PIOBJECT(PICodec) -public: - PICodec(): PIProcess() {setGrabOutput(true);} - PICodec(const PIString & from, const PIString & to): PIProcess() {setCodings(from, to);} - ~PICodec() {tf.remove();} - - void setFromCoding(const PIString & from) {c_from = from;} - void setToCoding(const PIString & to) {c_to = to;} - void setCodings(const PIString & from, const PIString & to) {c_from = from; c_to = to;} - - PIStringList availableCodecs(); - PIString encode(PIString & str) {return PIString(exec_iconv(c_from, c_to, str.toByteArray()));} - PIString encode(const PIByteArray & str) {return PIString(exec_iconv(c_from, c_to, str));} - PIString decode(PIString & str) {return PIString(exec_iconv(c_to, c_from, str.toByteArray()));} - PIString decode(const PIByteArray & str) {return PIString(exec_iconv(c_to, c_from, str));} - -private: - PIByteArray exec_iconv(const PIString & from, const PIString & to, const PIByteArray & str); - - PIString c_from, c_to; - PIFile tf; - -}; - -#endif // PIP_FREERTOS -#endif // PICODEC_H diff --git a/lib/main/system/pilibrary.h b/lib/main/system/pilibrary.h index 653f7db6..581fa5d1 100644 --- a/lib/main/system/pilibrary.h +++ b/lib/main/system/pilibrary.h @@ -42,7 +42,7 @@ private: bool loadInternal(); void getLastError(); - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) PIString libpath, liberror; }; diff --git a/lib/main/system/piprocess.h b/lib/main/system/piprocess.h index 74f48cc6..d7473432 100644 --- a/lib/main/system/piprocess.h +++ b/lib/main/system/piprocess.h @@ -93,7 +93,7 @@ private: void exec_(); void startProc(bool detached); - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) PIStringList args, env; PIString wd; PIByteArray out; diff --git a/lib/main/system/pisysteminfo.h b/lib/main/system/pisysteminfo.h index db1e54d2..5de39d5f 100644 --- a/lib/main/system/pisysteminfo.h +++ b/lib/main/system/pisysteminfo.h @@ -26,7 +26,7 @@ class PIP_EXPORT PISystemInfo { public: PISystemInfo(); - struct MountInfo { + struct PIP_EXPORT MountInfo { MountInfo(); PIString mount_point; PIString device; diff --git a/lib/main/system/pisystemmodule.h b/lib/main/system/pisystemmodule.h index f550868f..a75662c4 100644 --- a/lib/main/system/pisystemmodule.h +++ b/lib/main/system/pisystemmodule.h @@ -20,7 +20,6 @@ #ifndef PISYSTEMMODULE_H #define PISYSTEMMODULE_H -#include "picodec.h" #include "pisignals.h" #include "pilibrary.h" #include "pisysteminfo.h" diff --git a/lib/main/system/pisystemmonitor.cpp b/lib/main/system/pisystemmonitor.cpp index 6b28f9b1..98e259a6 100644 --- a/lib/main/system/pisystemmonitor.cpp +++ b/lib/main/system/pisystemmonitor.cpp @@ -331,9 +331,10 @@ void PISystemMonitor::run() { tstat.cpu_load_system = piClampf(tstat.cpu_load_system, 0.f, 100.f); tstat.cpu_load_user = piClampf(tstat.cpu_load_user , 0.f, 100.f); - for (PIMap::iterator i = cur_tm.begin(); i != cur_tm.end(); ++i) { + auto i = cur_tm.makeIterator(); + while (i.next()) { if (!last_tm.contains(i.key())) continue; - ThreadStats & ts_new(i.value()); + ThreadStats & ts_new(i.valueRef()); ThreadStats & ts_old(last_tm[i.key()]); ts_new.cpu_load_kernel = calcThreadUsage(ts_new.kernel_time, ts_old.kernel_time); ts_new.cpu_load_user = calcThreadUsage(ts_new.user_time, ts_old.user_time); diff --git a/lib/main/system/pisystemmonitor.h b/lib/main/system/pisystemmonitor.h index a860a19a..f3407f81 100644 --- a/lib/main/system/pisystemmonitor.h +++ b/lib/main/system/pisystemmonitor.h @@ -32,7 +32,7 @@ public: ~PISystemMonitor(); #pragma pack(push, 1) - struct ProcessStatsFixed { + struct PIP_EXPORT ProcessStatsFixed { ProcessStatsFixed(); int ID; int parent_ID; @@ -52,7 +52,7 @@ public: float cpu_load_user; }; - struct ThreadStatsFixed { + struct PIP_EXPORT ThreadStatsFixed { ThreadStatsFixed(); llong id; PISystemTime work_time; @@ -63,7 +63,7 @@ public: }; #pragma pack(pop) - struct ProcessStats: ProcessStatsFixed { + struct PIP_EXPORT ProcessStats: ProcessStatsFixed { void makeStrings(); PIString exec_name; PIString state; @@ -74,7 +74,7 @@ public: PIString data_memsize_readable; }; - struct ThreadStats: ThreadStatsFixed { + struct PIP_EXPORT ThreadStats: ThreadStatsFixed { PIString name; PIDateTime created; }; @@ -107,10 +107,10 @@ private: mutable PIMutex stat_mutex; int pID_, page_size, cpu_count, cycle; #ifndef FREERTOS - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) #endif - class Pool { + class PIP_EXPORT Pool { friend class PISystemMonitor; public: static Pool * instance(); @@ -136,9 +136,9 @@ inline PICout operator <<(PICout s, const PISystemMonitor::ThreadStats & v) { return s; } -PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v); -PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v); -PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v); -PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v); +PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ProcessStats & v); +PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ProcessStats & v); +PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PISystemMonitor::ThreadStats & v); +PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PISystemMonitor::ThreadStats & v); #endif // PISYSTEMMONITOR_H diff --git a/lib/main/system/pisystemtests.h b/lib/main/system/pisystemtests.h index 7aaafc85..094c85c1 100644 --- a/lib/main/system/pisystemtests.h +++ b/lib/main/system/pisystemtests.h @@ -23,16 +23,16 @@ #include "pibase.h" namespace PISystemTests { - PIP_EXPORT extern long time_resolution_ns; - PIP_EXPORT extern long time_elapsed_ns; - PIP_EXPORT extern long usleep_offset_us; + extern PIP_EXPORT long time_resolution_ns; + extern PIP_EXPORT long time_elapsed_ns; + extern PIP_EXPORT long usleep_offset_us; - class PISystemTestReader { + class PIP_EXPORT PISystemTestReader { public: PISystemTestReader(); }; - extern PISystemTestReader pisystestreader; + extern PIP_EXPORT PISystemTestReader pisystestreader; } #endif // PISYSTEMTESTS_H diff --git a/lib/main/concurrent/piblockingdequeue.h b/lib/main/thread/piblockingdequeue.h similarity index 92% rename from lib/main/concurrent/piblockingdequeue.h rename to lib/main/thread/piblockingdequeue.h index 5f64da06..27e23572 100644 --- a/lib/main/concurrent/piblockingdequeue.h +++ b/lib/main/thread/piblockingdequeue.h @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef PIP_TESTS_PIBLOCKINGDEQUEUE_H -#define PIP_TESTS_PIBLOCKINGDEQUEUE_H +#ifndef PIBLOCKINGDEQUEUE_H +#define PIBLOCKINGDEQUEUE_H #include "pideque.h" #include "piconditionvar.h" @@ -140,14 +140,14 @@ public: * return value is retrieved value * @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available */ - T poll(int timeoutMs, const T & defaultVal = T(), bool* isOk = nullptr) { + T poll(int timeoutMs, const T & defaultVal = T(), bool * isOk = nullptr) { T t; mutex.lock(); bool isNotEmpty = cond_var_add->waitFor(mutex, timeoutMs, [&]() { return !PIDeque::isEmpty(); }); t = isNotEmpty ? T(PIDeque::take_front()) : defaultVal; mutex.unlock(); if (isNotEmpty) cond_var_rem->notifyOne(); - if (isOk != nullptr) *isOk = isNotEmpty; + if (isOk) *isOk = isNotEmpty; return t; } @@ -160,14 +160,14 @@ public: * return value is retrieved value * @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available */ - T poll(const T & defaultVal = T(), bool* isOk = nullptr) { + T poll(const T & defaultVal = T(), bool * isOk = nullptr) { T t; mutex.lock(); bool isNotEmpty = !PIDeque::isEmpty(); - t = isNotEmpty ? T(PIDeque::take_front()) : defaultVal; + t = isNotEmpty ? PIDeque::take_front() : defaultVal; mutex.unlock(); if (isNotEmpty) cond_var_rem->notifyOne(); - if (isOk != nullptr) *isOk = isNotEmpty; + if (isOk) *isOk = isNotEmpty; return t; } @@ -213,7 +213,7 @@ public: */ size_t drainTo(PIDeque& other, size_t maxCount = SIZE_MAX) { mutex.lock(); - size_t count = maxCount > PIDeque::size() ? PIDeque::size() : maxCount; + size_t count = ((maxCount > PIDeque::size()) ? PIDeque::size() : maxCount); for (size_t i = 0; i < count; ++i) other.push_back(PIDeque::take_front()); mutex.unlock(); return count; @@ -235,11 +235,11 @@ public: } private: - PIConditionLock mutex; - PIConditionVariable* cond_var_add; - PIConditionVariable* cond_var_rem; + PIMutex mutex; + PIConditionVariable * cond_var_add, * cond_var_rem; size_t max_size; + }; -#endif //PIP_TESTS_PIBLOCKINGDEQUEUE_H +#endif // PIBLOCKINGDEQUEUE_H diff --git a/lib/concurrent/piconditionvar.cpp b/lib/main/thread/piconditionvar.cpp similarity index 87% rename from lib/concurrent/piconditionvar.cpp rename to lib/main/thread/piconditionvar.cpp index 5f3fac3a..395f53f6 100644 --- a/lib/concurrent/piconditionvar.cpp +++ b/lib/main/thread/piconditionvar.cpp @@ -1,141 +1,141 @@ -/* - PIP - Platform Independent Primitives - - Stephan Fomenko - - 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 . -*/ - -#include "piconditionvar.h" -#include "pithread.h" -#include "pitime.h" - -#ifdef WINDOWS -# undef _WIN32_WINNT -# define _WIN32_WINNT 0x0600 -# include -# include -# include -#endif - - -PRIVATE_DEFINITION_START(PIConditionVariable) -#ifdef WINDOWS - CONDITION_VARIABLE nativeHandle; -#else - pthread_cond_t nativeHandle; - PIConditionLock* currentLock; -#endif - bool isDestroying; -PRIVATE_DEFINITION_END(PIConditionVariable) - - -PIConditionVariable::PIConditionVariable() { -#ifdef WINDOWS - InitializeConditionVariable(&PRIVATE->nativeHandle); -#else - PRIVATE->isDestroying = false; - PRIVATE->currentLock = nullptr; - memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); - pthread_cond_init(&PRIVATE->nativeHandle, NULL); -#endif -} - - -PIConditionVariable::~PIConditionVariable() { -#ifdef WINDOWS -#else - pthread_cond_destroy(&PRIVATE->nativeHandle); -#endif -} - - -void PIConditionVariable::wait(PIConditionLock& lk) { -#ifdef WINDOWS - SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); -#else - pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); -#endif -} - - -void PIConditionVariable::wait(PIConditionLock& lk, const std::function& condition) { - bool isCondition; - while (true) { - isCondition = condition(); - if (isCondition) break; -#ifdef WINDOWS - SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); -#else - pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); -#endif - if (PRIVATE->isDestroying) return; - } -} - - -bool PIConditionVariable::waitFor(PIConditionLock &lk, int timeoutMs) { - bool isNotTimeout; -#ifdef WINDOWS - isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0; -#else - timespec abstime = {.tv_sec = timeoutMs / 1000, .tv_nsec = timeoutMs * 1000 * 1000}; - isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0; -#endif - if (PRIVATE->isDestroying) return false; - return isNotTimeout; -} - - -bool PIConditionVariable::waitFor(PIConditionLock& lk, int timeoutMs, const std::function &condition) { - bool isCondition; - PITimeMeasurer measurer; - while (true) { - isCondition = condition(); - if (isCondition) break; -#ifdef WINDOWS - WINBOOL isTimeout = SleepConditionVariableCS( - &PRIVATE->nativeHandle, - (PCRITICAL_SECTION)lk.handle(), - timeoutMs - (int)measurer.elapsed_m()); - if (isTimeout == 0) return false; -#else - int timeoutCurr = timeoutMs - (int)measurer.elapsed_m(); - timespec abstime = {.tv_sec = timeoutCurr / 1000, .tv_nsec = timeoutCurr * 1000 * 1000}; - bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0; - if (isTimeout) return false; -#endif - if (PRIVATE->isDestroying) return false; - } - return true; -} - - -void PIConditionVariable::notifyOne() { -#ifdef WINDOWS - WakeConditionVariable(&PRIVATE->nativeHandle); -#else - pthread_cond_signal(&PRIVATE->nativeHandle); -#endif -} - - -void PIConditionVariable::notifyAll() { -#ifdef WINDOWS - WakeAllConditionVariable(&PRIVATE->nativeHandle); -#else - pthread_cond_broadcast(&PRIVATE->nativeHandle); -#endif -} - +/* + PIP - Platform Independent Primitives + + Stephan Fomenko + + 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 . +*/ + +#include "piconditionvar.h" +#include "pithread.h" +#include "pitime.h" + +#ifdef WINDOWS +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0600 +# include +# include +# include +#endif + + +PRIVATE_DEFINITION_START(PIConditionVariable) +#ifdef WINDOWS + CONDITION_VARIABLE nativeHandle; +#else + pthread_cond_t nativeHandle; + PIMutex * currentLock; +#endif + bool isDestroying; +PRIVATE_DEFINITION_END(PIConditionVariable) + + +PIConditionVariable::PIConditionVariable() { +#ifdef WINDOWS + InitializeConditionVariable(&PRIVATE->nativeHandle); +#else + PRIVATE->isDestroying = false; + PRIVATE->currentLock = nullptr; + memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); + pthread_cond_init(&PRIVATE->nativeHandle, NULL); +#endif +} + + +PIConditionVariable::~PIConditionVariable() { +#ifdef WINDOWS +#else + pthread_cond_destroy(&PRIVATE->nativeHandle); +#endif +} + + +void PIConditionVariable::wait(PIMutex& lk) { +#ifdef WINDOWS + SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); +#else + pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); +#endif +} + + +void PIConditionVariable::wait(PIMutex& lk, const std::function& condition) { + bool isCondition; + while (true) { + isCondition = condition(); + if (isCondition) break; +#ifdef WINDOWS + SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); +#else + pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); +#endif + if (PRIVATE->isDestroying) return; + } +} + + +bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) { + bool isNotTimeout; +#ifdef WINDOWS + isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0; +#else + timespec abstime = {.tv_sec = timeoutMs / 1000, .tv_nsec = timeoutMs * 1000 * 1000}; + isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0; +#endif + if (PRIVATE->isDestroying) return false; + return isNotTimeout; +} + + +bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function &condition) { + bool isCondition; + PITimeMeasurer measurer; + while (true) { + isCondition = condition(); + if (isCondition) break; +#ifdef WINDOWS + WINBOOL isTimeout = SleepConditionVariableCS( + &PRIVATE->nativeHandle, + (PCRITICAL_SECTION)lk.handle(), + timeoutMs - (int)measurer.elapsed_m()); + if (isTimeout == 0) return false; +#else + int timeoutCurr = timeoutMs - (int)measurer.elapsed_m(); + timespec abstime = {.tv_sec = timeoutCurr / 1000, .tv_nsec = timeoutCurr * 1000 * 1000}; + bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0; + if (isTimeout) return false; +#endif + if (PRIVATE->isDestroying) return false; + } + return true; +} + + +void PIConditionVariable::notifyOne() { +#ifdef WINDOWS + WakeConditionVariable(&PRIVATE->nativeHandle); +#else + pthread_cond_signal(&PRIVATE->nativeHandle); +#endif +} + + +void PIConditionVariable::notifyAll() { +#ifdef WINDOWS + WakeAllConditionVariable(&PRIVATE->nativeHandle); +#else + pthread_cond_broadcast(&PRIVATE->nativeHandle); +#endif +} + diff --git a/lib/main/concurrent/piconditionvar.h b/lib/main/thread/piconditionvar.h similarity index 82% rename from lib/main/concurrent/piconditionvar.h rename to lib/main/thread/piconditionvar.h index dc32d43d..0e988e32 100644 --- a/lib/main/concurrent/piconditionvar.h +++ b/lib/main/thread/piconditionvar.h @@ -20,18 +20,18 @@ #ifndef PICONDITIONVAR_H #define PICONDITIONVAR_H -#include "piconditionlock.h" #include "pithread.h" /** * @brief A condition variable is an object able to block the calling thread until notified to resume. * - * It uses a PIConditionLock to lock the thread when one of its wait functions is called. The thread remains + * It uses a PIMutex to lock the thread when one of its wait functions is called. The thread remains * blocked until woken up by another thread that calls a notification function on the same PIConditionVariable object. */ class PIP_EXPORT PIConditionVariable { public: + NO_COPY_CLASS(PIConditionVariable) explicit PIConditionVariable(); virtual ~PIConditionVariable(); @@ -48,20 +48,20 @@ public: void notifyAll(); /** - * @brief see wait(PIConditionLock&, const std::function&) + * @brief see wait(PIMutex &, const std::function&) */ - virtual void wait(PIConditionLock& lk); + virtual void wait(PIMutex & lk); /** * @brief Wait until notified * - * The execution of the current thread (which shall have locked with lk method PIConditionLock::lock()) is blocked + * The execution of the current thread (which shall have locked with lk method PIMutex::lock()) is blocked * until notified. * - * At the moment of blocking the thread, the function automatically calls lk.unlock() (PIConditionLock::unlock()), + * At the moment of blocking the thread, the function automatically calls lk.unlock() (PIMutex::unlock()), * allowing other locked threads to continue. * - * Once notified (explicitly, by some other thread), the function unblocks and calls lk.lock() (PIConditionLock::lock()), + * Once notified (explicitly, by some other thread), the function unblocks and calls lk.lock() (PIMutex::lock()), * leaving lk in the same state as when the function was called. Then the function returns (notice that this last mutex * locking may block again the thread before returning). * @@ -76,23 +76,23 @@ public: * @param condition A callable object or function that takes no arguments and returns a value that can be evaluated * as a bool. This is called repeatedly until it evaluates to true. */ - virtual void wait(PIConditionLock& lk, const std::function& condition); + virtual void wait(PIMutex& lk, const std::function& condition); /** - * @brief see waitFor(PIConditionLock&, int, const std::function&) + * @brief see waitFor(PIMutex &, int, const std::function&) */ - virtual bool waitFor(PIConditionLock& lk, int timeoutMs); + virtual bool waitFor(PIMutex & lk, int timeoutMs); /** * @brief Wait for timeout or until notified * - * The execution of the current thread (which shall have locked with lk method PIConditionLock::lock()) is blocked + * The execution of the current thread (which shall have locked with lk method PIMutex::lock()) is blocked * during timeoutMs, or until notified (if the latter happens first). * - * At the moment of blocking the thread, the function automatically calls lk.lock() (PIConditionLock::lock()), allowing + * At the moment of blocking the thread, the function automatically calls lk.lock() (PIMutex::lock()), allowing * other locked threads to continue. * - * Once notified or once timeoutMs has passed, the function unblocks and calls lk.unlock() (PIConditionLock::unlock()), + * Once notified or once timeoutMs has passed, the function unblocks and calls lk.unlock() (PIMutex::unlock()), * leaving lk in the same state as when the function was called. Then the function returns (notice that this last * mutex locking may block again the thread before returning). * @@ -108,11 +108,10 @@ public: * as a bool. This is called repeatedly until it evaluates to true. * @return false if timeout reached or true if wakeup condition is true */ - virtual bool waitFor(PIConditionLock& lk, int timeoutMs, const std::function& condition); + virtual bool waitFor(PIMutex& lk, int timeoutMs, const std::function& condition); private: - NO_COPY_CLASS(PIConditionVariable) - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) }; diff --git a/lib/main/thread/pigrabberbase.h b/lib/main/thread/pigrabberbase.h index 3ba007fe..07a5c35d 100644 --- a/lib/main/thread/pigrabberbase.h +++ b/lib/main/thread/pigrabberbase.h @@ -28,7 +28,7 @@ template -class PIP_EXPORT PIGrabberBase: public PIThread +class PIGrabberBase: public PIThread { PIOBJECT_SUBCLASS(PIGrabberBase, PIThread) public: diff --git a/lib/main/thread/pimutex.cpp b/lib/main/thread/pimutex.cpp index efdf9918..2c0a97b2 100644 --- a/lib/main/thread/pimutex.cpp +++ b/lib/main/thread/pimutex.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Mutex - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + Ivan Pelipenko peri4ko@yandex.ru, Stephan Fomenko, 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 @@ -19,102 +19,88 @@ /** \class PIMutex * \brief Mutex - * \details + * \details * \section PIMutex_sec0 Synopsis * %PIMutex provides synchronization blocks between several threads. * Using mutex guarantees execution of some code only one of threads. * Mutex contains logic state and functions to change it: \a lock(), * \a unlock() and \a tryLock(). - * + * * \section PIMutex_sec1 Usage * Block of code that should to be executed only one thread simultaniously * should to be started with \a lock() and ended with \a unlock(). * \snippet pimutex.cpp main * "mutex" in this example is one for all threads. - * + * * */ #include "pimutex.h" #include "piincludes_p.h" -#ifdef BLACKBERRY +#ifdef WINDOWS +# include +#else # include #endif + PRIVATE_DEFINITION_START(PIMutex) #ifdef WINDOWS - HANDLE + CRITICAL_SECTION #else pthread_mutex_t #endif - mutex; + mutex; PRIVATE_DEFINITION_END(PIMutex) -PIMutex::PIMutex(): inited_(false) { - //printf("new Mutex %p\n", this); -#ifdef WINDOWS - PRIVATE->mutex = 0; -#endif +PIMutex::PIMutex() { init(); } PIMutex::~PIMutex() { - //printf("del Mutex %p\n", this); destroy(); } void PIMutex::lock() { #ifdef WINDOWS -// std::cout << (ullong)PRIVATE->mutex << "locking..." << std::endl; -// DWORD wr = - WaitForSingleObject(PRIVATE->mutex, INFINITE); -// std::cout << (ullong)PRIVATE->mutex << " lock wr=" << wr << std::endl; + EnterCriticalSection(&(PRIVATE->mutex)); #else pthread_mutex_lock(&(PRIVATE->mutex)); #endif - locked = true; } void PIMutex::unlock() { #ifdef WINDOWS -// BOOL wr = -// ReleaseMutex(PRIVATE->mutex); - SetEvent(PRIVATE->mutex); -// std::cout << (ullong)PRIVATE->mutex << " unlock wr=" << wr << std::endl; + LeaveCriticalSection(&(PRIVATE->mutex)); #else pthread_mutex_unlock(&(PRIVATE->mutex)); #endif - locked = false; } bool PIMutex::tryLock() { bool ret = #ifdef WINDOWS - (WaitForSingleObject(PRIVATE->mutex, 0) == WAIT_OBJECT_0); + (TryEnterCriticalSection(&(PRIVATE->mutex)) != 0); #else (pthread_mutex_trylock(&(PRIVATE->mutex)) == 0); #endif - locked = true; return ret; } -bool PIMutex::isLocked() const { -// std::cout << "test " << (ullong)PRIVATE->mutex << std::endl; - return locked; +void * PIMutex::handle() { + return (void*)&(PRIVATE->mutex); } void PIMutex::init() { - if (inited_) destroy(); #ifdef WINDOWS - PRIVATE->mutex = CreateEvent(NULL, FALSE, TRUE, NULL); -// std::cout << "create " << (ullong)PRIVATE->mutex << std::endl; + InitializeCriticalSection(&(PRIVATE->mutex)); #else pthread_mutexattr_t attr; memset(&attr, 0, sizeof(attr)); @@ -124,20 +110,13 @@ void PIMutex::init() { pthread_mutex_init(&(PRIVATE->mutex), &attr); pthread_mutexattr_destroy(&attr); #endif - locked = false; - inited_ = true; } void PIMutex::destroy() { - if (inited_) { #ifdef WINDOWS -// std::cout << "destroy " << (ullong)PRIVATE->mutex << std::endl; - if (PRIVATE->mutex) CloseHandle(PRIVATE->mutex); - PRIVATE->mutex = 0; + DeleteCriticalSection(&(PRIVATE->mutex)); #else - pthread_mutex_destroy(&(PRIVATE->mutex)); + pthread_mutex_destroy(&(PRIVATE->mutex)); #endif - } - locked = inited_ = false; } diff --git a/lib/main/thread/pimutex.h b/lib/main/thread/pimutex.h index ac4277e5..a551625d 100644 --- a/lib/main/thread/pimutex.h +++ b/lib/main/thread/pimutex.h @@ -1,10 +1,10 @@ /*! \file pimutex.h - * \brief Mutex + * \brief PIMutexLocker */ /* PIP - Platform Independent Primitives - Mutex - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + PIMutexLocker + Ivan Pelipenko peri4ko@yandex.ru, Stephan Fomenko, 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 @@ -24,13 +24,17 @@ #define PIMUTEX_H #include "piinit.h" +#include + class PIP_EXPORT PIMutex { public: + NO_COPY_CLASS(PIMutex) + //! Constructs unlocked mutex explicit PIMutex(); - + //! Destroy mutex ~PIMutex(); @@ -39,39 +43,43 @@ public: //! \details If mutex is unlocked it set to locked state and returns immediate. //! If mutex is already locked function blocks until mutex will be unlocked void lock(); - + //! \brief Unlock mutex //! \details In any case this function returns immediate - void unlock(); - + void unlock() ; + //! \brief Try to lock mutex //! \details If mutex is unlocked it set to locked state and returns "true" immediate. //! If mutex is already locked function returns immediate an returns "false" bool tryLock(); - - //! Returns if mutex is locked - bool isLocked() const; - -private: - NO_COPY_CLASS(PIMutex) + void * handle(); + +private: void init(); void destroy(); - bool inited_; - bool locked; - PRIVATE_DECLARATION + + PRIVATE_DECLARATION(PIP_EXPORT) + }; +//! \brief PIMutexLocker +//! \details Same as std::lock_guard. +//! When a PIMutexLocker object is created, it attempts to lock the mutex it is given, if "condition" true. +//! When control leaves the scope in which the PIMutexLocker object was created, +//! the PIMutexLocker is destructed and the mutex is released, if "condition" true. +//! If "condition" false this class do nothing. +//! The PIMutexLocker class is non-copyable. class PIP_EXPORT PIMutexLocker { public: - PIMutexLocker(PIMutex * m, bool condition = true): mutex(m), cond(condition) {if (cond) mutex->lock();} - PIMutexLocker(PIMutex & m, bool condition = true): mutex(&m), cond(condition) {if (cond) mutex->lock();} - ~PIMutexLocker() {if (cond) mutex->unlock();} + NO_COPY_CLASS(PIMutexLocker) + PIMutexLocker(PIMutex & m, bool condition = true): mutex(m), cond(condition) {if (cond) mutex.lock();} + ~PIMutexLocker() {if (cond) mutex.unlock();} private: - PIMutex * mutex; - volatile bool cond; + PIMutex & mutex; + bool cond; }; #endif // PIMUTEX_H diff --git a/lib/main/thread/pithread.cpp b/lib/main/thread/pithread.cpp index 9fdd98eb..5ce598e8 100644 --- a/lib/main/thread/pithread.cpp +++ b/lib/main/thread/pithread.cpp @@ -184,7 +184,6 @@ PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay) } -#ifdef PIP_CXX11_SUPPORT PIThread::PIThread(std::function func, bool startNow, int timer_delay) { PIINTROSPECTION_THREAD_NEW(this); tid_ = -1; @@ -196,7 +195,6 @@ PIThread::PIThread(std::function func, bool startNow, int timer_delay) delay_ = timer_delay; if (startNow) start(timer_delay); } -#endif PIThread::PIThread(bool startNow, int timer_delay): PIObject() { diff --git a/lib/main/thread/pithread.h b/lib/main/thread/pithread.h index a2805bea..b6aa3c95 100644 --- a/lib/main/thread/pithread.h +++ b/lib/main/thread/pithread.h @@ -60,25 +60,20 @@ public: static __PIThreadCollection_Initializer__ __PIThreadCollection_initializer__; -#ifdef PIP_CXX11_SUPPORT typedef std::function ThreadFunc; -#else -typedef void (*ThreadFunc)(void * ); -#endif class PIP_EXPORT PIThread: public PIObject { PIOBJECT_SUBCLASS(PIThread, PIObject) friend class PIIntrospectionThreads; public: - + NO_COPY_CLASS(PIThread) + //! Contructs thread with custom data "data", external function "func" and main loop delay "loop_delay". PIThread(void * data, ThreadFunc func, bool startNow = false, int loop_delay = -1); -#ifdef PIP_CXX11_SUPPORT //! Contructs thread with external function "func" and main loop delay "loop_delay". PIThread(std::function func, bool startNow = false, int loop_delay = -1); -#endif //! Contructs thread with main loop delay "loop_delay". PIThread(bool startNow = false, int loop_delay = -1); @@ -98,10 +93,8 @@ public: EVENT_HANDLER1(bool, start, int, timer_delay); bool start(ThreadFunc func) {return start(func, -1);} bool start(ThreadFunc func, int timer_delay) {ret_func = func; return start(timer_delay);} -#ifdef PIP_CXX11_SUPPORT bool start(std::function func) {return start(func, -1);} bool start(std::function func, int timer_delay) {ret_func = [func](void*){func();}; return start(timer_delay);} -#endif EVENT_HANDLER0(bool, startOnce); EVENT_HANDLER1(bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();} EVENT_HANDLER0(void, stop) {stop(false);} @@ -114,10 +107,8 @@ public: //! \brief Set external function that will be executed after every \a run() void setSlot(ThreadFunc func) {ret_func = func;} -#ifdef PIP_CXX11_SUPPORT //! \brief Set external function that will be executed after every \a run() void setSlot(std::function func) {ret_func = [func](void*){func();};} -#endif //! \brief Set priority of thread void setPriority(PIThread::Priority prior); @@ -160,11 +151,9 @@ public: //! and automatically delete it on function finish static void runOnce(PIObject * object, const char * handler, const PIString & name = PIString()); -#ifdef PIP_CXX11_SUPPORT //! \brief Start function \"func\" in separate thread with name \"name\" //! and automatically delete it on function finish static void runOnce(std::function func, const PIString & name = PIString()); -#endif //! \handlers //! \{ @@ -246,7 +235,7 @@ protected: //! Function executed once at the end of thread. virtual void end() {;} - volatile bool terminating, running_, lockRun; + std::atomic_bool terminating, running_, lockRun; int delay_, policy_; llong tid_; void * data_; @@ -254,11 +243,9 @@ protected: PITimeMeasurer tmf_, tms_, tmr_; PIThread::Priority priority_; ThreadFunc ret_func; - PRIVATE_DECLARATION + PRIVATE_DECLARATION(PIP_EXPORT) private: - NO_COPY_CLASS(PIThread) - bool _startThread(void * func); void _beginThread(); void _runThread(); diff --git a/lib/main/thread/pithreadmodule.h b/lib/main/thread/pithreadmodule.h index e0d97bcb..5973dfe4 100644 --- a/lib/main/thread/pithreadmodule.h +++ b/lib/main/thread/pithreadmodule.h @@ -25,5 +25,7 @@ #include "pitimer.h" #include "pipipelinethread.h" #include "pigrabberbase.h" +#include "pithreadpoolexecutor.h" +#include "piconditionvar.h" #endif // PITHREADMODULE_H diff --git a/lib/main/thread/pithreadpoolexecutor.cpp b/lib/main/thread/pithreadpoolexecutor.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/main/concurrent/executor.h b/lib/main/thread/pithreadpoolexecutor.h similarity index 95% rename from lib/main/concurrent/executor.h rename to lib/main/thread/pithreadpoolexecutor.h index a4ccdaff..02895181 100644 --- a/lib/main/concurrent/executor.h +++ b/lib/main/thread/pithreadpoolexecutor.h @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef PIP_TESTS_EXECUTOR_H -#define PIP_TESTS_EXECUTOR_H +#ifndef PIP_EXECUTOR_H +#define PIP_EXECUTOR_H #include "piblockingdequeue.h" #include @@ -31,7 +31,7 @@ * TODO adapt documentation to template */ template -class PIThreadPoolExecutorTemplate { +class PIP_EXPORT PIThreadPoolExecutorTemplate { public: explicit PIThreadPoolExecutorTemplate(size_t corePoolSize = 1) : isShutdown_(false) { makePool(corePoolSize); } @@ -47,7 +47,7 @@ public: * * @param runnable not empty function for thread pool execution */ - void execute(const std::function &runnable) { + void execute(const std::function & runnable) { if (!isShutdown_) taskQueue.offer(runnable); } @@ -108,4 +108,4 @@ protected: typedef PIThreadPoolExecutorTemplate > > PIThreadPoolExecutor; -#endif //PIP_TESTS_EXECUTOR_H +#endif //PIP_EXECUTOR_H diff --git a/lib/main/thread/pitimer.cpp b/lib/main/thread/pitimer.cpp index f3a68a64..b2878f42 100644 --- a/lib/main/thread/pitimer.cpp +++ b/lib/main/thread/pitimer.cpp @@ -479,7 +479,6 @@ PITimer::PITimer(TimerEvent slot, void * data, PITimer::TimerImplementation ti): } -#ifdef PIP_CXX11_SUPPORT PITimer::PITimer(std::function slot, PITimer::TimerImplementation ti) { imp_mode = ti; initFirst(); @@ -493,7 +492,7 @@ PITimer::PITimer(std::function slot, void * data, PITimer::TimerI data_t = data; ret_func = [slot](void *d, int){slot(d);}; } -#endif + PITimer::~PITimer() { destroy(); diff --git a/lib/main/thread/pitimer.h b/lib/main/thread/pitimer.h index 2d58b847..842af062 100644 --- a/lib/main/thread/pitimer.h +++ b/lib/main/thread/pitimer.h @@ -26,11 +26,7 @@ #include "pithread.h" #include "pitime.h" -#ifdef PIP_CXX11_SUPPORT typedef std::function TimerEvent; -#else -typedef void (*TimerEvent)(void *, int); -#endif class PITimer; @@ -68,7 +64,7 @@ protected: double interval_, deferred_delay; bool deferred_, deferred_mode; // mode: true - date, false - delay - volatile bool running_; + std::atomic_bool running_; PIDateTime deferred_datetime; }; @@ -78,7 +74,8 @@ protected: class PIP_EXPORT PITimer: public PIObject { PIOBJECT_SUBCLASS(PITimer, PIObject) public: - + NO_COPY_CLASS(PITimer) + //! \brief Constructs timer with PITimer::Thread implementation explicit PITimer(); @@ -96,13 +93,11 @@ public: //! \brief Constructs timer with "slot" slot void(void *,int), "data" data and "ti" implementation explicit PITimer(TimerEvent slot, void * data = 0, TimerImplementation ti = Thread); -#ifdef PIP_CXX11_SUPPORT //! \brief Constructs timer with "slot" slot void(), and "ti" implementation explicit PITimer(std::function slot, TimerImplementation ti = Thread); //! \brief Constructs timer with "slot" slot void(void *), "data" data and "ti" implementation explicit PITimer(std::function slot, void * data, TimerImplementation ti = Thread); -#endif virtual ~PITimer(); @@ -159,13 +154,11 @@ public: //! \brief Set timer tick function void setSlot(TimerEvent slot) {ret_func = slot;} -#ifdef PIP_CXX11_SUPPORT //! \brief Set timer tick function void setSlot(std::function slot) {ret_func = [slot](void *, int){slot();};} //! \brief Set timer tick function void setSlot(std::function slot) {ret_func = [slot](void *d, int){slot(d);};} -#endif //! \brief Returns common data passed to tick functions void * data() const {return data_t;} @@ -185,13 +178,11 @@ public: //! \brief Add frequency delimiter \b delim with optional delimiter slot \b slot. void addDelimiter(int delim, TimerEvent slot = 0) {delims << Delimiter(slot, delim);} -#ifdef PIP_CXX11_SUPPORT //! \brief Add frequency delimiter \b delim with optional delimiter slot \b slot. void addDelimiter(int delim, std::function slot) {delims << Delimiter([slot](void *, int){slot();}, delim);} //! \brief Add frequency delimiter \b delim with optional delimiter slot \b slot. void addDelimiter(int delim, std::function slot) {delims << Delimiter([slot](void *d, int){slot(d);}, delim);} -#endif //! \brief Remove all frequency delimiters \b delim. void removeDelimiter(int delim) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].delim == delim) {delims.remove(i); i--;}} @@ -254,17 +245,13 @@ protected: virtual void tick(void * data_, int delimiter) {} void * data_t; - volatile bool lockRun, callEvents; + std::atomic_bool lockRun, callEvents; PIMutex mutex_; TimerEvent ret_func; TimerImplementation imp_mode; PIVector delims; mutable _PITimerBase * imp; - -private: - NO_COPY_CLASS(PITimer) - }; diff --git a/main.cpp b/main.cpp index bf4ec44a..621a56e3 100644 --- a/main.cpp +++ b/main.cpp @@ -1,136 +1,114 @@ #include "pip.h" -#include -#include -#include -/*#include -#include +/*#ifdef PIP_LUA +#include "piluaprogram.h" -void print(PIConfig::Entry*e, PIString indent = "") { - piCout << indent << e->name() << "=" << e->value(); - indent += " "; - e->children().forEach([=](PIConfig::Entry*e)->PIConfig::Entry*{print(e, indent); return e;}); +static const char * script += "-- script.lua \n" + "test()\n" + "testString = \"LuaBridge works ававава!\" \n" + "number = 42 \n"; + + +void test() { + piCout << "C function test"; } -class AsyncIOWatcher: public PIThread { - PIOBJECT_SUBCLASS(AsyncIOWatcher, PIThread) -public: - AsyncIOWatcher() { - pipe_fd[0] = pipe_fd[1] = 0; - if (pipe(pipe_fd) != 0) { - piCoutObj << "Warning: can`t create pipe," << errorString(); - } else { - fd_list << pipe_fd[0]; - } - piCout << pipe_fd[0] << pipe_fd[1]; - fd_list_changed = false; - start(); - } - ~AsyncIOWatcher() { - stop(); - breakSelect(); - if (!waitForFinish(2000)) - terminate(); - if (pipe_fd[0]) ::close(pipe_fd[0]); - if (pipe_fd[1]) ::close(pipe_fd[1]); - } - - void add(int fd) { - que_mutex.lock(); - fd_list_changed = true; - if (!add_que.contains(fd)) - add_que.enqueue(fd); - que_mutex.unlock(); - breakSelect(); - } - void remove(int fd) { - que_mutex.lock(); - fd_list_changed = true; - if (!remove_que.contains(fd)) - remove_que.enqueue(fd); - que_mutex.unlock(); - breakSelect(); - } - -private: - virtual void run() { - que_mutex.lock(); - if (fd_list_changed) { - for (int i = 0; i < add_que.size_s(); ++i) { - if (!fd_list.contains(add_que[i])) - fd_list << add_que[i]; - } - for (int i = 0; i < remove_que.size_s(); ++i) { - fd_list.removeAll(remove_que[i]); - } - add_que.clear(); - remove_que.clear(); - } - fd_list_changed = false; - que_mutex.unlock(); - - s_tv.tv_sec = 1; - s_tv.tv_usec = 0; - FD_ZERO(&s_set); - int max_fd = 0; - piForeachC (int fd, fd_list) { - FD_SET(fd, &s_set); - if (max_fd < fd) - max_fd = fd; - } - int ret = select(max_fd + 1, &s_set, 0, 0, 0); - piCout << "select" << ret; - if (ret <= 0) return; - read_buff.resize(1024); - uint ibuff = 0; - piForeachC (int fd, fd_list) { - if (!FD_ISSET(fd, &s_set)) continue; - if (fd == pipe_fd[0]) { - read(fd, &ibuff, sizeof(ibuff)); - piCoutObj << "breaked"; - continue; - } - int readed = read(fd, read_buff.data(), read_buff.size_s()); - piCout << "readed" << fd << readed; - } - } - void breakSelect() { - if (pipe_fd[1]) - ::write(pipe_fd[1], "\0", 1); - } - - PIQueue add_que, remove_que; - PIDeque fd_list; - PIByteArray read_buff; - PIMutex que_mutex; - bool fd_list_changed; - int pipe_fd[2]; - - fd_set s_set; - struct timeval s_tv; - -}; -*/ - - -//PIKbdListener kbd(0, 0, false); - - -#include "pigpio.h" -int main(int argc, char * argv[]) { - PIObject * o = PIIODevice::createFromFullPath("ser://COM1"); - piCout << o; - piCout << o->cast(); - piCout << o->cast(); - piCout << o->scopeList(); - piCout << "\n\n"; - PIMap & m(PIObject::__meta_data()); - for (auto it = m.constBegin(); it != m.constEnd(); ++it) { - const PIObject::__MetaData & md(it.value()); - piCout << it.key() << md.scope_list << md.scope_id << ":"; - for (auto j = md.eh_func.constBegin(); j != md.eh_func.constEnd(); ++j) { - piCout << " " << j.value().fullFormat(); - } - piCout << ""; - }/**/ +int main() { + PILuaProgram p; + p.getGlobalNamespace().addFunction("test", test); + if (!p.load(PIString::fromUTF8(script))) piCout << "error"; + p.prepare(); + luabridge::LuaRef s = p.getGlobal("testString"); + luabridge::LuaRef n = p.getGlobal("number"); + PIString luaString = s.cast(); + int answer = n.cast(); + piCout << luaString; + piCout << "And here's our number:" << answer; +} +#else +int main() { return 0; } +#endif +*/ +class db { +public: + db() { + name = PIStringAscii("sflner;ljner.vjnrevsg;j35m4;gberjg2mnv"); + for (int i=0; i<10000; ++i) + x << sin(double(i)/180.0); + //printf("jkfkhg\n"); + } + PIString name; + PIVector x; +}; + +inline PIByteArray & operator <<(PIByteArray & ba, const db & v) { + PIChunkStream cs; + cs.add(1, v.name).add(2, v.x); + ba << cs.data(); + return ba; +} +inline PIByteArray & operator >>(PIByteArray & ba, db & v) { + PIByteArray src; ba >> src; PIChunkStream cs(src); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: cs.get(v.name); break; + case 2: cs.get(v.x); break; + } + } + return ba; +} + +PIEthernet eth; + +#include "picodeparser.h" +int main() { + //PICodeParser cp; + //cp.parseFile("SH_plugin_base.h"); + + PIMap m; + m[1] = "one"; + m[2] = "two"; + + auto it = m.makeIterator(); + while (it.next()) { + //it.next(); + it.valueRef() << "_!"; + piCout << it.key() << it.value(); + } + + /*eth.__meta_data + piForeachC (auto & i, cp.enums) { + i. + }*/ + + /*piDebug = false; + double min = -1, max = -1, mean = 0; + const int iterations = 50; + db d, d2; + for (int i = 0; i < iterations; ++i) { + //PICodeParser cp; + PITimeMeasurer tm; + for (int j = 0; j < 100; ++j) { + PIByteArray ba; + ba << d; + } + //cp.parseFile("SH_plugin_base.h"); + double ms = tm.elapsed_m(); + if (min < 0) min = ms; + if (max < 0) max = ms; + min = piMin(min, ms); + max = piMax(max, ms); + mean += ms; + + PIByteArray ba; + ba << d; + d2.name.clear(); + d2.x.clear(); + ba >> d2; + } + piDebug = true; + piCout << d2.name << d2.x.size_s(); + piCout << min << (mean / iterations) << max;*/ +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000..7f52c1a6 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,16 @@ +include(DownloadGTest) + +macro(pip_test NAME LIBS) + file(GLOB _CPPS "${NAME}/*.cpp") + file(GLOB _HDRS "${NAME}/*.h") + set(_target pip_${NAME}_test) + add_executable(${_target} ${_CPPS} ${_HDRS}) + target_link_libraries(${_target} pip ${LIBS} gtest_main gmock_main) + add_test(NAME ${_target} COMMAND tests) + add_custom_target(${_target}_perform ALL COMMAND ${_target}) + list(APPEND PIP_TESTS_LIST "${NAME}") + set(PIP_TESTS_LIST ${PIP_TESTS_LIST} PARENT_SCOPE) +endmacro() + +# Concurrent tests +pip_test(concurrent "") diff --git a/GTestCMakeLists.txt.in b/tests/GTestCMakeLists.txt.in similarity index 97% rename from GTestCMakeLists.txt.in rename to tests/GTestCMakeLists.txt.in index aacb573a..51b1cc0c 100644 --- a/GTestCMakeLists.txt.in +++ b/tests/GTestCMakeLists.txt.in @@ -1,16 +1,16 @@ -cmake_minimum_required(VERSION 2.8.2) - -project(googletest-download NONE) - -include(ExternalProject) -ExternalProject_Add(googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG "dea0216d0c6bc5e63cf5f6c8651cd268668032ec" - GIT_CONFIG "advice.detachedHead=false" - SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" - BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - TEST_COMMAND "" +cmake_minimum_required(VERSION 2.8.2) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG "dea0216d0c6bc5e63cf5f6c8651cd268668032ec" + GIT_CONFIG "advice.detachedHead=false" + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" ) \ No newline at end of file diff --git a/lib/concurrent/test/BlockingDequeueUnitTest.cpp b/tests/concurrent/BlockingDequeueUnitTest.cpp similarity index 93% rename from lib/concurrent/test/BlockingDequeueUnitTest.cpp rename to tests/concurrent/BlockingDequeueUnitTest.cpp index e0d4dd46..fae9f3ff 100644 --- a/lib/concurrent/test/BlockingDequeueUnitTest.cpp +++ b/tests/concurrent/BlockingDequeueUnitTest.cpp @@ -1,264 +1,264 @@ -#include "gtest/gtest.h" -#include "piblockingdequeue.h" - -class MockConditionVar: public PIConditionVariable { -public: - bool isWaitCalled = false; - bool isWaitForCalled = false; - bool isTrueCondition = false; - int timeout = -1; - - void wait(PIConditionLock& lk) override { - isWaitCalled = true; - } - - void wait(PIConditionLock& lk, const std::function& condition) override { - isWaitCalled = true; - lk.lock(); - isTrueCondition = condition(); - lk.unlock(); - } - - bool waitFor(PIConditionLock& lk, int timeoutMs) override { - isWaitForCalled = true; - timeout = timeoutMs; - return false; - } - - bool waitFor(PIConditionLock& lk, int timeoutMs, const std::function& condition) override { - isWaitForCalled = true; - lk.lock(); - isTrueCondition = condition(); - timeout = timeoutMs; - lk.unlock(); - return isTrueCondition; - } -}; - -TEST(BlockingDequeueUnitTest, put_is_block_when_capacity_reach) { - size_t capacity = 0; - auto conditionVarAdd = new MockConditionVar(); - auto conditionVarRem = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVarAdd, conditionVarRem); - dequeue.put(11); - ASSERT_TRUE(conditionVarRem->isWaitCalled); - ASSERT_FALSE(conditionVarRem->isTrueCondition); -} - -TEST(BlockingDequeueUnitTest, offer_timedout_is_false_when_capacity_reach) { - size_t capacity = 0; - int timeout = 11; - auto conditionVarAdd = new MockConditionVar(); - auto conditionVarRem = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVarAdd, conditionVarRem); - ASSERT_FALSE(dequeue.offer(11, timeout)); -} - -TEST(BlockingDequeueUnitTest, offer_timedout_is_block_when_capacity_reach) { - size_t capacity = 0; - int timeout = 11; - auto conditionVarAdd = new MockConditionVar(); - auto conditionVarRem = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVarAdd, conditionVarRem); - dequeue.offer(11, timeout); - EXPECT_TRUE(conditionVarRem->isWaitForCalled); - EXPECT_EQ(timeout, conditionVarRem->timeout); - ASSERT_FALSE(conditionVarRem->isTrueCondition); -} - -TEST(BlockingDequeueUnitTest, offer_is_true_before_capacity_reach) { - size_t capacity = 1; - PIBlockingDequeue dequeue(capacity); - ASSERT_TRUE(dequeue.offer(10)); -} - -TEST(BlockingDequeueUnitTest, offer_is_false_when_capacity_reach) { - size_t capacity = 1; - PIBlockingDequeue dequeue(capacity); - dequeue.offer(11); - ASSERT_FALSE(dequeue.offer(10)); -} - -// TODO change take_is_block_when_empty to prevent segfault -TEST(DISABLED_BlockingDequeueUnitTest, take_is_block_when_empty) { - size_t capacity = 1; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - // May cause segfault because take front of empty queue - dequeue.take(); - EXPECT_TRUE(conditionVar->isWaitCalled); - ASSERT_FALSE(conditionVar->isTrueCondition); -} - -TEST(BlockingDequeueUnitTest, take_is_not_block_when_not_empty) { - size_t capacity = 1; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - dequeue.offer(111); - dequeue.take(); - - EXPECT_TRUE(conditionVar->isWaitCalled); - ASSERT_TRUE(conditionVar->isTrueCondition); -} - -TEST(BlockingDequeueUnitTest, take_is_value_eq_to_offer_value) { - size_t capacity = 1; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - - dequeue.offer(111); - ASSERT_EQ(dequeue.take(), 111); -} - -TEST(BlockingDequeueUnitTest, take_is_last) { - size_t capacity = 10; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - EXPECT_TRUE(dequeue.offer(111)); - EXPECT_TRUE(dequeue.offer(222)); - ASSERT_EQ(dequeue.take(), 111); - ASSERT_EQ(dequeue.take(), 222); -} - -TEST(BlockingDequeueUnitTest, poll_is_not_block_when_empty) { - size_t capacity = 1; - bool isOk; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - dequeue.poll(111, &isOk); - EXPECT_FALSE(conditionVar->isWaitForCalled); -} - -TEST(BlockingDequeueUnitTest, poll_is_default_value_when_empty) { - size_t capacity = 1; - bool isOk; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - ASSERT_EQ(dequeue.poll(111, &isOk), 111); -} - -TEST(BlockingDequeueUnitTest, poll_is_offer_value_when_not_empty) { - size_t capacity = 1; - bool isOk; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - dequeue.offer(111); - ASSERT_EQ(dequeue.poll(-1, &isOk), 111); -} - -TEST(BlockingDequeueUnitTest, poll_timeouted_is_block_when_empty) { - size_t capacity = 1; - int timeout = 11; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - dequeue.poll(timeout, 111); - EXPECT_TRUE(conditionVar->isWaitForCalled); - EXPECT_EQ(timeout, conditionVar->timeout); - ASSERT_FALSE(conditionVar->isTrueCondition); -} - -TEST(BlockingDequeueUnitTest, poll_timeouted_is_default_value_when_empty) { - size_t capacity = 1; - int timeout = 11; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - ASSERT_EQ(dequeue.poll(timeout, 111), 111); -} - -TEST(BlockingDequeueUnitTest, poll_timeouted_is_not_block_when_not_empty) { - size_t capacity = 1; - int timeout = 11; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - dequeue.offer(111); - dequeue.poll(timeout, -1); - - EXPECT_TRUE(conditionVar->isWaitForCalled); - ASSERT_TRUE(conditionVar->isTrueCondition); -} - -TEST(BlockingDequeueUnitTest, poll_timeouted_is_offer_value_when_not_empty) { - size_t capacity = 1; - int timeout = 11; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - dequeue.offer(111); - ASSERT_EQ(dequeue.poll(timeout, -1), 111); -} - -TEST(BlockingDequeueUnitTest, poll_timeouted_is_last) { - size_t capacity = 10; - auto conditionVar = new MockConditionVar(); - PIBlockingDequeue dequeue(capacity, conditionVar); - dequeue.offer(111); - dequeue.offer(222); - ASSERT_EQ(dequeue.poll(10, -1), 111); - ASSERT_EQ(dequeue.poll(10, -1), 222); -} - -TEST(BlockingDequeueUnitTest, capacity_is_eq_constructor_capacity) { - size_t capacity = 10; - PIBlockingDequeue dequeue(capacity); - ASSERT_EQ(dequeue.capacity(), capacity); -} - -TEST(BlockingDequeueUnitTest, remainingCapacity_is_dif_of_capacity_and_size) { - size_t capacity = 2; - PIBlockingDequeue dequeue(capacity); - ASSERT_EQ(dequeue.remainingCapacity(), capacity); - dequeue.offer(111); - ASSERT_EQ(dequeue.remainingCapacity(), capacity - 1); -} - -TEST(BlockingDequeueUnitTest, remainingCapacity_is_zero_when_capacity_reach) { - size_t capacity = 1; - PIBlockingDequeue dequeue(capacity); - dequeue.offer(111); - dequeue.offer(111); - ASSERT_EQ(dequeue.remainingCapacity(), 0); -} - -TEST(BlockingDequeueUnitTest, size_is_eq_to_num_of_elements) { - size_t capacity = 1; - PIBlockingDequeue dequeue(capacity); - ASSERT_EQ(dequeue.size(), 0); - dequeue.offer(111); - ASSERT_EQ(dequeue.size(), 1); -} - -TEST(BlockingDequeueUnitTest, size_is_eq_to_capacity_when_capacity_reach) { - size_t capacity = 1; - PIBlockingDequeue dequeue(capacity); - dequeue.offer(111); - dequeue.offer(111); - ASSERT_EQ(dequeue.size(), capacity); -} - -TEST(BlockingDequeueUnitTest, drainTo_is_elements_moved) { - size_t capacity = 10; - PIDeque refDeque; - for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); - PIBlockingDequeue blockingDequeue(refDeque); - PIDeque deque; - blockingDequeue.drainTo(deque); - ASSERT_EQ(blockingDequeue.size(), 0); - ASSERT_TRUE(deque == refDeque); -} - -TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_size_when_all_moved) { - size_t capacity = 10; - PIDeque refDeque; - for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); - PIBlockingDequeue blockingDequeue(refDeque); - PIDeque deque; - ASSERT_EQ(blockingDequeue.drainTo(deque), refDeque.size()); -} - -TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_maxCount) { - size_t capacity = 10; - PIDeque refDeque; - for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); - PIBlockingDequeue blockingDequeue(refDeque); - PIDeque deque; - ASSERT_EQ(blockingDequeue.drainTo(deque, refDeque.size() - 1), refDeque.size() - 1); -} +#include "gtest/gtest.h" +#include "piblockingdequeue.h" + +class MockConditionVar: public PIConditionVariable { +public: + bool isWaitCalled = false; + bool isWaitForCalled = false; + bool isTrueCondition = false; + int timeout = -1; + + void wait(PIMutex& lk) override { + isWaitCalled = true; + } + + void wait(PIMutex& lk, const std::function& condition) override { + isWaitCalled = true; + lk.lock(); + isTrueCondition = condition(); + lk.unlock(); + } + + bool waitFor(PIMutex& lk, int timeoutMs) override { + isWaitForCalled = true; + timeout = timeoutMs; + return false; + } + + bool waitFor(PIMutex& lk, int timeoutMs, const std::function& condition) override { + isWaitForCalled = true; + lk.lock(); + isTrueCondition = condition(); + timeout = timeoutMs; + lk.unlock(); + return isTrueCondition; + } +}; + +TEST(BlockingDequeueUnitTest, put_is_block_when_capacity_reach) { + size_t capacity = 0; + auto conditionVarAdd = new MockConditionVar(); + auto conditionVarRem = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVarAdd, conditionVarRem); + dequeue.put(11); + ASSERT_TRUE(conditionVarRem->isWaitCalled); + ASSERT_FALSE(conditionVarRem->isTrueCondition); +} + +TEST(BlockingDequeueUnitTest, offer_timedout_is_false_when_capacity_reach) { + size_t capacity = 0; + int timeout = 11; + auto conditionVarAdd = new MockConditionVar(); + auto conditionVarRem = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVarAdd, conditionVarRem); + ASSERT_FALSE(dequeue.offer(11, timeout)); +} + +TEST(BlockingDequeueUnitTest, offer_timedout_is_block_when_capacity_reach) { + size_t capacity = 0; + int timeout = 11; + auto conditionVarAdd = new MockConditionVar(); + auto conditionVarRem = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVarAdd, conditionVarRem); + dequeue.offer(11, timeout); + EXPECT_TRUE(conditionVarRem->isWaitForCalled); + EXPECT_EQ(timeout, conditionVarRem->timeout); + ASSERT_FALSE(conditionVarRem->isTrueCondition); +} + +TEST(BlockingDequeueUnitTest, offer_is_true_before_capacity_reach) { + size_t capacity = 1; + PIBlockingDequeue dequeue(capacity); + ASSERT_TRUE(dequeue.offer(10)); +} + +TEST(BlockingDequeueUnitTest, offer_is_false_when_capacity_reach) { + size_t capacity = 1; + PIBlockingDequeue dequeue(capacity); + dequeue.offer(11); + ASSERT_FALSE(dequeue.offer(10)); +} + +// TODO change take_is_block_when_empty to prevent segfault +TEST(DISABLED_BlockingDequeueUnitTest, take_is_block_when_empty) { + size_t capacity = 1; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + // May cause segfault because take front of empty queue + dequeue.take(); + EXPECT_TRUE(conditionVar->isWaitCalled); + ASSERT_FALSE(conditionVar->isTrueCondition); +} + +TEST(BlockingDequeueUnitTest, take_is_not_block_when_not_empty) { + size_t capacity = 1; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + dequeue.offer(111); + dequeue.take(); + + EXPECT_TRUE(conditionVar->isWaitCalled); + ASSERT_TRUE(conditionVar->isTrueCondition); +} + +TEST(BlockingDequeueUnitTest, take_is_value_eq_to_offer_value) { + size_t capacity = 1; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + + dequeue.offer(111); + ASSERT_EQ(dequeue.take(), 111); +} + +TEST(BlockingDequeueUnitTest, take_is_last) { + size_t capacity = 10; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + EXPECT_TRUE(dequeue.offer(111)); + EXPECT_TRUE(dequeue.offer(222)); + ASSERT_EQ(dequeue.take(), 111); + ASSERT_EQ(dequeue.take(), 222); +} + +TEST(BlockingDequeueUnitTest, poll_is_not_block_when_empty) { + size_t capacity = 1; + bool isOk; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + dequeue.poll(111, &isOk); + EXPECT_FALSE(conditionVar->isWaitForCalled); +} + +TEST(BlockingDequeueUnitTest, poll_is_default_value_when_empty) { + size_t capacity = 1; + bool isOk; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + ASSERT_EQ(dequeue.poll(111, &isOk), 111); +} + +TEST(BlockingDequeueUnitTest, poll_is_offer_value_when_not_empty) { + size_t capacity = 1; + bool isOk; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + dequeue.offer(111); + ASSERT_EQ(dequeue.poll(-1, &isOk), 111); +} + +TEST(BlockingDequeueUnitTest, poll_timeouted_is_block_when_empty) { + size_t capacity = 1; + int timeout = 11; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + dequeue.poll(timeout, 111); + EXPECT_TRUE(conditionVar->isWaitForCalled); + EXPECT_EQ(timeout, conditionVar->timeout); + ASSERT_FALSE(conditionVar->isTrueCondition); +} + +TEST(BlockingDequeueUnitTest, poll_timeouted_is_default_value_when_empty) { + size_t capacity = 1; + int timeout = 11; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + ASSERT_EQ(dequeue.poll(timeout, 111), 111); +} + +TEST(BlockingDequeueUnitTest, poll_timeouted_is_not_block_when_not_empty) { + size_t capacity = 1; + int timeout = 11; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + dequeue.offer(111); + dequeue.poll(timeout, -1); + + EXPECT_TRUE(conditionVar->isWaitForCalled); + ASSERT_TRUE(conditionVar->isTrueCondition); +} + +TEST(BlockingDequeueUnitTest, poll_timeouted_is_offer_value_when_not_empty) { + size_t capacity = 1; + int timeout = 11; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + dequeue.offer(111); + ASSERT_EQ(dequeue.poll(timeout, -1), 111); +} + +TEST(BlockingDequeueUnitTest, poll_timeouted_is_last) { + size_t capacity = 10; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + dequeue.offer(111); + dequeue.offer(222); + ASSERT_EQ(dequeue.poll(10, -1), 111); + ASSERT_EQ(dequeue.poll(10, -1), 222); +} + +TEST(BlockingDequeueUnitTest, capacity_is_eq_constructor_capacity) { + size_t capacity = 10; + PIBlockingDequeue dequeue(capacity); + ASSERT_EQ(dequeue.capacity(), capacity); +} + +TEST(BlockingDequeueUnitTest, remainingCapacity_is_dif_of_capacity_and_size) { + size_t capacity = 2; + PIBlockingDequeue dequeue(capacity); + ASSERT_EQ(dequeue.remainingCapacity(), capacity); + dequeue.offer(111); + ASSERT_EQ(dequeue.remainingCapacity(), capacity - 1); +} + +TEST(BlockingDequeueUnitTest, remainingCapacity_is_zero_when_capacity_reach) { + size_t capacity = 1; + PIBlockingDequeue dequeue(capacity); + dequeue.offer(111); + dequeue.offer(111); + ASSERT_EQ(dequeue.remainingCapacity(), 0); +} + +TEST(BlockingDequeueUnitTest, size_is_eq_to_num_of_elements) { + size_t capacity = 1; + PIBlockingDequeue dequeue(capacity); + ASSERT_EQ(dequeue.size(), 0); + dequeue.offer(111); + ASSERT_EQ(dequeue.size(), 1); +} + +TEST(BlockingDequeueUnitTest, size_is_eq_to_capacity_when_capacity_reach) { + size_t capacity = 1; + PIBlockingDequeue dequeue(capacity); + dequeue.offer(111); + dequeue.offer(111); + ASSERT_EQ(dequeue.size(), capacity); +} + +TEST(BlockingDequeueUnitTest, drainTo_is_elements_moved) { + size_t capacity = 10; + PIDeque refDeque; + for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); + PIBlockingDequeue blockingDequeue(refDeque); + PIDeque deque; + blockingDequeue.drainTo(deque); + ASSERT_EQ(blockingDequeue.size(), 0); + ASSERT_TRUE(deque == refDeque); +} + +TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_size_when_all_moved) { + size_t capacity = 10; + PIDeque refDeque; + for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); + PIBlockingDequeue blockingDequeue(refDeque); + PIDeque deque; + ASSERT_EQ(blockingDequeue.drainTo(deque), refDeque.size()); +} + +TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_maxCount) { + size_t capacity = 10; + PIDeque refDeque; + for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); + PIBlockingDequeue blockingDequeue(refDeque); + PIDeque deque; + ASSERT_EQ(blockingDequeue.drainTo(deque, refDeque.size() - 1), refDeque.size() - 1); +} diff --git a/lib/concurrent/test/ConditionLockIntegrationTest.cpp b/tests/concurrent/ConditionLockIntegrationTest.cpp similarity index 89% rename from lib/concurrent/test/ConditionLockIntegrationTest.cpp rename to tests/concurrent/ConditionLockIntegrationTest.cpp index 8d42a597..e7f211ae 100644 --- a/lib/concurrent/test/ConditionLockIntegrationTest.cpp +++ b/tests/concurrent/ConditionLockIntegrationTest.cpp @@ -1,53 +1,53 @@ -#include "gtest/gtest.h" -#include "gmock/gmock.h" - -#include "piconditionvar.h" -#include -#include "testutil.h" - -class ConditionLock : public ::testing::Test, public TestUtil { -public: - PIConditionLock* m = new PIConditionLock(); -}; - -TEST_F(ConditionLock, lock_is_protect) { - m->lock(); - bool* isProtect = new bool(true); - - createThread([&](){ - m->lock(); - *isProtect = false; - }); - EXPECT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); - ASSERT_TRUE(*isProtect); -} - -TEST_F(ConditionLock, unlock_is_release) { - m->lock(); - bool* isReleased = new bool(false); - m->unlock(); - - createThread([&](){ - m->lock(); - *isReleased = true; - m->unlock(); - }); - ASSERT_TRUE(*isReleased); -} - -TEST_F(ConditionLock, tryLock_is_false_when_locked) { - createThread([&](){ - m->lock(); - piMSleep(WAIT_THREAD_TIME_MS); - }); - ASSERT_FALSE(m->tryLock()); -} - -TEST_F(ConditionLock, tryLock_is_true_when_unlocked) { - ASSERT_TRUE(m->tryLock()); -} - -TEST_F(ConditionLock, tryLock_is_recursive_lock_enable) { - m->lock(); - ASSERT_TRUE(m->tryLock()); -} \ No newline at end of file +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "piconditionvar.h" +#include "pithread.h" +#include "testutil.h" + +class ConditionLock : public ::testing::Test, public TestUtil { +public: + PIMutex* m = new PIMutex(); +}; + +TEST_F(ConditionLock, lock_is_protect) { + m->lock(); + bool* isProtect = new bool(true); + + createThread([&](){ + m->lock(); + *isProtect = false; + }); + EXPECT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); + ASSERT_TRUE(*isProtect); +} + +TEST_F(ConditionLock, unlock_is_release) { + m->lock(); + bool* isReleased = new bool(false); + m->unlock(); + + createThread([&](){ + m->lock(); + *isReleased = true; + m->unlock(); + }); + ASSERT_TRUE(*isReleased); +} + +TEST_F(ConditionLock, tryLock_is_false_when_locked) { + createThread([&](){ + m->lock(); + piMSleep(WAIT_THREAD_TIME_MS); + }); + ASSERT_FALSE(m->tryLock()); +} + +TEST_F(ConditionLock, tryLock_is_true_when_unlocked) { + ASSERT_TRUE(m->tryLock()); +} + +TEST_F(ConditionLock, tryLock_is_recursive_lock_enable) { + m->lock(); + ASSERT_TRUE(m->tryLock()); +} diff --git a/lib/concurrent/test/ConditionVariableIntegrationTest.cpp b/tests/concurrent/ConditionVariableIntegrationTest.cpp similarity index 96% rename from lib/concurrent/test/ConditionVariableIntegrationTest.cpp rename to tests/concurrent/ConditionVariableIntegrationTest.cpp index 6a2609fa..b8d82a92 100644 --- a/lib/concurrent/test/ConditionVariableIntegrationTest.cpp +++ b/tests/concurrent/ConditionVariableIntegrationTest.cpp @@ -1,200 +1,200 @@ -#include "gtest/gtest.h" -#include "piconditionvar.h" -#include "pithread.h" -#include "testutil.h" - -class ConditionVariable : public ::testing::Test, public TestUtil { -public: - PIConditionLock m; - PIConditionVariable* variable; - -protected: - void SetUp() override { - variable = new PIConditionVariable(); - adapterFunctionDefault = [&](){ - m.lock(); - variable->wait(m); - m.unlock(); - }; - } -}; - -TEST_F(ConditionVariable, wait_is_block) { - createThread(); - ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); -} - -TEST_F(ConditionVariable, wait_is_block_when_notifyOne_before_wait) { - variable->notifyOne(); - createThread(); - ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); -} - -TEST_F(ConditionVariable, wait_is_block_when_notifyAll_before_wait) { - variable->notifyAll(); - createThread(); - ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); -} - -TEST_F(ConditionVariable, wait_is_unblock_when_notifyOne_after_wait) { - createThread(); - variable->notifyOne(); - ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); -} - -TEST_F(ConditionVariable, wait_is_unblock_when_notifyAll_after_wait) { - PIVector threads; - - for (int i = 0; i < THREAD_COUNT; ++i) { - threads.push_back(new PIThread([=](){ adapterFunctionDefault(); })); - } - - piForeach(PIThread* thread, threads) thread->startOnce(); - piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); - variable->notifyAll(); - PITimeMeasurer measurer; - piForeach(PIThread* thread, threads) { - int timeout = WAIT_THREAD_TIME_MS * THREAD_COUNT - (int)measurer.elapsed_m(); - thread->waitForFinish(timeout > 0 ? timeout : 0); - } - for (size_t i = 0; i < threads.size(); ++i) EXPECT_FALSE(threads[i]->isRunning()) << "Thread " << i << " still running"; - piForeach(PIThread* thread, threads) delete thread; -} - -TEST_F(ConditionVariable, wait_is_one_unblock_when_notifyOne) { - PIVector threads; - - for (int i = 0; i < THREAD_COUNT; ++i) { - threads.push_back(new PIThread(adapterFunctionDefault)); - } - - piForeach(PIThread* thread, threads) thread->startOnce(); - piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); - variable->notifyOne(); - piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); - int runningThreadCount = 0; - piForeach(PIThread* thread, threads) if (thread->isRunning()) runningThreadCount++; - ASSERT_EQ(runningThreadCount, THREAD_COUNT - 1); -} - -TEST_F(ConditionVariable, wait_is_protected_unblock_when_notifyOne) { - createThread([&](){ - m.lock(); - variable->wait(m); - piMSleep(2 * WAIT_THREAD_TIME_MS); - // Missing unlock - }); - variable->notifyOne(); - msleep(WAIT_THREAD_TIME_MS); - ASSERT_FALSE(m.tryLock()); -} - -TEST_F(ConditionVariable, wait_condition_is_block) { - createThread([&](){ - m.lock(); - variable->wait(m, [](){ return false; }); - m.unlock(); - }); - ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); -} - -TEST_F(ConditionVariable, wait_condition_is_check_condition_before_block) { - bool isConditionChecked = false; - createThread([&](){ - m.lock(); - variable->wait(m, [&](){ - isConditionChecked = true; - return false; - }); - m.unlock(); - }); - m.lock(); - ASSERT_TRUE(isConditionChecked); - m.unlock(); -} - -TEST_F(ConditionVariable, wait_condition_is_check_condition_when_notifyOne) { - bool isConditionChecked; - createThread([&](){ - m.lock(); - variable->wait(m, [&](){ - isConditionChecked = true; - return false; - }); - m.unlock(); - }); - m.lock(); - isConditionChecked = false; - m.unlock(); - variable->notifyOne(); - msleep(threadStartTime + 1); - m.lock(); - ASSERT_TRUE(isConditionChecked); - m.unlock(); -} - -TEST_F(ConditionVariable, wait_condition_is_unblock_when_condition_and_notifyOne) { - bool condition = false; - createThread([&](){ - m.lock(); - variable->wait(m, [&](){ return condition; }); - m.unlock(); - }); - m.lock(); - condition = true; - m.unlock(); - variable->notifyOne(); - ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); -} - -TEST_F(ConditionVariable, DISABLED_waitFor_is_block_before_timeout) { - createThread([&](){ - PITimeMeasurer measurer; - m.lock(); - variable->waitFor(m, WAIT_THREAD_TIME_MS * 2); - m.unlock(); - // Not reliable because spurious wakeup may happen - ASSERT_GE(measurer.elapsed_m(), WAIT_THREAD_TIME_MS); - }); - EXPECT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS * 3)); -} - -TEST_F(ConditionVariable, waitFor_is_unblock_when_timeout) { - std::atomic_bool isUnblock(false); - createThread([&](){ - m.lock(); - variable->waitFor(m, WAIT_THREAD_TIME_MS); - isUnblock = true; - m.unlock(); - }); - // Test failed if suspend forever - EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); - ASSERT_TRUE(isUnblock); -} - -TEST_F(ConditionVariable, waitFor_is_false_when_timeout) { - bool waitRet = true; - createThread([&](){ - m.lock(); - waitRet = variable->waitFor(m, WAIT_THREAD_TIME_MS); - m.unlock(); - }); - EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); - ASSERT_FALSE(waitRet); -} - -TEST_F(ConditionVariable, waitFor_is_unblock_when_condition_and_notifyOne) { - bool condition = false; - createThread([&](){ - m.lock(); - variable->waitFor(m, 3 * WAIT_THREAD_TIME_MS, [&](){ return condition; }); - m.unlock(); - }); - EXPECT_TRUE(thread->isRunning()); - m.lock(); - condition = true; - m.unlock(); - variable->notifyOne(); - msleep(WAIT_THREAD_TIME_MS); - ASSERT_FALSE(thread->isRunning()); -} \ No newline at end of file +#include "gtest/gtest.h" +#include "piconditionvar.h" +#include "pithread.h" +#include "testutil.h" + +class ConditionVariable : public ::testing::Test, public TestUtil { +public: + PIMutex m; + PIConditionVariable* variable; + +protected: + void SetUp() override { + variable = new PIConditionVariable(); + adapterFunctionDefault = [&](){ + m.lock(); + variable->wait(m); + m.unlock(); + }; + } +}; + +TEST_F(ConditionVariable, wait_is_block) { + createThread(); + ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); +} + +TEST_F(ConditionVariable, wait_is_block_when_notifyOne_before_wait) { + variable->notifyOne(); + createThread(); + ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); +} + +TEST_F(ConditionVariable, wait_is_block_when_notifyAll_before_wait) { + variable->notifyAll(); + createThread(); + ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); +} + +TEST_F(ConditionVariable, wait_is_unblock_when_notifyOne_after_wait) { + createThread(); + variable->notifyOne(); + ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); +} + +TEST_F(ConditionVariable, wait_is_unblock_when_notifyAll_after_wait) { + PIVector threads; + + for (int i = 0; i < THREAD_COUNT; ++i) { + threads.push_back(new PIThread([=](){ adapterFunctionDefault(); })); + } + + piForeach(PIThread* thread, threads) thread->startOnce(); + piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); + variable->notifyAll(); + PITimeMeasurer measurer; + piForeach(PIThread* thread, threads) { + int timeout = WAIT_THREAD_TIME_MS * THREAD_COUNT - (int)measurer.elapsed_m(); + thread->waitForFinish(timeout > 0 ? timeout : 0); + } + for (size_t i = 0; i < threads.size(); ++i) EXPECT_FALSE(threads[i]->isRunning()) << "Thread " << i << " still running"; + piForeach(PIThread* thread, threads) delete thread; +} + +TEST_F(ConditionVariable, wait_is_one_unblock_when_notifyOne) { + PIVector threads; + + for (int i = 0; i < THREAD_COUNT; ++i) { + threads.push_back(new PIThread(adapterFunctionDefault)); + } + + piForeach(PIThread* thread, threads) thread->startOnce(); + piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); + variable->notifyOne(); + piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); + int runningThreadCount = 0; + piForeach(PIThread* thread, threads) if (thread->isRunning()) runningThreadCount++; + ASSERT_EQ(runningThreadCount, THREAD_COUNT - 1); +} + +TEST_F(ConditionVariable, wait_is_protected_unblock_when_notifyOne) { + createThread([&](){ + m.lock(); + variable->wait(m); + piMSleep(2 * WAIT_THREAD_TIME_MS); + // Missing unlock + }); + variable->notifyOne(); + msleep(WAIT_THREAD_TIME_MS); + ASSERT_FALSE(m.tryLock()); +} + +TEST_F(ConditionVariable, wait_condition_is_block) { + createThread([&](){ + m.lock(); + variable->wait(m, [](){ return false; }); + m.unlock(); + }); + ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); +} + +TEST_F(ConditionVariable, wait_condition_is_check_condition_before_block) { + bool isConditionChecked = false; + createThread([&](){ + m.lock(); + variable->wait(m, [&](){ + isConditionChecked = true; + return false; + }); + m.unlock(); + }); + m.lock(); + ASSERT_TRUE(isConditionChecked); + m.unlock(); +} + +TEST_F(ConditionVariable, wait_condition_is_check_condition_when_notifyOne) { + bool isConditionChecked; + createThread([&](){ + m.lock(); + variable->wait(m, [&](){ + isConditionChecked = true; + return false; + }); + m.unlock(); + }); + m.lock(); + isConditionChecked = false; + m.unlock(); + variable->notifyOne(); + msleep(threadStartTime + 1); + m.lock(); + ASSERT_TRUE(isConditionChecked); + m.unlock(); +} + +TEST_F(ConditionVariable, wait_condition_is_unblock_when_condition_and_notifyOne) { + bool condition = false; + createThread([&](){ + m.lock(); + variable->wait(m, [&](){ return condition; }); + m.unlock(); + }); + m.lock(); + condition = true; + m.unlock(); + variable->notifyOne(); + ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); +} + +TEST_F(ConditionVariable, DISABLED_waitFor_is_block_before_timeout) { + createThread([&](){ + PITimeMeasurer measurer; + m.lock(); + variable->waitFor(m, WAIT_THREAD_TIME_MS * 2); + m.unlock(); + // Not reliable because spurious wakeup may happen + ASSERT_GE(measurer.elapsed_m(), WAIT_THREAD_TIME_MS); + }); + EXPECT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS * 3)); +} + +TEST_F(ConditionVariable, waitFor_is_unblock_when_timeout) { + std::atomic_bool isUnblock(false); + createThread([&](){ + m.lock(); + variable->waitFor(m, WAIT_THREAD_TIME_MS); + isUnblock = true; + m.unlock(); + }); + // Test failed if suspend forever + EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); + ASSERT_TRUE(isUnblock); +} + +TEST_F(ConditionVariable, waitFor_is_false_when_timeout) { + bool waitRet = true; + createThread([&](){ + m.lock(); + waitRet = variable->waitFor(m, WAIT_THREAD_TIME_MS); + m.unlock(); + }); + EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); + ASSERT_FALSE(waitRet); +} + +TEST_F(ConditionVariable, waitFor_is_unblock_when_condition_and_notifyOne) { + bool condition = false; + createThread([&](){ + m.lock(); + variable->waitFor(m, 3 * WAIT_THREAD_TIME_MS, [&](){ return condition; }); + m.unlock(); + }); + EXPECT_TRUE(thread->isRunning()); + m.lock(); + condition = true; + m.unlock(); + variable->notifyOne(); + msleep(WAIT_THREAD_TIME_MS); + ASSERT_FALSE(thread->isRunning()); +} diff --git a/lib/concurrent/test/ExecutorIntegrationTest.cpp b/tests/concurrent/ExecutorIntegrationTest.cpp similarity index 95% rename from lib/concurrent/test/ExecutorIntegrationTest.cpp rename to tests/concurrent/ExecutorIntegrationTest.cpp index e2a40299..9485521f 100644 --- a/lib/concurrent/test/ExecutorIntegrationTest.cpp +++ b/tests/concurrent/ExecutorIntegrationTest.cpp @@ -1,55 +1,55 @@ -#include "gtest/gtest.h" -#include "executor.h" -#include "pimutex.h" -#include "testutil.h" - -TEST(ExcutorIntegrationTest, execute_is_runnable_invoke) { - PIMutex m; - int invokedRunnables = 0; - PIThreadPoolExecutor executorService(1); - executorService.execute([&]() { - m.lock(); - invokedRunnables++; - m.unlock(); - }); - piMSleep(WAIT_THREAD_TIME_MS); - m.lock(); - ASSERT_EQ(invokedRunnables, 1); - m.unlock(); -} - -TEST(ExcutorIntegrationTest, execute_is_not_execute_after_shutdown) { - volatile bool isRunnableInvoke = false; - PIThreadPoolExecutor executorService(1); - executorService.shutdown(); - executorService.execute([&]() { - isRunnableInvoke = true; - }); - piMSleep(WAIT_THREAD_TIME_MS); - ASSERT_FALSE(isRunnableInvoke); -} - -TEST(ExcutorIntegrationTest, execute_is_execute_before_shutdown) { - volatile bool isRunnableInvoke = false; - PIThreadPoolExecutor executorService(1); - executorService.execute([&]() { - piMSleep(WAIT_THREAD_TIME_MS); - isRunnableInvoke = true; - }); - executorService.shutdown(); - piMSleep(2 * WAIT_THREAD_TIME_MS); - ASSERT_TRUE(isRunnableInvoke); -} - -TEST(ExcutorIntegrationTest, execute_is_awaitTermination_wait) { - PIThreadPoolExecutor executorService(1); - executorService.execute([&]() { - piMSleep(2 * WAIT_THREAD_TIME_MS); - }); - executorService.shutdown(); - PITimeMeasurer measurer; - ASSERT_TRUE(executorService.awaitTermination(3 * WAIT_THREAD_TIME_MS)); - double waitTime = measurer.elapsed_m(); - ASSERT_GE(waitTime, WAIT_THREAD_TIME_MS); - ASSERT_LE(waitTime, 4 * WAIT_THREAD_TIME_MS); -} \ No newline at end of file +#include "gtest/gtest.h" +#include "pithreadpoolexecutor.h" +#include "pimutex.h" +#include "testutil.h" + +TEST(ExcutorIntegrationTest, execute_is_runnable_invoke) { + PIMutex m; + int invokedRunnables = 0; + PIThreadPoolExecutor executorService(1); + executorService.execute([&]() { + m.lock(); + invokedRunnables++; + m.unlock(); + }); + piMSleep(WAIT_THREAD_TIME_MS); + m.lock(); + ASSERT_EQ(invokedRunnables, 1); + m.unlock(); +} + +TEST(ExcutorIntegrationTest, execute_is_not_execute_after_shutdown) { + volatile bool isRunnableInvoke = false; + PIThreadPoolExecutor executorService(1); + executorService.shutdown(); + executorService.execute([&]() { + isRunnableInvoke = true; + }); + piMSleep(WAIT_THREAD_TIME_MS); + ASSERT_FALSE(isRunnableInvoke); +} + +TEST(ExcutorIntegrationTest, execute_is_execute_before_shutdown) { + volatile bool isRunnableInvoke = false; + PIThreadPoolExecutor executorService(1); + executorService.execute([&]() { + piMSleep(WAIT_THREAD_TIME_MS); + isRunnableInvoke = true; + }); + executorService.shutdown(); + piMSleep(2 * WAIT_THREAD_TIME_MS); + ASSERT_TRUE(isRunnableInvoke); +} + +TEST(ExcutorIntegrationTest, execute_is_awaitTermination_wait) { + PIThreadPoolExecutor executorService(1); + executorService.execute([&]() { + piMSleep(2 * WAIT_THREAD_TIME_MS); + }); + executorService.shutdown(); + PITimeMeasurer measurer; + ASSERT_TRUE(executorService.awaitTermination(3 * WAIT_THREAD_TIME_MS)); + double waitTime = measurer.elapsed_m(); + ASSERT_GE(waitTime, WAIT_THREAD_TIME_MS); + ASSERT_LE(waitTime, 4 * WAIT_THREAD_TIME_MS); +} diff --git a/lib/concurrent/test/ExecutorUnitTest.cpp b/tests/concurrent/ExecutorUnitTest.cpp similarity index 100% rename from lib/concurrent/test/ExecutorUnitTest.cpp rename to tests/concurrent/ExecutorUnitTest.cpp diff --git a/lib/concurrent/test/testutil.h b/tests/concurrent/testutil.h similarity index 96% rename from lib/concurrent/test/testutil.h rename to tests/concurrent/testutil.h index eb48c2c8..6bb4fa2a 100644 --- a/lib/concurrent/test/testutil.h +++ b/tests/concurrent/testutil.h @@ -55,7 +55,6 @@ public: return !isTimeout; } - }; #endif //AWRCANFLASHER_TESTUTIL_H diff --git a/utils/cloud_dispatcher/CMakeLists.txt b/utils/cloud_dispatcher/CMakeLists.txt index 80d86378..e48f86f4 100644 --- a/utils/cloud_dispatcher/CMakeLists.txt +++ b/utils/cloud_dispatcher/CMakeLists.txt @@ -1,4 +1,5 @@ -message(STATUS "Building picloud") +list(APPEND PIP_UTILS_LIST "picloud") +set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) file(GLOB CPPS "*.cpp") file(GLOB HDRS "*.h") add_executable(picloud ${CPPS} ${HDRS}) diff --git a/utils/cloud_dispatcher/dispatcherclient.cpp b/utils/cloud_dispatcher/dispatcherclient.cpp new file mode 100644 index 00000000..83f3c02e --- /dev/null +++ b/utils/cloud_dispatcher/dispatcherclient.cpp @@ -0,0 +1,28 @@ +#include "dispatcherclient.h" + + +DispatcherClient::DispatcherClient(PIEthernet * eth_) { + eth = eth_; + eth->startThreadedRead(); + CONNECTU(eth, threadedReadEvent, this, readed); + CONNECTU(eth, disconnected, this, disconnected); + piCoutObj << "client connected" << eth->sendAddress(); +} + + +DispatcherClient::~DispatcherClient() { +} + + +void DispatcherClient::disconnected(bool withError) { + piCoutObj << "client disconnected" << eth->sendAddress(); + disconnectEvent(this); +} + + +void DispatcherClient::readed(uchar *data, int size) { + PIByteArray ba(data, size); + piCoutObj << "readed" << ba.toHex(); + eth->write(ba); +} + diff --git a/utils/cloud_dispatcher/dispatcherclient.h b/utils/cloud_dispatcher/dispatcherclient.h new file mode 100644 index 00000000..aa0e0c6f --- /dev/null +++ b/utils/cloud_dispatcher/dispatcherclient.h @@ -0,0 +1,21 @@ +#ifndef DISPATCHERCLIENT_H +#define DISPATCHERCLIENT_H + +#include "piethernet.h" + + +class DispatcherClient: public PIObject { + PIOBJECT(DispatcherClient) +public: + DispatcherClient(PIEthernet * eth_); + ~DispatcherClient(); + EVENT_HANDLER2(void, readed, uchar * , data, int, size); + EVENT_HANDLER1(void, disconnected, bool, withError); + EVENT1(disconnectEvent, DispatcherClient *, client) + +private: + PIEthernet * eth; +}; + + +#endif // DISPATCHERCLIENT_H diff --git a/utils/cloud_dispatcher/dispatcherserver.cpp b/utils/cloud_dispatcher/dispatcherserver.cpp new file mode 100644 index 00000000..40959cbf --- /dev/null +++ b/utils/cloud_dispatcher/dispatcherserver.cpp @@ -0,0 +1,32 @@ +#include "dispatcherserver.h" + + +DispatcherServer::DispatcherServer(PIEthernet::Address addr) { + eth = new PIEthernet(PIEthernet::TCP_Server); + eth->setParameter(PIEthernet::ReuseAddress); + CONNECTU(eth, newConnection, this, newConnection); + eth->listen(addr, true); + piCoutObj << eth << "server started" << addr; +} + + +DispatcherServer::~DispatcherServer() { + eth->close(); + piCoutObj << "server stoped"; + delete eth; +} + + +void DispatcherServer::disconnectClient(DispatcherClient *client) { + piCoutObj << "remove client" << client; + clients.removeOne(client); + delete client; +} + + +void DispatcherServer::newConnection(PIEthernet *cl) { + DispatcherClient * client = new DispatcherClient(cl); + piCoutObj << "add client" << client; + CONNECTU(client, disconnectEvent, this, disconnectClient); + clients.push_back(client); +} diff --git a/utils/cloud_dispatcher/dispatcherserver.h b/utils/cloud_dispatcher/dispatcherserver.h new file mode 100644 index 00000000..4edf2c23 --- /dev/null +++ b/utils/cloud_dispatcher/dispatcherserver.h @@ -0,0 +1,20 @@ +#ifndef DISPATCHERSERVER_H +#define DISPATCHERSERVER_H + +#include "dispatcherclient.h" + + +class DispatcherServer: public PIObject { + PIOBJECT(DispatcherServer) +public: + DispatcherServer(PIEthernet::Address addr); + ~DispatcherServer(); + EVENT_HANDLER1(void, newConnection, PIEthernet * , cl); + EVENT_HANDLER1(void, disconnectClient, DispatcherClient *, client); + +private: + PIEthernet * eth; + PIVector clients; +}; + +#endif // DISPATCHERSERVER_H diff --git a/utils/cloud_dispatcher/main.cpp b/utils/cloud_dispatcher/main.cpp index d85c147c..6a685a3d 100644 --- a/utils/cloud_dispatcher/main.cpp +++ b/utils/cloud_dispatcher/main.cpp @@ -19,12 +19,12 @@ #include "pip.h" #include "picrypt.h" +#include "dispatcherserver.h" using namespace PICoutManipulators; -PIString ip = "0.0.0.0"; -int port = 10101; +PIEthernet::Address addr = PIEthernet::Address("0.0.0.0", 10101); void usage() { piCout << Bold << "PIP Cloud Dispatcher"; @@ -49,10 +49,11 @@ int main (int argc, char * argv[]) { return 0; } if (cli.hasArgument("ip")) - ip = cli.argumentValue("ip"); + addr.setIP(cli.argumentValue("ip")); if (cli.hasArgument("port")) - port = cli.argumentValue("port").toInt(); - + addr.setPort(cli.argumentValue("port").toInt()); + DispatcherServer server(addr); + WAIT_FOR_EXIT return 0; } diff --git a/utils/code_model_generator/CMakeLists.txt b/utils/code_model_generator/CMakeLists.txt index 51995226..bdbef9b6 100755 --- a/utils/code_model_generator/CMakeLists.txt +++ b/utils/code_model_generator/CMakeLists.txt @@ -1,4 +1,5 @@ -message(STATUS "Building pip_cmg") +list(APPEND PIP_UTILS_LIST "pip_cmg") +set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) import_version(pip_cmg pip) set_deploy_property(pip_cmg LABEL "PIP code model generator" diff --git a/utils/code_model_generator/main.cpp b/utils/code_model_generator/main.cpp index 6cb26cbf..b207d679 100755 --- a/utils/code_model_generator/main.cpp +++ b/utils/code_model_generator/main.cpp @@ -87,7 +87,8 @@ void makeClassInfo(PIFile & f, const PICodeParser::Entity * e) { f << "\tci->name = \"" << e->name << "\";\n"; f << "\tci->has_name = " << (e->has_name ? "true" : "false") << ";\n"; if (!e->meta.isEmpty()) { - for (PICodeParser::MetaMap::const_iterator i = e->meta.begin(); i != e->meta.end(); ++i) + auto i = e->meta.makeIterator(); + while (i.next()) f << "\tci->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n"; } f << "\t(*classesInfo)[ci->name] = ci;\n"; @@ -176,14 +177,16 @@ void makeEnumInfo(PIFile & f, const PICodeParser::Enum * e) { f << "\t(*enumsInfo)[\"" << e->name << "\"] = ei;\n"; f << "\tei->name = \"" << e->name << "\";\n"; if (!e->meta.isEmpty()) { - for (PICodeParser::MetaMap::const_iterator i = e->meta.begin(); i != e->meta.end(); ++i) + auto i = e->meta.makeIterator(); + while (i.next()) f << "\tei->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n"; } } piForeachC (PICodeParser::EnumeratorInfo & m, e->members) { f << "\tei->members << PICodeInfo::EnumeratorInfo(\"" << m.name << "\", " << m.value << ");\n"; if (!m.meta.isEmpty()) { - for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i) + auto i = m.meta.makeIterator(); + while (i.next()) f << "\tei->members.back().meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n"; } } @@ -218,7 +221,7 @@ void writeClassStreamMembersOut(PIFile & f, const PICodeParser::Entity * e, int f << "));\n"; } if (is_union) - piBreak; + break; } if (is_union) return; piForeachC (PICodeParser::Entity * ce, e->children) { @@ -261,7 +264,7 @@ void writeClassStreamMembersIn(PIFile & f, const PICodeParser::Entity * e, int & f << "\t\t\tbreak;\n"; } if (is_union) - piBreak; + break; } if (is_union) return; piForeachC (PICodeParser::Entity * ce, e->children) { @@ -331,13 +334,13 @@ void makeGetterValue(PIFile & f, const PICodeParser::Entity * e) { void writeModel(PICodeParser & parser, PICLI & cli, const PIString out, bool meta, bool enums, bool streams, bool texts, bool getters) { PIVector ventities; PIString defname = out - .replaceAll(".", "_") - .replaceAll("/", "_") - .replaceAll(":", "_") - .replaceAll("-", "_") - .replaceAll("@", "_") - .replaceAll("\\", "_") - .removeAll(" ") + .replacedAll('.', '_') + .replaceAll('/', '_') + .replaceAll(':', '_') + .replaceAll('-', '_') + .replaceAll('@', '_') + .replaceAll('\\', '_') + .removeAll(' ') .toUpperCase() + "_H"; bool inc_h, inc_cpp; diff --git a/utils/crypt_tool/CMakeLists.txt b/utils/crypt_tool/CMakeLists.txt index 302631d0..0b99f04f 100644 --- a/utils/crypt_tool/CMakeLists.txt +++ b/utils/crypt_tool/CMakeLists.txt @@ -1,4 +1,5 @@ -message(STATUS "Building picrypt") +list(APPEND PIP_UTILS_LIST "picrypt") +set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) add_executable(picrypt "main.cpp") target_link_libraries(picrypt pip pip_crypt) if (DEFINED LIB) diff --git a/utils/deploy_tool/CMakeLists.txt b/utils/deploy_tool/CMakeLists.txt index ce53d07f..3441412c 100644 --- a/utils/deploy_tool/CMakeLists.txt +++ b/utils/deploy_tool/CMakeLists.txt @@ -1,4 +1,5 @@ -message(STATUS "Building deploy_tool") +list(APPEND PIP_UTILS_LIST "deploy_tool") +set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) import_version(deploy_tool pip) set_deploy_property(deploy_tool LABEL "PIP deploy tool" diff --git a/utils/deploy_tool/main.cpp b/utils/deploy_tool/main.cpp index 88019be2..45455398 100644 --- a/utils/deploy_tool/main.cpp +++ b/utils/deploy_tool/main.cpp @@ -370,7 +370,7 @@ void procQt() { } } } - piBreak; + break; } } } @@ -583,8 +583,9 @@ int main(int argc, char * argv[]) { qt_filters["platforms"] = platforms; qt_filters["styles" ] = styles ; - for (PIMap::iterator it = qt_filters.begin(); it != qt_filters.end(); ++it) - it.value().forEachInplace([](PIString i)->PIString{ + auto it = qt_filters.makeIterator(); + while (it.next()) + it.valueRef().forEachInplace([](PIString i)->PIString{ if (!i.startsWith("*")) i.prepend("*"); if (!i.endsWith("*")) i.append("*"); return i; diff --git a/lib/main/auxiliary/piterminal/CMakeLists.txt b/utils/piterminal/CMakeLists.txt similarity index 74% rename from lib/main/auxiliary/piterminal/CMakeLists.txt rename to utils/piterminal/CMakeLists.txt index 81f2d998..89e51920 100644 --- a/lib/main/auxiliary/piterminal/CMakeLists.txt +++ b/utils/piterminal/CMakeLists.txt @@ -2,4 +2,6 @@ add_executable(piterminal "main.cpp") target_link_libraries(piterminal pip pip_console) if (DEFINED LIB) install(TARGETS piterminal DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -endif () +else() + install(TARGETS piterminal DESTINATION bin) +endif() diff --git a/lib/main/auxiliary/piterminal/main.cpp b/utils/piterminal/main.cpp similarity index 99% rename from lib/main/auxiliary/piterminal/main.cpp rename to utils/piterminal/main.cpp index 8e077933..eae32a9a 100644 --- a/lib/main/auxiliary/piterminal/main.cpp +++ b/utils/piterminal/main.cpp @@ -23,11 +23,13 @@ int main (int argc, char * argv[]) { return 0; } #else +# define PIP_CONSOLE_STATIC_DEFINE +# include "pip_console_export.h" # include "piscreentypes.h" # include "pisharedmemory.h" -# include "../../lib/console/piterminal.cpp" # include "pifile.h" # include +# include "../../lib/console/piterminal.cpp" PIVector > cells; diff --git a/utils/remote_console/CMakeLists.txt b/utils/remote_console/CMakeLists.txt deleted file mode 100755 index 33234067..00000000 --- a/utils/remote_console/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -message(STATUS "Building pip_remote_console") -add_executable(pip_remote_console "main.cpp") -target_link_libraries(pip_remote_console pip pip_console) -if (DEFINED LIB) - install(TARGETS pip_remote_console DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -endif () diff --git a/utils/remote_console/main.cpp b/utils/remote_console/main.cpp deleted file mode 100755 index d0c89fcc..00000000 --- a/utils/remote_console/main.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - PIP - Platform Independent Primitives - Remote console viewer - 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 . -*/ - -#include "pip.h" - -void key_event(PIKbdListener::KeyEvent key, void * ); - -PIConsole console(false, key_event); -PIStringList as; -bool selected = false; - -void key_event(PIKbdListener::KeyEvent key, void * ) { - if (key.key < '1' || key.key > '9') return; - int ind = key.key - '1'; - if (ind < 0 || ind >= as.size_s()) return; - selected = true; - console.connectToServer(as[ind]); -} - -int main(int argc, char * argv[]) { - console.enableExitCapture(); - console.listenServers(); - while (!PIKbdListener::exiting) { - msleep(200); - if (selected) break; - console.clearScreen(); - as = console.availableServers(); - if (as.isEmpty()) { - piCout << "No servers are available!"; - } else { - piCout << "Select one with numeric key:"; - for (int i = 0; i < as.size_s(); ++i) - piCout << (i + 1) << as[i]; - } - } - if (!selected) return 0; - piCout << "Connecting to" << console.selectedServer() << "..."; - while (!PIKbdListener::exiting) { - msleep(20); - if (console.isConnected()) - break; - } - if (PIKbdListener::exiting) - return 0; - console.start(); - console.waitForFinish(); -}; diff --git a/utils/resources_compiler/CMakeLists.txt b/utils/resources_compiler/CMakeLists.txt index af7642ab..e0a575c6 100644 --- a/utils/resources_compiler/CMakeLists.txt +++ b/utils/resources_compiler/CMakeLists.txt @@ -1,4 +1,5 @@ -message(STATUS "Building pip_rc") +list(APPEND PIP_UTILS_LIST "pip_rc") +set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) import_version(pip_rc pip) set_deploy_property(pip_rc LABEL "PIP resources compiler" diff --git a/utils/system_daemon/CMakeLists.txt b/utils/system_daemon/CMakeLists.txt index 004a22f8..ecf2bbf2 100755 --- a/utils/system_daemon/CMakeLists.txt +++ b/utils/system_daemon/CMakeLists.txt @@ -1,4 +1,5 @@ -message(STATUS "Building pisd") +list(APPEND PIP_UTILS_LIST "pisd") +set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) file(GLOB CPPS "*.cpp") file(GLOB HDRS "*.h") add_executable(pisd ${CPPS} ${HDRS}) diff --git a/utils/system_daemon/main.cpp b/utils/system_daemon/main.cpp index 40962fa0..85900bd1 100755 --- a/utils/system_daemon/main.cpp +++ b/utils/system_daemon/main.cpp @@ -164,19 +164,20 @@ public: tl->content << TileSimple::Row("Quality: " + PIString::fromNumber((int)ds.quality), CellFormat()); } void updatePeerInfo() { - bool pm = daemon_.lockedPeers(); +// bool pm = daemon_.lockedPeers(); screen->lock(); daemon_.lock(); peers_tl->content.clear(); addrs_tl->content.clear(); peerinfo_tl->content.clear(); peermap_tl->content.clear(); - peers_tl->content << TileList::Row("this | 0 | 0 | " + PIString::fromNumber(daemon_.allPeers().size_s()) + - " [em = " + PIString::fromBool(daemon_.lockedEth()) + ", " - "mm = " + PIString::fromBool(daemon_.lockedMBcasts()) + ", " - "sm = " + PIString::fromBool(daemon_.lockedSends()) + ", " - "ms = " + PIString::fromBool(daemon_.lockedMCSends()) + ", " - "pm = " + PIString::fromBool(pm) + "]", CellFormat()); + peers_tl->content << TileList::Row("this | 0 | 0 | " + PIString::fromNumber(daemon_.allPeers().size_s()) +// + " [em = " + PIString::fromBool(daemon_.lockedEth()) + ", " +// "mm = " + PIString::fromBool(daemon_.lockedMBcasts()) + ", " +// "sm = " + PIString::fromBool(daemon_.lockedSends()) + ", " +// "ms = " + PIString::fromBool(daemon_.lockedMCSends()) + ", " +// "pm = " + PIString::fromBool(pm) + "]" + , CellFormat()); piForeachC(PIPeer::PeerInfo &p , daemon_.allPeers()) peers_tl->content << TileList::Row(p.name + " | d = " + PIString::fromNumber(p.dist) + " | p = " + PIString::fromNumber(p.ping()) + @@ -191,11 +192,10 @@ public: addrs_tl->content << TileList::Row(a.address.toString() + " | p = " + PIString::fromNumber(a.ping) + " | a = " + PIString::fromBool(a.isAvailable()), CellFormat()); - typedef PIPair > PeerPair; PIStringList peermap; - piForeachC(PeerPair &p , daemon_._peerMap()) { - PIString s = p.first + " | "; - piForeachCR(PIPeer::PeerInfo * pp, p.second) s += " -> " + pp->name; + for (auto p = daemon_._peerMap().constBegin(); p != daemon_._peerMap().constEnd(); p++) { + PIString s = p.key() + " | "; + piForeachCR(PIPeer::PeerInfo * pp, p.value()) s += " -> " + pp->name; peermap << s; } piForeachC(PIString &s , peermap) diff --git a/utils/system_test/CMakeLists.txt b/utils/system_test/CMakeLists.txt index fe07d4bb..e93f6be7 100755 --- a/utils/system_test/CMakeLists.txt +++ b/utils/system_test/CMakeLists.txt @@ -1,4 +1,5 @@ -message(STATUS "Building pip_system_test") +list(APPEND PIP_UTILS_LIST "pip_system_test") +set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) add_executable(pip_system_test "main.cpp") target_link_libraries(pip_system_test pip) if (DEFINED LIB) diff --git a/utils/udp_file_transfer/CMakeLists.txt b/utils/udp_file_transfer/CMakeLists.txt index cc3ab463..d2404bb9 100644 --- a/utils/udp_file_transfer/CMakeLists.txt +++ b/utils/udp_file_transfer/CMakeLists.txt @@ -1,4 +1,5 @@ -message(STATUS "Building pift") +list(APPEND PIP_UTILS_LIST "pift") +set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) add_executable(pift "main.cpp") target_link_libraries(pift pip pip_console) if (DEFINED LIB)