Updates from BitShares FC #22
74 changed files with 2535 additions and 3044 deletions
124
.github/workflows/build-and-test.yml
vendored
Normal file
124
.github/workflows/build-and-test.yml
vendored
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
name: Github Autobuild
|
||||
on: [ push, pull_request ]
|
||||
env:
|
||||
CCACHE_COMPRESS: exists means true
|
||||
CCACHE_SLOPPINESS: include_file_ctime,include_file_mtime,time_macros
|
||||
jobs:
|
||||
test-release:
|
||||
name: Build and run tests in Release mode
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install -y \
|
||||
ccache \
|
||||
parallel \
|
||||
libboost-thread-dev \
|
||||
libboost-iostreams-dev \
|
||||
libboost-date-time-dev \
|
||||
libboost-system-dev \
|
||||
libboost-filesystem-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-chrono-dev \
|
||||
libboost-test-dev \
|
||||
libboost-context-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-coroutine-dev
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir -p _build
|
||||
pushd _build
|
||||
export -n BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR
|
||||
cmake -D CMAKE_BUILD_TYPE=Release \
|
||||
-D CMAKE_CXX_OUTPUT_EXTENSION_REPLACE=ON \
|
||||
-D CMAKE_C_COMPILER=gcc \
|
||||
-D CMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-D CMAKE_CXX_COMPILER=g++ \
|
||||
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
..
|
||||
popd
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ccache
|
||||
key: ccache-release-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-release-${{ github.ref }}-
|
||||
ccache-release-
|
||||
ccache-
|
||||
- name: Build
|
||||
run: |
|
||||
export CCACHE_DIR="$GITHUB_WORKSPACE/ccache"
|
||||
mkdir -p "$CCACHE_DIR"
|
||||
make -j 2 -C _build
|
||||
- name: Test
|
||||
run: |
|
||||
parallel echo Running {}\; sh -c "_build/tests/{}" <<_EOT_
|
||||
all_tests -l message
|
||||
bloom_test -- README.md
|
||||
ecc_test README.md
|
||||
hmac_test
|
||||
task_cancel_test
|
||||
_EOT_
|
||||
test-debug:
|
||||
name: Build and run tests in Debug mode
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install -y \
|
||||
ccache \
|
||||
parallel \
|
||||
libboost-thread-dev \
|
||||
libboost-iostreams-dev \
|
||||
libboost-date-time-dev \
|
||||
libboost-system-dev \
|
||||
libboost-filesystem-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-chrono-dev \
|
||||
libboost-test-dev \
|
||||
libboost-context-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-coroutine-dev
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir -p _build
|
||||
pushd _build
|
||||
export -n BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR
|
||||
cmake -D CMAKE_BUILD_TYPE=Debug \
|
||||
-D CMAKE_CXX_OUTPUT_EXTENSION_REPLACE=ON \
|
||||
-D CMAKE_C_COMPILER=gcc \
|
||||
-D CMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-D CMAKE_CXX_COMPILER=g++ \
|
||||
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
..
|
||||
popd
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ccache
|
||||
key: ccache-debug-${{ github.ref }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-debug-${{ github.ref }}-
|
||||
ccache-debug-
|
||||
ccache-
|
||||
- name: Build
|
||||
run: |
|
||||
export CCACHE_DIR="$GITHUB_WORKSPACE/ccache"
|
||||
mkdir -p "$CCACHE_DIR"
|
||||
make -j 2 -C _build
|
||||
- name: Test
|
||||
run: |
|
||||
parallel echo Running {}\; sh -c "_build/tests/{}" <<_EOT_
|
||||
all_tests -l message
|
||||
bloom_test -- README.md
|
||||
ecc_test README.md
|
||||
hmac_test
|
||||
task_cancel_test
|
||||
_EOT_
|
||||
|
|
@ -29,7 +29,7 @@ script:
|
|||
- cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS=--coverage -DCMAKE_CXX_FLAGS=--coverage -DBoost_USE_STATIC_LIBS=OFF -DCMAKE_CXX_OUTPUT_EXTENSION_REPLACE=ON .
|
||||
- 'which build-wrapper-linux-x86-64 && build-wrapper-linux-x86-64 --out-dir bw-output make -j 2 || make -j 2'
|
||||
- set -o pipefail
|
||||
- tests/run-parallel-tests.sh tests/all_tests
|
||||
- tests/run-parallel-tests.sh tests/all_tests -l message
|
||||
- tests/hmac_test 2>&1 | cat
|
||||
- tests/ecc_test README.md 2>&1 | cat
|
||||
- 'find CMakeFiles/fc.dir -type d | while read d; do gcov -o "$d" "${d/CMakeFiles*.dir/./}"/*.cpp; done >/dev/null'
|
||||
|
|
|
|||
161
CMakeLists.txt
161
CMakeLists.txt
|
|
@ -1,17 +1,17 @@
|
|||
#
|
||||
# Defines fc library target.
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED( VERSION 3.2 FATAL_ERROR )
|
||||
PROJECT( fc )
|
||||
CMAKE_MINIMUM_REQUIRED( VERSION 3.1 )
|
||||
|
||||
set( CMAKE_CXX_STANDARD 14 )
|
||||
SET( CMAKE_CXX_STANDARD_REQUIRED ON )
|
||||
|
||||
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" )
|
||||
if( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" )
|
||||
set( CMAKE_CXX_EXTENSIONS ON ) # for __int128 support
|
||||
else( GNU )
|
||||
else( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" )
|
||||
set( CMAKE_CXX_EXTENSIONS OFF )
|
||||
endif( GNU )
|
||||
endif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" )
|
||||
|
||||
MESSAGE(STATUS "Configuring project fc located in: ${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
SET( CMAKE_AUTOMOC OFF )
|
||||
|
|
@ -21,11 +21,8 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/GitVersionGen")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
|
||||
|
||||
INCLUDE(GetPrerequisites)
|
||||
INCLUDE( VersionMacros )
|
||||
INCLUDE( SetupTargetMacros )
|
||||
INCLUDE(GetGitRevisionDescription)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE(CheckLibcxxAtomic)
|
||||
|
||||
get_git_head_revision(GIT_REFSPEC FC_GIT_REVISION_SHA)
|
||||
get_git_unix_timestamp(FC_GIT_REVISION_UNIX_TIMESTAMP)
|
||||
|
|
@ -41,15 +38,13 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|||
set(platformBitness 64)
|
||||
endif()
|
||||
|
||||
SET (ORIGINAL_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
|
||||
SET(BOOST_COMPONENTS)
|
||||
LIST(APPEND BOOST_COMPONENTS thread date_time filesystem system program_options chrono unit_test_framework context iostreams regex)
|
||||
LIST(APPEND BOOST_COMPONENTS coroutine thread date_time filesystem system program_options chrono unit_test_framework context iostreams regex)
|
||||
# boost::endian is also required, but FindBoost can't handle header-only libs
|
||||
SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" )
|
||||
|
||||
# Configure secp256k1-zkp
|
||||
if ( MSVC )
|
||||
if ( WIN32 )
|
||||
# autoconf won't work here, hard code the defines
|
||||
set( SECP256K1_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp" )
|
||||
|
||||
|
|
@ -65,18 +60,9 @@ if ( MSVC )
|
|||
USE_SCALAR_8X32
|
||||
USE_SCALAR_INV_BUILTIN )
|
||||
set_target_properties( secp256k1 PROPERTIES COMPILE_DEFINITIONS "${SECP256K1_BUILD_DEFINES}" LINKER_LANGUAGE C )
|
||||
else ( MSVC )
|
||||
else ( WIN32 )
|
||||
include(ExternalProject)
|
||||
if ( MINGW )
|
||||
ExternalProject_Add( project_secp256k1
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
||||
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp --with-bignum=no --host=x86_64-w64-mingw32
|
||||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND true
|
||||
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp/src/project_secp256k1-build/.libs/libsecp256k1.a
|
||||
)
|
||||
else ( MINGW )
|
||||
|
||||
ExternalProject_Add( project_secp256k1
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
||||
|
|
@ -85,7 +71,7 @@ else ( MSVC )
|
|||
INSTALL_COMMAND true
|
||||
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp/src/project_secp256k1-build/.libs/libsecp256k1.a
|
||||
)
|
||||
endif ( MINGW )
|
||||
|
||||
ExternalProject_Add_Step(project_secp256k1 autogen
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/autogen.sh
|
||||
|
|
@ -99,25 +85,13 @@ else ( MSVC )
|
|||
set_property(TARGET secp256k1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/include)
|
||||
add_dependencies(secp256k1 project_secp256k1)
|
||||
install( FILES ${binary_dir}/.libs/libsecp256k1${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib/cryptonomex )
|
||||
endif ( MSVC )
|
||||
endif ( WIN32 )
|
||||
# End configure secp256k1-zkp
|
||||
|
||||
# Configure editline
|
||||
if ( MSVC )
|
||||
# # autoconf won't work here, hard code the defines
|
||||
# set( EDITLINE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline" )
|
||||
#
|
||||
# file( GLOB EDITLINE_SOURCES "${EDITLINE_DIR}/src/editline.c" )
|
||||
# add_library( editline ${EDITLINE_SOURCES} )
|
||||
#
|
||||
# target_include_directories( editline PRIVATE "${EDITLINE_DIR}" PUBLIC "${EDITLINE_DIR}/include" )
|
||||
#
|
||||
# set_target_properties( editline PROPERTIES COMPILE_DEFINITIONS LINKER_LANGUAGE C )
|
||||
else ( MSVC )
|
||||
if ( NOT WIN32 )
|
||||
include(ExternalProject)
|
||||
if ( MINGW )
|
||||
# Editline is not avalible in MINGW
|
||||
else ( MINGW )
|
||||
|
||||
ExternalProject_Add( project_editline
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
|
||||
|
|
@ -125,7 +99,8 @@ else ( MSVC )
|
|||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND true
|
||||
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/src/.libs/libeditline.a
|
||||
)
|
||||
)
|
||||
|
||||
ExternalProject_Add_Step(project_editline autogen
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/autogen.sh
|
||||
|
|
@ -137,8 +112,7 @@ else ( MSVC )
|
|||
set_property(TARGET editline PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/include)
|
||||
add_dependencies(editline project_editline)
|
||||
install( FILES ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib/cryptonomex )
|
||||
endif ( MINGW )
|
||||
endif ( MSVC )
|
||||
endif ( NOT WIN32 )
|
||||
# End configure editline
|
||||
|
||||
IF( WIN32 )
|
||||
|
|
@ -147,42 +121,31 @@ IF( WIN32 )
|
|||
set( RPCRT4 rpcrt4 )
|
||||
|
||||
#boost
|
||||
SET(BOOST_ROOT $ENV{BOOST_ROOT})
|
||||
# set(Boost_USE_DEBUG_PYTHON ON)
|
||||
if ($ENV{BOOST_ROOT})
|
||||
SET(BOOST_ROOT $ENV{BOOST_ROOT})
|
||||
endif()
|
||||
|
||||
set(Boost_USE_DEBUG_PYTHON ON)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(BOOST_ALL_DYN_LINK OFF) # force dynamic linking for all libraries
|
||||
|
||||
FIND_PACKAGE(Boost 1.53 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
# For Boost 1.53 on windows, coroutine was not in BOOST_LIBRARYDIR and do not need it to build, but if boost versin >= 1.54, find coroutine otherwise will cause link errors
|
||||
IF(NOT "${Boost_VERSION}" MATCHES "1.53(.*)")
|
||||
SET(BOOST_LIBRARIES_TEMP ${Boost_LIBRARIES})
|
||||
FIND_PACKAGE(Boost 1.54 REQUIRED COMPONENTS coroutine)
|
||||
LIST(APPEND BOOST_COMPONENTS coroutine)
|
||||
SET(Boost_LIBRARIES ${BOOST_LIBRARIES_TEMP} ${Boost_LIBRARIES})
|
||||
ENDIF()
|
||||
LIST(APPEND PLATFORM_SPECIFIC_LIBS ws2_32 crypt32 mswsock userenv)
|
||||
|
||||
LIST(APPEND PLATFORM_SPECIFIC_LIBS wsock32.lib ws2_32.lib userenv.lib)
|
||||
# iphlpapi.lib
|
||||
|
||||
ELSE(WIN32)
|
||||
MESSAGE(STATUS "Configuring fc to build on Unix/Apple")
|
||||
|
||||
LIST(APPEND BOOST_COMPONENTS coroutine)
|
||||
|
||||
FIND_PACKAGE(Boost 1.53 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
|
||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so")
|
||||
|
||||
IF(NOT APPLE)
|
||||
# Linux or other unix
|
||||
SET(rt_library rt )
|
||||
SET(pthread_library pthread)
|
||||
ENDIF(NOT APPLE)
|
||||
ENDIF(WIN32)
|
||||
|
||||
set(Boost_DIR "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/Boost")
|
||||
FIND_PACKAGE(Boost CONFIG COMPONENTS ${BOOST_COMPONENTS} )
|
||||
|
||||
IF(NOT WIN32)
|
||||
MESSAGE(STATUS "Configuring fc to build on Unix/Apple")
|
||||
|
||||
IF(NOT "$ENV{OPENSSL_ROOT_DIR}" STREQUAL "")
|
||||
IF(NOT APPLE AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD")
|
||||
SET(rt_library rt )
|
||||
ENDIF(NOT APPLE AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD")
|
||||
ENDIF(NOT WIN32)
|
||||
|
||||
IF($ENV{OPENSSL_ROOT_DIR})
|
||||
set(OPENSSL_ROOT_DIR $ENV{OPENSSL_ROOT_DIR} )
|
||||
set(OPENSSL_INCLUDE_DIR ${OPENSSL_ROOT_DIR}/include)
|
||||
message(STATUS "Setting up OpenSSL root and include vars to ${OPENSSL_ROOT_DIR}, ${OPENSSL_INCLUDE_DIR}")
|
||||
|
|
@ -194,10 +157,6 @@ ENDIF( LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB )
|
|||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${ORIGINAL_LIB_SUFFIXES} )
|
||||
|
||||
option( UNITY_BUILD OFF )
|
||||
|
||||
set( fc_sources
|
||||
src/popcount.cpp
|
||||
src/variant.cpp
|
||||
|
|
@ -249,6 +208,7 @@ set( fc_sources
|
|||
src/crypto/hex.cpp
|
||||
src/crypto/sha1.cpp
|
||||
src/crypto/ripemd160.cpp
|
||||
src/crypto/hash160.cpp
|
||||
src/crypto/sha256.cpp
|
||||
src/crypto/sha224.cpp
|
||||
src/crypto/sha512.cpp
|
||||
|
|
@ -280,16 +240,15 @@ list(APPEND sources ${fc_headers})
|
|||
|
||||
add_subdirectory( vendor/websocketpp EXCLUDE_FROM_ALL )
|
||||
|
||||
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC )
|
||||
add_library( fc ${sources} )
|
||||
install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include )
|
||||
|
||||
# begin editline stuff
|
||||
if(NOT (MSVC OR MINGW))
|
||||
target_compile_definitions (fc PRIVATE HAVE_EDITLINE)
|
||||
set(editline_libraries editline)
|
||||
endif(NOT (MSVC OR MINGW))
|
||||
if(WIN32)
|
||||
target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE )
|
||||
else(WIN32)
|
||||
target_compile_definitions( fc PRIVATE HAVE_EDITLINE )
|
||||
set( editline_libraries editline )
|
||||
endif(WIN32)
|
||||
# end editline stuff
|
||||
|
||||
|
|
@ -341,6 +300,7 @@ ENDIF(APPLE)
|
|||
|
||||
if( ZLIB_FOUND )
|
||||
MESSAGE( STATUS "zlib found" )
|
||||
target_include_directories(fc PUBLIC ${ZLIB_INCLUDE_DIRS})
|
||||
add_definitions( -DHAS_ZLIB )
|
||||
else()
|
||||
MESSAGE( STATUS "zlib not found" )
|
||||
|
|
@ -384,12 +344,14 @@ target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${OPENSSL_LIBRARIES} ${Z
|
|||
${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library}
|
||||
${editline_libraries} secp256k1 ${CMAKE_REQUIRED_LIBRARIES} )
|
||||
|
||||
if(MSVC)
|
||||
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
endif(MSVC)
|
||||
if(WIN32 AND MSVC)
|
||||
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
elseif(WIN32 AND MINGW)
|
||||
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES LINK_FLAGS "-mbig-obj" )
|
||||
endif()
|
||||
|
||||
|
||||
IF(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY MATCHES "\\.(a|lib)$")
|
||||
IF(Boost_UNIT_TEST_FRAMEWORK_LIBRARY MATCHES "\\.(so|dll)$")
|
||||
IF(MSVC)
|
||||
add_definitions(/DBOOST_TEST_DYN_LINK)
|
||||
ELSE(MSVC)
|
||||
|
|
@ -401,18 +363,10 @@ include_directories( vendor/websocketpp )
|
|||
|
||||
add_subdirectory(tests)
|
||||
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
# add addtional import library on windows platform
|
||||
target_link_libraries( fc PUBLIC crypt32.lib)
|
||||
|
||||
# now generate a list of the DLLs we're using to use during the install process
|
||||
include (ParseLibraryList)
|
||||
PARSE_LIBRARY_LIST(${Boost_LIBRARIES}
|
||||
FOUND parseOk
|
||||
DEBUG Boost_LIBRARIES_DEBUG
|
||||
OPT Boost_LIBRARIES_RELEASE
|
||||
GENERAL Boost_LIBRARIES_GENERAL)
|
||||
|
||||
#Variable will hold list of .pdb files generated for libraries the 'fc' module is linked to
|
||||
set(INTERFACE_LINK_PDB_RELEASE)
|
||||
|
||||
|
|
@ -481,31 +435,8 @@ if(WIN32)
|
|||
set_property(TARGET fc PROPERTY SHARED_LIBRARIES_DEBUG ${SHARED_LIBRARIES_DEBUG})
|
||||
set_property(TARGET fc PROPERTY SHARED_LIBRARIES_RELEASE ${SHARED_LIBRARIES_RELEASE})
|
||||
|
||||
endif(WIN32)
|
||||
endif(MSVC)
|
||||
|
||||
SET(OPENSSL_CONF_TARGET )
|
||||
IF(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
||||
SET (OPENSSL_CONF_TARGET ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
ELSE()
|
||||
SET (OPENSSL_CONF_TARGET ${CMAKE_CURRENT_BINARY_DIR})
|
||||
ENDIF()
|
||||
|
||||
IF(WIN32)
|
||||
IF("${OPENSSL_ROOT_DIR}" STREQUAL "")
|
||||
get_filename_component(OPENSSL_ROOT_DIR "${OPENSSL_INCLUDE_DIR}/.." REALPATH)
|
||||
ENDIF()
|
||||
IF("${OPENSSL_CONF_SOURCE}" STREQUAL "")
|
||||
SET(OPENSSL_CONF_SOURCE "${OPENSSL_ROOT_DIR}/ssl/openssl.cnf")
|
||||
IF(MINGW)
|
||||
SET(OPENSSL_CONF_SOURCE "${OPENSSL_ROOT_DIR}/openssl.cnf")
|
||||
ENDIF(MINGW)
|
||||
ENDIF()
|
||||
SET(POST_BUILD_STEP_COMMANDS ${POST_BUILD_STEP_COMMANDS}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OPENSSL_CONF_SOURCE}" "${OPENSSL_CONF_TARGET}/openssl.cnf")
|
||||
ENDIF(WIN32)
|
||||
|
||||
ADD_CUSTOM_COMMAND(TARGET fc POST_BUILD ${POST_BUILD_STEP_COMMANDS}
|
||||
COMMENT "Copying OpenSSL/ssl/openssl.cnf into target directory."
|
||||
)
|
||||
INCLUDE(CheckLibcxxAtomic)
|
||||
|
||||
MESSAGE(STATUS "Finished fc module configuration...")
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
# This module defines the ARGUMENT_PARSER macro for parsing macro arguments.
|
||||
|
||||
# ARGUMENT_PARSER Macro
|
||||
# This macro parses a mixed list of arguments and headers into lists and boolean
|
||||
# variables. The output lists and boolean variables are stored using
|
||||
# tolower( header ) variable names. All non-header arguments will be added to
|
||||
# the output list that corresponds to the header that they follow (or to the
|
||||
# default list if no header has been parsed yet). If a boolean header is passed,
|
||||
# then its corresponding output variable is set to YES.
|
||||
#
|
||||
# Usage:
|
||||
# ARGUMENT_PARSER( default_list lists bools ARGN )
|
||||
#
|
||||
# Parameters:
|
||||
# default_list The name of the variable that list values should be added
|
||||
# to before any list headers have been reached. You may
|
||||
# pass "" to disregard premature list values.
|
||||
# lists The list headers (semicolon-separated string).
|
||||
# bools The boolean headers (semicolon-separated string).
|
||||
# ARGN The arguments to parse.
|
||||
MACRO( ARGUMENT_PARSER default_list lists bools )
|
||||
|
||||
# Start using the default list.
|
||||
SET( dest "${default_list}" )
|
||||
IF( NOT dest )
|
||||
SET( dest tmp )
|
||||
ENDIF( NOT dest )
|
||||
|
||||
# Clear all of the lists.
|
||||
FOREACH( list_itr ${lists} )
|
||||
STRING( TOLOWER ${list_itr} lower )
|
||||
SET( ${lower} "" )
|
||||
ENDFOREACH( list_itr )
|
||||
|
||||
# Set all boolean variables to NO.
|
||||
FOREACH( bool_itr ${bools} )
|
||||
STRING( TOLOWER ${bool_itr} lower )
|
||||
SET( ${lower} NO )
|
||||
ENDFOREACH( bool_itr )
|
||||
|
||||
# For all arguments.
|
||||
FOREACH( arg_itr ${ARGN} )
|
||||
|
||||
SET( done NO )
|
||||
|
||||
# For each of the list headers, if the current argument matches a list
|
||||
# header, then set the destination to the header.
|
||||
FOREACH( list_itr ${lists} )
|
||||
IF( ${arg_itr} STREQUAL ${list_itr} )
|
||||
STRING( TOLOWER ${arg_itr} lower )
|
||||
SET( dest ${lower} )
|
||||
SET( done YES )
|
||||
ENDIF( ${arg_itr} STREQUAL ${list_itr} )
|
||||
ENDFOREACH( list_itr )
|
||||
|
||||
# For each of the boolean headers, if the current argument matches a
|
||||
# boolean header, then set the boolean variable to true.
|
||||
FOREACH( bool_itr ${bools} )
|
||||
IF( ${arg_itr} STREQUAL ${bool_itr} )
|
||||
STRING( TOLOWER ${arg_itr} lower )
|
||||
SET( ${lower} YES )
|
||||
SET( done YES )
|
||||
ENDIF( ${arg_itr} STREQUAL ${bool_itr} )
|
||||
ENDFOREACH( bool_itr )
|
||||
|
||||
# If the current argument is not a header, then add it to the current
|
||||
# destination list.
|
||||
IF( NOT done )
|
||||
SET( ${dest} ${${dest}} ${arg_itr} )
|
||||
ENDIF( NOT done )
|
||||
|
||||
ENDFOREACH( arg_itr )
|
||||
|
||||
ENDMACRO( ARGUMENT_PARSER )
|
||||
18
CMakeModules/Boost/BoostConfig.cmake
Normal file
18
CMakeModules/Boost/BoostConfig.cmake
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# This overrides `find_package(Boost ... CONFIG ... )` calls
|
||||
# - calls the CMake's built-in `FindBoost.cmake` and adds `pthread` library dependency
|
||||
|
||||
MESSAGE(STATUS "Using custom FindBoost config")
|
||||
|
||||
find_package(Boost 1.58 REQUIRED COMPONENTS ${Boost_FIND_COMPONENTS})
|
||||
|
||||
# Inject `pthread` dependency to Boost if needed
|
||||
if (UNIX AND NOT CYGWIN)
|
||||
list(FIND Boost_FIND_COMPONENTS thread _using_boost_thread)
|
||||
if (_using_boost_thread GREATER -1)
|
||||
find_library(BOOST_THREAD_LIBRARY NAMES pthread DOC "The threading library used by boost-thread")
|
||||
if (BOOST_THREAD_LIBRARY)
|
||||
MESSAGE(STATUS "Adding Boost thread lib dependency: ${BOOST_THREAD_LIBRARY}")
|
||||
list(APPEND Boost_LIBRARIES ${BOOST_THREAD_LIBRARY})
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
|
@ -18,11 +18,15 @@ function(check_cxx_atomics varname)
|
|||
if (CMAKE_C_FLAGS MATCHES -fsanitize-coverage OR CMAKE_CXX_FLAGS MATCHES -fsanitize-coverage)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters")
|
||||
endif()
|
||||
|
||||
set(OLD_CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES})
|
||||
set(CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIRS})
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <cstdint>
|
||||
#include <boost/lockfree/queue.hpp>
|
||||
|
||||
boost::lockfree::queue<uint32_t*> q;
|
||||
boost::lockfree::queue<uint32_t*,boost::lockfree::capacity<5>> q;
|
||||
int main(int, char**) {
|
||||
uint32_t* a;
|
||||
uint32_t* b;
|
||||
|
|
@ -31,6 +35,7 @@ int main(int, char**) {
|
|||
}
|
||||
" ${varname})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OLD_CMAKE_REQUIRED_INCLUDES})
|
||||
endfunction(check_cxx_atomics)
|
||||
|
||||
# Perform the check for 64bit atomics without libatomic.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,123 +0,0 @@
|
|||
# Module for locating Visual Leak Detector.
|
||||
#
|
||||
# Customizable variables:
|
||||
# VLD_ROOT_DIR
|
||||
# This variable points to the Visual Leak Detector root directory. By
|
||||
# default, the module looks for the installation directory by examining the
|
||||
# Program Files/Program Files (x86) folders and the VLDROOT environment
|
||||
# variable.
|
||||
#
|
||||
# Read-only variables:
|
||||
# VLD_FOUND
|
||||
# Indicates that the library has been found.
|
||||
#
|
||||
# VLD_INCLUDE_DIRS
|
||||
# Points to the Visual Leak Detector include directory.
|
||||
#
|
||||
# VLD_LIBRARY_DIRS
|
||||
# Points to the Visual Leak Detector directory that contains the libraries.
|
||||
# The content of this variable can be passed to link_directories.
|
||||
#
|
||||
# VLD_LIBRARIES
|
||||
# Points to the Visual Leak Detector libraries that can be passed to
|
||||
# target_link_libararies.
|
||||
#
|
||||
#
|
||||
# Copyright (c) 2012 Sergiu Dotenco
|
||||
#
|
||||
# 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.
|
||||
|
||||
INCLUDE (FindPackageHandleStandardArgs)
|
||||
|
||||
SET (_VLD_POSSIBLE_LIB_SUFFIXES lib)
|
||||
|
||||
# Version 2.0 uses vld_x86 and vld_x64 instead of simply vld as library names
|
||||
IF (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
LIST (APPEND _VLD_POSSIBLE_LIB_SUFFIXES lib/Win32)
|
||||
ELSEIF (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
LIST (APPEND _VLD_POSSIBLE_LIB_SUFFIXES lib/Win64)
|
||||
ENDIF (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
|
||||
FIND_PATH (VLD_ROOT_DIR
|
||||
NAMES include/vld.h
|
||||
PATHS ENV VLDROOT
|
||||
"$ENV{PROGRAMFILES}/Visual Leak Detector"
|
||||
"$ENV{PROGRAMFILES(X86)}/Visual Leak Detector"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Visual Leak Detector;InstallLocation]"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Visual Leak Detector;InstallLocation]"
|
||||
DOC "VLD root directory")
|
||||
|
||||
FIND_PATH (VLD_INCLUDE_DIR
|
||||
NAMES vld.h
|
||||
HINTS ${VLD_ROOT_DIR}
|
||||
PATH_SUFFIXES include
|
||||
DOC "VLD include directory")
|
||||
|
||||
FIND_LIBRARY (VLD_LIBRARY_DEBUG
|
||||
NAMES vld
|
||||
HINTS ${VLD_ROOT_DIR}
|
||||
PATH_SUFFIXES ${_VLD_POSSIBLE_LIB_SUFFIXES}
|
||||
DOC "VLD debug library")
|
||||
|
||||
IF (VLD_ROOT_DIR)
|
||||
SET (_VLD_VERSION_FILE ${VLD_ROOT_DIR}/CHANGES.txt)
|
||||
|
||||
IF (EXISTS ${_VLD_VERSION_FILE})
|
||||
SET (_VLD_VERSION_REGEX
|
||||
"Visual Leak Detector \\(VLD\\) Version (([0-9]+)\\.([0-9]+)([a-z]|(.([0-9]+)))?)")
|
||||
FILE (STRINGS ${_VLD_VERSION_FILE} _VLD_VERSION_TMP REGEX
|
||||
${_VLD_VERSION_REGEX})
|
||||
|
||||
STRING (REGEX REPLACE ${_VLD_VERSION_REGEX} "\\1" _VLD_VERSION_TMP
|
||||
"${_VLD_VERSION_TMP}")
|
||||
|
||||
STRING (REGEX REPLACE "([0-9]+).([0-9]+).*" "\\1" VLD_VERSION_MAJOR
|
||||
"${_VLD_VERSION_TMP}")
|
||||
STRING (REGEX REPLACE "([0-9]+).([0-9]+).*" "\\2" VLD_VERSION_MINOR
|
||||
"${_VLD_VERSION_TMP}")
|
||||
|
||||
SET (VLD_VERSION ${VLD_VERSION_MAJOR}.${VLD_VERSION_MINOR})
|
||||
|
||||
IF ("${_VLD_VERSION_TMP}" MATCHES "^([0-9]+).([0-9]+).([0-9]+)$")
|
||||
# major.minor.patch version numbering scheme
|
||||
STRING (REGEX REPLACE "([0-9]+).([0-9]+).([0-9]+)" "\\3"
|
||||
VLD_VERSION_PATCH "${_VLD_VERSION_TMP}")
|
||||
SET (VLD_VERSION "${VLD_VERSION}.${VLD_VERSION_PATCH}")
|
||||
SET (VLD_VERSION_COUNT 3)
|
||||
ELSE ("${_VLD_VERSION_TMP}" MATCHES "^([0-9]+).([0-9]+).([0-9]+)$")
|
||||
# major.minor version numbering scheme. The trailing letter is ignored.
|
||||
SET (VLD_VERSION_COUNT 2)
|
||||
ENDIF ("${_VLD_VERSION_TMP}" MATCHES "^([0-9]+).([0-9]+).([0-9]+)$")
|
||||
ENDIF (EXISTS ${_VLD_VERSION_FILE})
|
||||
ENDIF (VLD_ROOT_DIR)
|
||||
|
||||
IF (VLD_LIBRARY_DEBUG)
|
||||
SET (VLD_LIBRARY debug ${VLD_LIBRARY_DEBUG} CACHE DOC "VLD library")
|
||||
GET_FILENAME_COMPONENT (_VLD_LIBRARY_DIR ${VLD_LIBRARY_DEBUG} PATH)
|
||||
SET (VLD_LIBRARY_DIR ${_VLD_LIBRARY_DIR} CACHE PATH "VLD library directory")
|
||||
ENDIF (VLD_LIBRARY_DEBUG)
|
||||
|
||||
SET (VLD_INCLUDE_DIRS ${VLD_INCLUDE_DIR})
|
||||
SET (VLD_LIBRARY_DIRS ${VLD_LIBRARY_DIR})
|
||||
SET (VLD_LIBRARIES ${VLD_LIBRARY})
|
||||
|
||||
MARK_AS_ADVANCED (VLD_INCLUDE_DIR VLD_LIBRARY_DIR VLD_LIBRARY_DEBUG VLD_LIBRARY)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS (VLD REQUIRED_VARS VLD_ROOT_DIR
|
||||
VLD_INCLUDE_DIR VLD_LIBRARY VERSION_VAR VLD_VERSION)
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
# -*- mode: cmake -*-
|
||||
|
||||
#
|
||||
# Shamelessly stolen from MSTK who shamelessly stole from Amanzi open source code https://software.lanl.gov/ascem/trac)
|
||||
#
|
||||
# PARSE_LIBRARY_LIST( <lib_list>
|
||||
# DEBUG <out_debug_list>
|
||||
# OPT <out_opt_list>
|
||||
# GENERAL <out_gen_list> )
|
||||
|
||||
# CMake module
|
||||
include(CMakeParseArguments)
|
||||
|
||||
function(PARSE_LIBRARY_LIST)
|
||||
|
||||
# Macro: _print_usage
|
||||
macro(_print_usage)
|
||||
message("PARSE_LIBRARY_LIST <lib_list>\n"
|
||||
" FOUND <out_flag>\n"
|
||||
" DEBUG <out_debug_list>\n"
|
||||
" OPT <out_opt_list>\n"
|
||||
" GENERAL <out_gen_list>\n"
|
||||
"lib_list string to parse\n"
|
||||
"FOUND flag to indicate if keywords were found\n"
|
||||
"DEBUG variable containing debug libraries\n"
|
||||
"OPT variable containing optimized libraries\n"
|
||||
"GENERAL variable containing debug libraries\n")
|
||||
|
||||
endmacro()
|
||||
|
||||
# Read in args
|
||||
cmake_parse_arguments(PARSE_ARGS "" "FOUND;DEBUG;OPT;GENERAL" "" ${ARGN})
|
||||
set(_parse_list "${PARSE_ARGS_UNPARSED_ARGUMENTS}")
|
||||
if ( (NOT PARSE_ARGS_FOUND) OR
|
||||
(NOT PARSE_ARGS_DEBUG) OR
|
||||
(NOT PARSE_ARGS_OPT) OR
|
||||
(NOT PARSE_ARGS_GENERAL) OR
|
||||
(NOT _parse_list )
|
||||
)
|
||||
_print_usage()
|
||||
message(FATAL_ERROR "Invalid arguments")
|
||||
endif()
|
||||
|
||||
# Now split the list
|
||||
set(_debug_libs "")
|
||||
set(_opt_libs "")
|
||||
set(_gen_libs "")
|
||||
foreach( item ${_parse_list} )
|
||||
if( ${item} MATCHES debug OR
|
||||
${item} MATCHES optimized OR
|
||||
${item} MATCHES general )
|
||||
|
||||
if( ${item} STREQUAL "debug" )
|
||||
set( mylist "_debug_libs" )
|
||||
elseif( ${item} STREQUAL "optimized" )
|
||||
set( mylist "_opt_libs" )
|
||||
elseif( ${item} STREQUAL "general" )
|
||||
set( mylist "_gen_libs" )
|
||||
endif()
|
||||
else()
|
||||
list( APPEND ${mylist} ${item} )
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
|
||||
# Now set output vairables
|
||||
set(${PARSE_ARGS_DEBUG} "${_debug_libs}" PARENT_SCOPE)
|
||||
set(${PARSE_ARGS_OPT} "${_opt_libs}" PARENT_SCOPE)
|
||||
set(${PARSE_ARGS_GENERAL} "${_gen_libs}" PARENT_SCOPE)
|
||||
|
||||
# If any of the lib lists are defined set flag to TRUE
|
||||
if ( (_debug_libs) OR (_opt_libs) OR (_gen_libs) )
|
||||
set(${PARSE_ARGS_FOUND} TRUE PARENT_SCOPE)
|
||||
else()
|
||||
set(${PARSE_ARGS_FOUND} FALSE PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
endfunction(PARSE_LIBRARY_LIST)
|
||||
|
||||
|
|
@ -1,369 +0,0 @@
|
|||
# This module defines several macros that are useful for setting up library,
|
||||
# plugin, and executable targets.
|
||||
|
||||
|
||||
INCLUDE( ArgumentParser )
|
||||
|
||||
function(enable_unity_build UB_SUFFIX SOURCE_VARIABLE_NAME)
|
||||
set(files ${${SOURCE_VARIABLE_NAME}})
|
||||
# Generate a unique filename for the unity build translation unit
|
||||
set(unit_build_file ${CMAKE_CURRENT_BINARY_DIR}/ub_${UB_SUFFIX}.cpp)
|
||||
# Exclude all translation units from compilation
|
||||
set_source_files_properties(${files} PROPERTIES HEADER_FILE_ONLY true)
|
||||
# Open the ub file
|
||||
FILE(WRITE ${unit_build_file} "// Unity Build generated by CMake\n")
|
||||
# Add include statement for each translation unit
|
||||
foreach(source_file ${files} )
|
||||
FILE( APPEND ${unit_build_file} "#include <${CMAKE_CURRENT_SOURCE_DIR}/${source_file}>\n")
|
||||
endforeach(source_file)
|
||||
# Complement list of translation units with the name of ub
|
||||
set(${SOURCE_VARIABLE_NAME} ${${SOURCE_VARIABLE_NAME}} ${unit_build_file} PARENT_SCOPE)
|
||||
endfunction(enable_unity_build)
|
||||
|
||||
# SETUP_LIBRARY Macro
|
||||
# Sets up to build a library target. The macro uses the following global
|
||||
# variables to define default values (you may change these variables to change
|
||||
# the defaults:
|
||||
# DEFAULT_HEADER_INSTALL_DIR
|
||||
# DEFAULT_LIBRARY_INSTALL_DIR
|
||||
#
|
||||
# Usage:
|
||||
# SETUP_LIBRARY( target
|
||||
# SOURCES source1 [source2...]
|
||||
# MOC_HEADERS header1 [header2...]
|
||||
# LIBRARIES library1 [library2...]
|
||||
# INSTALL_HEADERS header1 [header2...]
|
||||
# HEADER_INSTALL_DIR dir
|
||||
# LIBRARY_INSTALL_DIR dir
|
||||
# DEBUG_POSTFIX string
|
||||
# LIBRARY_TYPE string
|
||||
# AUTO_INSTALL_HEADERS
|
||||
# DONT_INSTALL_LIBRARY )
|
||||
#
|
||||
# Parameters:
|
||||
# target The target library.
|
||||
# SOURCES Follow with the sources to compile.
|
||||
# MOC_HEADERS Follow with the headers to moc (Requires Qt).
|
||||
# LIBRARIES Follow with the libraries to link.
|
||||
# INSTALL_HEADERS Follow with the headers to install.
|
||||
# HEADER_INSTALL_DIR Follow with the directory to install the headers
|
||||
# in (${DEFAULT_HEADER_INSTALL_DIR} by default).
|
||||
# LIBRARY_INSTALL_DIR Follow with the directory to install the library
|
||||
# in (${DEFAULT_LIBRARY_INSTALL_DIR} by default).
|
||||
# DEBUG_POSTFIX Follow with the postfix to use when building in
|
||||
# debug mode (${CMAKE_DEBUG_POSTFIX} by default).
|
||||
# LIBRARY_TYPE Follow with the type of library to build: SHARED,
|
||||
# STATIC, or MODULE (if not passed, then the
|
||||
# behavior is defined by BUILD_SHARED_LIBS).
|
||||
# AUTO_INSTALL_HEADERS If passed, all *.h files in the current directory
|
||||
# will be installed.
|
||||
# DONT_INSTALL_LIBRARY If passed, the library will not be installed.
|
||||
MACRO( SETUP_LIBRARY target )
|
||||
|
||||
# Setup the list headers.
|
||||
SET( list_headers
|
||||
SOURCES
|
||||
MOC_HEADERS
|
||||
LIBRARIES
|
||||
INSTALL_HEADERS
|
||||
HEADER_INSTALL_DIR
|
||||
LIBRARY_INSTALL_DIR
|
||||
DEBUG_POSTFIX
|
||||
LIBRARY_TYPE
|
||||
)
|
||||
|
||||
# Setup the boolean headers.
|
||||
SET( bool_headers
|
||||
AUTO_INSTALL_HEADERS
|
||||
DONT_INSTALL_LIBRARY
|
||||
)
|
||||
|
||||
# Parse the arguments into variables.
|
||||
ARGUMENT_PARSER( "" "${list_headers}" "${bool_headers}" ${ARGN} )
|
||||
|
||||
# Set the default values for the header_install_dir, library_install_dir,
|
||||
# and debug_postfix.
|
||||
IF( NOT "${ARGN}" MATCHES "(^|;)HEADER_INSTALL_DIR($|;)" )
|
||||
SET( header_install_dir ${DEFAULT_HEADER_INSTALL_DIR} )
|
||||
ENDIF( NOT "${ARGN}" MATCHES "(^|;)HEADER_INSTALL_DIR($|;)" )
|
||||
|
||||
IF( NOT "${ARGN}" MATCHES "(^|;)LIBRARY_INSTALL_DIR($|;)" )
|
||||
SET( library_install_dir ${DEFAULT_LIBRARY_INSTALL_DIR} )
|
||||
ENDIF( NOT "${ARGN}" MATCHES "(^|;)LIBRARY_INSTALL_DIR($|;)" )
|
||||
|
||||
IF( NOT "${ARGN}" MATCHES "(^|;)DEBUG_POSTFIX($|;)" )
|
||||
SET( debug_postfix ${CMAKE_DEBUG_POSTFIX} )
|
||||
ENDIF( NOT "${ARGN}" MATCHES "(^|;)DEBUG_POSTFIX($|;)" )
|
||||
|
||||
# Configure the header_install_dir and library_install_dir so that ${target}
|
||||
# may be used in them. Setting target to itself is REQUIRED for the
|
||||
# configuration to work.
|
||||
SET( target "${target}" )
|
||||
STRING( CONFIGURE "${header_install_dir}" header_install_dir )
|
||||
STRING( CONFIGURE "${library_install_dir}" library_install_dir )
|
||||
|
||||
# Setup the library_type.
|
||||
IF( NOT library_type )
|
||||
SET( library_type STATIC )
|
||||
IF( BUILD_SHARED_LIBS )
|
||||
SET( library_type SHARED )
|
||||
ENDIF( BUILD_SHARED_LIBS )
|
||||
ENDIF( NOT library_type )
|
||||
|
||||
# Clear the moc_sources.
|
||||
SET( moc_sources "" )
|
||||
|
||||
# If Qt is being used...
|
||||
IF( QT_FOUND AND QT_LIBRARIES )
|
||||
# Setup QT to build a shared library.
|
||||
IF( library_type MATCHES SHARED )
|
||||
ADD_DEFINITIONS( -DQT_SHARED )
|
||||
ENDIF( library_type MATCHES SHARED )
|
||||
|
||||
# Setup the moc sources.
|
||||
IF( moc_headers )
|
||||
QT4_WRAP_CPP( moc_sources ${moc_headers} )
|
||||
ENDIF( moc_headers )
|
||||
ENDIF( QT_FOUND AND QT_LIBRARIES )
|
||||
|
||||
# Fatal error if moc_headers given but moc_sources not created.
|
||||
IF( moc_headers AND NOT moc_sources )
|
||||
MESSAGE( FATAL_ERROR "Calling SETUP_LIBRARY() with MOC_HEADERS failed. "
|
||||
"Make sure that you included \${QT_USE_FILE} prior to calling "
|
||||
"SETUP_LIBRARY()." )
|
||||
ENDIF( moc_headers AND NOT moc_sources )
|
||||
|
||||
|
||||
IF( UNITY_BUILD )
|
||||
enable_unity_build( ${target} sources )
|
||||
ENDIF( UNITY_BUILD )
|
||||
|
||||
# Add the library.
|
||||
ADD_LIBRARY( "${target}" ${library_type} ${sources} ${moc_sources} )
|
||||
|
||||
# Setup the debug_postfix.
|
||||
SET_TARGET_PROPERTIES ( "${target}" PROPERTIES
|
||||
DEBUG_POSTFIX "${debug_postfix}" )
|
||||
|
||||
# Link in the dependency libraries.
|
||||
TARGET_LINK_LIBRARIES( "${target}" ${libraries} )
|
||||
|
||||
# If auto_install_headers, then set the headers to all .h files in the
|
||||
# directory.
|
||||
IF( auto_install_headers )
|
||||
FILE( GLOB install_headers *.h )
|
||||
ENDIF( auto_install_headers )
|
||||
|
||||
# Install the headers.
|
||||
IF( install_headers )
|
||||
INSTALL( FILES ${install_headers} DESTINATION "${header_install_dir}" )
|
||||
ENDIF( install_headers )
|
||||
|
||||
# Install the library.
|
||||
IF( NOT dont_install_library )
|
||||
INSTALL( TARGETS "${target}"
|
||||
LIBRARY DESTINATION "${library_install_dir}"
|
||||
ARCHIVE DESTINATION "${library_install_dir}" )
|
||||
ENDIF( NOT dont_install_library )
|
||||
|
||||
ENDMACRO( SETUP_LIBRARY )
|
||||
|
||||
|
||||
# SETUP_MODULE Macro
|
||||
# Sets up to build a module (also setup as a Qt plugin if using Qt). A module is
|
||||
# built as a shared library; however, modules are typically loaded dynamically
|
||||
# rather than linked against. Therefore, this macro does not install header
|
||||
# files and uses its own default install directory. The macro uses the following
|
||||
# global variables to define default values (you may change these variables to
|
||||
# change the defaults:
|
||||
# DEFAULT_MODULE_INSTALL_DIR
|
||||
#
|
||||
# Usage:
|
||||
# SETUP_MODULE( target
|
||||
# SOURCES source1 [source2...]
|
||||
# MOC_HEADERS header1 [header2...]
|
||||
# LIBRARIES library1 [library2...]
|
||||
# MODULE_INSTALL_DIR dir
|
||||
# DEBUG_POSTFIX string
|
||||
# DONT_INSTALL_MODULE )
|
||||
#
|
||||
# Parameters:
|
||||
# target The target module (built as a shared library).
|
||||
# SOURCES Follow with the sources to compile.
|
||||
# MOC_HEADERS Follow with the headers to moc (Requires Qt).
|
||||
# LIBRARIES Follow with the libraries to link.
|
||||
# MODULE_INSTALL_DIR Follow with the directory to install the module in
|
||||
# (${DEFAULT_MODULE_INSTALL_DIR} by default).
|
||||
# DEBUG_POSTFIX Follow with the postfix to use when building in
|
||||
# debug mode (${CMAKE_DEBUG_POSTFIX} by default).
|
||||
# DONT_INSTALL_MODULE If passed, the module will not be installed.
|
||||
MACRO( SETUP_MODULE target )
|
||||
|
||||
# Setup the list headers.
|
||||
SET( list_headers
|
||||
SOURCES
|
||||
MOC_HEADERS
|
||||
LIBRARIES
|
||||
MODULE_INSTALL_DIR
|
||||
DEBUG_POSTFIX
|
||||
)
|
||||
|
||||
# Setup the boolean headers.
|
||||
SET( bool_headers
|
||||
DONT_INSTALL_MODULE
|
||||
)
|
||||
|
||||
# Parse the arguments into variables.
|
||||
ARGUMENT_PARSER( "" "${list_headers}" "${bool_headers}" ${ARGN} )
|
||||
|
||||
# Set the default values for the module_install_dir and debug postfix.
|
||||
IF( NOT "${ARGN}" MATCHES "(^|;)MODULE_INSTALL_DIR($|;)" )
|
||||
SET( module_install_dir ${DEFAULT_MODULE_INSTALL_DIR} )
|
||||
ENDIF( NOT "${ARGN}" MATCHES "(^|;)MODULE_INSTALL_DIR($|;)" )
|
||||
|
||||
IF( NOT "${ARGN}" MATCHES "(^|;)DEBUG_POSTFIX($|;)" )
|
||||
SET( debug_postfix ${CMAKE_DEBUG_POSTFIX} )
|
||||
ENDIF( NOT "${ARGN}" MATCHES "(^|;)DEBUG_POSTFIX($|;)" )
|
||||
|
||||
# Configure the module_install_dir so that ${target} may be used in it.
|
||||
# Setting target to itself is REQUIRED for the configuration to work.
|
||||
SET( target "${target}" )
|
||||
STRING( CONFIGURE "${module_install_dir}" module_install_dir )
|
||||
|
||||
# Clear the moc_sources.
|
||||
SET( moc_sources "" )
|
||||
|
||||
# If Qt is being used...
|
||||
IF( QT_FOUND AND QT_LIBRARIES )
|
||||
ADD_DEFINITIONS( -DQT_PLUGIN )
|
||||
|
||||
# Setup the moc sources.
|
||||
IF( moc_headers )
|
||||
QT4_WRAP_CPP( moc_sources ${moc_headers} )
|
||||
ENDIF( moc_headers )
|
||||
ENDIF( QT_FOUND AND QT_LIBRARIES )
|
||||
|
||||
# Fatal error if moc_headers given but moc_sources not created.
|
||||
IF( moc_headers AND NOT moc_sources )
|
||||
MESSAGE( FATAL_ERROR "Calling SETUP_MODULE() with MOC_HEADERS failed. "
|
||||
"Make sure that you included \${QT_USE_FILE} prior to calling "
|
||||
"SETUP_MODULE()." )
|
||||
ENDIF( moc_headers AND NOT moc_sources )
|
||||
|
||||
# Add the module (built as a shared library).
|
||||
ADD_LIBRARY( "${target}" SHARED ${sources} ${moc_sources} )
|
||||
|
||||
# Setup the debug postfix.
|
||||
SET_TARGET_PROPERTIES ( "${target}" PROPERTIES
|
||||
DEBUG_POSTFIX "${debug_postfix}" )
|
||||
|
||||
# Link in the dependency libraries.
|
||||
TARGET_LINK_LIBRARIES( "${target}" ${libraries} )
|
||||
|
||||
# Install the module.
|
||||
IF( NOT dont_install_module )
|
||||
INSTALL( TARGETS "${target}"
|
||||
LIBRARY DESTINATION "${module_install_dir}" )
|
||||
ENDIF( NOT dont_install_module )
|
||||
|
||||
ENDMACRO( SETUP_MODULE )
|
||||
|
||||
|
||||
# SETUP_EXECUTABLE Macro
|
||||
# Sets up to build an executable target. The macro uses the following global
|
||||
# variables to define default values (you may change these variables to change
|
||||
# the defaults:
|
||||
# DEFAULT_EXECUTABLE_INSTALL_DIR
|
||||
#
|
||||
# Usage:
|
||||
# SETUP_EXECUTABLE( target
|
||||
# SOURCES source1 [source2...]
|
||||
# MOC_HEADERS header1 [header2...]
|
||||
# LIBRARIES library1 [library2...]
|
||||
# EXECUTABLE_INSTALL_DIR dir
|
||||
# DEBUG_POSTFIX string
|
||||
# DONT_INSTALL_EXECUTABLE )
|
||||
#
|
||||
# Parameters:
|
||||
# target The target executable.
|
||||
# SOURCES Follow with the sources to compile.
|
||||
# MOC_HEADERS Follow with the headers to moc (Requires Qt).
|
||||
# LIBRARIES Follow with the libraries to link.
|
||||
# EXECUTABLE_INSTALL_DIR Follow with the directory to install the
|
||||
# executable in
|
||||
# (${DEFAULT_EXECUTABLE_INSTALL_DIR} by default).
|
||||
# DEBUG_POSTFIX Follow with the postfix to use when building in
|
||||
# debug mode (${CMAKE_DEBUG_POSTFIX} by
|
||||
# default).
|
||||
# DONT_INSTALL_EXECUTABLE If passed, the executable will not be
|
||||
# installed.
|
||||
MACRO( SETUP_EXECUTABLE target )
|
||||
|
||||
# Setup the list headers.
|
||||
SET( list_headers
|
||||
SOURCES
|
||||
MOC_HEADERS
|
||||
LIBRARIES
|
||||
EXECUTABLE_INSTALL_DIR
|
||||
DEBUG_POSTFIX
|
||||
)
|
||||
|
||||
# Setup the boolean headers.
|
||||
SET( bool_headers
|
||||
DONT_INSTALL_EXECUTABLE
|
||||
)
|
||||
|
||||
# Parse the arguments into variables.
|
||||
ARGUMENT_PARSER( "" "${list_headers}" "${bool_headers}" ${ARGN} )
|
||||
|
||||
# Set the default values for the executable_install_dir and debug postfix.
|
||||
IF( NOT "${ARGN}" MATCHES "(^|;)EXECUTABLE_INSTALL_DIR($|;)" )
|
||||
SET( executable_install_dir ${DEFAULT_EXECUTABLE_INSTALL_DIR} )
|
||||
ENDIF( NOT "${ARGN}" MATCHES "(^|;)EXECUTABLE_INSTALL_DIR($|;)" )
|
||||
|
||||
IF( NOT "${ARGN}" MATCHES "(^|;)DEBUG_POSTFIX($|;)" )
|
||||
SET( debug_postfix ${CMAKE_DEBUG_POSTFIX} )
|
||||
ENDIF( NOT "${ARGN}" MATCHES "(^|;)DEBUG_POSTFIX($|;)" )
|
||||
|
||||
# Configure the executable_install_dir so that ${target} may be used in it.
|
||||
# Setting target to itself is REQUIRED for the configuration to work.
|
||||
SET( target "${target}" )
|
||||
STRING( CONFIGURE "${executable_install_dir}" executable_install_dir )
|
||||
|
||||
# Clear the moc_sources.
|
||||
SET( moc_sources "" )
|
||||
|
||||
# If Qt is being used...
|
||||
IF( QT_FOUND AND QT_LIBRARIES )
|
||||
ADD_DEFINITIONS( -DQT_SHARED )
|
||||
|
||||
# Setup the moc sources.
|
||||
IF( moc_headers )
|
||||
QT4_WRAP_CPP( moc_sources ${moc_headers} )
|
||||
ENDIF( moc_headers )
|
||||
ENDIF( QT_FOUND AND QT_LIBRARIES )
|
||||
|
||||
# Fatal error if moc_headers given but moc_sources not created.
|
||||
IF( moc_headers AND NOT moc_sources )
|
||||
MESSAGE( FATAL_ERROR "Calling SETUP_EXECUTABLE() with MOC_HEADERS failed. "
|
||||
"Make sure that you included \${QT_USE_FILE} prior to calling "
|
||||
"SETUP_EXECUTABLE()." )
|
||||
ENDIF( moc_headers AND NOT moc_sources )
|
||||
|
||||
# Add the executable.
|
||||
ADD_EXECUTABLE( "${target}" ${sources} ${moc_sources} )
|
||||
|
||||
# Setup the debug postfix.
|
||||
SET_TARGET_PROPERTIES ( "${target}" PROPERTIES
|
||||
DEBUG_POSTFIX "${debug_postfix}" )
|
||||
|
||||
# Link in the dependency libraries.
|
||||
TARGET_LINK_LIBRARIES( "${target}" ${libraries} )
|
||||
|
||||
# Install the executable.
|
||||
IF( NOT dont_install_executable )
|
||||
INSTALL( TARGETS "${target}" RUNTIME DESTINATION
|
||||
"${executable_install_dir}" )
|
||||
ENDIF( NOT dont_install_executable )
|
||||
|
||||
ENDMACRO( SETUP_EXECUTABLE )
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
# This module defines macros that are useful for using libraries in a build. The
|
||||
# macros in this module are typically used along with the FindDependencyMacros.
|
||||
|
||||
# ADD_LIBRARY_TO_LIST Macro
|
||||
# Adds a library to a list of libraries if it is found. Otherwise, reports an
|
||||
# error.
|
||||
#
|
||||
# Usage:
|
||||
# ADD_LIBRARY_TO_LIST( libraries found lib lib_name )
|
||||
#
|
||||
# Parameters:
|
||||
# libraries The list of libraries to add the library to.
|
||||
# found Whether or not the library to add was found.
|
||||
# lib The library to add to the list.
|
||||
# lib_name The name of the library to add to the list.
|
||||
MACRO( ADD_LIBRARY_TO_LIST libraries found lib lib_name )
|
||||
|
||||
# Setting found to itself is necessary for the conditional to work.
|
||||
SET( found ${found} )
|
||||
|
||||
# IF found, then add the library to the list, else report an error.
|
||||
IF( found )
|
||||
LIST( REMOVE_ITEM ${libraries} ${lib} )
|
||||
SET( ${libraries} ${${libraries}} ${lib} )
|
||||
ENDIF( found )
|
||||
IF( NOT found )
|
||||
MESSAGE( "Using ${lib_name} failed." )
|
||||
ENDIF( NOT found )
|
||||
|
||||
ENDMACRO( ADD_LIBRARY_TO_LIST )
|
||||
|
||||
|
||||
# USE_LIBRARY_GLOBALS Macro
|
||||
# If ${prefix}_USE_${LIB} is true, then ${prefix}_${LIB}_LIBRARY will be added
|
||||
# to ${prefix}_LIBRARIES (assuming the library was correctly found). All of the
|
||||
# dependencies will also be added to ${prefix}_LIBRARIES.
|
||||
#
|
||||
# Usage:
|
||||
# USE_LIBRARY_GLOBALS( prefix lib
|
||||
# DEPS dependency1 [dependency2...] )
|
||||
#
|
||||
# Parameters:
|
||||
# prefix The prefix for the global variables.
|
||||
# lib The library to try to use.
|
||||
# DEPS Follow with the list of dependencies that should be added with
|
||||
# the given library.
|
||||
MACRO( USE_LIBRARY_GLOBALS prefix lib )
|
||||
|
||||
STRING( TOUPPER ${lib} upper )
|
||||
|
||||
# If the library should be used...
|
||||
IF( ${prefix}_USE_${upper} )
|
||||
|
||||
# Parse the arguments into variables.
|
||||
ARGUMENT_PARSER( "" "DEPS" "" ${ARGN} )
|
||||
|
||||
# Add the library to the list.
|
||||
ADD_LIBRARY_TO_LIST( ${prefix}_LIBRARIES "${${prefix}_${upper}_FOUND}"
|
||||
"${${prefix}_${upper}_LIBRARY}" ${lib} )
|
||||
|
||||
# For each of the library's dependencies.
|
||||
FOREACH( dep_itr ${deps} )
|
||||
STRING( TOUPPER ${dep_itr} upper )
|
||||
|
||||
# Add the dependency to the list.
|
||||
ADD_LIBRARY_TO_LIST( ${prefix}_LIBRARIES
|
||||
"${${prefix}_${upper}_FOUND}"
|
||||
"${${prefix}_${upper}_LIBRARY}" ${dep_itr} )
|
||||
ENDFOREACH( dep_itr )
|
||||
ENDIF( ${prefix}_USE_${upper} )
|
||||
|
||||
ENDMACRO( USE_LIBRARY_GLOBALS )
|
||||
|
|
@ -1,244 +0,0 @@
|
|||
# This module defines several macros that are useful for handling version
|
||||
# information. These macros work for version strings of format "#.#.#"
|
||||
# representing major, minor, and patch integer components.
|
||||
|
||||
|
||||
INCLUDE( ArgumentParser )
|
||||
|
||||
|
||||
# PARSE_VERSION_STR Macro
|
||||
# This macro parses the version string information from a string. The macro
|
||||
# parses the string for the given definitions followed by whitespace (or by ':'
|
||||
# or '"' characters) and then version information. For example, passing
|
||||
# "MyVersion" as a definition would properly retrieve the version from a string
|
||||
# "containing the line "def MyVersion: 1.2.3".
|
||||
#
|
||||
# Usage:
|
||||
# PARSE_VERSION_STR( version string definition [definition2...] )
|
||||
#
|
||||
# Parameters:
|
||||
# version The variable to store the version string in.
|
||||
# string The string to parse.
|
||||
# definition The definition(s) that may preceed the version string
|
||||
# information.
|
||||
MACRO( PARSE_VERSION_STR version string )
|
||||
|
||||
# Parse the arguments into variables.
|
||||
ARGUMENT_PARSER( definitions "" "" ${ARGN} )
|
||||
|
||||
# For each of the given definitions...
|
||||
FOREACH( def_itr ${definitions} )
|
||||
# If the version has not been found, then attempt to parse it.
|
||||
IF( NOT ${version} )
|
||||
# Parse the version string.
|
||||
STRING( REGEX MATCH "${def_itr}[ \t\":]+[0-9]+(.[0-9]+)?(.[0-9]+)?"
|
||||
${version} ${string} )
|
||||
|
||||
STRING( REGEX MATCH "[0-9]+(.[0-9]+)?(.[0-9]+)?" ${version}
|
||||
"${${version}}" )
|
||||
|
||||
CORRECT_VERSION_STR( ${version} "${${version}}" )
|
||||
ENDIF( NOT ${version} )
|
||||
ENDFOREACH( def_itr )
|
||||
|
||||
ENDMACRO( PARSE_VERSION_STR )
|
||||
|
||||
|
||||
# PARSE_VERSION_INT Macro
|
||||
# This macro parses the version integer component information from a string. The
|
||||
# macro parses the string for the given definitions followed by whitespace (or
|
||||
# by ':' or '"' characters) and then version information. For example, passing
|
||||
# "MyVersionMajor" as a definition would properly retrieve the version from a
|
||||
# string "containing the line "def MyVersionMajor: 1".
|
||||
#
|
||||
# Usage:
|
||||
# PARSE_VERSION_INT( version string definition [definition2...] )
|
||||
#
|
||||
# Parameters:
|
||||
# version The variable to store the version integer component in.
|
||||
# string The string to parse.
|
||||
# definition The definition(s) that may preceed the version integer
|
||||
# component information.
|
||||
MACRO( PARSE_VERSION_INT version string )
|
||||
|
||||
# Parse the arguments into variables.
|
||||
ARGUMENT_PARSER( definitions "" "" ${ARGN} )
|
||||
|
||||
# For each of the given definitions...
|
||||
FOREACH( def_itr ${definitions} )
|
||||
# If the version has not been found, then attempt to parse it.
|
||||
IF( NOT ${version} )
|
||||
# Parse the version string.
|
||||
STRING( REGEX MATCH "${def_itr}[ \t\":]+[0-9]+" ${version}
|
||||
${string} )
|
||||
|
||||
STRING( REGEX MATCH "[0-9]+" ${version} "${${version}}" )
|
||||
ENDIF( NOT ${version} )
|
||||
ENDFOREACH( def_itr )
|
||||
|
||||
ENDMACRO( PARSE_VERSION_INT )
|
||||
|
||||
|
||||
# VERSION_STR_TO_INTS Macro
|
||||
# This macro converts a version string into its three integer components.
|
||||
#
|
||||
# Usage:
|
||||
# VERSION_STR_TO_INTS( major minor patch version )
|
||||
#
|
||||
# Parameters:
|
||||
# major The variable to store the major integer component in.
|
||||
# minor The variable to store the minor integer component in.
|
||||
# patch The variable to store the patch integer component in.
|
||||
# version The version string to convert ("#.#.#" format).
|
||||
MACRO( VERSION_STR_TO_INTS major minor patch version )
|
||||
|
||||
STRING( REGEX REPLACE "([0-9]+).[0-9]+.[0-9]+" "\\1" ${major} ${version} )
|
||||
STRING( REGEX REPLACE "[0-9]+.([0-9]+).[0-9]+" "\\1" ${minor} ${version} )
|
||||
STRING( REGEX REPLACE "[0-9]+.[0-9]+.([0-9]+)" "\\1" ${patch} ${version} )
|
||||
|
||||
ENDMACRO( VERSION_STR_TO_INTS )
|
||||
|
||||
|
||||
# VERSION_INTS_TO_STR Macro
|
||||
# This macro converts three version integer components into a version string.
|
||||
#
|
||||
# Usage:
|
||||
# VERSION_INTS_TO_STR( version major minor patch )
|
||||
#
|
||||
# Parameters:
|
||||
# version The variable to store the version string in.
|
||||
# major The major version integer.
|
||||
# minor The minor version integer.
|
||||
# patch The patch version integer.
|
||||
MACRO( VERSION_INTS_TO_STR version major minor patch )
|
||||
|
||||
SET( ${version} "${major}.${minor}.${patch}" )
|
||||
CORRECT_VERSION_STR( ${version} ${${version}} )
|
||||
|
||||
ENDMACRO( VERSION_INTS_TO_STR version major minor patch )
|
||||
|
||||
|
||||
# COMPARE_VERSION_STR Macro
|
||||
# This macro compares two version strings to each other. The macro sets the
|
||||
# result variable to -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
|
||||
#
|
||||
# Usage:
|
||||
# COMPARE_VERSION_STR( result lhs rhs )
|
||||
#
|
||||
# Parameters:
|
||||
# result The variable to store the result of the comparison in.
|
||||
# lhs The version of the left hand side ("#.#.#" format).
|
||||
# rhs The version of the right hand side ("#.#.#" format).
|
||||
MACRO( COMPARE_VERSION_STR result lhs rhs )
|
||||
|
||||
VERSION_STR_TO_INTS( lhs_major lhs_minor lhs_patch ${lhs} )
|
||||
VERSION_STR_TO_INTS( rhs_major rhs_minor rhs_patch ${rhs} )
|
||||
|
||||
COMPARE_VERSION_INTS( ${result}
|
||||
${lhs_major} ${lhs_minor} ${lhs_patch}
|
||||
${rhs_major} ${rhs_minor} ${rhs_patch} )
|
||||
|
||||
ENDMACRO( COMPARE_VERSION_STR result lhs rhs )
|
||||
|
||||
|
||||
# COMPARE_VERSION_INTS Macro
|
||||
# This macro compares two versions to each other using their integer components.
|
||||
# The macro sets the result variable to -1 if lhs < rhs, 0 if lhs == rhs, and 1
|
||||
# if lhs > rhs.
|
||||
#
|
||||
# Usage:
|
||||
# COMPARE_VERSION_INTS( result
|
||||
# lhs_major lhs_minor lhs_patch
|
||||
# rhs_major rhs_minor rhs_patch )
|
||||
#
|
||||
# Parameters:
|
||||
# result The variable to store the result of the comparison in.
|
||||
# lhs_major The major integer component for the left hand side.
|
||||
# lhs_minor The minor integer component for the left hand side.
|
||||
# lhs_patch The patch integer component for the left hand side.
|
||||
# rhs_major The major integer component for the right hand side.
|
||||
# rhs_minor The minor integer component for the right hand side.
|
||||
# rhs_patch The patch integer component for the right hand side.
|
||||
MACRO( COMPARE_VERSION_INTS result lhs_major lhs_minor lhs_patch
|
||||
rhs_major rhs_minor rhs_patch )
|
||||
|
||||
SET( ${result} 0 )
|
||||
IF( NOT ${result} AND ${lhs_major} LESS ${rhs_major} )
|
||||
SET( ${result} -1 )
|
||||
ENDIF( NOT ${result} AND ${lhs_major} LESS ${rhs_major} )
|
||||
IF( NOT ${result} AND ${lhs_major} GREATER ${rhs_major} )
|
||||
SET( ${result} 1 )
|
||||
ENDIF( NOT ${result} AND ${lhs_major} GREATER ${rhs_major} )
|
||||
|
||||
IF( NOT ${result} AND ${lhs_minor} LESS ${rhs_minor} )
|
||||
SET( ${result} -1 )
|
||||
ENDIF( NOT ${result} AND ${lhs_minor} LESS ${rhs_minor} )
|
||||
IF( NOT ${result} AND ${lhs_minor} GREATER ${rhs_minor} )
|
||||
SET( ${result} 1 )
|
||||
ENDIF( NOT ${result} AND ${lhs_minor} GREATER ${rhs_minor} )
|
||||
|
||||
IF( NOT ${result} AND ${lhs_patch} LESS ${rhs_patch} )
|
||||
SET( ${result} -1 )
|
||||
ENDIF( NOT ${result} AND ${lhs_patch} LESS ${rhs_patch} )
|
||||
IF( NOT ${result} AND ${lhs_patch} GREATER ${rhs_patch} )
|
||||
SET( ${result} 1 )
|
||||
ENDIF( NOT ${result} AND ${lhs_patch} GREATER ${rhs_patch} )
|
||||
|
||||
ENDMACRO( COMPARE_VERSION_INTS result lhs_major lhs_minor lhs_patch
|
||||
rhs_major rhs_minor rhs_patch )
|
||||
|
||||
|
||||
# CORRECT_VERSION_STR Macro
|
||||
# This macro corrects the version_str and stores the result in the version
|
||||
# variable. If the version_str contains a version string in "#" or "#.#" format,
|
||||
# then ".0" will be appended to the string to convert it to "#.#.#" format. If
|
||||
# the version_str is invalid, then version will be set to "".
|
||||
#
|
||||
# Usage:
|
||||
# CORRECT_VERSION_STR( version version_str )
|
||||
#
|
||||
# Parameters:
|
||||
# version The variable to store the corrected version string in.
|
||||
# version_str The version string to correct.
|
||||
MACRO( CORRECT_VERSION_STR version version_str )
|
||||
|
||||
SET( ${version} "${version_str}" )
|
||||
|
||||
# Add ".0" to the end of the version string in case a full "#.#.#" string
|
||||
# was not given.
|
||||
FOREACH( itr RANGE 2 )
|
||||
IF( NOT ${version} MATCHES "[0-9]+.[0-9]+.[0-9]+" )
|
||||
SET( ${version} "${${version}}.0" )
|
||||
ENDIF( NOT ${version} MATCHES "[0-9]+.[0-9]+.[0-9]+" )
|
||||
ENDFOREACH( itr )
|
||||
|
||||
# If the version string is not correct, then set it to "".
|
||||
IF( NOT ${version} MATCHES "^[0-9]+.[0-9]+.[0-9]+$" )
|
||||
SET( ${version} "" )
|
||||
ENDIF( NOT ${version} MATCHES "^[0-9]+.[0-9]+.[0-9]+$" )
|
||||
|
||||
ENDMACRO( CORRECT_VERSION_STR )
|
||||
|
||||
|
||||
|
||||
# CORRECT_VERSION_Int Macro
|
||||
# This macro corrects the version_int and stores the result in the version
|
||||
# variable. If the version_int is invalid, then version will be set to "".
|
||||
#
|
||||
# Usage:
|
||||
# CORRECT_VERSION_Int( version version_int )
|
||||
#
|
||||
# Parameters:
|
||||
# version The variable to store the corrected version integer
|
||||
# component in.
|
||||
# version_INT The version integer component to correct.
|
||||
MACRO( CORRECT_VERSION_INT version version_int )
|
||||
|
||||
SET( ${version} "${version_int}" )
|
||||
|
||||
# If the version is not an integer, then set it to "".
|
||||
IF( NOT ${version} MATCHES "^[0-9]+$" )
|
||||
SET( ${version} "" )
|
||||
ENDIF( NOT ${version} MATCHES "^[0-9]+$" )
|
||||
|
||||
ENDMACRO( CORRECT_VERSION_INT )
|
||||
52
LICENSE.md
Normal file
52
LICENSE.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
The following license only applies to code that was contributed to this repository in the context of BitShares worker proposals and/or BitShares-1 delegate workers. Other code may be licensed indirectly by our "sister" repositories https://github.com/EOSIO/fc and https://github.com/bytemaster/fc/tree/phoenix .
|
||||
|
||||
All subsequent contributions to this repository are licensed by their respective authors under this same license as well, unless explicitly stated otherwise.
|
||||
|
||||
Furthermore, this repository includes code from third party authors. See the list at the end of this file.
|
||||
|
||||
----
|
||||
|
||||
Copyright (c) 2018-2019 BitShares Blockchain Foundation and contributors
|
||||
|
||||
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.
|
||||
|
||||
----
|
||||
|
||||
The following terms apply to third-party code included here. Most have to be published along with binaries of this software.
|
||||
Some of the files are only used for building binaries of this software, without becoming an actual part of those binaries. Their respective licenses also do not apply to the binaries.
|
||||
|
||||
include/bloom_filter.hpp is copyright Arash Partow and covered by the MIT license. See http://www.opensource.org/licenses/MIT .
|
||||
|
||||
src/utf8 is copyright Nemanja Trifunovic and covered by the MIT license (Thrift variant). See licenses/MIT_Thrift_LICENSE.md.
|
||||
|
||||
src/crypto/base58.cpp is copyright Satoshi Nakamoto and The Bitcoin Developers and is covered by the MIT/X11 license. See licenses/MIT_X11_LICENSE.md.
|
||||
|
||||
src/crypto/base64.cpp is copyright René Nyffenegger and covered by the zlib/libpng license. See licenses/ZLIB_LICENSE.md.
|
||||
|
||||
src/crypto/city.cpp and libraries/fc/include/fc/crypto/city.hpp are copyright Google, Inc. and covered by the MIT/X11 license. See licenses/MIT_X11_LICENSE.md.
|
||||
|
||||
CMakeModules/CheckLibcxxAtomic.cmake was taken from the LLVM repository and is licensed under the Apache-2.0 license. See licenses/Apache.txt .
|
||||
|
||||
GitVersionGen/GetGitRevisionDescription.cmake is copyright Iowa State University and covered by the Boost Software License. See licenses/Boost_License-1.0.txt.
|
||||
|
||||
vendor/editline is copyright Simmule Turner and Rich Salz and covered by a BSD-like license. See vendor/editline/LICENSE.
|
||||
|
||||
vendor/secp256k1-zkp is copyright Pieter Wuille and covered by the MIT/X11 license. See vendor/secp256k1-zkp/COPYING.
|
||||
|
||||
vendor/websocketpp is copyright Peter Thorson and covered by a 3-clause BSD-license. It also includes code from 4th-party authors with various copyrights, see vendor/websocketpp/COPYING.
|
||||
|
|
@ -2,6 +2,7 @@ fc
|
|||
==
|
||||
|
||||
[](https://travis-ci.org/bitshares/bitshares-fc)
|
||||
[](https://github.com/bitshares/bitshares-fc/actions?query=branch%3Amaster)
|
||||
|
||||
**NOTE:** This fork reverts upstream commit a421e280488385cab26a42153f7ce3c8d5b6281f to avoid changing the BitShares API.
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ namespace asio {
|
|||
*/
|
||||
template<typename AsyncReadStream, typename MutableBufferSequence>
|
||||
size_t read( AsyncReadStream& s, const MutableBufferSequence& buf ) {
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::asio::read"));
|
||||
promise<size_t>::ptr p = promise<size_t>::create("fc::asio::read");
|
||||
boost::asio::async_read( s, buf, detail::read_write_handler(p) );
|
||||
return p->wait();
|
||||
}
|
||||
|
|
@ -249,7 +249,6 @@ namespace asio {
|
|||
*/
|
||||
template<typename SocketType, typename AcceptorType>
|
||||
void accept( AcceptorType& acc, SocketType& sock ) {
|
||||
//promise<boost::system::error_code>::ptr p( new promise<boost::system::error_code>("fc::asio::tcp::accept") );
|
||||
promise<void>::ptr p = promise<void>::create("fc::asio::tcp::accept");
|
||||
acc.async_accept( sock, boost::bind( fc::asio::detail::error_handler, p, _1 ) );
|
||||
p->wait();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* *
|
||||
|
|
@ -11,27 +9,29 @@
|
|||
* *
|
||||
* Copyright notice: *
|
||||
* Free use of the Open Bloom Filter Library is permitted under the *
|
||||
* guidelines and in accordance with the most current version of the *
|
||||
* Common Public License. *
|
||||
* http://www.opensource.org/licenses/cpl1.0.php *
|
||||
* guidelines and in accordance with the MIT License. *
|
||||
* http://www.opensource.org/licenses/MIT *
|
||||
* *
|
||||
*********************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#ifndef INCLUDE_BLOOM_FILTER_HPP
|
||||
#define INCLUDE_BLOOM_FILTER_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
|
||||
static constexpr std::size_t bits_per_char = 0x08; // 8 bits in 1 char(unsigned)
|
||||
|
||||
static const unsigned char bit_mask[bits_per_char] = {
|
||||
0x01, //00000001
|
||||
0x02, //00000010
|
||||
|
|
@ -87,22 +87,22 @@ public:
|
|||
(0xFFFFFFFFFFFFFFFFULL == random_seed);
|
||||
}
|
||||
|
||||
//Allowed min/max size of the bloom filter in bits
|
||||
// Allowable min/max size of the bloom filter in bits
|
||||
unsigned long long int minimum_size;
|
||||
unsigned long long int maximum_size;
|
||||
|
||||
//Allowed min/max number of hash functions
|
||||
// Allowable min/max number of hash functions
|
||||
unsigned int minimum_number_of_hashes;
|
||||
unsigned int maximum_number_of_hashes;
|
||||
|
||||
//The approximate number of elements to be inserted
|
||||
//into the bloom filter, should be within one order
|
||||
//of magnitude. The default is 10000.
|
||||
// The approximate number of elements to be inserted
|
||||
// into the bloom filter, should be within one order
|
||||
// of magnitude. The default is 10000.
|
||||
unsigned long long int projected_element_count;
|
||||
|
||||
//The approximate false positive probability expected
|
||||
//from the bloom filter. The default is the reciprocal
|
||||
//of the projected_element_count.
|
||||
// The approximate false positive probability expected
|
||||
// from the bloom filter. The default is assumed to be
|
||||
// the reciprocal of the projected_element_count.
|
||||
double false_positive_probability;
|
||||
|
||||
unsigned long long int random_seed;
|
||||
|
|
@ -133,28 +133,32 @@ public:
|
|||
if (!(*this))
|
||||
return false;
|
||||
|
||||
double min_m = std::numeric_limits<double>::infinity();
|
||||
double min_k = 0.0;
|
||||
double curr_m = 0.0;
|
||||
double k = 1.0;
|
||||
double min_m = std::numeric_limits<double>::infinity();
|
||||
double min_k = 0.0;
|
||||
double k = 1.0;
|
||||
|
||||
while (k < 1000.0)
|
||||
{
|
||||
double numerator = (- k * projected_element_count);
|
||||
double denominator = std::log(1.0 - std::pow(false_positive_probability, 1.0 / k));
|
||||
curr_m = numerator / denominator;
|
||||
const double numerator = (- k * projected_element_count);
|
||||
const double denominator = std::log(1.0 - std::pow(false_positive_probability, 1.0 / k));
|
||||
|
||||
const double curr_m = numerator / denominator;
|
||||
|
||||
if (curr_m < min_m)
|
||||
{
|
||||
min_m = curr_m;
|
||||
min_k = k;
|
||||
}
|
||||
|
||||
k += 1.0;
|
||||
}
|
||||
|
||||
optimal_parameters_t& optp = optimal_parameters;
|
||||
|
||||
optp.number_of_hashes = static_cast<unsigned int>(min_k);
|
||||
|
||||
optp.table_size = static_cast<unsigned long long int>(min_m);
|
||||
|
||||
optp.table_size += (((optp.table_size % bits_per_char) != 0) ? (bits_per_char - (optp.table_size % bits_per_char)) : 0);
|
||||
|
||||
if (optp.number_of_hashes < minimum_number_of_hashes)
|
||||
|
|
@ -178,15 +182,15 @@ protected:
|
|||
|
||||
typedef unsigned int bloom_type;
|
||||
typedef unsigned char cell_type;
|
||||
typedef std::vector<unsigned char> table_type;
|
||||
|
||||
public:
|
||||
|
||||
bloom_filter()
|
||||
: salt_count_(0),
|
||||
table_size_(0),
|
||||
raw_table_size_(0),
|
||||
projected_element_count_(0),
|
||||
inserted_element_count_(0),
|
||||
inserted_element_count_ (0),
|
||||
random_seed_(0),
|
||||
desired_false_positive_probability_(0.0)
|
||||
{}
|
||||
|
|
@ -199,12 +203,10 @@ public:
|
|||
{
|
||||
salt_count_ = p.optimal_parameters.number_of_hashes;
|
||||
table_size_ = p.optimal_parameters.table_size;
|
||||
generate_unique_salt();
|
||||
raw_table_size_ = table_size_ / bits_per_char;
|
||||
|
||||
bit_table_.resize( static_cast<std::size_t>(raw_table_size_) );
|
||||
//bit_table_ = new cell_type[static_cast<std::size_t>(raw_table_size_)];
|
||||
std::fill_n(bit_table_.data(),raw_table_size_,0x00);
|
||||
generate_unique_salt();
|
||||
|
||||
bit_table_.resize(table_size_ / bits_per_char, static_cast<unsigned char>(0x00));
|
||||
}
|
||||
|
||||
bloom_filter(const bloom_filter& filter)
|
||||
|
|
@ -217,15 +219,15 @@ public:
|
|||
if (this != &f)
|
||||
{
|
||||
return
|
||||
(salt_count_ == f.salt_count_) &&
|
||||
(table_size_ == f.table_size_) &&
|
||||
(raw_table_size_ == f.raw_table_size_) &&
|
||||
(projected_element_count_ == f.projected_element_count_) &&
|
||||
(inserted_element_count_ == f.inserted_element_count_) &&
|
||||
(random_seed_ == f.random_seed_) &&
|
||||
(salt_count_ == f.salt_count_ ) &&
|
||||
(table_size_ == f.table_size_ ) &&
|
||||
(bit_table_.size() == f.bit_table_.size() ) &&
|
||||
(projected_element_count_ == f.projected_element_count_ ) &&
|
||||
(inserted_element_count_ == f.inserted_element_count_ ) &&
|
||||
(random_seed_ == f.random_seed_ ) &&
|
||||
(desired_false_positive_probability_ == f.desired_false_positive_probability_) &&
|
||||
(salt_ == f.salt_) &&
|
||||
std::equal(f.bit_table_.data(),f.bit_table_.data() + raw_table_size_,bit_table_.data());
|
||||
(salt_ == f.salt_ ) &&
|
||||
(bit_table_ == f.bit_table_ ) ;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
|
|
@ -242,21 +244,22 @@ public:
|
|||
{
|
||||
salt_count_ = f.salt_count_;
|
||||
table_size_ = f.table_size_;
|
||||
raw_table_size_ = f.raw_table_size_;
|
||||
bit_table_ = f.bit_table_;
|
||||
salt_ = f.salt_;
|
||||
|
||||
projected_element_count_ = f.projected_element_count_;
|
||||
inserted_element_count_ = f.inserted_element_count_;
|
||||
inserted_element_count_ = f.inserted_element_count_;
|
||||
|
||||
random_seed_ = f.random_seed_;
|
||||
|
||||
desired_false_positive_probability_ = f.desired_false_positive_probability_;
|
||||
bit_table_.resize( raw_table_size_ );
|
||||
std::copy(f.bit_table_.data(),f.bit_table_.data() + raw_table_size_,bit_table_.data());
|
||||
salt_ = f.salt_;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~bloom_filter()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
inline bool operator!() const
|
||||
{
|
||||
|
|
@ -265,23 +268,26 @@ public:
|
|||
|
||||
inline void clear()
|
||||
{
|
||||
std::fill_n(bit_table_.data(),raw_table_size_,0x00);
|
||||
std::fill(bit_table_.begin(), bit_table_.end(), static_cast<unsigned char>(0x00));
|
||||
inserted_element_count_ = 0;
|
||||
}
|
||||
|
||||
inline void insert(const unsigned char* key_begin, const std::size_t& length)
|
||||
{
|
||||
std::size_t bit_index = 0;
|
||||
std::size_t bit = 0;
|
||||
std::size_t bit = 0;
|
||||
|
||||
for (std::size_t i = 0; i < salt_.size(); ++i)
|
||||
{
|
||||
compute_indices(hash_ap(key_begin,length,salt_[i]),bit_index,bit);
|
||||
compute_indices(hash_ap(key_begin, length, salt_[i]), bit_index, bit);
|
||||
|
||||
bit_table_[bit_index / bits_per_char] |= bit_mask[bit];
|
||||
}
|
||||
|
||||
++inserted_element_count_;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline void insert(const T& t)
|
||||
{
|
||||
// Note: T must be a C++ POD type.
|
||||
|
|
@ -290,7 +296,7 @@ public:
|
|||
|
||||
inline void insert(const std::string& key)
|
||||
{
|
||||
insert(reinterpret_cast<const unsigned char*>(key.c_str()),key.size());
|
||||
insert(reinterpret_cast<const unsigned char*>(key.data()),key.size());
|
||||
}
|
||||
|
||||
inline void insert(const char* data, const std::size_t& length)
|
||||
|
|
@ -298,10 +304,11 @@ public:
|
|||
insert(reinterpret_cast<const unsigned char*>(data),length);
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
template <typename InputIterator>
|
||||
inline void insert(const InputIterator begin, const InputIterator end)
|
||||
{
|
||||
InputIterator itr = begin;
|
||||
|
||||
while (end != itr)
|
||||
{
|
||||
insert(*(itr++));
|
||||
|
|
@ -311,19 +318,22 @@ public:
|
|||
inline virtual bool contains(const unsigned char* key_begin, const std::size_t length) const
|
||||
{
|
||||
std::size_t bit_index = 0;
|
||||
std::size_t bit = 0;
|
||||
std::size_t bit = 0;
|
||||
|
||||
for (std::size_t i = 0; i < salt_.size(); ++i)
|
||||
{
|
||||
compute_indices(hash_ap(key_begin,length,salt_[i]),bit_index,bit);
|
||||
compute_indices(hash_ap(key_begin, length, salt_[i]), bit_index, bit);
|
||||
|
||||
if ((bit_table_[bit_index / bits_per_char] & bit_mask[bit]) != bit_mask[bit])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline bool contains(const T& t) const
|
||||
{
|
||||
return contains(reinterpret_cast<const unsigned char*>(&t),static_cast<std::size_t>(sizeof(T)));
|
||||
|
|
@ -339,33 +349,39 @@ public:
|
|||
return contains(reinterpret_cast<const unsigned char*>(data),length);
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
template <typename InputIterator>
|
||||
inline InputIterator contains_all(const InputIterator begin, const InputIterator end) const
|
||||
{
|
||||
InputIterator itr = begin;
|
||||
|
||||
while (end != itr)
|
||||
{
|
||||
if (!contains(*itr))
|
||||
{
|
||||
return itr;
|
||||
}
|
||||
|
||||
++itr;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
template <typename InputIterator>
|
||||
inline InputIterator contains_none(const InputIterator begin, const InputIterator end) const
|
||||
{
|
||||
InputIterator itr = begin;
|
||||
|
||||
while (end != itr)
|
||||
{
|
||||
if (contains(*itr))
|
||||
{
|
||||
return itr;
|
||||
}
|
||||
|
||||
++itr;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
|
|
@ -374,7 +390,7 @@ public:
|
|||
return table_size_;
|
||||
}
|
||||
|
||||
inline std::size_t element_count() const
|
||||
inline unsigned long long int element_count() const
|
||||
{
|
||||
return inserted_element_count_;
|
||||
}
|
||||
|
|
@ -395,16 +411,17 @@ public:
|
|||
{
|
||||
/* intersection */
|
||||
if (
|
||||
(salt_count_ == f.salt_count_) &&
|
||||
(table_size_ == f.table_size_) &&
|
||||
(random_seed_ == f.random_seed_)
|
||||
(salt_count_ == f.salt_count_ ) &&
|
||||
(table_size_ == f.table_size_ ) &&
|
||||
(random_seed_ == f.random_seed_)
|
||||
)
|
||||
{
|
||||
for (std::size_t i = 0; i < raw_table_size_; ++i)
|
||||
for (std::size_t i = 0; i < bit_table_.size(); ++i)
|
||||
{
|
||||
bit_table_[i] &= f.bit_table_[i];
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -412,16 +429,17 @@ public:
|
|||
{
|
||||
/* union */
|
||||
if (
|
||||
(salt_count_ == f.salt_count_) &&
|
||||
(table_size_ == f.table_size_) &&
|
||||
(random_seed_ == f.random_seed_)
|
||||
(salt_count_ == f.salt_count_ ) &&
|
||||
(table_size_ == f.table_size_ ) &&
|
||||
(random_seed_ == f.random_seed_)
|
||||
)
|
||||
{
|
||||
for (std::size_t i = 0; i < raw_table_size_; ++i)
|
||||
for (std::size_t i = 0; i < bit_table_.size(); ++i)
|
||||
{
|
||||
bit_table_[i] |= f.bit_table_[i];
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -429,16 +447,17 @@ public:
|
|||
{
|
||||
/* difference */
|
||||
if (
|
||||
(salt_count_ == f.salt_count_) &&
|
||||
(table_size_ == f.table_size_) &&
|
||||
(random_seed_ == f.random_seed_)
|
||||
(salt_count_ == f.salt_count_ ) &&
|
||||
(table_size_ == f.table_size_ ) &&
|
||||
(random_seed_ == f.random_seed_)
|
||||
)
|
||||
{
|
||||
for (std::size_t i = 0; i < raw_table_size_; ++i)
|
||||
for (std::size_t i = 0; i < bit_table_.size(); ++i)
|
||||
{
|
||||
bit_table_[i] ^= f.bit_table_[i];
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -457,7 +476,7 @@ protected:
|
|||
inline virtual void compute_indices(const bloom_type& hash, std::size_t& bit_index, std::size_t& bit) const
|
||||
{
|
||||
bit_index = hash % table_size_;
|
||||
bit = bit_index % bits_per_char;
|
||||
bit = bit_index % bits_per_char;
|
||||
}
|
||||
|
||||
void generate_unique_salt()
|
||||
|
|
@ -469,6 +488,7 @@ protected:
|
|||
hash function with different values seems to be adequate.
|
||||
*/
|
||||
const unsigned int predef_salt_count = 128;
|
||||
|
||||
static const bloom_type predef_salt[predef_salt_count] =
|
||||
{
|
||||
0xAAAAAAAA, 0x55555555, 0x33333333, 0xCCCCCCCC,
|
||||
|
|
@ -510,25 +530,31 @@ protected:
|
|||
std::copy(predef_salt,
|
||||
predef_salt + salt_count_,
|
||||
std::back_inserter(salt_));
|
||||
for (unsigned int i = 0; i < salt_.size(); ++i)
|
||||
{
|
||||
|
||||
for (std::size_t i = 0; i < salt_.size(); ++i)
|
||||
{
|
||||
/*
|
||||
Note:
|
||||
This is done to integrate the user defined random seed,
|
||||
so as to allow for the generation of unique bloom filter
|
||||
instances.
|
||||
Note:
|
||||
This is done to integrate the user defined random seed,
|
||||
so as to allow for the generation of unique bloom filter
|
||||
instances.
|
||||
*/
|
||||
salt_[i] = salt_[i] * salt_[(i + 3) % salt_.size()] + static_cast<bloom_type>(random_seed_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::copy(predef_salt,predef_salt + predef_salt_count,std::back_inserter(salt_));
|
||||
std::copy(predef_salt, predef_salt + predef_salt_count, std::back_inserter(salt_));
|
||||
|
||||
srand(static_cast<unsigned int>(random_seed_));
|
||||
|
||||
while (salt_.size() < salt_count_)
|
||||
{
|
||||
bloom_type current_salt = static_cast<bloom_type>(rand()) * static_cast<bloom_type>(rand());
|
||||
if (0 == current_salt) continue;
|
||||
|
||||
if (0 == current_salt)
|
||||
continue;
|
||||
|
||||
if (salt_.end() == std::find(salt_.begin(), salt_.end(), current_salt))
|
||||
{
|
||||
salt_.push_back(current_salt);
|
||||
|
|
@ -540,57 +566,71 @@ protected:
|
|||
inline bloom_type hash_ap(const unsigned char* begin, std::size_t remaining_length, bloom_type hash) const
|
||||
{
|
||||
const unsigned char* itr = begin;
|
||||
unsigned int loop = 0;
|
||||
unsigned int loop = 0;
|
||||
|
||||
while (remaining_length >= 8)
|
||||
{
|
||||
const unsigned int& i1 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
|
||||
const unsigned int& i2 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
|
||||
|
||||
hash ^= (hash << 7) ^ i1 * (hash >> 3) ^
|
||||
(~((hash << 11) + (i2 ^ (hash >> 5))));
|
||||
|
||||
remaining_length -= 8;
|
||||
}
|
||||
|
||||
if (remaining_length)
|
||||
{
|
||||
if (remaining_length >= 4)
|
||||
{
|
||||
const unsigned int& i = *(reinterpret_cast<const unsigned int*>(itr));
|
||||
|
||||
if (loop & 0x01)
|
||||
hash ^= (hash << 7) ^ i * (hash >> 3);
|
||||
else
|
||||
hash ^= (~((hash << 11) + (i ^ (hash >> 5))));
|
||||
|
||||
++loop;
|
||||
|
||||
remaining_length -= 4;
|
||||
|
||||
itr += sizeof(unsigned int);
|
||||
}
|
||||
|
||||
if (remaining_length >= 2)
|
||||
{
|
||||
const unsigned short& i = *(reinterpret_cast<const unsigned short*>(itr));
|
||||
|
||||
if (loop & 0x01)
|
||||
hash ^= (hash << 7) ^ i * (hash >> 3);
|
||||
else
|
||||
hash ^= (~((hash << 11) + (i ^ (hash >> 5))));
|
||||
|
||||
++loop;
|
||||
|
||||
remaining_length -= 2;
|
||||
|
||||
itr += sizeof(unsigned short);
|
||||
}
|
||||
|
||||
if (remaining_length)
|
||||
{
|
||||
hash += ((*itr) ^ (hash * 0xA5A5A5A5)) + loop;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<bloom_type> salt_;
|
||||
std::vector<unsigned char> bit_table_;
|
||||
unsigned int salt_count_;
|
||||
unsigned long long int table_size_;
|
||||
unsigned long long int raw_table_size_;
|
||||
unsigned long long int projected_element_count_;
|
||||
unsigned int inserted_element_count_;
|
||||
unsigned long long int random_seed_;
|
||||
double desired_false_positive_probability_;
|
||||
public:
|
||||
std::vector<bloom_type> salt_;
|
||||
std::vector<unsigned char> bit_table_;
|
||||
unsigned int salt_count_;
|
||||
unsigned long long int table_size_;
|
||||
unsigned long long int projected_element_count_;
|
||||
unsigned long long int inserted_element_count_;
|
||||
unsigned long long int random_seed_;
|
||||
double desired_false_positive_probability_;
|
||||
};
|
||||
|
||||
inline bloom_filter operator & (const bloom_filter& a, const bloom_filter& b)
|
||||
|
|
@ -617,12 +657,15 @@ inline bloom_filter operator ^ (const bloom_filter& a, const bloom_filter& b)
|
|||
|
||||
} // namespace fc
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Note 1:
|
||||
If it can be guaranteed that bits_per_char will be of the form 2^n then
|
||||
the following optimization can be used:
|
||||
|
||||
hash_table[bit_index >> n] |= bit_mask[bit_index & (bits_per_char - 1)];
|
||||
bit_table_[bit_index >> n] |= bit_mask[bit_index & (bits_per_char - 1)];
|
||||
|
||||
Note 2:
|
||||
For performance reasons where possible when allocating memory it should
|
||||
|
|
|
|||
79
include/fc/container/zeroed_array.hpp
Normal file
79
include/fc/container/zeroed_array.hpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2019 BitShares Blockchain Foundation, and contributors
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* 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 <fc/io/raw_fwd.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
template< typename T, size_t N >
|
||||
class zero_initialized_array;
|
||||
|
||||
template< size_t N >
|
||||
class zero_initialized_array< unsigned char, N > : public std::array< unsigned char, N > {
|
||||
public:
|
||||
zero_initialized_array() : std::array< unsigned char, N >() { }
|
||||
};
|
||||
|
||||
template<typename T,size_t N>
|
||||
struct get_typename< zero_initialized_array<T,N> >
|
||||
{
|
||||
static const char* name()
|
||||
{
|
||||
static std::string _name = std::string("zero_initialized_array<")
|
||||
+ std::string(fc::get_typename<T>::name())
|
||||
+ "," + fc::to_string(N) + ">";
|
||||
return _name.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
class variant;
|
||||
template<size_t N>
|
||||
void to_variant( const zero_initialized_array<unsigned char,N>& bi, variant& v, uint32_t max_depth = 1 )
|
||||
{
|
||||
to_variant( static_cast<const std::array<unsigned char,N>&>( bi ), v, max_depth );
|
||||
}
|
||||
template<size_t N>
|
||||
void from_variant( const variant& v, zero_initialized_array<unsigned char,N>& bi, uint32_t max_depth = 1 )
|
||||
{
|
||||
from_variant( v, static_cast<std::array<unsigned char,N>&>( bi ), max_depth );
|
||||
}
|
||||
|
||||
namespace raw {
|
||||
template<typename Stream, size_t N>
|
||||
inline void pack( Stream& s, const zero_initialized_array<unsigned char,N>& v, uint32_t _max_depth ) {
|
||||
pack( s, static_cast<const std::array<unsigned char,N>&>( v ), _max_depth );
|
||||
}
|
||||
template<typename Stream, size_t N>
|
||||
inline void unpack( Stream& s, zero_initialized_array<unsigned char,N>& v, uint32_t _max_depth ) {
|
||||
try {
|
||||
unpack( s, static_cast<std::array<unsigned char,N>&>( v ), _max_depth );
|
||||
} FC_RETHROW_EXCEPTIONS( warn, "zero_initialized_array<unsigned char,${length}>", ("length",N) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template< typename T, size_t N >
|
||||
class tuple_size< fc::zero_initialized_array< T, N > > : public tuple_size< array< T, N > > {};
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include <fc/container/zeroed_array.hpp>
|
||||
#include <fc/crypto/bigint.hpp>
|
||||
#include <fc/crypto/openssl.hpp>
|
||||
#include <fc/crypto/sha256.hpp>
|
||||
|
|
@ -17,15 +18,15 @@ namespace fc {
|
|||
class private_key_impl;
|
||||
}
|
||||
|
||||
typedef fc::sha256 blind_factor_type;
|
||||
typedef std::array<unsigned char,33> commitment_type;
|
||||
typedef std::array<unsigned char,33> public_key_data;
|
||||
typedef fc::sha256 private_key_secret;
|
||||
typedef std::array<unsigned char,65> public_key_point_data; ///< the full non-compressed version of the ECC point
|
||||
typedef std::array<unsigned char,72> signature;
|
||||
typedef std::array<unsigned char,65> compact_signature;
|
||||
typedef std::vector<char> range_proof_type;
|
||||
typedef std::array<unsigned char,78> extended_key_data;
|
||||
typedef fc::sha256 blind_factor_type;
|
||||
typedef zero_initialized_array<unsigned char,33> commitment_type;
|
||||
typedef zero_initialized_array<unsigned char,33> public_key_data;
|
||||
typedef fc::sha256 private_key_secret;
|
||||
typedef zero_initialized_array<unsigned char,65> public_key_point_data; ///< the full non-compressed version of the ECC point
|
||||
typedef zero_initialized_array<unsigned char,72> signature;
|
||||
typedef zero_initialized_array<unsigned char,65> compact_signature;
|
||||
typedef std::vector<char> range_proof_type;
|
||||
typedef zero_initialized_array<unsigned char,78> extended_key_data;
|
||||
|
||||
/**
|
||||
* @class public_key
|
||||
|
|
|
|||
124
include/fc/crypto/hash160.hpp
Normal file
124
include/fc/crypto/hash160.hpp
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2018 jmjatlanta and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* 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 <boost/endian/buffers.hpp>
|
||||
#include <fc/fwd.hpp>
|
||||
#include <fc/string.hpp>
|
||||
#include <fc/io/raw_fwd.hpp>
|
||||
|
||||
namespace fc{
|
||||
|
||||
class hash160
|
||||
{
|
||||
public:
|
||||
hash160();
|
||||
explicit hash160( const string& hex_str );
|
||||
|
||||
string str()const;
|
||||
explicit operator string()const;
|
||||
|
||||
char* data() const;
|
||||
static constexpr size_t data_size() { return 160/8; }
|
||||
|
||||
static hash160 hash( const char* d, uint32_t dlen );
|
||||
static hash160 hash( const string& );
|
||||
|
||||
template<typename T>
|
||||
static hash160 hash( const T& t )
|
||||
{
|
||||
hash160::encoder e;
|
||||
fc::raw::pack(e,t);
|
||||
return e.result();
|
||||
}
|
||||
|
||||
class encoder
|
||||
{
|
||||
public:
|
||||
encoder();
|
||||
~encoder();
|
||||
|
||||
void write( const char* d, uint32_t dlen );
|
||||
void put( char c ) { write( &c, 1 ); }
|
||||
void reset();
|
||||
hash160 result();
|
||||
|
||||
private:
|
||||
class impl;
|
||||
fc::fwd<impl,117> my;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline friend T& operator<<( T& ds, const hash160& ep ) {
|
||||
ds.write( ep.data(), sizeof(ep) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline friend T& operator>>( T& ds, hash160& ep ) {
|
||||
ds.read( ep.data(), sizeof(ep) );
|
||||
return ds;
|
||||
}
|
||||
friend hash160 operator << ( const hash160& h1, uint32_t i );
|
||||
friend bool operator == ( const hash160& h1, const hash160& h2 );
|
||||
friend bool operator != ( const hash160& h1, const hash160& h2 );
|
||||
friend hash160 operator ^ ( const hash160& h1, const hash160& h2 );
|
||||
friend bool operator >= ( const hash160& h1, const hash160& h2 );
|
||||
friend bool operator > ( const hash160& h1, const hash160& h2 );
|
||||
friend bool operator < ( const hash160& h1, const hash160& h2 );
|
||||
|
||||
boost::endian::little_uint32_buf_t _hash[5];
|
||||
};
|
||||
|
||||
namespace raw {
|
||||
|
||||
template<typename T>
|
||||
inline void pack( T& ds, const hash160& ep, uint32_t _max_depth ) {
|
||||
ds << ep;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void unpack( T& ds, hash160& ep, uint32_t _max_depth ) {
|
||||
ds >> ep;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class variant;
|
||||
void to_variant( const hash160& bi, variant& v, uint32_t max_depth );
|
||||
void from_variant( const variant& v, hash160& bi, uint32_t max_depth );
|
||||
|
||||
template<> struct get_typename<hash160> { static const char* name() { return "hash160"; } };
|
||||
} // namespace fc
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<fc::hash160>
|
||||
{
|
||||
size_t operator()( const fc::hash160& s )const
|
||||
{
|
||||
return *((size_t*)&s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/err.h>
|
||||
|
|
@ -21,6 +22,8 @@ namespace fc
|
|||
struct ssl_wrapper
|
||||
{
|
||||
ssl_wrapper(ssl_type* obj):obj(obj) {}
|
||||
ssl_wrapper( ssl_wrapper& copy ) = delete;
|
||||
ssl_wrapper& operator=( ssl_wrapper& copy ) = delete;
|
||||
|
||||
operator ssl_type*() { return obj; }
|
||||
operator const ssl_type*() const { return obj; }
|
||||
|
|
@ -30,23 +33,21 @@ namespace fc
|
|||
ssl_type* obj;
|
||||
};
|
||||
|
||||
#define SSL_TYPE(name, ssl_type, free_func) \
|
||||
#define SSL_TYPE_DECL(name, ssl_type) \
|
||||
struct name : public ssl_wrapper<ssl_type> \
|
||||
{ \
|
||||
name(ssl_type* obj=nullptr) \
|
||||
: ssl_wrapper(obj) {} \
|
||||
~name() \
|
||||
{ \
|
||||
if( obj != nullptr ) \
|
||||
free_func(obj); \
|
||||
} \
|
||||
name( ssl_type* obj=nullptr ); \
|
||||
name( name&& move ); \
|
||||
~name(); \
|
||||
name& operator=( name&& move ); \
|
||||
};
|
||||
|
||||
SSL_TYPE(ec_group, EC_GROUP, EC_GROUP_free)
|
||||
SSL_TYPE(ec_point, EC_POINT, EC_POINT_free)
|
||||
SSL_TYPE(ecdsa_sig, ECDSA_SIG, ECDSA_SIG_free)
|
||||
SSL_TYPE(bn_ctx, BN_CTX, BN_CTX_free)
|
||||
SSL_TYPE(evp_cipher_ctx, EVP_CIPHER_CTX, EVP_CIPHER_CTX_free )
|
||||
SSL_TYPE_DECL(ec_group, EC_GROUP)
|
||||
SSL_TYPE_DECL(ec_point, EC_POINT)
|
||||
SSL_TYPE_DECL(ecdsa_sig, ECDSA_SIG)
|
||||
SSL_TYPE_DECL(bn_ctx, BN_CTX)
|
||||
SSL_TYPE_DECL(evp_cipher_ctx, EVP_CIPHER_CTX)
|
||||
SSL_TYPE_DECL(ssl_dh, DH)
|
||||
|
||||
/** allocates a bignum by default.. */
|
||||
struct ssl_bignum : public ssl_wrapper<BIGNUM>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace fc {
|
|||
boost::endian::little_uint64_buf_at hilo[2];
|
||||
hilo[0] = uint128_hi64( v );
|
||||
hilo[1] = uint128_lo64( v );
|
||||
s.write( hilo[0].data(), sizeof(hilo) );
|
||||
s.write( (char*)hilo[0].data(), sizeof(hilo) );
|
||||
}
|
||||
template<typename Stream>
|
||||
inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth )
|
||||
|
|
@ -307,7 +307,7 @@ namespace fc {
|
|||
template<typename Stream> inline void pack( Stream& s, const bool& v, uint32_t _max_depth )
|
||||
{
|
||||
FC_ASSERT( _max_depth > 0 );
|
||||
fc::raw::pack( s, uint8_t(v), _max_depth - 1 );
|
||||
fc::raw::pack( s, v ? uint8_t(1) : uint8_t(0), _max_depth - 1 );
|
||||
}
|
||||
template<typename Stream> inline void unpack( Stream& s, bool& v, uint32_t _max_depth )
|
||||
{
|
||||
|
|
@ -731,7 +731,7 @@ namespace fc {
|
|||
void pack( Stream& s, const boost::endian::endian_buffer<O,T,N,A>& v, uint32_t _max_depth )
|
||||
{
|
||||
FC_ASSERT( _max_depth > 0 );
|
||||
s.write( v.data(), sizeof(v) );
|
||||
s.write( (char*)v.data(), sizeof(v) );
|
||||
}
|
||||
template<typename Stream, boost::endian::order O, class T, std::size_t N, boost::endian::align A>
|
||||
void unpack( Stream& s, boost::endian::endian_buffer<O,T,N,A>& v, uint32_t _max_depth )
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ namespace fc {
|
|||
return register_appender( type, appender_factory::ptr( new detail::appender_factory_impl<T>() ) );
|
||||
}
|
||||
|
||||
virtual ~appender() = default;
|
||||
static appender::ptr create( const std::string& name, const std::string& type, const variant& args );
|
||||
static appender::ptr get( const std::string& name );
|
||||
static bool register_appender( const std::string& type, const appender_factory::ptr& f );
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ namespace fc {
|
|||
{
|
||||
public:
|
||||
tcp_socket();
|
||||
tcp_socket( tcp_socket& copy ) = delete;
|
||||
~tcp_socket();
|
||||
tcp_socket& operator=( tcp_socket& copy ) = delete;
|
||||
|
||||
void connect_to( const fc::ip::endpoint& remote_endpoint );
|
||||
void bind( const fc::ip::endpoint& local_endpoint );
|
||||
|
|
@ -51,9 +53,9 @@ namespace fc {
|
|||
friend class tcp_server;
|
||||
class impl;
|
||||
#ifdef _WIN64
|
||||
fc::fwd<impl,0x88> my;
|
||||
fc::fwd<impl,0xa8> my;
|
||||
#else
|
||||
fc::fwd<impl,0x54> my;
|
||||
fc::fwd<impl,0x60> my;
|
||||
#endif
|
||||
};
|
||||
typedef std::shared_ptr<tcp_socket> tcp_socket_ptr;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @file fc/reflect.hpp
|
||||
* @file fc/reflect/reflect.hpp
|
||||
*
|
||||
* @brief Defines types and macros used to provide reflection.
|
||||
*
|
||||
|
|
@ -18,9 +18,114 @@
|
|||
#include <type_traits>
|
||||
|
||||
#include <fc/reflect/typename.hpp>
|
||||
#include <fc/reflect/typelist.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
template<typename> struct reflector;
|
||||
namespace member_names {
|
||||
/// A template which stores the name of the native member at a given index in a given class
|
||||
template<typename Class, std::size_t index> struct member_name {
|
||||
constexpr static const char* value = "Unknown member";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A template to store compile-time information about a field in a reflected struct
|
||||
*
|
||||
* @tparam Container The type of the struct or class containing the field
|
||||
* @tparam Member The type of the field
|
||||
* @tparam field A pointer-to-member for the reflected field
|
||||
*/
|
||||
template<std::size_t Index, typename Container, typename Member, Member Container::*field>
|
||||
struct field_reflection {
|
||||
using container = Container;
|
||||
using type = Member;
|
||||
using reflector = fc::reflector<type>;
|
||||
constexpr static std::size_t index = Index;
|
||||
constexpr static bool is_derived = false;
|
||||
constexpr static type container::*pointer = field;
|
||||
|
||||
/// @brief Given a reference to the container type, get a reference to the field
|
||||
static type& get(container& c) { return c.*field; }
|
||||
static const type& get(const container& c) { return c.*field; }
|
||||
/// @brief Get the name of the field
|
||||
static const char* get_name() { return fc::member_names::member_name<container, index>::value; }
|
||||
};
|
||||
/// Basically the same as @ref field_reflection, but for inherited fields
|
||||
/// Note that inherited field reflections do not have an index field; indexes are for native fields only
|
||||
template<std::size_t IndexInBase, typename Base, typename Derived, typename Member, Member Base::*field>
|
||||
struct inherited_field_reflection {
|
||||
using container = Derived;
|
||||
using field_container = Base;
|
||||
using type = Member;
|
||||
using reflector = fc::reflector<type>;
|
||||
constexpr static std::size_t index_in_base = IndexInBase;
|
||||
constexpr static bool is_derived = true;
|
||||
constexpr static type field_container::*pointer = field;
|
||||
|
||||
static type& get(container& c) {
|
||||
// And we need a distinct inherited_field_reflection type because this conversion can't be done statically
|
||||
type container::* derived_field = field;
|
||||
return c.*derived_field;
|
||||
}
|
||||
static const type& get(const container& c) {
|
||||
type container::* derived_field = field;
|
||||
return c.*derived_field;
|
||||
}
|
||||
static const char* get_name() {
|
||||
using Reflector = typename fc::reflector<Base>::native_members::template at<IndexInBase>;
|
||||
return Reflector::get_name();
|
||||
}
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
/// Helper template to create a @ref field_reflection without any commas (makes it macro-friendly)
|
||||
template<typename Container>
|
||||
struct Reflect_type {
|
||||
template<typename Member>
|
||||
struct with_field_type {
|
||||
template<std::size_t Index>
|
||||
struct at_index {
|
||||
template<Member Container::*field>
|
||||
struct with_field_pointer {
|
||||
using type = field_reflection<Index, Container, Member, field>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/// Template to make a transformer of a @ref field_reflection from a base class to a derived class
|
||||
template<typename Derived>
|
||||
struct Derivation_reflection_transformer {
|
||||
template<typename> struct transform;
|
||||
template<std::size_t IndexInBase, typename BaseContainer, typename Member, Member BaseContainer::*field>
|
||||
struct transform<field_reflection<IndexInBase, BaseContainer, Member, field>> {
|
||||
using type = inherited_field_reflection<IndexInBase, BaseContainer, Derived, Member, field>;
|
||||
};
|
||||
template<std::size_t IndexInBase, typename BaseContainer, typename IntermediateContainer,
|
||||
typename Member, Member BaseContainer::*field>
|
||||
struct transform<inherited_field_reflection<IndexInBase, BaseContainer, IntermediateContainer, Member, field>> {
|
||||
using type = inherited_field_reflection<IndexInBase, BaseContainer, Derived, Member, field>;
|
||||
};
|
||||
};
|
||||
} // namespace impl
|
||||
|
||||
/// Macro to transform reflected fields of a base class to a derived class and concatenate them to a type list
|
||||
#define FC_CONCAT_BASE_MEMBER_REFLECTIONS(r, derived, base) \
|
||||
::add_list<typelist::transform<reflector<base>::members, impl::Derivation_reflection_transformer<derived>>>
|
||||
/// Macro to concatenate a new @ref field_reflection to a typelist
|
||||
#define FC_CONCAT_MEMBER_REFLECTION(r, container, idx, member) \
|
||||
::add<typename impl::Reflect_type<container>::template with_field_type<decltype(container::member)> \
|
||||
::template at_index<idx> \
|
||||
::template with_field_pointer<&container::member>::type>
|
||||
#define FC_REFLECT_MEMBER_NAME(r, container, idx, member) \
|
||||
template<> struct member_name<container, idx> { constexpr static const char* value = BOOST_PP_STRINGIZE(member); };
|
||||
#define FC_REFLECT_TEMPLATE_MEMBER_NAME(r, data, idx, member) \
|
||||
template<BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_ELEM(0, data))> struct member_name<BOOST_PP_SEQ_ELEM(1, data), idx> { \
|
||||
constexpr static const char* value = BOOST_PP_STRINGIZE(member); };
|
||||
/// Macro to concatenate a new type to a typelist
|
||||
#define FC_CONCAT_TYPE(r, x, TYPE) ::add<TYPE>
|
||||
|
||||
/**
|
||||
* @brief defines visit functions for T
|
||||
* Unless this is specialized, visit() will not be defined for T.
|
||||
|
|
@ -34,6 +139,14 @@ template<typename T>
|
|||
struct reflector{
|
||||
typedef T type;
|
||||
typedef std::false_type is_defined;
|
||||
/// A typelist with a @ref field_reflection for each native member (non-inherited) of the struct
|
||||
using native_members = typelist::list<>;
|
||||
/// A typelist with a @ref field_reflection for each inherited member of the struct
|
||||
using inherited_members = typelist::list<>;
|
||||
/// A typelist with a @ref field_reflection for each member of the struct, starting with inherited members
|
||||
using members = typelist::list<>;
|
||||
/// A typelist of base classes for this type
|
||||
using base_classes = typelist::list<>;
|
||||
|
||||
/**
|
||||
* @tparam Visitor a function object of the form:
|
||||
|
|
@ -91,31 +204,11 @@ void throw_bad_enum_cast( const char* k, const char* e );
|
|||
case I: FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) break;
|
||||
|
||||
|
||||
#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \
|
||||
OP fc::reflector<elem>::total_member_count
|
||||
|
||||
#define FC_REFLECT_MEMBER_COUNT( r, OP, elem ) \
|
||||
OP 1
|
||||
|
||||
#define FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
|
||||
template<typename Visitor>\
|
||||
static inline void visit( const Visitor& v ) { \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
|
||||
}\
|
||||
template<typename Visitor, typename IndexType>\
|
||||
static inline void visit_local_member( const Visitor& v, IndexType index ) { \
|
||||
switch( index ) {\
|
||||
BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_VISIT_MEMBER_I, v, MEMBERS ) \
|
||||
default: break;\
|
||||
}\
|
||||
}
|
||||
|
||||
#define FC_REFLECT_DERIVED_IMPL_EXT( TYPE, INHERITS, MEMBERS ) \
|
||||
template<typename Visitor>\
|
||||
void fc::reflector<TYPE>::visit( const Visitor& v ) { \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
|
||||
}
|
||||
|
||||
#endif // DOXYGEN
|
||||
|
|
@ -175,7 +268,7 @@ template<> struct reflector<ENUM> { \
|
|||
{ \
|
||||
i = boost::lexical_cast<int64_t>(s); \
|
||||
} \
|
||||
catch( const boost::bad_lexical_cast& e ) \
|
||||
catch( const boost::bad_lexical_cast& ) \
|
||||
{ \
|
||||
fc::throw_bad_enum_cast( s, BOOST_PP_STRINGIZE(ENUM) ); \
|
||||
} \
|
||||
|
|
@ -214,26 +307,73 @@ namespace fc { \
|
|||
template<> struct reflector<TYPE> {\
|
||||
typedef TYPE type; \
|
||||
typedef std::true_type is_defined; \
|
||||
using native_members = \
|
||||
typename typelist::builder<>::type \
|
||||
BOOST_PP_SEQ_FOR_EACH_I( FC_CONCAT_MEMBER_REFLECTION, TYPE, MEMBERS ) ::finalize; \
|
||||
using inherited_members = \
|
||||
typename typelist::builder<>::type \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_BASE_MEMBER_REFLECTIONS, TYPE, INHERITS ) ::finalize; \
|
||||
using members = typename typelist::concat<inherited_members, native_members>::type; \
|
||||
using base_classes = typename typelist::builder<>::type \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \
|
||||
enum member_count_enum { \
|
||||
local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\
|
||||
total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
|
||||
local_member_count = typelist::length<native_members>(), \
|
||||
total_member_count = typelist::length<members>() \
|
||||
}; \
|
||||
FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
|
||||
}; }
|
||||
}; \
|
||||
namespace member_names { \
|
||||
BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_MEMBER_NAME, TYPE, MEMBERS ) \
|
||||
} }
|
||||
|
||||
#define FC_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, INHERITS, MEMBERS ) \
|
||||
namespace fc { \
|
||||
template<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
|
||||
template<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct get_typename<TYPE> { \
|
||||
static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } \
|
||||
}; \
|
||||
template<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct reflector<TYPE> {\
|
||||
typedef TYPE type; \
|
||||
typedef std::true_type is_defined; \
|
||||
using native_members = \
|
||||
typename typelist::builder<>::type \
|
||||
BOOST_PP_SEQ_FOR_EACH_I( FC_CONCAT_MEMBER_REFLECTION, TYPE, MEMBERS ) ::finalize; \
|
||||
using inherited_members = \
|
||||
typename typelist::builder<>::type \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_BASE_MEMBER_REFLECTIONS, TYPE, INHERITS ) ::finalize; \
|
||||
using members = typename typelist::concat<inherited_members, native_members>::type; \
|
||||
using base_classes = typename typelist::builder<>::type \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \
|
||||
enum member_count_enum { \
|
||||
local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\
|
||||
total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
|
||||
local_member_count = typelist::length<native_members>(), \
|
||||
total_member_count = typelist::length<members>() \
|
||||
}; \
|
||||
FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
|
||||
}; }
|
||||
}; \
|
||||
namespace member_names { \
|
||||
BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_TEMPLATE_MEMBER_NAME, (TEMPLATE_ARGS)(TYPE), MEMBERS ) \
|
||||
} }
|
||||
|
||||
//BOOST_PP_SEQ_SIZE(MEMBERS),
|
||||
#define FC_REFLECT_DERIVED_NO_TYPENAME( TYPE, INHERITS, MEMBERS ) \
|
||||
namespace fc { \
|
||||
template<> struct reflector<TYPE> {\
|
||||
typedef TYPE type; \
|
||||
typedef std::true_type is_defined; \
|
||||
using native_members = \
|
||||
typename typelist::builder<>::type \
|
||||
BOOST_PP_SEQ_FOR_EACH_I( FC_CONCAT_MEMBER_REFLECTION, TYPE, MEMBERS ) ::finalize; \
|
||||
using inherited_members = \
|
||||
typename typelist::builder<>::type \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_BASE_MEMBER_REFLECTIONS, TYPE, INHERITS ) ::finalize; \
|
||||
using members = typename typelist::concat<inherited_members, native_members>::type; \
|
||||
using base_classes = typename typelist::builder<>::type \
|
||||
BOOST_PP_SEQ_FOR_EACH( FC_CONCAT_TYPE, x, INHERITS ) ::finalize; \
|
||||
enum member_count_enum { \
|
||||
local_member_count = typelist::length<native_members>(), \
|
||||
total_member_count = typelist::length<members>() \
|
||||
}; \
|
||||
FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
|
||||
}; \
|
||||
} // fc
|
||||
|
||||
/**
|
||||
* @def FC_REFLECT(TYPE,MEMBERS)
|
||||
|
|
@ -244,7 +384,8 @@ template<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct reflector<TYPE> {\
|
|||
* @see FC_REFLECT_DERIVED
|
||||
*/
|
||||
#define FC_REFLECT( TYPE, MEMBERS ) \
|
||||
FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
|
||||
FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
|
||||
|
||||
|
||||
#define FC_REFLECT_TEMPLATE( TEMPLATE_ARGS, TYPE, MEMBERS ) \
|
||||
FC_REFLECT_DERIVED_TEMPLATE( TEMPLATE_ARGS, TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
|
||||
|
|
@ -257,25 +398,3 @@ namespace fc { \
|
|||
template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
|
||||
}
|
||||
|
||||
#define FC_REFLECT_FWD( TYPE ) \
|
||||
namespace fc { \
|
||||
template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
|
||||
template<> struct reflector<TYPE> {\
|
||||
typedef TYPE type; \
|
||||
typedef std::true_type is_defined; \
|
||||
enum member_count_enum { \
|
||||
local_member_count = BOOST_PP_SEQ_SIZE(MEMBERS), \
|
||||
total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
|
||||
}; \
|
||||
template<typename Visitor> static void visit( const Visitor& v ); \
|
||||
}; }
|
||||
|
||||
|
||||
#define FC_REFLECT_DERIVED_IMPL( TYPE, MEMBERS ) \
|
||||
FC_REFLECT_IMPL_DERIVED_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
|
||||
|
||||
#define FC_REFLECT_IMPL( TYPE, MEMBERS ) \
|
||||
FC_REFLECT_DERIVED_IMPL_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
262
include/fc/reflect/typelist.hpp
Normal file
262
include/fc/reflect/typelist.hpp
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @file fc/reflect/typelist.hpp
|
||||
*
|
||||
* @brief Defines a template for manipulating and storing compile-time lists of types
|
||||
*/
|
||||
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
|
||||
namespace fc {
|
||||
|
||||
/// This namespace contains the list type, and all of the operations and queries which can be performed upon it
|
||||
namespace typelist {
|
||||
|
||||
// Forward declare the list so impl can see it
|
||||
template<typename...> struct list;
|
||||
|
||||
namespace impl {
|
||||
using typelist::list;
|
||||
|
||||
template<typename, template<typename...> class> struct apply;
|
||||
template<typename... Ts, template<typename...> class Delegate>
|
||||
struct apply<list<Ts...>, Delegate> { using type = Delegate<Ts...>; };
|
||||
|
||||
template<typename... Ts>
|
||||
struct length;
|
||||
template<> struct length<> { constexpr static std::size_t value = 0; };
|
||||
template<typename T, typename... Ts>
|
||||
struct length<T, Ts...> { constexpr static std::size_t value = length<Ts...>::value+1; };
|
||||
|
||||
template<typename...> struct concat;
|
||||
template<typename... OldTypes, typename... NewTypes>
|
||||
struct concat<list<OldTypes...>, list<NewTypes...>> {
|
||||
using type = list<OldTypes..., NewTypes...>;
|
||||
};
|
||||
template<typename... OldTypes, typename... NewTypes, typename NextList, typename... Lists>
|
||||
struct concat<list<OldTypes...>, list<NewTypes...>, NextList, Lists...> {
|
||||
using type = typename concat<list<OldTypes..., NewTypes...>, NextList, Lists...>::type;
|
||||
};
|
||||
|
||||
template<std::size_t count> struct make_sequence;
|
||||
template<> struct make_sequence<0> { using type = list<>; };
|
||||
template<> struct make_sequence<1> { using type = list<std::integral_constant<std::size_t, 0>>; };
|
||||
template<std::size_t count>
|
||||
struct make_sequence {
|
||||
using type = typename concat<typename make_sequence<count-1>::type,
|
||||
list<std::integral_constant<std::size_t, count-1>>>::type;
|
||||
};
|
||||
|
||||
template<typename, typename> struct transform;
|
||||
template<typename... List, typename Transformer>
|
||||
struct transform<list<List...>, Transformer> {
|
||||
using type = list<typename Transformer::template transform<List>::type...>;
|
||||
};
|
||||
|
||||
template<typename Search, typename List> struct index_of;
|
||||
template<typename Search> struct index_of<Search, list<>> { constexpr static int value = -1; };
|
||||
template<typename Search, typename T, typename... Ts>
|
||||
struct index_of<Search, list<T, Ts...>> {
|
||||
constexpr static int deeper = index_of<Search, list<Ts...>>::value;
|
||||
constexpr static int value = std::is_same<Search, T>::value? 0 : (deeper == -1? -1 : deeper + 1);
|
||||
};
|
||||
|
||||
template<typename...> struct concat_unique;
|
||||
template<typename... Uniques>
|
||||
struct concat_unique<list<Uniques...>, list<>> {
|
||||
using type = list<Uniques...>;
|
||||
};
|
||||
template<typename... Uniques, typename T>
|
||||
struct concat_unique<list<Uniques...>, list<T>> {
|
||||
using type = std::conditional_t<index_of<T, list<Uniques...>>::value >= 0,
|
||||
list<Uniques...>, list<Uniques..., T>>;
|
||||
};
|
||||
template<typename... Uniques, typename T1, typename T2, typename... Types>
|
||||
struct concat_unique<list<Uniques...>, list<T1, T2, Types...>> {
|
||||
using type = typename concat_unique<
|
||||
typename concat_unique<list<Uniques...>, list<T1>>::type, list<T2, Types...>>::type;
|
||||
};
|
||||
template<typename... Uniques, typename... Lists>
|
||||
struct concat_unique<list<Uniques...>, list<>, Lists...> {
|
||||
using type = typename concat_unique<list<Uniques...>, Lists...>::type;
|
||||
};
|
||||
template<typename Uniques, typename L1a, typename... L1s, typename L2, typename... Lists>
|
||||
struct concat_unique<Uniques, list<L1a, L1s...>, L2, Lists...> {
|
||||
using type = typename concat_unique<typename concat_unique<Uniques, list<L1a, L1s...>>::type, L2, Lists...>::type;
|
||||
};
|
||||
|
||||
template<typename, std::size_t> struct at;
|
||||
template<typename T, typename... Types>
|
||||
struct at<list<T, Types...>, 0> { using type = T; };
|
||||
template<typename T, typename... Types, std::size_t index>
|
||||
struct at<list<T, Types...>, index> : at<list<Types...>, index-1> {};
|
||||
|
||||
template<typename, typename, std::size_t> struct remove_at;
|
||||
template<typename... Left, typename T, typename... Right>
|
||||
struct remove_at<list<Left...>, list<T, Right...>, 0> { using type = list<Left..., Right...>; };
|
||||
template<typename... Left, typename T, typename... Right, std::size_t index>
|
||||
struct remove_at<list<Left...>, list<T, Right...>, index> {
|
||||
using type = typename remove_at<list<Left..., T>, list<Right...>, index-1>::type;
|
||||
};
|
||||
|
||||
template<template<typename> class Filter, typename Filtered, typename List> struct filter;
|
||||
template<template<typename> class Filter, typename... Filtered>
|
||||
struct filter<Filter, list<Filtered...>, list<>> { using type = list<Filtered...>; };
|
||||
template<template<typename> class Filter, typename... Filtered, typename T1, typename... Types>
|
||||
struct filter<Filter, list<Filtered...>, list<T1, Types...>> {
|
||||
using type = typename std::conditional_t<Filter<T1>::value,
|
||||
filter<Filter, list<Filtered..., T1>, list<Types...>>,
|
||||
filter<Filter, list<Filtered...>, list<Types...>>>::type;
|
||||
};
|
||||
|
||||
template<typename, typename, std::size_t, std::size_t, typename = void> struct slice;
|
||||
template<typename... Results, typename... Types, std::size_t index>
|
||||
struct slice<list<Results...>, list<Types...>, index, index, void> { using type = list<Results...>; };
|
||||
template<typename... Results, typename T, typename... Types, std::size_t end>
|
||||
struct slice<list<Results...>, list<T, Types...>, 0, end, std::enable_if_t<end != 0>>
|
||||
: slice<list<Results..., T>, list<Types...>, 0, end-1> {};
|
||||
template<typename T, typename... Types, std::size_t start, std::size_t end>
|
||||
struct slice<list<>, list<T, Types...>, start, end, std::enable_if_t<start != 0>>
|
||||
: slice<list<>, list<Types...>, start-1, end-1> {};
|
||||
|
||||
template<typename, typename> struct zip;
|
||||
template<>
|
||||
struct zip<list<>, list<>> { using type = list<>; };
|
||||
template<typename A, typename... As, typename B, typename... Bs>
|
||||
struct zip<list<A, As...>, list<B, Bs...>> {
|
||||
using type = typename concat<list<list<A, B>>, typename zip<list<As...>, list<Bs...>>::type>::type;
|
||||
};
|
||||
|
||||
template<typename Callable, typename Ret, typename T>
|
||||
Ret dispatch_helper(Callable& c) { return c(T()); }
|
||||
|
||||
} // namespace impl
|
||||
|
||||
/// The actual list type
|
||||
template<typename... Types>
|
||||
struct list { using type = list; };
|
||||
|
||||
/// Apply a list of types as arguments to another template
|
||||
template<typename List, template<typename...> class Delegate>
|
||||
using apply = typename impl::apply<List, Delegate>::type;
|
||||
|
||||
/// Get the number of types in a list
|
||||
template<typename List>
|
||||
constexpr static std::size_t length() { return apply<List, impl::length>::value; }
|
||||
|
||||
/// Concatenate two or more typelists together
|
||||
template<typename... Lists>
|
||||
using concat = typename impl::concat<Lists...>::type;
|
||||
|
||||
/// Create a list of sequential integers ranging from [0, count)
|
||||
template<std::size_t count>
|
||||
using make_sequence = typename impl::make_sequence<count>::type;
|
||||
|
||||
/// Template to build typelists using the following syntax:
|
||||
/// builder<>::type::add<T1>::add<T2>::add<T3>[...]::finalize
|
||||
/// Or:
|
||||
/// builder<>::type::add_list<list<T1, T2>>::add_list<T3, T4>>[...]::finalize
|
||||
template<typename List = list<>>
|
||||
struct builder {
|
||||
template<typename NewType> using add = typename builder<typename impl::concat<List, list<NewType>>::type>::type;
|
||||
template<typename NewList> using add_list = typename builder<typename impl::concat<List, NewList>::type>::type;
|
||||
using type = builder;
|
||||
using finalize = List;
|
||||
};
|
||||
|
||||
/// Transform elements of a typelist
|
||||
template<typename List, typename Transformer>
|
||||
using transform = typename impl::transform<List, Transformer>::type;
|
||||
|
||||
/// Get the index of the given type within a list, or -1 if type is not found
|
||||
template<typename List, typename T>
|
||||
constexpr static int index_of() { return impl::index_of<T, List>::value; }
|
||||
|
||||
/// Check if a given type is in a list
|
||||
template<typename List, typename T>
|
||||
constexpr static bool contains() { return impl::index_of<T, List>::value != -1; }
|
||||
|
||||
/// Remove duplicate items from one or more typelists and concatenate them all together
|
||||
template<typename... TypeLists>
|
||||
using concat_unique = typename impl::concat_unique<list<>, TypeLists...>::type;
|
||||
|
||||
/// Get the type at the specified list index
|
||||
template<typename List, std::size_t index>
|
||||
using at = typename impl::at<List, index>::type;
|
||||
|
||||
/// Get the type at the beginning of the list
|
||||
template<typename List>
|
||||
using first = at<List, 0>;
|
||||
/// Get the type at the end of the list
|
||||
template<typename List>
|
||||
using last = at<List, length<List>()-1>;
|
||||
|
||||
/// Get the list with the element at the given index removed
|
||||
template<typename List, std::size_t index>
|
||||
using remove_at = typename impl::remove_at<list<>, List, index>::type;
|
||||
|
||||
/// Get the list with the given type removed
|
||||
template<typename List, typename Remove>
|
||||
using remove_element = remove_at<List, index_of<List, Remove>()>;
|
||||
|
||||
/// Get a list with all elements that do not pass a filter removed
|
||||
template<typename List, template<typename> class Filter>
|
||||
using filter = typename impl::filter<Filter, list<>, List>::type;
|
||||
|
||||
/// Template to invert a filter, i.e. filter<mylist, filter_inverter<myfilter>::type>
|
||||
template<template<typename> class Filter>
|
||||
struct invert_filter {
|
||||
template<typename T>
|
||||
struct type { constexpr static bool value = !Filter<T>::value; };
|
||||
};
|
||||
|
||||
/// Take the sublist at indexes [start, end)
|
||||
template<typename List, std::size_t start, std::size_t end = length<List>()>
|
||||
using slice = typename impl::slice<list<>, List, start, end>::type;
|
||||
|
||||
/// Zip two equal-length typelists together, i.e. zip<list<X, Y>, list<A, B>> == list<list<X, A>, list<Y, B>>
|
||||
template<typename ListA, typename ListB>
|
||||
using zip = typename impl::zip<ListA, ListB>::type;
|
||||
|
||||
/// Add indexes to types in the list, i.e. index<list<A, B, C>> == list<list<0, A>, list<1, B>, list<2, C>> where
|
||||
/// 0, 1, and 2 are std::integral_constants of type std::size_t
|
||||
template<typename List>
|
||||
using index = typename impl::zip<typename impl::make_sequence<length<List>()>::type, List>::type;
|
||||
|
||||
/// This namespace contains some utilities that provide runtime operations on typelists
|
||||
namespace runtime {
|
||||
/// Type wrapper object allowing arbitrary types to be passed to functions as information rather than data
|
||||
template<typename T> struct wrapper { using type = T; };
|
||||
|
||||
/**
|
||||
* @brief Index into the typelist for a type T, and invoke the callable with an argument wrapper<T>()
|
||||
* @param index Index of the type in the typelist to invoke the callable with
|
||||
* @param c The callable to invoke
|
||||
* @return The value returned by the callable
|
||||
* @note The callable return type must be the same for all list elements
|
||||
*
|
||||
* If index is out of bounds, throws std::out_of_range exception
|
||||
*/
|
||||
template<typename... Types, typename Callable, typename = std::enable_if_t<impl::length<Types...>::value != 0>,
|
||||
typename Return = decltype(std::declval<Callable>()(wrapper<at<list<Types...>, 0>>()))>
|
||||
Return dispatch(list<Types...>, std::size_t index, Callable c) {
|
||||
static std::function<Return(Callable&)> call_table[] =
|
||||
{ impl::dispatch_helper<Callable, Return, wrapper<Types>>... };
|
||||
if (index < impl::length<Types...>::value) return call_table[index](c);
|
||||
throw std::out_of_range("Invalid index to fc::typelist::runtime::dispatch()");
|
||||
}
|
||||
template<typename List, typename Callable>
|
||||
auto dispatch(List l, int64_t index, Callable c) {
|
||||
if (index < 0) throw std::out_of_range("Negative index to fc::typelist::runtime::dispatch()");
|
||||
return dispatch(l, std::size_t(index), std::move(c));
|
||||
}
|
||||
|
||||
/// @brief Invoke the provided callable with an argument wrapper<Type>() for each type in the list
|
||||
template<typename... Types, typename Callable>
|
||||
void for_each(list<Types...>, Callable c) {
|
||||
bool trues[] = { [](Callable& c, auto t) { c(t); return true; }(c, wrapper<Types>())... };
|
||||
(void)(trues);
|
||||
}
|
||||
|
||||
} } } // namespace fc::typelist::runtime
|
||||
|
|
@ -12,11 +12,15 @@
|
|||
#include <fc/container/flat_fwd.hpp>
|
||||
|
||||
namespace fc {
|
||||
template<typename...> class static_variant;
|
||||
class value;
|
||||
class exception;
|
||||
namespace ip { class address; }
|
||||
|
||||
template<typename... T> struct get_typename;
|
||||
#if defined(__APPLE__) or defined(__OpenBSD__)
|
||||
template<> struct get_typename<size_t> { static const char* name() { return "size_t"; } };
|
||||
#endif
|
||||
template<> struct get_typename<int32_t> { static const char* name() { return "int32_t"; } };
|
||||
template<> struct get_typename<int64_t> { static const char* name() { return "int64_t"; } };
|
||||
template<> struct get_typename<int16_t> { static const char* name() { return "int16_t"; } };
|
||||
|
|
@ -41,10 +45,19 @@ namespace fc {
|
|||
return n.c_str();
|
||||
}
|
||||
};
|
||||
template<typename T> struct get_typename<flat_set<T>>
|
||||
template<typename T> struct get_typename<flat_set<T>>
|
||||
{
|
||||
static const char* name() {
|
||||
static std::string n = std::string("flat_set<") + get_typename<T>::name() + ">";
|
||||
return n.c_str();
|
||||
}
|
||||
};
|
||||
template<typename... Ts>
|
||||
struct get_typename<flat_set<static_variant<Ts...>, typename static_variant<Ts...>::type_lt>>
|
||||
{
|
||||
static const char* name() {
|
||||
static std::string n = std::string("flat_set<") + get_typename<T>::name() + ">";
|
||||
using TN = get_typename<static_variant<Ts...>>;
|
||||
static std::string n = std::string("flat_set<") + TN::name() + ", " + TN::name() + "::type_lt>";
|
||||
return n.c_str();
|
||||
}
|
||||
};
|
||||
|
|
@ -102,6 +115,22 @@ namespace fc {
|
|||
return _name.c_str();
|
||||
}
|
||||
};
|
||||
template<typename T> struct get_typename< const T* >
|
||||
{
|
||||
static const char* name()
|
||||
{
|
||||
static std::string n = std::string("const ") + get_typename<T>::name() + "*";
|
||||
return n.c_str();
|
||||
}
|
||||
};
|
||||
template<typename T> struct get_typename< T* >
|
||||
{
|
||||
static const char* name()
|
||||
{
|
||||
static std::string n = std::string(get_typename<T>::name()) + "*";
|
||||
return n.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
struct unsigned_int;
|
||||
class variant_object;
|
||||
|
|
|
|||
|
|
@ -44,13 +44,18 @@ namespace fc {
|
|||
}
|
||||
|
||||
template<typename R, typename Arg0, typename ... Args>
|
||||
R call_generic( const std::function<R(Arg0,Args...)>& f, variants::const_iterator a0, variants::const_iterator e, uint32_t max_depth )
|
||||
R call_generic( const std::function<R(Arg0,Args...)>& f, variants::const_iterator a0,
|
||||
variants::const_iterator e, uint32_t max_depth )
|
||||
{
|
||||
bool optional_args = all_optionals<std::decay_t<Arg0>, std::decay_t<Args>...>::value;
|
||||
FC_ASSERT( a0 != e || optional_args );
|
||||
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
|
||||
auto arg = (a0 == e)? std::decay_t<Arg0>() : a0->as<std::decay_t<Arg0>>(max_depth - 1);
|
||||
return call_generic<R,Args...>( bind_first_arg<R,Arg0,Args...>( f, arg ), a0+1, e, max_depth - 1 );
|
||||
if (a0==e)
|
||||
return call_generic<R,Args...>( bind_first_arg<R,Arg0,Args...>( f, std::decay_t<Arg0>() ), a0,
|
||||
e, max_depth - 1 );
|
||||
auto arg = a0->as<std::decay_t<Arg0>>(max_depth - 1);
|
||||
return call_generic<R,Args...>( bind_first_arg<R,Arg0,Args...>( f, std::move(arg) ), a0+1, e,
|
||||
max_depth - 1 );
|
||||
}
|
||||
|
||||
template<typename R, typename ... Args>
|
||||
|
|
@ -180,13 +185,18 @@ namespace fc {
|
|||
}
|
||||
|
||||
template<typename R, typename Arg0, typename ... Args>
|
||||
R call_generic( const std::function<R(Arg0,Args...)>& f, variants::const_iterator a0, variants::const_iterator e, uint32_t max_depth )
|
||||
R call_generic( const std::function<R(Arg0,Args...)>& f, variants::const_iterator a0,
|
||||
variants::const_iterator e, uint32_t max_depth )
|
||||
{
|
||||
bool optional_args = detail::all_optionals<std::decay_t<Arg0>, std::decay_t<Args>...>::value;
|
||||
FC_ASSERT( a0 != e || optional_args, "too few arguments passed to method" );
|
||||
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
|
||||
auto arg = (a0 == e)? std::decay_t<Arg0>() : a0->as<std::decay_t<Arg0>>(max_depth - 1);
|
||||
return call_generic<R,Args...>( this->bind_first_arg<R,Arg0,Args...>( f, arg ), a0+1, e, max_depth - 1 );
|
||||
if (a0==e)
|
||||
return call_generic<R,Args...>( this->bind_first_arg<R,Arg0,Args...>( f, std::decay_t<Arg0>() ), a0,
|
||||
e, max_depth - 1 );
|
||||
auto arg = a0->as<std::decay_t<Arg0>>(max_depth - 1);
|
||||
return call_generic<R,Args...>( this->bind_first_arg<R,Arg0,Args...>( f, std::move(arg) ), a0+1, e,
|
||||
max_depth - 1 );
|
||||
}
|
||||
|
||||
struct api_visitor
|
||||
|
|
|
|||
|
|
@ -1,8 +1,26 @@
|
|||
// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/
|
||||
// published under the WTFPL v2.0
|
||||
|
||||
// Downloaded from http://panthema.net/2008/0901-stacktrace-demangled/
|
||||
// and modified for C++ and FC by Steemit, Inc.
|
||||
/*
|
||||
* Copyright (c) 2018 BitShares Blockchain Foundation, and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* 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
|
||||
|
||||
|
|
|
|||
|
|
@ -23,174 +23,6 @@ namespace fc {
|
|||
// Implementation details, the user should not import this:
|
||||
namespace impl {
|
||||
|
||||
template<int N, typename... Ts>
|
||||
struct storage_ops;
|
||||
|
||||
template<typename X, typename... Ts>
|
||||
struct position;
|
||||
|
||||
template<typename... Ts>
|
||||
struct type_info;
|
||||
|
||||
template<typename StaticVariant>
|
||||
struct copy_construct
|
||||
{
|
||||
typedef void result_type;
|
||||
StaticVariant& sv;
|
||||
copy_construct( StaticVariant& s ):sv(s){}
|
||||
template<typename T>
|
||||
void operator()( const T& v )const
|
||||
{
|
||||
sv.init(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename StaticVariant>
|
||||
struct move_construct
|
||||
{
|
||||
typedef void result_type;
|
||||
StaticVariant& sv;
|
||||
move_construct( StaticVariant& s ):sv(s){}
|
||||
template<typename T>
|
||||
void operator()( T& v )const
|
||||
{
|
||||
sv.init( std::move(v) );
|
||||
}
|
||||
};
|
||||
|
||||
template<int N, typename T, typename... Ts>
|
||||
struct storage_ops<N, T&, Ts...> {
|
||||
static void del(int n, void *data) {}
|
||||
static void con(int n, void *data) {}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, const visitor& v) {}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, visitor& v) {}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {}
|
||||
};
|
||||
|
||||
template<int N, typename T, typename... Ts>
|
||||
struct storage_ops<N, T, Ts...> {
|
||||
static void del(int n, void *data) {
|
||||
if(n == N) reinterpret_cast<T*>(data)->~T();
|
||||
else storage_ops<N + 1, Ts...>::del(n, data);
|
||||
}
|
||||
static void con(int n, void *data) {
|
||||
if(n == N) new(reinterpret_cast<T*>(data)) T();
|
||||
else storage_ops<N + 1, Ts...>::con(n, data);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, const visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<const T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {
|
||||
if(n == N) return v(*reinterpret_cast<const T*>(data));
|
||||
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
|
||||
}
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct storage_ops<N> {
|
||||
static void del(int n, void *data) {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid.");
|
||||
}
|
||||
static void con(int n, void *data) {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." );
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, visitor& v) {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." );
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, void *data, const visitor& v) {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." );
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, visitor& v) {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." );
|
||||
}
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename X>
|
||||
struct position<X> {
|
||||
static constexpr int pos = -1;
|
||||
};
|
||||
|
||||
template<typename X, typename... Ts>
|
||||
struct position<X, X, Ts...> {
|
||||
static constexpr int pos = 0;
|
||||
};
|
||||
|
||||
template<typename X, typename T, typename... Ts>
|
||||
struct position<X, T, Ts...> {
|
||||
static constexpr int pos = position<X, Ts...>::pos != -1 ? position<X, Ts...>::pos + 1 : -1;
|
||||
};
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
struct type_info<T&, Ts...> {
|
||||
static constexpr bool no_reference_types = false;
|
||||
static constexpr bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates;
|
||||
static constexpr size_t size = type_info<Ts...>::size > sizeof(T&) ? type_info<Ts...>::size : sizeof(T&);
|
||||
static constexpr size_t count = 1 + type_info<Ts...>::count;
|
||||
};
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
struct type_info<T, Ts...> {
|
||||
static constexpr bool no_reference_types = type_info<Ts...>::no_reference_types;
|
||||
static constexpr bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates;
|
||||
static constexpr size_t size = type_info<Ts...>::size > sizeof(T) ? type_info<Ts...>::size : sizeof(T&);
|
||||
static constexpr size_t count = 1 + type_info<Ts...>::count;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct type_info<> {
|
||||
static constexpr bool no_reference_types = true;
|
||||
static constexpr bool no_duplicates = true;
|
||||
static constexpr size_t count = 0;
|
||||
static constexpr size_t size = 0;
|
||||
};
|
||||
|
||||
template<typename TTag>
|
||||
constexpr size_t size( TTag )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename TTag, typename A, typename...Ts>
|
||||
constexpr size_t size( TTag tag )
|
||||
{
|
||||
return tag <= 0 ? sizeof(A) : size<TTag, Ts...>( --tag );
|
||||
}
|
||||
|
||||
|
||||
class dynamic_storage
|
||||
{
|
||||
char* storage;
|
||||
|
|
@ -206,71 +38,36 @@ public:
|
|||
void release();
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template<int L,typename Visitor,typename Data>
|
||||
static const std::array<typename Visitor::result_type(*)(Visitor&,Data),L>
|
||||
init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0)
|
||||
{
|
||||
return std::array<typename Visitor::result_type(*)(Visitor&,Data),L>();
|
||||
}
|
||||
|
||||
template<int L,typename Visitor,typename Data,typename T, typename ... Types>
|
||||
static const std::array<typename Visitor::result_type(*)(Visitor&,Data),L>
|
||||
init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 )
|
||||
{
|
||||
std::array<typename Visitor::result_type(*)(Visitor&,Data),L> result{};
|
||||
if( !funcs ) funcs = result.begin();
|
||||
*funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast<T*>( d ) ); };
|
||||
init_wrappers<L,Visitor,Data,Types...>( v, d, funcs );
|
||||
return result;
|
||||
}
|
||||
|
||||
template<int L,typename Visitor,typename Data>
|
||||
static const std::array<typename Visitor::result_type(*)(Visitor&,Data),L>
|
||||
init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 )
|
||||
{
|
||||
return std::array<typename Visitor::result_type(*)(Visitor&,Data),L>();
|
||||
}
|
||||
|
||||
template<int L,typename Visitor,typename Data,typename T, typename ... Types>
|
||||
static const std::array<typename Visitor::result_type(*)(Visitor&,Data),L>
|
||||
init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 )
|
||||
{
|
||||
std::array<typename Visitor::result_type(*)(Visitor&,Data),L> result{};
|
||||
if( !funcs ) funcs = result.begin();
|
||||
*funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast<const T*>( d ) ); };
|
||||
init_const_wrappers<L,Visitor,Data,Types...>( v, d, funcs );
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename... Types>
|
||||
class static_variant {
|
||||
public:
|
||||
using tag_type = int64_t;
|
||||
using list = typelist::list<Types...>;
|
||||
|
||||
protected:
|
||||
static_assert(impl::type_info<Types...>::no_reference_types, "Reference types are not permitted in static_variant.");
|
||||
static_assert(impl::type_info<Types...>::no_duplicates, "static_variant type arguments contain duplicate types.");
|
||||
static_assert(typelist::length<typelist::filter<list, std::is_reference>>() == 0,
|
||||
"Reference types are not permitted in static_variant.");
|
||||
static_assert(typelist::length<typelist::concat_unique<list>>() == typelist::length<list>(),
|
||||
"static_variant type arguments contain duplicate types.");
|
||||
|
||||
template<typename X>
|
||||
using type_in_typelist = typename std::enable_if<impl::position<X, Types...>::pos != -1, X>::type; // type is in typelist of static_variant.
|
||||
using type_in_typelist = std::enable_if_t<typelist::index_of<list, X>() != -1>;
|
||||
|
||||
tag_type _tag;
|
||||
impl::dynamic_storage storage;
|
||||
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
void init(const X& x) {
|
||||
_tag = impl::position<X, Types...>::pos;
|
||||
_tag = typelist::index_of<list, X>();
|
||||
storage.alloc( sizeof(X) );
|
||||
new(storage.data()) X(x);
|
||||
}
|
||||
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
void init(X&& x) {
|
||||
_tag = impl::position<X, Types...>::pos;
|
||||
_tag = typelist::index_of<list, X>();
|
||||
storage.alloc( sizeof(X) );
|
||||
new(storage.data()) X( std::move(x) );
|
||||
}
|
||||
|
|
@ -278,30 +75,79 @@ protected:
|
|||
void init_from_tag(tag_type tag)
|
||||
{
|
||||
FC_ASSERT( tag >= 0 );
|
||||
FC_ASSERT( tag < count() );
|
||||
FC_ASSERT( static_cast<size_t>(tag) < count() );
|
||||
_tag = tag;
|
||||
storage.alloc( impl::size<tag_type, Types...>( tag ) );
|
||||
impl::storage_ops<0, Types...>::con(_tag, storage.data());
|
||||
typelist::runtime::dispatch(list(), tag, [this](auto t) {
|
||||
using T = typename decltype(t)::type;
|
||||
storage.alloc(sizeof(T));
|
||||
new(reinterpret_cast<T*>(storage.data())) T();
|
||||
});
|
||||
}
|
||||
|
||||
void clean()
|
||||
{
|
||||
impl::storage_ops<0, Types...>::del(_tag, storage.data() );
|
||||
typelist::runtime::dispatch(list(), _tag, [data=storage.data()](auto t) {
|
||||
using T = typename decltype(t)::type;
|
||||
reinterpret_cast<T*>(data)->~T();
|
||||
});
|
||||
storage.release();
|
||||
}
|
||||
|
||||
template<typename T, typename = void>
|
||||
struct import_helper {
|
||||
static static_variant construct(const T&) {
|
||||
FC_THROW_EXCEPTION(assert_exception, "Cannot import unsupported type ${T} into static_variant",
|
||||
("T", get_typename<T>::name()));
|
||||
}
|
||||
static static_variant construct(T&&) {
|
||||
FC_THROW_EXCEPTION(assert_exception, "Cannot import unsupported type ${T} into static_variant",
|
||||
("T", get_typename<T>::name()));
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct import_helper<T, type_in_typelist<T>> {
|
||||
static static_variant construct(const T& t) {
|
||||
return static_variant(t);
|
||||
}
|
||||
static static_variant construct(T&& t) {
|
||||
return static_variant(std::move(t));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename StaticVariant>
|
||||
friend struct impl::copy_construct;
|
||||
template<typename StaticVariant>
|
||||
friend struct impl::move_construct;
|
||||
public:
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
struct tag
|
||||
{
|
||||
static constexpr int value = impl::position<X, Types...>::pos;
|
||||
static constexpr tag_type value = typelist::index_of<list, X>();
|
||||
};
|
||||
|
||||
struct type_lt {
|
||||
bool operator()(const static_variant& a, const static_variant& b) const { return a.which() < b.which(); }
|
||||
};
|
||||
struct type_eq {
|
||||
bool operator()(const static_variant& a, const static_variant& b) const { return a.which() == b.which(); }
|
||||
};
|
||||
using flat_set_type = flat_set<static_variant, type_lt>;
|
||||
|
||||
/// Import the value from a foreign static_variant with types not in this one, and throw if the value is an
|
||||
/// incompatible type
|
||||
template<typename... Other>
|
||||
static static_variant import_from(const static_variant<Other...>& other) {
|
||||
return typelist::runtime::dispatch(typelist::list<Other...>(), other.which(), [&other](auto t) {
|
||||
using other_type = typename decltype(t)::type;
|
||||
return import_helper<other_type>::construct(other.template get<other_type>());
|
||||
});
|
||||
}
|
||||
/// Import the value from a foreign static_variant with types not in this one, and throw if the value is an
|
||||
/// incompatible type
|
||||
template<typename... Other>
|
||||
static static_variant import_from(static_variant<Other...>&& other) {
|
||||
return typelist::runtime::dispatch(typelist::list<Other...>(), other.which(), [&other](auto t) {
|
||||
using other_type = typename decltype(t)::type;
|
||||
return import_helper<other_type>::construct(std::move(other.template get<other_type>()));
|
||||
});
|
||||
}
|
||||
|
||||
static_variant()
|
||||
{
|
||||
init_from_tag(0);
|
||||
|
|
@ -310,23 +156,41 @@ public:
|
|||
template<typename... Other>
|
||||
static_variant( const static_variant<Other...>& cpy )
|
||||
{
|
||||
cpy.visit( impl::copy_construct<static_variant>(*this) );
|
||||
typelist::runtime::dispatch(typelist::list<Other...>(), cpy.which(), [this, &cpy](auto t) mutable {
|
||||
this->init(cpy.template get<typename decltype(t)::type>());
|
||||
});
|
||||
}
|
||||
|
||||
static_variant( const static_variant& cpy )
|
||||
{
|
||||
cpy.visit( impl::copy_construct<static_variant>(*this) );
|
||||
typelist::runtime::dispatch(list(), cpy.which(), [this, &cpy](auto t) mutable {
|
||||
this->init(cpy.template get<typename decltype(t)::type>());
|
||||
});
|
||||
}
|
||||
|
||||
static_variant( static_variant&& mv )
|
||||
{
|
||||
mv.visit( impl::move_construct<static_variant>(*this) );
|
||||
typelist::runtime::dispatch(list(), mv.which(), [this, &mv](auto t) mutable {
|
||||
this->init(std::move(mv.template get<typename decltype(t)::type>()));
|
||||
});
|
||||
}
|
||||
|
||||
template<typename... Other>
|
||||
static_variant( static_variant<Other...>&& mv )
|
||||
{
|
||||
typelist::runtime::dispatch(typelist::list<Other...>(), mv.which(), [this, &mv](auto t) mutable {
|
||||
this->init(std::move(mv.template get<typename decltype(t)::type>()));
|
||||
});
|
||||
}
|
||||
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
static_variant(const X& v) {
|
||||
init(v);
|
||||
}
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
static_variant(X&& v) {
|
||||
init(std::move(v));
|
||||
}
|
||||
|
||||
~static_variant() {
|
||||
clean();
|
||||
|
|
@ -342,28 +206,33 @@ public:
|
|||
{
|
||||
if( this == &v ) return *this;
|
||||
clean();
|
||||
v.visit( impl::copy_construct<static_variant>(*this) );
|
||||
typelist::runtime::dispatch(list(), v.which(), [this, &v](auto t)mutable {
|
||||
this->init(v.template get<typename decltype(t)::type>());
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
static_variant& operator=( static_variant&& v )
|
||||
{
|
||||
if( this == &v ) return *this;
|
||||
clean();
|
||||
v.visit( impl::move_construct<static_variant>(*this) );
|
||||
typelist::runtime::dispatch(list(), v.which(), [this, &v](auto t)mutable {
|
||||
this->init(std::move(v.template get<typename decltype(t)::type>()));
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
friend bool operator == ( const static_variant& a, const static_variant& b )
|
||||
{
|
||||
return a.which() == b.which();
|
||||
}
|
||||
friend bool operator < ( const static_variant& a, const static_variant& b )
|
||||
{
|
||||
return a.which() < b.which();
|
||||
|
||||
friend bool operator==( const static_variant& a, const static_variant& b ) {
|
||||
if (a.which() != b.which())
|
||||
return false;
|
||||
return typelist::runtime::dispatch(list(), a.which(), [&a, &b](auto t) {
|
||||
using Value = typename decltype(t)::type;
|
||||
return a.template get<Value>() == b.template get<Value>();
|
||||
});
|
||||
}
|
||||
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
X& get() {
|
||||
if(_tag == impl::position<X, Types...>::pos) {
|
||||
if(_tag == typelist::index_of<list, X>()) {
|
||||
return *reinterpret_cast<X*>(storage.data());
|
||||
} else {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename<X>::name()) );
|
||||
|
|
@ -371,7 +240,7 @@ public:
|
|||
}
|
||||
template<typename X, typename = type_in_typelist<X>>
|
||||
const X& get() const {
|
||||
if(_tag == impl::position<X, Types...>::pos) {
|
||||
if(_tag == typelist::index_of<list, X>()) {
|
||||
return *reinterpret_cast<const X*>(storage.data());
|
||||
} else {
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename<X>::name()) );
|
||||
|
|
@ -400,41 +269,45 @@ public:
|
|||
template<typename visitor>
|
||||
static typename visitor::result_type visit( tag_type tag, visitor& v, void* data )
|
||||
{
|
||||
static const auto wrappers = init_wrappers<impl::type_info<Types...>::count,visitor,void*,Types...>( v, data );
|
||||
FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return wrappers[tag]( v, data );
|
||||
FC_ASSERT( tag >= 0 && static_cast<size_t>(tag) < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) {
|
||||
return v(*reinterpret_cast<typename decltype(t)::type*>(data));
|
||||
});
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type visit( tag_type tag, const visitor& v, void* data )
|
||||
{
|
||||
static const auto wrappers = init_wrappers<impl::type_info<Types...>::count,const visitor,void*,Types...>( v, data );
|
||||
FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return wrappers[tag]( v, data );
|
||||
FC_ASSERT( tag >= 0 && static_cast<size_t>(tag) < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) {
|
||||
return v(*reinterpret_cast<typename decltype(t)::type*>(data));
|
||||
});
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type visit( tag_type tag, visitor& v, const void* data )
|
||||
{
|
||||
static const auto wrappers = init_const_wrappers<impl::type_info<Types...>::count,visitor,const void*,Types...>( v, data );
|
||||
FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return wrappers[tag]( v, data );
|
||||
FC_ASSERT( tag >= 0 && static_cast<size_t>(tag) < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) {
|
||||
return v(*reinterpret_cast<const typename decltype(t)::type*>(data));
|
||||
});
|
||||
}
|
||||
|
||||
template<typename visitor>
|
||||
static typename visitor::result_type visit( tag_type tag, const visitor& v, const void* data )
|
||||
{
|
||||
static const auto wrappers = init_const_wrappers<impl::type_info<Types...>::count,const visitor,const void*,Types...>( v, data );
|
||||
FC_ASSERT( tag >= 0 && tag < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return wrappers[tag]( v, data );
|
||||
FC_ASSERT( tag >= 0 && static_cast<size_t>(tag) < count(), "Unsupported type ${tag}!", ("tag",tag) );
|
||||
return typelist::runtime::dispatch(list(), tag, [&v, data](auto t) {
|
||||
return v(*reinterpret_cast<const typename decltype(t)::type*>(data));
|
||||
});
|
||||
}
|
||||
|
||||
static constexpr int count() { return impl::type_info<Types...>::count; }
|
||||
void set_which( tag_type w ) {
|
||||
FC_ASSERT( w >= 0 );
|
||||
FC_ASSERT( w < count() );
|
||||
static constexpr size_t count() { return typelist::length<list>(); }
|
||||
void set_which( tag_type tag ) {
|
||||
FC_ASSERT( tag >= 0 );
|
||||
FC_ASSERT( static_cast<size_t>(tag) < count() );
|
||||
clean();
|
||||
init_from_tag(w);
|
||||
init_from_tag(tag);
|
||||
}
|
||||
|
||||
tag_type which() const {return _tag;}
|
||||
|
|
@ -442,6 +315,12 @@ public:
|
|||
template<typename T>
|
||||
bool is_type() const { return _tag == tag<T>::value; }
|
||||
};
|
||||
template<> class static_variant<> {
|
||||
public:
|
||||
using tag_type = int64_t;
|
||||
static_variant() { FC_THROW_EXCEPTION(assert_exception, "Cannot create static_variant with no types"); }
|
||||
};
|
||||
template<typename... Types> class static_variant<typelist::list<Types...>> : public static_variant<Types...> {};
|
||||
|
||||
struct from_static_variant
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace fc
|
|||
std::string to_pretty_string( int64_t );
|
||||
inline std::string to_string( int32_t v ) { return to_string( int64_t(v) ); }
|
||||
inline std::string to_string( uint32_t v ){ return to_string( uint64_t(v) ); }
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) or defined(__OpenBSD__)
|
||||
inline std::string to_string( size_t s) { return to_string(uint64_t(s)); }
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
#include <fc/exception/exception.hpp>
|
||||
#include <fc/thread/spin_yield_lock.hpp>
|
||||
#include <fc/optional.hpp>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/atomic.hpp>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
//#define FC_TASK_NAMES_ARE_MANDATORY 1
|
||||
#ifdef FC_TASK_NAMES_ARE_MANDATORY
|
||||
|
|
@ -77,23 +77,22 @@ namespace fc {
|
|||
|
||||
void _wait( const microseconds& timeout_us );
|
||||
void _wait_until( const time_point& timeout_us );
|
||||
void _enqueue_thread();
|
||||
void _dequeue_thread();
|
||||
void _notify();
|
||||
void _set_timeout();
|
||||
void _set_value(const void* v);
|
||||
|
||||
void _on_complete( detail::completion_handler* c );
|
||||
|
||||
private:
|
||||
void _enqueue_thread();
|
||||
void _dequeue_thread();
|
||||
|
||||
friend class thread;
|
||||
friend struct context;
|
||||
friend class thread_d;
|
||||
|
||||
bool _ready;
|
||||
mutable spin_yield_lock _spin_yield;
|
||||
thread* _blocked_thread;
|
||||
unsigned _blocked_fiber_count;
|
||||
std::atomic<bool> _ready;
|
||||
std::atomic<thread*> _blocked_thread;
|
||||
std::atomic<int32_t> _blocked_fiber_count;
|
||||
time_point _timeout;
|
||||
fc::exception_ptr _exceptp;
|
||||
bool _canceled;
|
||||
|
|
@ -103,7 +102,7 @@ namespace fc {
|
|||
private:
|
||||
#endif
|
||||
const char* _desc;
|
||||
detail::completion_handler* _compl;
|
||||
std::atomic<detail::completion_handler*> _compl;
|
||||
};
|
||||
|
||||
template<typename T = void>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include <fc/fwd.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/atomic.hpp>
|
||||
|
||||
namespace fc {
|
||||
struct context;
|
||||
class spin_lock;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
/// This file contains general purpose utilities related to UTF-8 <-> Unicode conversions
|
||||
// This file contains general purpose utilities related to UTF-8 <-> Unicode conversions
|
||||
|
||||
namespace fc
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace fc
|
|||
{
|
||||
void throw_assertion_failure( const std::string& message );
|
||||
}
|
||||
#define _FC_ASSERT( cond, msg ) { if( !(cond) ) { fc::throw_assertion_failure( #cond ": " msg ); } }
|
||||
#define _FC_ASSERT( cond, msg ) { if( !(cond) ) { char t[] = #cond ": " msg; fc::throw_assertion_failure( t ); } }
|
||||
#endif
|
||||
|
||||
namespace fc
|
||||
|
|
@ -153,9 +153,9 @@ namespace fc
|
|||
void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth = 1 );
|
||||
void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth = 1 );
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) or defined(__OpenBSD__)
|
||||
void to_variant( size_t s, variant& v, uint32_t max_depth = 1 );
|
||||
#elif !defined(_MSC_VER)
|
||||
#elif !defined(_WIN32)
|
||||
void to_variant( long long int s, variant& v, uint32_t max_depth = 1 );
|
||||
void to_variant( unsigned long long int s, variant& v, uint32_t max_depth = 1 );
|
||||
#endif
|
||||
|
|
@ -229,7 +229,7 @@ namespace fc
|
|||
variant( uint32_t val, uint32_t max_depth = 1 );
|
||||
variant( int32_t val, uint32_t max_depth = 1 );
|
||||
variant( uint64_t val, uint32_t max_depth = 1 );
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) or defined(__OpenBSD__)
|
||||
variant( size_t val, uint32_t max_depth = 1 );
|
||||
#endif
|
||||
variant( int64_t val, uint32_t max_depth = 1 );
|
||||
|
|
@ -581,9 +581,7 @@ namespace fc
|
|||
memset( this, 0, sizeof(*this) );
|
||||
to_variant( val, *this, max_depth );
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
inline void to_variant( size_t s, variant& v, uint32_t max_depth ) { v = variant(uint64_t(s)); }
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
void to_variant( const std::shared_ptr<T>& var, variant& vo, uint32_t max_depth )
|
||||
{
|
||||
|
|
@ -632,7 +630,7 @@ namespace fc
|
|||
|
||||
template<typename T>
|
||||
void to_variant( const safe<T>& s, variant& v, uint32_t max_depth ) {
|
||||
to_variant( s.value, v, max_depth );
|
||||
to_variant( static_cast<T>(s.value), v, max_depth );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
311
licenses/Apache.txt
Normal file
311
licenses/Apache.txt
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
==============================================================================
|
||||
The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
|
||||
==============================================================================
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
---- LLVM Exceptions to the Apache 2.0 License ----
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into an Object form of such source code, you
|
||||
may redistribute such embedded portions in such Object form without complying
|
||||
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||
|
||||
In addition, if you combine or link compiled forms of this Software with
|
||||
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||
court of competent jurisdiction determines that the patent provision (Section
|
||||
3), the indemnity provision (Section 9) or other Section of the License
|
||||
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||
the License, but only in their entirety and only with respect to the Combined
|
||||
Software.
|
||||
|
||||
==============================================================================
|
||||
Software from third parties included in the LLVM Project:
|
||||
==============================================================================
|
||||
The LLVM Project contains third party software which is under different license
|
||||
terms. All such code will be identified clearly using at least one of two
|
||||
mechanisms:
|
||||
1) It will be in a separate directory tree with its own `LICENSE.txt` or
|
||||
`LICENSE` file at the top containing the specific license and restrictions
|
||||
which apply to that software, or
|
||||
2) It will contain specific license and restriction terms at the top of every
|
||||
file.
|
||||
|
||||
==============================================================================
|
||||
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
|
||||
==============================================================================
|
||||
|
||||
The libc++ library is dual licensed under both the University of Illinois
|
||||
"BSD-Like" license and the MIT license. As a user of this code you may choose
|
||||
to use it under either license. As a contributor, you agree to allow your code
|
||||
to be used under both.
|
||||
|
||||
Full text of the relevant licenses is included below.
|
||||
|
||||
==============================================================================
|
||||
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
||||
LLVM Team
|
||||
|
||||
University of Illinois at Urbana-Champaign
|
||||
|
||||
http://llvm.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal with
|
||||
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:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimers in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the LLVM Team, University of Illinois at
|
||||
Urbana-Champaign, nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this Software without specific
|
||||
prior written permission.
|
||||
|
||||
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
|
||||
CONTRIBUTORS 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 WITH THE
|
||||
SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
|
||||
|
||||
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.
|
||||
23
licenses/Boost_License-1.0.txt
Normal file
23
licenses/Boost_License-1.0.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
22
licenses/COPYING-CMAKE-SCRIPTS
Normal file
22
licenses/COPYING-CMAKE-SCRIPTS
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
23
licenses/MIT_Thrift_LICENSE.md
Normal file
23
licenses/MIT_Thrift_LICENSE.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
17
licenses/MIT_X11_LICENSE.md
Normal file
17
licenses/MIT_X11_LICENSE.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
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.
|
||||
17
licenses/ZLIB_LICENSE.md
Normal file
17
licenses/ZLIB_LICENSE.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
|
@ -28,6 +28,8 @@
|
|||
#include <vector>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
namespace fc { namespace detail {
|
||||
|
||||
/** Errors thrown by the bignum class */
|
||||
class bignum_error : public std::runtime_error
|
||||
{
|
||||
|
|
@ -605,11 +607,10 @@ inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vch
|
|||
return DecodeBase58(str.c_str(), vchRet);
|
||||
}
|
||||
|
||||
|
||||
namespace fc {
|
||||
} // detail
|
||||
|
||||
std::string to_base58( const char* d, size_t s ) {
|
||||
return EncodeBase58( (const unsigned char*)d, (const unsigned char*)d+s ).c_str();
|
||||
return fc::detail::EncodeBase58( (const unsigned char*)d, (const unsigned char*)d+s ).c_str();
|
||||
}
|
||||
|
||||
std::string to_base58( const std::vector<char>& d )
|
||||
|
|
@ -620,8 +621,9 @@ std::string to_base58( const std::vector<char>& d )
|
|||
}
|
||||
std::vector<char> from_base58( const std::string& base58_str ) {
|
||||
std::vector<unsigned char> out;
|
||||
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||
if( !fc::detail::DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}",
|
||||
("base58_str",base58_str) );
|
||||
}
|
||||
return std::vector<char>((const char*)out.data(), ((const char*)out.data())+out.size() );
|
||||
}
|
||||
|
|
@ -629,10 +631,10 @@ std::vector<char> from_base58( const std::string& base58_str ) {
|
|||
* @return the number of bytes decoded
|
||||
*/
|
||||
size_t from_base58( const std::string& base58_str, char* out_data, size_t out_data_len ) {
|
||||
//slog( "%s", base58_str.c_str() );
|
||||
std::vector<unsigned char> out;
|
||||
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||
if( !fc::detail::DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}",
|
||||
("base58_str",base58_str) );
|
||||
}
|
||||
FC_ASSERT( out.size() <= out_data_len );
|
||||
if (!out.empty()) {
|
||||
|
|
@ -640,6 +642,7 @@ size_t from_base58( const std::string& base58_str, char* out_data, size_t out_da
|
|||
}
|
||||
return out.size();
|
||||
}
|
||||
}
|
||||
|
||||
} // fc
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,9 +37,10 @@
|
|||
#include <boost/endian/buffers.hpp>
|
||||
|
||||
#if defined(__SSE4_2__) && defined(__x86_64__)
|
||||
#include <nmmintrin.h>
|
||||
#include <nmmintrin.h>
|
||||
#define _mm_crc32_u64_impl _mm_crc32_u64
|
||||
#else
|
||||
uint64_t _mm_crc32_u64(uint64_t a, uint64_t b );
|
||||
uint64_t _mm_crc32_u64_impl(uint64_t a, uint64_t b );
|
||||
#endif
|
||||
|
||||
namespace fc {
|
||||
|
|
@ -556,9 +557,9 @@ static void CityHashCrc256Long(const char *s, size_t len,
|
|||
g += e; \
|
||||
e += z; \
|
||||
g += x; \
|
||||
z = _mm_crc32_u64(z, b + g); \
|
||||
y = _mm_crc32_u64(y, e + h); \
|
||||
x = _mm_crc32_u64(x, f + a); \
|
||||
z = _mm_crc32_u64_impl(z, b + g); \
|
||||
y = _mm_crc32_u64_impl(y, e + h); \
|
||||
x = _mm_crc32_u64_impl(x, f + a); \
|
||||
e = Rotate(e, r); \
|
||||
c += e; \
|
||||
s += 40
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@ static const uint32_t crc_c[256] = {
|
|||
#if !defined __SSE4_2__ || (defined __SSE4_2__ && !defined __x86_64__)
|
||||
|
||||
|
||||
uint64_t _mm_crc32_u64(uint64_t a, uint64_t b )
|
||||
uint64_t _mm_crc32_u64_impl(uint64_t a, uint64_t b )
|
||||
{
|
||||
// Squelch warning about unusued variable crc_c
|
||||
(void)(crc_c);
|
||||
|
|
@ -619,7 +619,7 @@ int main( int argc, char** argv )
|
|||
{
|
||||
uint64_t f = 0x1234;
|
||||
uint64_t a = 0x5678;
|
||||
uint32_t f1 = _mm_crc32_u64(f, a);
|
||||
uint32_t f1 = _mm_crc32_u64_impl(f, a);
|
||||
uint32_t f4 = crc32cSlicingBy8(f, (unsigned char*)&a, sizeof(a));
|
||||
std::cout<<std::hex<<f1<<"\n"<<f2<<"\n"<<f3<<"\n"<<f4<<"\n";
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
#include <fc/crypto/dh.hpp>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
#endif
|
||||
|
||||
namespace fc {
|
||||
SSL_TYPE(ssl_dh, DH, DH_free)
|
||||
|
||||
static bool validate( const ssl_dh& dh, bool& valid ) {
|
||||
int check;
|
||||
DH_check(dh,&check);
|
||||
|
|
@ -36,7 +33,7 @@ namespace fc {
|
|||
{
|
||||
if( !p.size() )
|
||||
return valid = false;
|
||||
ssl_dh dh = DH_new();
|
||||
ssl_dh dh(DH_new());
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
|
||||
const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
|
||||
|
|
@ -52,7 +49,7 @@ namespace fc {
|
|||
{
|
||||
if( !p.size() )
|
||||
return valid = false;
|
||||
ssl_dh dh = DH_new();
|
||||
ssl_dh dh(DH_new());
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
|
||||
const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
|
||||
|
|
@ -90,7 +87,7 @@ namespace fc {
|
|||
return true;
|
||||
}
|
||||
bool diffie_hellman::compute_shared_key( const char* buf, uint32_t s ) {
|
||||
ssl_dh dh = DH_new();
|
||||
ssl_dh dh(DH_new());
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
|
||||
auto bn_pub_key = BN_bin2bn( (unsigned char*)&pub_key.front(), pub_key.size(), NULL );
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
# include <malloc.h>
|
||||
#else
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
/* stuff common to all ecc implementations */
|
||||
|
|
@ -19,7 +17,7 @@
|
|||
namespace fc { namespace ecc {
|
||||
|
||||
namespace detail {
|
||||
typedef std::array<unsigned char,37> chr37;
|
||||
typedef zero_initialized_array<unsigned char,37> chr37;
|
||||
|
||||
fc::sha256 _left( const fc::sha512& v )
|
||||
{
|
||||
|
|
@ -55,7 +53,7 @@ namespace fc { namespace ecc {
|
|||
static chr37 _derive_message( unsigned char first, const unsigned char* key32, int i )
|
||||
{
|
||||
chr37 result;
|
||||
unsigned char* dest = result.begin();
|
||||
unsigned char* dest = result.data();
|
||||
*dest++ = first;
|
||||
memcpy( dest, key32, 32 ); dest += 32;
|
||||
_put( &dest, i );
|
||||
|
|
@ -64,7 +62,7 @@ namespace fc { namespace ecc {
|
|||
|
||||
chr37 _derive_message( const public_key_data& key, int i )
|
||||
{
|
||||
return _derive_message( *key.begin(), key.begin() + 1, i );
|
||||
return _derive_message( *key.data(), key.data() + 1, i );
|
||||
}
|
||||
|
||||
static chr37 _derive_message( const private_key_secret& key, int i )
|
||||
|
|
@ -142,9 +140,9 @@ namespace fc { namespace ecc {
|
|||
sha256 check = sha256::hash((char*) key.data(), sizeof(key));
|
||||
static_assert(sizeof(key) + 4 == 37, "Elliptic public key size (or its hash) is incorrect");
|
||||
detail::chr37 data;
|
||||
memcpy(data.data(), key.begin(), key.size());
|
||||
memcpy(data.begin() + key.size(), (const char*)check._hash, 4);
|
||||
return fc::to_base58((char*) data.begin(), data.size());
|
||||
memcpy(data.data(), key.data(), key.size());
|
||||
memcpy(data.data() + key.size(), (const char*)check._hash, 4);
|
||||
return fc::to_base58((char*) data.data(), data.size());
|
||||
}
|
||||
|
||||
public_key public_key::from_base58( const std::string& b58 )
|
||||
|
|
@ -163,7 +161,7 @@ namespace fc { namespace ecc {
|
|||
unsigned int public_key::fingerprint() const
|
||||
{
|
||||
public_key_data key = serialize();
|
||||
ripemd160 hash = ripemd160::hash( sha256::hash( (char*) key.begin(), key.size() ) );
|
||||
ripemd160 hash = ripemd160::hash( sha256::hash( (char*) key.data(), key.size() ) );
|
||||
unsigned char* fp = (unsigned char*) hash._hash;
|
||||
return (fp[0] << 24) | (fp[1] << 16) | (fp[2] << 8) | fp[3];
|
||||
}
|
||||
|
|
@ -231,12 +229,11 @@ namespace fc { namespace ecc {
|
|||
|
||||
static std::string _to_base58( const extended_key_data& key )
|
||||
{
|
||||
size_t buf_len = key.size() + 4;
|
||||
char *buffer = (char*)alloca(buf_len);
|
||||
memcpy( buffer, key.begin(), key.size() );
|
||||
fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*) key.begin(), key.size() ));
|
||||
char buffer[std::tuple_size<extended_key_data>::value + 4]; // it's a small static array => allocate on stack
|
||||
memcpy( buffer, key.data(), key.size() );
|
||||
fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*)key.data(), key.size() ));
|
||||
memcpy( buffer + key.size(), double_hash.data(), 4 );
|
||||
return fc::to_base58( buffer, buf_len );
|
||||
return fc::to_base58( buffer, sizeof(buffer) );
|
||||
}
|
||||
|
||||
static void _parse_extended_data( unsigned char* buffer, std::string base58 )
|
||||
|
|
@ -260,14 +257,14 @@ namespace fc { namespace ecc {
|
|||
extended_key_data extended_public_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
unsigned char* dest = (unsigned char*) result.data();
|
||||
detail::_put( &dest, BTC_EXT_PUB_MAGIC );
|
||||
*dest++ = depth;
|
||||
detail::_put( &dest, parent_fp );
|
||||
detail::_put( &dest, child_num );
|
||||
memcpy( dest, c.data(), c.data_size() ); dest += 32;
|
||||
public_key_data key = serialize();
|
||||
memcpy( dest, key.begin(), key.size() );
|
||||
memcpy( dest, key.data(), key.size() );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +290,7 @@ namespace fc { namespace ecc {
|
|||
fc::sha256 chain;
|
||||
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
|
||||
public_key_data key;
|
||||
memcpy( key.begin(), ptr, key.size() );
|
||||
memcpy( key.data(), ptr, key.size() );
|
||||
return extended_public_key( key, chain, cn, fp, d );
|
||||
}
|
||||
|
||||
|
|
@ -311,7 +308,7 @@ namespace fc { namespace ecc {
|
|||
{
|
||||
const detail::chr37 data = detail::_derive_message( get_public_key().serialize(), i );
|
||||
hmac_sha512 mac;
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.begin(), data.size() );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.data(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
|
|
@ -320,14 +317,14 @@ namespace fc { namespace ecc {
|
|||
hmac_sha512 mac;
|
||||
private_key_secret key = get_secret();
|
||||
const detail::chr37 data = detail::_derive_message( key, i );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.begin(), data.size() );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.data(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
extended_key_data extended_private_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
unsigned char* dest = (unsigned char*) result.data();
|
||||
detail::_put( &dest, BTC_EXT_PRIV_MAGIC );
|
||||
*dest++ = depth;
|
||||
detail::_put( &dest, parent_fp );
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ namespace fc { namespace ecc {
|
|||
FC_ASSERT( my->_key != empty_priv );
|
||||
public_key_data pub;
|
||||
unsigned int pk_len;
|
||||
FC_ASSERT( secp256k1_ec_pubkey_create( detail::_get_context(), (unsigned char*) pub.begin(), (int*) &pk_len, (unsigned char*) my->_key.data(), 1 ) );
|
||||
FC_ASSERT( secp256k1_ec_pubkey_create( detail::_get_context(), pub.data(), (int*) &pk_len,
|
||||
(unsigned char*) my->_key.data(), 1 ) );
|
||||
FC_ASSERT( pk_len == pub.size() );
|
||||
return public_key(pub);
|
||||
}
|
||||
|
|
@ -93,9 +94,11 @@ namespace fc { namespace ecc {
|
|||
unsigned int counter = 0;
|
||||
do
|
||||
{
|
||||
FC_ASSERT( secp256k1_ecdsa_sign_compact( detail::_get_context(), (unsigned char*) digest.data(), (unsigned char*) result.begin() + 1, (unsigned char*) my->_key.data(), extended_nonce_function, &counter, &recid ));
|
||||
FC_ASSERT( secp256k1_ecdsa_sign_compact( detail::_get_context(), (unsigned char*) digest.data(),
|
||||
result.data() + 1, (unsigned char*) my->_key.data(),
|
||||
extended_nonce_function, &counter, &recid ));
|
||||
} while( require_canonical && !public_key::is_canonical( result ) );
|
||||
result.begin()[0] = 27 + 4 + recid;
|
||||
result.data()[0] = 27 + 4 + recid;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
|
||||
#if _WIN32
|
||||
# include <malloc.h>
|
||||
#else
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include "_elliptic_impl_priv.hpp"
|
||||
|
|
@ -53,7 +51,7 @@ namespace fc { namespace ecc {
|
|||
public_key_data _key;
|
||||
};
|
||||
|
||||
typedef std::array<char,37> chr37;
|
||||
typedef zero_initialized_array<unsigned char,37> chr37;
|
||||
chr37 _derive_message( const public_key_data& key, int i );
|
||||
fc::sha256 _left( const fc::sha512& v );
|
||||
fc::sha256 _right( const fc::sha512& v );
|
||||
|
|
@ -70,8 +68,9 @@ namespace fc { namespace ecc {
|
|||
FC_ASSERT( my->_key != empty_priv );
|
||||
FC_ASSERT( other.my->_key != empty_pub );
|
||||
public_key_data pub(other.my->_key);
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), pub.begin(), pub.size(), (unsigned char*) my->_key.data() ) );
|
||||
return fc::sha512::hash( (char*) pub.begin() + 1, pub.size() - 1 );
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), pub.data(), pub.size(),
|
||||
(unsigned char*) my->_key.data() ) );
|
||||
return fc::sha512::hash( (char*) pub.data() + 1, pub.size() - 1 );
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -104,8 +103,9 @@ namespace fc { namespace ecc {
|
|||
{
|
||||
FC_ASSERT( my->_key != empty_pub );
|
||||
public_key_data new_key;
|
||||
memcpy( new_key.begin(), my->_key.begin(), new_key.size() );
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), new_key.begin(), new_key.size(), (unsigned char*) digest.data() ) );
|
||||
memcpy( new_key.data(), my->_key.data(), new_key.size() );
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), new_key.data(), new_key.size(),
|
||||
(unsigned char*) digest.data() ) );
|
||||
return public_key( new_key );
|
||||
}
|
||||
|
||||
|
|
@ -126,8 +126,8 @@ namespace fc { namespace ecc {
|
|||
FC_ASSERT( my->_key != empty_pub );
|
||||
public_key_point_data dat;
|
||||
unsigned int pk_len = my->_key.size();
|
||||
memcpy( dat.begin(), my->_key.begin(), pk_len );
|
||||
FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), dat.begin(), (int*) &pk_len ) );
|
||||
memcpy( dat.data(), my->_key.data(), pk_len );
|
||||
FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), dat.data(), (int*) &pk_len ) );
|
||||
FC_ASSERT( pk_len == dat.size() );
|
||||
return dat;
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ namespace fc { namespace ecc {
|
|||
key = o2i_ECPublicKey( &key, &front, sizeof(dat) );
|
||||
FC_ASSERT( key );
|
||||
EC_KEY_set_conv_form( key, POINT_CONVERSION_COMPRESSED );
|
||||
unsigned char* buffer = my->_key.begin();
|
||||
unsigned char* buffer = my->_key.data();
|
||||
i2o_ECPublicKey( key, &buffer ); // FIXME: questionable memory handling
|
||||
EC_KEY_free( key );
|
||||
}
|
||||
|
|
@ -165,7 +165,9 @@ namespace fc { namespace ecc {
|
|||
}
|
||||
|
||||
unsigned int pk_len;
|
||||
FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(), c.begin() + 1, my->_key.begin(), (int*) &pk_len, 1, (*c.begin() - 27) & 3 ) );
|
||||
FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(),
|
||||
c.data() + 1, my->_key.data(), (int*) &pk_len, 1,
|
||||
(*c.data() - 27) & 3 ) );
|
||||
FC_ASSERT( pk_len == my->_key.size() );
|
||||
}
|
||||
|
||||
|
|
@ -178,10 +180,11 @@ namespace fc { namespace ecc {
|
|||
hmac_sha512 mac;
|
||||
public_key_data key = serialize();
|
||||
const detail::chr37 data = detail::_derive_message( key, i );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), (const char*) data.data(), data.size() );
|
||||
fc::sha256 left = detail::_left(l);
|
||||
FC_ASSERT( left < detail::get_curve_order() );
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), key.begin(), key.size(), (unsigned char*) left.data() ) > 0 );
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), key.data(), key.size(),
|
||||
(unsigned char*) left.data() ) > 0 );
|
||||
// FIXME: check validity - if left + key == infinity then invalid
|
||||
extended_public_key result( key, detail::_right(l), i, fingerprint(), depth + 1 );
|
||||
return result;
|
||||
|
|
|
|||
143
src/crypto/hash160.cpp
Normal file
143
src/crypto/hash160.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2018 jmjatlanta and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/ripemd.h>
|
||||
#include <string.h>
|
||||
#include <cmath>
|
||||
#include <fc/crypto/hash160.hpp>
|
||||
#include <fc/variant.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include "_digest_common.hpp"
|
||||
|
||||
namespace fc
|
||||
{
|
||||
|
||||
hash160::hash160() { memset( _hash, 0, sizeof(_hash) ); }
|
||||
|
||||
hash160::hash160( const string& hex_str ) {
|
||||
fc::from_hex( hex_str, (char*)_hash, sizeof(_hash) );
|
||||
}
|
||||
|
||||
string hash160::str()const {
|
||||
return fc::to_hex( (char*)_hash, sizeof(_hash) );
|
||||
}
|
||||
|
||||
hash160::operator string()const { return str(); }
|
||||
|
||||
char* hash160::data()const { return (char*)&_hash[0]; }
|
||||
|
||||
struct hash160::encoder::impl {
|
||||
SHA256_CTX ctx;
|
||||
};
|
||||
|
||||
hash160::encoder::~encoder() {}
|
||||
hash160::encoder::encoder() { SHA256_Init(&my->ctx); }
|
||||
|
||||
hash160 hash160::hash( const char* d, uint32_t dlen ) {
|
||||
encoder e;
|
||||
e.write(d,dlen);
|
||||
return e.result();
|
||||
}
|
||||
|
||||
hash160 hash160::hash( const string& s ) {
|
||||
return hash( s.c_str(), s.size() );
|
||||
}
|
||||
|
||||
void hash160::encoder::write( const char* d, uint32_t dlen )
|
||||
{
|
||||
SHA256_Update( &my->ctx, d, dlen);
|
||||
}
|
||||
|
||||
hash160 hash160::encoder::result() {
|
||||
// finalize the first hash
|
||||
unsigned char sha_hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256_Final( sha_hash, &my->ctx );
|
||||
// perform the second hashing function
|
||||
RIPEMD160_CTX ripe_ctx;
|
||||
RIPEMD160_Init(&ripe_ctx);
|
||||
RIPEMD160_Update( &ripe_ctx, sha_hash, SHA256_DIGEST_LENGTH );
|
||||
hash160 h;
|
||||
RIPEMD160_Final( (uint8_t *)h.data(), &ripe_ctx );
|
||||
return h;
|
||||
}
|
||||
|
||||
void hash160::encoder::reset()
|
||||
{
|
||||
SHA256_Init(&my->ctx);
|
||||
}
|
||||
|
||||
hash160 operator << ( const hash160& h1, uint32_t i ) {
|
||||
hash160 result;
|
||||
fc::detail::shift_l( h1.data(), result.data(), result.data_size(), i );
|
||||
return result;
|
||||
}
|
||||
|
||||
hash160 operator ^ ( const hash160& h1, const hash160& h2 ) {
|
||||
hash160 result;
|
||||
result._hash[0] = h1._hash[0].value() ^ h2._hash[0].value();
|
||||
result._hash[1] = h1._hash[1].value() ^ h2._hash[1].value();
|
||||
result._hash[2] = h1._hash[2].value() ^ h2._hash[2].value();
|
||||
result._hash[3] = h1._hash[3].value() ^ h2._hash[3].value();
|
||||
result._hash[4] = h1._hash[4].value() ^ h2._hash[4].value();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator >= ( const hash160& h1, const hash160& h2 ) {
|
||||
return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) >= 0;
|
||||
}
|
||||
|
||||
bool operator > ( const hash160& h1, const hash160& h2 ) {
|
||||
return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) > 0;
|
||||
}
|
||||
|
||||
bool operator < ( const hash160& h1, const hash160& h2 ) {
|
||||
return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) < 0;
|
||||
}
|
||||
|
||||
bool operator != ( const hash160& h1, const hash160& h2 ) {
|
||||
return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) != 0;
|
||||
}
|
||||
|
||||
bool operator == ( const hash160& h1, const hash160& h2 ) {
|
||||
return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) == 0;
|
||||
}
|
||||
|
||||
void to_variant( const hash160& bi, variant& v, uint32_t max_depth )
|
||||
{
|
||||
to_variant( std::vector<char>( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ), v, max_depth );
|
||||
}
|
||||
|
||||
void from_variant( const variant& v, hash160& bi, uint32_t max_depth )
|
||||
{
|
||||
std::vector<char> ve = v.as< std::vector<char> >( max_depth );
|
||||
memset( &bi, char(0), sizeof(bi) );
|
||||
if( ve.size() )
|
||||
memcpy( &bi, ve.data(), std::min<size_t>(ve.size(),sizeof(bi)) );
|
||||
}
|
||||
|
||||
} // fc
|
||||
|
|
@ -39,7 +39,11 @@ namespace fc
|
|||
|
||||
~openssl_scope()
|
||||
{
|
||||
#if not defined(LIBRESSL_VERSION_NUMBER)
|
||||
// No FIPS in LibreSSL.
|
||||
// https://marc.info/?l=openbsd-misc&m=139819485423701&w=2
|
||||
FIPS_mode_set(0);
|
||||
#endif
|
||||
CONF_modules_unload(1);
|
||||
EVP_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
|
|
@ -59,4 +63,34 @@ namespace fc
|
|||
static openssl_scope ossl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SSL_TYPE_IMPL(name, ssl_type, free_func) \
|
||||
name::name( ssl_type* obj ) : ssl_wrapper(obj) {} \
|
||||
name::name( name&& move ) : ssl_wrapper( move.obj ) \
|
||||
{ \
|
||||
move.obj = nullptr; \
|
||||
} \
|
||||
name::~name() \
|
||||
{ \
|
||||
if( obj != nullptr ) \
|
||||
free_func(obj); \
|
||||
} \
|
||||
name& name::operator=( name&& move ) \
|
||||
{ \
|
||||
if( this != &move ) \
|
||||
{ \
|
||||
if( obj != nullptr ) \
|
||||
free_func(obj); \
|
||||
obj = move.obj; \
|
||||
move.obj = nullptr; \
|
||||
} \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
SSL_TYPE_IMPL(ec_group, EC_GROUP, EC_GROUP_free)
|
||||
SSL_TYPE_IMPL(ec_point, EC_POINT, EC_POINT_free)
|
||||
SSL_TYPE_IMPL(ecdsa_sig, ECDSA_SIG, ECDSA_SIG_free)
|
||||
SSL_TYPE_IMPL(bn_ctx, BN_CTX, BN_CTX_free)
|
||||
SSL_TYPE_IMPL(evp_cipher_ctx, EVP_CIPHER_CTX, EVP_CIPHER_CTX_free )
|
||||
SSL_TYPE_IMPL(ssl_dh, DH, DH_free)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,22 +182,41 @@ namespace fc
|
|||
*/
|
||||
string exception::to_detail_string( log_level ll )const
|
||||
{
|
||||
fc::stringstream ss;
|
||||
ss << variant(my->_code).as_string() <<" " << my->_name << ": " <<my->_what<<"\n";
|
||||
for( auto itr = my->_elog.begin(); itr != my->_elog.end(); )
|
||||
{
|
||||
ss << itr->get_message() <<"\n";
|
||||
try
|
||||
{
|
||||
ss << " " << json::to_string( itr->get_data() )<<"\n";
|
||||
std::stringstream ss;
|
||||
try {
|
||||
try {
|
||||
ss << variant( my->_code ).as_string();
|
||||
} catch( std::bad_alloc& ) {
|
||||
throw;
|
||||
} catch( ... ) {
|
||||
ss << "<- exception in to_detail_string.";
|
||||
}
|
||||
catch( const fc::assert_exception& e )
|
||||
ss << " " << my->_name << ": " << my->_what << "\n";
|
||||
for( auto itr = my->_elog.begin(); itr != my->_elog.end(); )
|
||||
{
|
||||
ss << "ERROR: Failed to convert log data to string!\n";
|
||||
try {
|
||||
ss << itr->get_message() <<"\n";
|
||||
try
|
||||
{
|
||||
ss << " " << json::to_string( itr->get_data() )<<"\n";
|
||||
}
|
||||
catch( const fc::assert_exception& e )
|
||||
{
|
||||
ss << "ERROR: Failed to convert log data to string!\n";
|
||||
}
|
||||
ss << " " << itr->get_context().to_string();
|
||||
} catch( std::bad_alloc& ) {
|
||||
throw;
|
||||
} catch( ... ) {
|
||||
ss << "<- exception in to_detail_string.";
|
||||
}
|
||||
++itr;
|
||||
if( itr != my->_elog.end() ) ss<<"\n";
|
||||
}
|
||||
ss << " " << itr->get_context().to_string();
|
||||
++itr;
|
||||
if( itr != my->_elog.end() ) ss<<"\n";
|
||||
} catch( std::bad_alloc& ) {
|
||||
throw;
|
||||
} catch( ... ) {
|
||||
ss << "<- exception in to_detail_string.\n";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
|
@ -207,12 +226,23 @@ namespace fc
|
|||
*/
|
||||
string exception::to_string( log_level ll )const
|
||||
{
|
||||
fc::stringstream ss;
|
||||
ss << what() << ":";
|
||||
for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr )
|
||||
{
|
||||
if( itr->get_format().size() )
|
||||
ss << " " << fc::format_string( itr->get_format(), itr->get_data() );
|
||||
std::stringstream ss;
|
||||
try {
|
||||
ss << what() << ":";
|
||||
for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) {
|
||||
if( itr->get_format().size() )
|
||||
try {
|
||||
ss << " " << fc::format_string( itr->get_format(), itr->get_data() );
|
||||
} catch( std::bad_alloc& ) {
|
||||
throw;
|
||||
} catch( ... ) {
|
||||
ss << "<- exception in to_string.\n";
|
||||
}
|
||||
}
|
||||
} catch( std::bad_alloc& ) {
|
||||
throw;
|
||||
} catch( ... ) {
|
||||
ss << "<- exception in to_string.\n";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,18 +21,13 @@ namespace fc {
|
|||
boost::mutex slock;
|
||||
|
||||
private:
|
||||
future<void> _rotation_task;
|
||||
time_point_sec _current_file_start_time;
|
||||
|
||||
time_point_sec get_file_start_time( const time_point_sec& timestamp, const microseconds& interval )
|
||||
{
|
||||
int64_t interval_seconds = interval.to_seconds();
|
||||
int64_t file_number = timestamp.sec_since_epoch() / interval_seconds;
|
||||
return time_point_sec( (uint32_t)(file_number * interval_seconds) );
|
||||
}
|
||||
future<void> _deletion_task;
|
||||
boost::atomic<int64_t> _current_file_number;
|
||||
const int64_t _interval_seconds;
|
||||
time_point _next_file_time;
|
||||
|
||||
public:
|
||||
impl( const config& c) : cfg( c )
|
||||
impl( const config& c) : cfg( c ), _interval_seconds( cfg.rotation_interval.to_seconds() )
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -44,6 +39,7 @@ namespace fc {
|
|||
FC_ASSERT( cfg.rotation_limit >= cfg.rotation_interval );
|
||||
|
||||
rotate_files( true );
|
||||
delete_files();
|
||||
} else {
|
||||
out.open( cfg.filename, std::ios_base::out | std::ios_base::app);
|
||||
}
|
||||
|
|
@ -58,7 +54,7 @@ namespace fc {
|
|||
{
|
||||
try
|
||||
{
|
||||
_rotation_task.cancel_and_wait("file_appender is destructing");
|
||||
_deletion_task.cancel_and_wait("file_appender is destructing");
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
|
|
@ -67,9 +63,22 @@ namespace fc {
|
|||
|
||||
void rotate_files( bool initializing = false )
|
||||
{
|
||||
FC_ASSERT( cfg.rotate );
|
||||
if( !cfg.rotate ) return;
|
||||
|
||||
fc::time_point now = time_point::now();
|
||||
fc::time_point_sec start_time = get_file_start_time( now, cfg.rotation_interval );
|
||||
if( now < _next_file_time ) return;
|
||||
|
||||
int64_t new_file_number = now.sec_since_epoch() / _interval_seconds;
|
||||
if( initializing )
|
||||
_current_file_number.store( new_file_number );
|
||||
else
|
||||
{
|
||||
int64_t prev_file_number = _current_file_number.load();
|
||||
if( prev_file_number >= new_file_number ) return;
|
||||
if( !_current_file_number.compare_exchange_weak( prev_file_number, new_file_number ) ) return;
|
||||
}
|
||||
fc::time_point_sec start_time = time_point_sec( (uint32_t)(new_file_number * _interval_seconds) );
|
||||
_next_file_time = start_time + _interval_seconds;
|
||||
string timestamp_string = start_time.to_non_delimited_iso_string();
|
||||
fc::path link_filename = cfg.filename;
|
||||
fc::path log_filename = link_filename.parent_path() / (link_filename.filename().string() + "." + timestamp_string);
|
||||
|
|
@ -79,14 +88,6 @@ namespace fc {
|
|||
|
||||
if( !initializing )
|
||||
{
|
||||
if( start_time <= _current_file_start_time )
|
||||
{
|
||||
_rotation_task = schedule( [this]() { rotate_files(); },
|
||||
_current_file_start_time + cfg.rotation_interval.to_seconds(),
|
||||
"rotate_files(2)" );
|
||||
return;
|
||||
}
|
||||
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
|
@ -94,29 +95,34 @@ namespace fc {
|
|||
out.open( log_filename, std::ios_base::out | std::ios_base::app );
|
||||
create_hard_link(log_filename, link_filename);
|
||||
}
|
||||
}
|
||||
|
||||
void delete_files()
|
||||
{
|
||||
/* Delete old log files */
|
||||
fc::time_point limit_time = now - cfg.rotation_limit;
|
||||
auto current_file = _current_file_number.load();
|
||||
fc::time_point_sec start_time = time_point_sec( (uint32_t)(current_file * _interval_seconds) );
|
||||
fc::time_point limit_time = time_point::now() - cfg.rotation_limit;
|
||||
fc::path link_filename = cfg.filename;
|
||||
string link_filename_string = link_filename.filename().string();
|
||||
directory_iterator itr(link_filename.parent_path());
|
||||
string timestamp_string = start_time.to_non_delimited_iso_string();
|
||||
for( ; itr != directory_iterator(); itr++ )
|
||||
{
|
||||
try
|
||||
{
|
||||
string current_filename = itr->filename().string();
|
||||
if (current_filename.compare(0, link_filename_string.size(), link_filename_string) != 0 ||
|
||||
current_filename.size() <= link_filename_string.size() + 1)
|
||||
continue;
|
||||
if( current_filename.compare(0, link_filename_string.size(), link_filename_string) != 0
|
||||
|| current_filename.size() <= link_filename_string.size() + 1 )
|
||||
continue;
|
||||
string current_timestamp_str = current_filename.substr(link_filename_string.size() + 1,
|
||||
timestamp_string.size());
|
||||
fc::time_point_sec current_timestamp = fc::time_point_sec::from_iso_string( current_timestamp_str );
|
||||
if( current_timestamp < start_time )
|
||||
if( current_timestamp < start_time
|
||||
&& ( current_timestamp < limit_time || file_size( current_filename ) <= 0 ) )
|
||||
{
|
||||
if( current_timestamp < limit_time || file_size( current_filename ) <= 0 )
|
||||
{
|
||||
remove_all( *itr );
|
||||
continue;
|
||||
}
|
||||
remove_all( *itr );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (const fc::canceled_exception&)
|
||||
|
|
@ -127,11 +133,10 @@ namespace fc {
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
_current_file_start_time = start_time;
|
||||
_rotation_task = schedule( [this]() { rotate_files(); },
|
||||
_current_file_start_time + cfg.rotation_interval.to_seconds(),
|
||||
"rotate_files(3)" );
|
||||
uint64_t next_file = time_point::now().sec_since_epoch() / _interval_seconds + 1;
|
||||
_deletion_task = schedule( [this]() { delete_files(); },
|
||||
fc::time_point_sec( next_file * _interval_seconds),
|
||||
"delete_files(3)" );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -151,8 +156,9 @@ namespace fc {
|
|||
// MS THREAD METHOD MESSAGE \t\t\t File:Line
|
||||
void file_appender::log( const log_message& m )
|
||||
{
|
||||
my->rotate_files();
|
||||
|
||||
std::stringstream line;
|
||||
//line << (m.get_context().get_timestamp().time_since_epoch().count() % (1000ll*1000ll*60ll*60))/1000 <<"ms ";
|
||||
line << string(m.get_context().get_timestamp()) << " ";
|
||||
line << std::setw( 21 ) << (m.get_context().get_thread_name().substr(0,9) + string(":") + m.get_context().get_task_name()).c_str() << " ";
|
||||
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ std::vector<header> parse_urlencoded_params( const std::string& f ) {
|
|||
std::vector<header> h(num_args);
|
||||
int arg = 0;
|
||||
for( size_t i = 0; i < f.size(); ++i ) {
|
||||
while( f[i] != '=' && i < f.size() ) {
|
||||
while( i < f.size() && f[i] != '=' ) {
|
||||
if( f[i] == '%' ) {
|
||||
h[arg].key += char((fc::from_hex(f[i+1]) << 4) | fc::from_hex(f[i+2]));
|
||||
i += 3;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#if WIN32
|
||||
#include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
#ifdef DEFAULT_LOGGER
|
||||
# undef DEFAULT_LOGGER
|
||||
#endif
|
||||
|
|
@ -30,7 +34,33 @@
|
|||
namespace fc { namespace http {
|
||||
|
||||
namespace detail {
|
||||
#if WIN32
|
||||
// taken from https://stackoverflow.com/questions/39772878/reliable-way-to-get-root-ca-certificates-on-windows/40710806
|
||||
static void add_windows_root_certs(boost::asio::ssl::context &ctx)
|
||||
{
|
||||
HCERTSTORE hStore = CertOpenSystemStore( 0, "ROOT" );
|
||||
if( hStore == NULL )
|
||||
return;
|
||||
|
||||
X509_STORE *store = X509_STORE_new();
|
||||
PCCERT_CONTEXT pContext = NULL;
|
||||
while( (pContext = CertEnumCertificatesInStore( hStore, pContext )) != NULL )
|
||||
{
|
||||
X509 *x509 = d2i_X509( NULL, (const unsigned char **)&pContext->pbCertEncoded,
|
||||
pContext->cbCertEncoded);
|
||||
if( x509 != NULL )
|
||||
{
|
||||
X509_STORE_add_cert( store, x509 );
|
||||
X509_free( x509 );
|
||||
}
|
||||
}
|
||||
|
||||
CertFreeCertificateContext( pContext );
|
||||
CertCloseStore( hStore, 0 );
|
||||
|
||||
SSL_CTX_set_cert_store( ctx.native_handle(), store );
|
||||
}
|
||||
#endif
|
||||
struct asio_with_stub_log : public websocketpp::config::asio {
|
||||
|
||||
typedef asio_with_stub_log type;
|
||||
|
|
@ -545,7 +575,13 @@ namespace fc { namespace http {
|
|||
return;
|
||||
ctx->set_verify_mode( boost::asio::ssl::verify_peer );
|
||||
if( ca_filename == "_default" )
|
||||
{
|
||||
#if WIN32
|
||||
add_windows_root_certs( *ctx );
|
||||
#else
|
||||
ctx->set_default_verify_paths();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
ctx->load_verify_file( ca_filename );
|
||||
ctx->set_verify_depth(10);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@
|
|||
# include <mstcpip.h>
|
||||
#endif
|
||||
|
||||
#if defined __OpenBSD__
|
||||
# include <sys/types.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <netinet/tcp_timer.h>
|
||||
# include <netinet/tcp_var.h>
|
||||
#endif
|
||||
|
||||
namespace fc {
|
||||
|
||||
namespace detail
|
||||
|
|
@ -186,16 +193,37 @@ namespace fc {
|
|||
if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP,
|
||||
#if defined( __APPLE__ )
|
||||
TCP_KEEPALIVE,
|
||||
#elif defined( __OpenBSD__ )
|
||||
SO_KEEPALIVE,
|
||||
#else
|
||||
TCP_KEEPIDLE,
|
||||
#endif
|
||||
(char*)&timeout_sec, sizeof(timeout_sec)) < 0)
|
||||
wlog("Error setting TCP keepalive idle time");
|
||||
# if !defined(__APPLE__) || defined(TCP_KEEPINTVL) // TCP_KEEPINTVL not defined before 10.9
|
||||
# if defined(__OpenBSD__)
|
||||
int name[4];
|
||||
name[0] = CTL_NET;
|
||||
name[1] = PF_INET;
|
||||
name[2] = IPPROTO_TCP;
|
||||
|
||||
int value;
|
||||
size_t sz;
|
||||
|
||||
// get tics per second
|
||||
name[3] = TCPCTL_SLOWHZ;
|
||||
if (sysctl(name, 4, &value, &sz, NULL, 0) == -1)
|
||||
wlog("Error setting TCP keepalive interval");
|
||||
|
||||
// set interval
|
||||
value *= timeout_sec;
|
||||
name[3] = TCPCTL_KEEPINTVL;
|
||||
if (sysctl(name, 4, NULL, NULL, &value, sizeof(value)) == -1)
|
||||
wlog("Error setting TCP keepalive interval");
|
||||
# elif !defined(__APPLE__) || defined(TCP_KEEPINTVL) // TCP_KEEPINTVL not defined before 10.9
|
||||
if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP, TCP_KEEPINTVL,
|
||||
(char*)&timeout_sec, sizeof(timeout_sec)) < 0)
|
||||
wlog("Error setting TCP keepalive interval");
|
||||
# endif // !__APPLE__ || TCP_KEEPINTVL
|
||||
# endif // (__OpenBSD__) or (!__APPLE__ || TCP_KEEPINTVL)
|
||||
#endif // !WIN32
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -74,7 +74,10 @@ websocket_api_connection::websocket_api_connection( const std::shared_ptr<fc::ht
|
|||
|
||||
return result;
|
||||
} );
|
||||
_connection->closed.connect( [this](){ closed(); } );
|
||||
_connection->closed.connect( [this](){
|
||||
closed();
|
||||
_connection = nullptr;
|
||||
} );
|
||||
}
|
||||
|
||||
variant websocket_api_connection::send_call(
|
||||
|
|
@ -218,7 +221,8 @@ response websocket_api_connection::on_request( const variant& var )
|
|||
catch ( const fc::exception& e )
|
||||
{
|
||||
if( has_id )
|
||||
return response( call.id, error_object{ e.code(), "Execution error", variant( e, _max_conversion_depth ) },
|
||||
return response( call.id, error_object{ e.code(), "Execution error: " + e.to_string(),
|
||||
variant( e, _max_conversion_depth ) },
|
||||
call.jsonrpc );
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
|
|
|
|||
|
|
@ -1,6 +1,27 @@
|
|||
//
|
||||
// A stacktrace handler for bitshares
|
||||
//
|
||||
/*
|
||||
* Copyright (c) 2018-2019 BitShares Blockchain Foundation, and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <ostream>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
|
|
@ -8,6 +29,9 @@
|
|||
#if BOOST_VERSION / 100 >= 1065 && !defined(__APPLE__)
|
||||
#include <signal.h>
|
||||
#include <fc/log/logger.hpp>
|
||||
#if defined(__OpenBSD__)
|
||||
#define BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED
|
||||
#endif
|
||||
#include <boost/stacktrace.hpp>
|
||||
|
||||
namespace fc
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@
|
|||
namespace bc = boost::context::detail;
|
||||
namespace bco = boost::coroutines;
|
||||
typedef bco::stack_allocator stack_allocator;
|
||||
#elif BOOST_VERSION >= 105400
|
||||
#else
|
||||
# include <boost/coroutine/stack_context.hpp>
|
||||
namespace bc = boost::context;
|
||||
namespace bco = boost::coroutines;
|
||||
# if BOOST_VERSION >= 105600 && !defined(NDEBUG)
|
||||
# if !defined(NDEBUG)
|
||||
# include <boost/assert.hpp>
|
||||
# include <boost/coroutine/protected_stack_allocator.hpp>
|
||||
typedef bco::protected_stack_allocator stack_allocator;
|
||||
|
|
@ -32,16 +32,7 @@
|
|||
typedef bco::stack_allocator stack_allocator;
|
||||
# endif
|
||||
|
||||
#elif BOOST_VERSION >= 105300
|
||||
#include <boost/coroutine/stack_allocator.hpp>
|
||||
namespace bc = boost::context;
|
||||
namespace bco = boost::coroutines;
|
||||
#elif BOOST_VERSION >= 105200
|
||||
namespace bc = boost::context;
|
||||
#else
|
||||
namespace bc = boost::ctx;
|
||||
namespace bco = boost::coroutine;
|
||||
#endif
|
||||
#endif // BOOST_VERSION >= 106100
|
||||
|
||||
namespace fc {
|
||||
class thread;
|
||||
|
|
@ -55,10 +46,7 @@ namespace fc {
|
|||
*/
|
||||
struct context {
|
||||
typedef fc::context* ptr;
|
||||
|
||||
#if BOOST_VERSION >= 105400
|
||||
bco::stack_context stack_ctx;
|
||||
#endif
|
||||
|
||||
#if BOOST_VERSION >= 106100
|
||||
using context_fn = void (*)(bc::transfer_t);
|
||||
|
|
@ -81,32 +69,13 @@ namespace fc {
|
|||
cur_task(0),
|
||||
context_posted_num(0)
|
||||
{
|
||||
#if BOOST_VERSION >= 105600
|
||||
size_t stack_size = FC_CONTEXT_STACK_SIZE;
|
||||
alloc.allocate(stack_ctx, stack_size);
|
||||
my_context = bc::make_fcontext( stack_ctx.sp, stack_ctx.size, sf);
|
||||
#elif BOOST_VERSION >= 105400
|
||||
size_t stack_size = FC_CONTEXT_STACK_SIZE;
|
||||
alloc.allocate(stack_ctx, stack_size);
|
||||
my_context = bc::make_fcontext( stack_ctx.sp, stack_ctx.size, sf);
|
||||
#elif BOOST_VERSION >= 105300
|
||||
size_t stack_size = FC_CONTEXT_STACK_SIZE;
|
||||
void* stackptr = alloc.allocate(stack_size);
|
||||
my_context = bc::make_fcontext( stackptr, stack_size, sf);
|
||||
#else
|
||||
size_t stack_size = FC_CONTEXT_STACK_SIZE;
|
||||
my_context.fc_stack.base = alloc.allocate( stack_size );
|
||||
my_context.fc_stack.limit = static_cast<char*>( my_context.fc_stack.base) - stack_size;
|
||||
make_fcontext( &my_context, sf );
|
||||
#endif
|
||||
}
|
||||
|
||||
context( fc::thread* t) :
|
||||
#if BOOST_VERSION >= 105600
|
||||
my_context(nullptr),
|
||||
#elif BOOST_VERSION >= 105300
|
||||
my_context(new bc::fcontext_t),
|
||||
#endif
|
||||
caller_context(0),
|
||||
stack_alloc(0),
|
||||
next_blocked(0),
|
||||
|
|
@ -123,23 +92,8 @@ namespace fc {
|
|||
{}
|
||||
|
||||
~context() {
|
||||
#if BOOST_VERSION >= 105600
|
||||
if(stack_alloc)
|
||||
stack_alloc->deallocate( stack_ctx );
|
||||
#elif BOOST_VERSION >= 105400
|
||||
if(stack_alloc)
|
||||
stack_alloc->deallocate( stack_ctx );
|
||||
else
|
||||
delete my_context;
|
||||
#elif BOOST_VERSION >= 105300
|
||||
if(stack_alloc)
|
||||
stack_alloc->deallocate( my_context->fc_stack.sp, FC_CONTEXT_STACK_SIZE);
|
||||
else
|
||||
delete my_context;
|
||||
#else
|
||||
if(stack_alloc)
|
||||
stack_alloc->deallocate( my_context.fc_stack.base, FC_CONTEXT_STACK_SIZE );
|
||||
#endif
|
||||
}
|
||||
|
||||
void reinitialize()
|
||||
|
|
@ -225,13 +179,7 @@ namespace fc {
|
|||
|
||||
bool is_complete()const { return complete; }
|
||||
|
||||
|
||||
|
||||
#if BOOST_VERSION >= 105300 && BOOST_VERSION < 105600
|
||||
bc::fcontext_t* my_context;
|
||||
#else
|
||||
bc::fcontext_t my_context;
|
||||
#endif
|
||||
fc::context* caller_context;
|
||||
stack_allocator* stack_alloc;
|
||||
priority prio;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
|
||||
namespace fc {
|
||||
|
||||
promise_base::promise_base( const char* desc )
|
||||
|
|
@ -22,6 +21,8 @@ namespace fc {
|
|||
_compl(nullptr)
|
||||
{ }
|
||||
|
||||
promise_base::~promise_base() { }
|
||||
|
||||
const char* promise_base::get_desc()const{
|
||||
return _desc;
|
||||
}
|
||||
|
|
@ -34,16 +35,14 @@ namespace fc {
|
|||
#endif
|
||||
}
|
||||
bool promise_base::ready()const {
|
||||
return _ready;
|
||||
return _ready.load();
|
||||
}
|
||||
bool promise_base::error()const {
|
||||
{ synchronized(_spin_yield)
|
||||
return _exceptp != nullptr;
|
||||
}
|
||||
return std::atomic_load( &_exceptp ) != nullptr;
|
||||
}
|
||||
|
||||
void promise_base::set_exception( const fc::exception_ptr& e ){
|
||||
_exceptp = e;
|
||||
std::atomic_store( &_exceptp, e );
|
||||
_set_value(nullptr);
|
||||
}
|
||||
|
||||
|
|
@ -54,16 +53,21 @@ namespace fc {
|
|||
_wait_until( time_point::now() + timeout_us );
|
||||
}
|
||||
void promise_base::_wait_until( const time_point& timeout_us ){
|
||||
{ synchronized(_spin_yield)
|
||||
if( _ready ) {
|
||||
if( _exceptp )
|
||||
_exceptp->dynamic_rethrow_exception();
|
||||
return;
|
||||
}
|
||||
_enqueue_thread();
|
||||
if( _ready.load() ) {
|
||||
fc::exception_ptr ex = std::atomic_load( &_exceptp );
|
||||
if( ex )
|
||||
ex->dynamic_rethrow_exception();
|
||||
return;
|
||||
}
|
||||
_enqueue_thread();
|
||||
// Need to check _ready again to avoid a race condition.
|
||||
if( _ready.load() )
|
||||
{
|
||||
_dequeue_thread();
|
||||
return _wait_until( timeout_us ); // this will simply return or throw _exceptp
|
||||
}
|
||||
std::exception_ptr e;
|
||||
|
||||
std::exception_ptr e;
|
||||
//
|
||||
// Create shared_ptr to take ownership of this; i.e. this will
|
||||
// be deleted when p_this goes out of scope. Consequently,
|
||||
|
|
@ -71,9 +75,7 @@ namespace fc {
|
|||
// before we're done reading/writing instance variables!
|
||||
// See https://github.com/cryptonomex/graphene/issues/597
|
||||
//
|
||||
|
||||
ptr p_this = shared_from_this();
|
||||
|
||||
try
|
||||
{
|
||||
//
|
||||
|
|
@ -94,61 +96,45 @@ namespace fc {
|
|||
|
||||
if( e ) std::rethrow_exception(e);
|
||||
|
||||
if( _ready )
|
||||
{
|
||||
if( _exceptp )
|
||||
_exceptp->dynamic_rethrow_exception();
|
||||
return;
|
||||
}
|
||||
if( _ready.load() ) return _wait_until( timeout_us ); // this will simply return or throw _exceptp
|
||||
|
||||
FC_THROW_EXCEPTION( timeout_exception, "" );
|
||||
}
|
||||
void promise_base::_enqueue_thread(){
|
||||
++_blocked_fiber_count;
|
||||
_blocked_fiber_count.fetch_add( 1 );
|
||||
thread* blocked_thread = _blocked_thread.load();
|
||||
// only one thread can wait on a promise at any given time
|
||||
assert(!_blocked_thread ||
|
||||
_blocked_thread == &thread::current());
|
||||
_blocked_thread = &thread::current();
|
||||
do
|
||||
assert( !blocked_thread || blocked_thread == &thread::current() );
|
||||
while( !_blocked_thread.compare_exchange_weak( blocked_thread, &thread::current() ) );
|
||||
}
|
||||
void promise_base::_dequeue_thread(){
|
||||
synchronized(_spin_yield)
|
||||
if (!--_blocked_fiber_count)
|
||||
_blocked_thread = nullptr;
|
||||
if( _blocked_fiber_count.fetch_add( -1 ) == 1 )
|
||||
_blocked_thread.store( nullptr );
|
||||
}
|
||||
void promise_base::_notify(){
|
||||
// copy _blocked_thread into a local so that if the thread unblocks (e.g.,
|
||||
// because of a timeout) before we get a chance to notify it, we won't be
|
||||
// calling notify on a null pointer
|
||||
thread* blocked_thread;
|
||||
{ synchronized(_spin_yield)
|
||||
blocked_thread = _blocked_thread;
|
||||
}
|
||||
thread* blocked_thread = _blocked_thread.load();
|
||||
if( blocked_thread )
|
||||
blocked_thread->notify( shared_from_this() );
|
||||
}
|
||||
promise_base::~promise_base() { }
|
||||
void promise_base::_set_timeout(){
|
||||
if( _ready )
|
||||
return;
|
||||
set_exception( std::make_shared<fc::timeout_exception>() );
|
||||
}
|
||||
|
||||
void promise_base::_set_value(const void* s){
|
||||
// slog( "%p == %d", &_ready, int(_ready));
|
||||
// BOOST_ASSERT( !_ready );
|
||||
{ synchronized(_spin_yield)
|
||||
if (_ready) //don't allow promise to be set more than once
|
||||
bool ready = false;
|
||||
if( !_ready.compare_exchange_strong( ready, true ) ) //don't allow promise to be set more than once
|
||||
return;
|
||||
_ready = true;
|
||||
}
|
||||
_notify();
|
||||
if( nullptr != _compl ) {
|
||||
_compl->on_complete(s,_exceptp);
|
||||
}
|
||||
_notify();
|
||||
auto* hdl = _compl.load();
|
||||
if( nullptr != hdl )
|
||||
hdl->on_complete( s, std::atomic_load( &_exceptp ) );
|
||||
}
|
||||
|
||||
void promise_base::_on_complete( detail::completion_handler* c ) {
|
||||
{ synchronized(_spin_yield)
|
||||
delete _compl;
|
||||
_compl = c;
|
||||
}
|
||||
auto* hdl = _compl.load();
|
||||
while( !_compl.compare_exchange_weak( hdl, c ) );
|
||||
delete hdl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
#include <fc/thread/thread.hpp>
|
||||
#include <fc/stacktrace.hpp>
|
||||
#include <fc/time.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include "context.hpp"
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/atomic.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
//#include <fc/logger.hpp>
|
||||
|
||||
namespace fc {
|
||||
struct sleep_priority_less {
|
||||
|
|
@ -390,7 +392,14 @@ namespace fc {
|
|||
/* NB: At least on Win64, this only catches a yield while in the body of
|
||||
* a catch block; it fails to catch a yield while unwinding the stack, which
|
||||
* is probably just as likely to cause crashes */
|
||||
assert(std::current_exception() == std::exception_ptr());
|
||||
if( std::current_exception() != std::exception_ptr() )
|
||||
{
|
||||
std::stringstream stacktrace;
|
||||
print_stacktrace( stacktrace );
|
||||
elog( "Thread ${name} yielded in exception handler!\n${trace}",
|
||||
("name",thread::current().name())("trace",stacktrace.str()) );
|
||||
assert( std::current_exception() == std::exception_ptr() );
|
||||
}
|
||||
|
||||
check_for_timeouts();
|
||||
if( !current )
|
||||
|
|
@ -424,12 +433,8 @@ namespace fc {
|
|||
auto p = context_pair{nullptr, prev};
|
||||
auto t = bc::jump_fcontext( next->my_context, &p );
|
||||
static_cast<context_pair*>(t.data)->second->my_context = t.fctx;
|
||||
#elif BOOST_VERSION >= 105600
|
||||
bc::jump_fcontext( &prev->my_context, next->my_context, 0 );
|
||||
#elif BOOST_VERSION >= 105300
|
||||
bc::jump_fcontext( prev->my_context, next->my_context, 0 );
|
||||
#else
|
||||
bc::jump_fcontext( &prev->my_context, &next->my_context, 0 );
|
||||
bc::jump_fcontext( &prev->my_context, next->my_context, 0 );
|
||||
#endif
|
||||
BOOST_ASSERT( current );
|
||||
BOOST_ASSERT( current == prev );
|
||||
|
|
@ -470,12 +475,8 @@ namespace fc {
|
|||
auto p = context_pair{this, prev};
|
||||
auto t = bc::jump_fcontext( next->my_context, &p );
|
||||
static_cast<context_pair*>(t.data)->second->my_context = t.fctx;
|
||||
#elif BOOST_VERSION >= 105600
|
||||
bc::jump_fcontext( &prev->my_context, next->my_context, (intptr_t)this );
|
||||
#elif BOOST_VERSION >= 105300
|
||||
bc::jump_fcontext( prev->my_context, next->my_context, (intptr_t)this );
|
||||
#else
|
||||
bc::jump_fcontext( &prev->my_context, &next->my_context, (intptr_t)this );
|
||||
bc::jump_fcontext( &prev->my_context, next->my_context, (intptr_t)this );
|
||||
#endif
|
||||
BOOST_ASSERT( current );
|
||||
BOOST_ASSERT( current == prev );
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@
|
|||
#include <fc/reflect/variant.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#if defined(__APPLE__) or defined(__OpenBSD__)
|
||||
#include <boost/multiprecision/integer.hpp>
|
||||
#endif
|
||||
|
||||
namespace fc
|
||||
{
|
||||
|
||||
|
|
@ -75,7 +79,7 @@ variant::variant( uint64_t val, uint32_t max_depth )
|
|||
set_variant_type( this, uint64_type );
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) or defined(__OpenBSD__)
|
||||
variant::variant( size_t val, uint32_t max_depth )
|
||||
{
|
||||
*reinterpret_cast<uint64_t*>(this) = val;
|
||||
|
|
@ -675,16 +679,31 @@ void from_variant( const variant& var, std::vector<char>& vo, uint32_t max_depth
|
|||
|
||||
void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth )
|
||||
{
|
||||
#if defined(__APPLE__) or defined(__OpenBSD__)
|
||||
boost::multiprecision::uint128_t helper = uint128_hi64( var );
|
||||
helper <<= 64;
|
||||
helper += uint128_lo64( var );
|
||||
vo = boost::lexical_cast<std::string>( helper );
|
||||
#else
|
||||
vo = boost::lexical_cast<std::string>( var );
|
||||
#endif
|
||||
}
|
||||
|
||||
void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth )
|
||||
{
|
||||
#if defined(__APPLE__) or defined(__OpenBSD__)
|
||||
boost::multiprecision::uint128_t helper = boost::lexical_cast<boost::multiprecision::uint128_t>( var.as_string() );
|
||||
vo = static_cast<uint64_t>( helper >> 64 );
|
||||
vo <<= 64;
|
||||
vo += static_cast<uint64_t>( helper & 0xffffffffffffffffULL );
|
||||
#else
|
||||
vo = boost::lexical_cast<uint128_t>( var.as_string() );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
#elif !defined(_MSC_VER)
|
||||
#if defined(__APPLE__) or defined(__OpenBSD__)
|
||||
void to_variant( size_t s, variant& v, uint32_t max_depth ) { v = variant( uint64_t(s) ); }
|
||||
#elif !defined(_WIN32)
|
||||
void to_variant( long long int s, variant& v, uint32_t max_depth ) { v = variant( int64_t(s) ); }
|
||||
void to_variant( unsigned long long int s, variant& v, uint32_t max_depth ) { v = variant( uint64_t(s)); }
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ target_link_libraries( ws_test_client fc )
|
|||
add_executable( all_tests all_tests.cpp
|
||||
compress/compress.cpp
|
||||
crypto/aes_test.cpp
|
||||
crypto/array_initialization_test.cpp
|
||||
crypto/base_n_tests.cpp
|
||||
crypto/bigint_test.cpp
|
||||
crypto/blind.cpp
|
||||
|
|
@ -47,6 +48,7 @@ add_executable( all_tests all_tests.cpp
|
|||
thread/thread_tests.cpp
|
||||
thread/parallel_tests.cpp
|
||||
bloom_test.cpp
|
||||
reflection_tests.cpp
|
||||
serialization_test.cpp
|
||||
stacktrace_test.cpp
|
||||
time_test.cpp
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include <fc/rpc/api_connection.hpp>
|
||||
#include <fc/rpc/websocket_api.hpp>
|
||||
|
||||
namespace fc { namespace test {
|
||||
|
||||
class calculator
|
||||
{
|
||||
public:
|
||||
|
|
@ -15,9 +17,6 @@ class calculator
|
|||
void on_result2( const std::function<void(int32_t)>& cb, int test );
|
||||
};
|
||||
|
||||
FC_API( calculator, (add)(sub)(on_result)(on_result2) )
|
||||
|
||||
|
||||
class login_api
|
||||
{
|
||||
public:
|
||||
|
|
@ -29,8 +28,6 @@ class login_api
|
|||
fc::optional<fc::api<calculator>> calc;
|
||||
std::set<std::string> test( const std::string&, const std::string& ) { return std::set<std::string>(); }
|
||||
};
|
||||
FC_API( login_api, (get_calc)(test) );
|
||||
|
||||
|
||||
class optionals_api
|
||||
{
|
||||
|
|
@ -39,10 +36,11 @@ public:
|
|||
const fc::optional<std::string>& third ) {
|
||||
return fc::json::to_string(fc::variants{first, {second, 2}, {third, 2}});
|
||||
}
|
||||
std::string bar( fc::optional<std::string> first, fc::optional<std::string> second,
|
||||
fc::optional<std::string> third ) {
|
||||
return fc::json::to_string(fc::variants{{first,2}, {second, 2}, {third, 2}});
|
||||
}
|
||||
};
|
||||
FC_API( optionals_api, (foo) );
|
||||
|
||||
using namespace fc;
|
||||
|
||||
class some_calculator
|
||||
{
|
||||
|
|
@ -54,6 +52,12 @@ class some_calculator
|
|||
std::function<void(int32_t)> _cb;
|
||||
};
|
||||
|
||||
}} // fc::test
|
||||
|
||||
FC_API( fc::test::calculator, (add)(sub)(on_result)(on_result2) )
|
||||
FC_API( fc::test::login_api, (get_calc)(test) );
|
||||
FC_API( fc::test::optionals_api, (foo)(bar) );
|
||||
|
||||
using namespace fc::http;
|
||||
using namespace fc::rpc;
|
||||
|
||||
|
|
@ -63,14 +67,14 @@ BOOST_AUTO_TEST_SUITE(api_tests)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(login_test) {
|
||||
try {
|
||||
fc::api<calculator> calc_api( std::make_shared<some_calculator>() );
|
||||
fc::api<fc::test::calculator> calc_api( std::make_shared<fc::test::some_calculator>() );
|
||||
|
||||
auto server = std::make_shared<fc::http::websocket_server>("");
|
||||
server->on_connection([&]( const websocket_connection_ptr& c ){
|
||||
auto wsc = std::make_shared<websocket_api_connection>(c, MAX_DEPTH);
|
||||
auto login = std::make_shared<login_api>();
|
||||
auto login = std::make_shared<fc::test::login_api>();
|
||||
login->calc = calc_api;
|
||||
wsc->register_api(fc::api<login_api>(login));
|
||||
wsc->register_api(fc::api<fc::test::login_api>(login));
|
||||
c->set_session_data( wsc );
|
||||
});
|
||||
|
||||
|
|
@ -82,7 +86,7 @@ BOOST_AUTO_TEST_CASE(login_test) {
|
|||
auto con = client->connect( "ws://localhost:" + std::to_string(listen_port) );
|
||||
server->stop_listening();
|
||||
auto apic = std::make_shared<websocket_api_connection>(con, MAX_DEPTH);
|
||||
auto remote_login_api = apic->get_remote_api<login_api>();
|
||||
auto remote_login_api = apic->get_remote_api<fc::test::login_api>();
|
||||
auto remote_calc = remote_login_api->get_calc();
|
||||
bool remote_triggered = false;
|
||||
remote_calc->on_result( [&remote_triggered]( uint32_t r ) { remote_triggered = true; } );
|
||||
|
|
@ -99,17 +103,23 @@ BOOST_AUTO_TEST_CASE(login_test) {
|
|||
|
||||
BOOST_AUTO_TEST_CASE(optionals_test) {
|
||||
try {
|
||||
auto optionals = std::make_shared<optionals_api>();
|
||||
fc::api<optionals_api> oapi(optionals);
|
||||
auto optionals = std::make_shared<fc::test::optionals_api>();
|
||||
fc::api<fc::test::optionals_api> oapi(optionals);
|
||||
BOOST_CHECK_EQUAL(oapi->foo("a"), "[\"a\",null,null]");
|
||||
BOOST_CHECK_EQUAL(oapi->foo("a", "b"), "[\"a\",\"b\",null]");
|
||||
BOOST_CHECK_EQUAL(oapi->foo("a", "b", "c"), "[\"a\",\"b\",\"c\"]");
|
||||
BOOST_CHECK_EQUAL(oapi->foo("a", {}, "c"), "[\"a\",null,\"c\"]");
|
||||
|
||||
BOOST_CHECK_EQUAL(oapi->bar(), "[null,null,null]");
|
||||
BOOST_CHECK_EQUAL(oapi->bar("a"), "[\"a\",null,null]");
|
||||
BOOST_CHECK_EQUAL(oapi->bar("a", "b"), "[\"a\",\"b\",null]");
|
||||
BOOST_CHECK_EQUAL(oapi->bar("a", "b", "c"), "[\"a\",\"b\",\"c\"]");
|
||||
BOOST_CHECK_EQUAL(oapi->bar("a", {}, "c"), "[\"a\",null,\"c\"]");
|
||||
|
||||
auto server = std::make_shared<fc::http::websocket_server>("");
|
||||
server->on_connection([&]( const websocket_connection_ptr& c ){
|
||||
auto wsc = std::make_shared<websocket_api_connection>(c, MAX_DEPTH);
|
||||
wsc->register_api(fc::api<optionals_api>(optionals));
|
||||
wsc->register_api(fc::api<fc::test::optionals_api>(optionals));
|
||||
c->set_session_data( wsc );
|
||||
});
|
||||
|
||||
|
|
@ -119,15 +129,45 @@ BOOST_AUTO_TEST_CASE(optionals_test) {
|
|||
|
||||
auto client = std::make_shared<fc::http::websocket_client>();
|
||||
auto con = client->connect( "ws://localhost:" + std::to_string(listen_port) );
|
||||
server->stop_listening();
|
||||
auto apic = std::make_shared<websocket_api_connection>(con, MAX_DEPTH);
|
||||
auto remote_optionals = apic->get_remote_api<optionals_api>();
|
||||
auto remote_optionals = apic->get_remote_api<fc::test::optionals_api>();
|
||||
|
||||
BOOST_CHECK_EQUAL(remote_optionals->foo("a"), "[\"a\",null,null]");
|
||||
BOOST_CHECK_EQUAL(remote_optionals->foo("a", "b"), "[\"a\",\"b\",null]");
|
||||
BOOST_CHECK_EQUAL(remote_optionals->foo("a", "b", "c"), "[\"a\",\"b\",\"c\"]");
|
||||
BOOST_CHECK_EQUAL(remote_optionals->foo("a", {}, "c"), "[\"a\",null,\"c\"]");
|
||||
|
||||
BOOST_CHECK_EQUAL(remote_optionals->bar(), "[null,null,null]");
|
||||
BOOST_CHECK_EQUAL(remote_optionals->bar("a"), "[\"a\",null,null]");
|
||||
BOOST_CHECK_EQUAL(remote_optionals->bar("a", "b"), "[\"a\",\"b\",null]");
|
||||
BOOST_CHECK_EQUAL(remote_optionals->bar("a", "b", "c"), "[\"a\",\"b\",\"c\"]");
|
||||
BOOST_CHECK_EQUAL(remote_optionals->bar("a", {}, "c"), "[\"a\",null,\"c\"]");
|
||||
|
||||
auto client2 = std::make_shared<fc::http::websocket_client>();
|
||||
auto con2 = client2->connect( "ws://localhost:" + std::to_string(listen_port) );
|
||||
std::string response;
|
||||
con2->on_message_handler([&response](const std::string& s){
|
||||
response = s;
|
||||
});
|
||||
|
||||
con2->send_message( "{\"id\":1,\"method\":\"call\",\"params\":[0,\"bar\",[\"a\",\"b\",\"c\"]]}" );
|
||||
fc::usleep(fc::milliseconds(50));
|
||||
BOOST_CHECK_EQUAL( response, "{\"id\":1,\"result\":\"[\\\"a\\\",\\\"b\\\",\\\"c\\\"]\"}" );
|
||||
|
||||
con2->send_message( "{\"id\":2,\"method\":\"call\",\"params\":[0,\"bar\",[\"a\",\"b\"]]}" );
|
||||
fc::usleep(fc::milliseconds(50));
|
||||
BOOST_CHECK_EQUAL( response, "{\"id\":2,\"result\":\"[\\\"a\\\",\\\"b\\\",null]\"}" );
|
||||
|
||||
con2->send_message( "{\"id\":3,\"method\":\"call\",\"params\":[0,\"bar\",[\"a\"]]}" );
|
||||
fc::usleep(fc::milliseconds(50));
|
||||
BOOST_CHECK_EQUAL( response, "{\"id\":3,\"result\":\"[\\\"a\\\",null,null]\"}" );
|
||||
|
||||
con2->send_message( "{\"id\":4,\"method\":\"call\",\"params\":[0,\"bar\",[]]}" );
|
||||
fc::usleep(fc::milliseconds(50));
|
||||
BOOST_CHECK_EQUAL( response, "{\"id\":4,\"result\":\"[null,null,null]\"}" );
|
||||
|
||||
server->stop_listening();
|
||||
|
||||
client->synchronous_close();
|
||||
server->close();
|
||||
fc::usleep(fc::milliseconds(50));
|
||||
|
|
|
|||
67
tests/crypto/array_initialization_test.cpp
Normal file
67
tests/crypto/array_initialization_test.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2019 BitShares Blockchain Foundation, and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
#include <fc/crypto/rand.hpp>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void check_null_key()
|
||||
{
|
||||
fc::ecc::public_key_data key1;
|
||||
fc::ecc::public_key_data key2;
|
||||
unsigned char zeroes[33];
|
||||
static_assert( key1.size() == sizeof(zeroes), "Wrong array size!" );
|
||||
memset( zeroes, 0, sizeof(zeroes) );
|
||||
BOOST_CHECK( !memcmp( key1.data(), zeroes, sizeof(zeroes) ) );
|
||||
BOOST_CHECK( !memcmp( key2.data(), zeroes, sizeof(zeroes) ) );
|
||||
|
||||
// now "pollute" the keys for the next invocation
|
||||
key1 = fc::ecc::private_key::generate().get_public_key();
|
||||
for( unsigned char c = 0; c < key2.size(); c++ )
|
||||
{
|
||||
key2[c] = c ^ 17;
|
||||
zeroes[c] = c ^ 47;
|
||||
}
|
||||
|
||||
// ...and use them to prevent the compiler from optimizing the pollution away.
|
||||
wlog( "Key1: ${k}", ("k",fc::ecc::public_key::to_base58(key1)) );
|
||||
wlog( "Key2: ${k}", ("k",fc::ecc::public_key::to_base58(key2)) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(fc_crypto)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_init_test)
|
||||
{
|
||||
check_null_key();
|
||||
check_null_key();
|
||||
{
|
||||
char junk[128];
|
||||
fc::rand_bytes( junk, sizeof(junk) );
|
||||
}
|
||||
check_null_key();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(dh_test)
|
|||
alice.p.clear(); alice.p.push_back(100); alice.p.push_back(2);
|
||||
BOOST_CHECK( !alice.validate() );
|
||||
alice.p = bob.p;
|
||||
alice.g = 9;
|
||||
alice.g = 1;
|
||||
BOOST_CHECK( !alice.validate() );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ static void interop_do(const char * const data, size_t len) {
|
|||
}
|
||||
|
||||
static void interop_do(const fc::ecc::public_key_data &data) {
|
||||
interop_do((char*) data.begin(), data.size());
|
||||
interop_do((char*) data.data(), data.size());
|
||||
}
|
||||
|
||||
static void interop_do(const fc::ecc::private_key_secret &data) {
|
||||
|
|
@ -31,7 +31,7 @@ static void interop_do(const fc::ecc::private_key_secret &data) {
|
|||
}
|
||||
|
||||
static void interop_do(const fc::ecc::public_key_point_data &data) {
|
||||
interop_do((char*) data.begin(), data.size());
|
||||
interop_do((char*) data.data(), data.size());
|
||||
}
|
||||
|
||||
static void interop_do(const std::string &data) {
|
||||
|
|
@ -44,11 +44,11 @@ static void interop_do(const fc::sha512 &data) {
|
|||
|
||||
static void interop_do(fc::ecc::compact_signature &data) {
|
||||
if (write_mode) {
|
||||
interop_data.write((char*) data.begin(), data.size());
|
||||
interop_data.write((char*) data.data(), data.size());
|
||||
return;
|
||||
}
|
||||
|
||||
interop_data.read((char*) data.begin(), data.size());
|
||||
interop_data.read((char*) data.data(), data.size());
|
||||
}
|
||||
|
||||
static void interop_file(const char * const name) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <fc/crypto/digest.hpp>
|
||||
#include <fc/crypto/ripemd160.hpp>
|
||||
#include <fc/crypto/hash160.hpp>
|
||||
#include <fc/crypto/sha1.hpp>
|
||||
#include <fc/crypto/sha224.hpp>
|
||||
#include <fc/crypto/sha256.hpp>
|
||||
|
|
@ -108,6 +109,18 @@ BOOST_AUTO_TEST_CASE(ripemd160_test)
|
|||
test_stream<fc::ripemd160>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( hash160_test )
|
||||
{
|
||||
|
||||
test<fc::hash160>( TEST1, "bb1be98c142444d7a56aa3981c3942a978e4dc33" );
|
||||
test<fc::hash160>( TEST2, "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb" );
|
||||
test<fc::hash160>( TEST3, "69dda8a60e0cfc2353aa776864092c0e5ccb4834" );
|
||||
test<fc::hash160>( TEST4, "dfcc6db6ea54d85d2e3a76573183f7a037a729b0" );
|
||||
init_5();
|
||||
test<fc::hash160>( TEST5, "f9be0e104ef2ed83a7ddb4765780951405e56ba4" );
|
||||
test<fc::hash160>( TEST6, "3eca00d3b1fcafb0b74fa07fe890bea9b053a17e" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sha1_test)
|
||||
{
|
||||
init_5();
|
||||
|
|
|
|||
|
|
@ -79,13 +79,13 @@ static void run_test( const std::string& key, const std::string& data, const std
|
|||
{
|
||||
|
||||
std::array<char,N> key_arr;
|
||||
BOOST_CHECK_EQUAL( fc::from_hex( key, key_arr.begin(), key_arr.size() ), N );
|
||||
BOOST_CHECK_EQUAL( fc::from_hex( key, key_arr.data(), key_arr.size() ), N );
|
||||
std::array<char,M> data_arr;
|
||||
BOOST_CHECK_EQUAL( fc::from_hex( data, data_arr.begin(), data_arr.size() ), M );
|
||||
BOOST_CHECK_EQUAL( fc::from_hex( data, data_arr.data(), data_arr.size() ), M );
|
||||
|
||||
BOOST_CHECK_EQUAL( mac_224.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_224 );
|
||||
BOOST_CHECK_EQUAL( mac_256.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_256 );
|
||||
BOOST_CHECK_EQUAL( mac_512.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_512 );
|
||||
BOOST_CHECK_EQUAL( mac_224.digest( key_arr.data(), N, data_arr.data(), M ).str(), expect_224 );
|
||||
BOOST_CHECK_EQUAL( mac_256.digest( key_arr.data(), N, data_arr.data(), M ).str(), expect_256 );
|
||||
BOOST_CHECK_EQUAL( mac_512.digest( key_arr.data(), N, data_arr.data(), M ).str(), expect_512 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hmac_test_1)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,16 @@
|
|||
#include <fc/network/tcp_socket.hpp>
|
||||
#include <fc/asio.hpp>
|
||||
|
||||
namespace fc { namespace test {
|
||||
|
||||
class my_io_class : public fc::asio::default_io_service_scope
|
||||
{
|
||||
public:
|
||||
static void reset_num_threads() { fc::asio::default_io_service_scope::num_io_threads = 0; }
|
||||
};
|
||||
|
||||
}} // fc::test
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(tcp_tests)
|
||||
|
||||
/***
|
||||
|
|
@ -15,23 +25,17 @@ BOOST_AUTO_TEST_CASE(tcpconstructor_test)
|
|||
fc::tcp_socket socket;
|
||||
}
|
||||
|
||||
class my_io_class : public fc::asio::default_io_service_scope
|
||||
{
|
||||
public:
|
||||
static void reset_num_threads() { fc::asio::default_io_service_scope::num_io_threads = 0; }
|
||||
};
|
||||
|
||||
/***
|
||||
* Test the control of number of threads from outside
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( number_threads_test )
|
||||
{
|
||||
// to erase leftovers from previous tests
|
||||
my_io_class::reset_num_threads();
|
||||
fc::test::my_io_class::reset_num_threads();
|
||||
|
||||
fc::asio::default_io_service_scope::set_num_threads(12);
|
||||
|
||||
my_io_class my_class;
|
||||
fc::test::my_io_class my_class;
|
||||
|
||||
BOOST_CHECK_EQUAL( 12, my_class.get_num_threads() );
|
||||
}
|
||||
|
|
@ -42,9 +46,9 @@ BOOST_AUTO_TEST_CASE( number_threads_test )
|
|||
BOOST_AUTO_TEST_CASE( default_number_threads_test )
|
||||
{
|
||||
// to erase leftovers from previous tests
|
||||
my_io_class::reset_num_threads();
|
||||
fc::test::my_io_class::reset_num_threads();
|
||||
|
||||
my_io_class my_class;
|
||||
fc::test::my_io_class my_class;
|
||||
|
||||
fc::asio::default_io_service();
|
||||
|
||||
|
|
|
|||
126
tests/reflection_tests.cpp
Normal file
126
tests/reflection_tests.cpp
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
struct reflect_test_base {
|
||||
int x = 1;
|
||||
char y = 'a';
|
||||
};
|
||||
struct reflect_test_derived : reflect_test_base {
|
||||
double z = 3.14;
|
||||
};
|
||||
struct reflect_layer_1 { reflect_test_base b; int32_t n; };
|
||||
struct reflect_layer_2 { reflect_layer_1 l1; reflect_test_derived d; };
|
||||
struct reflect_layer_3 { reflect_layer_2 l2; int32_t i; };
|
||||
|
||||
FC_REFLECT( reflect_test_base, (x)(y) );
|
||||
FC_REFLECT_DERIVED( reflect_test_derived, (reflect_test_base), (z) );
|
||||
FC_REFLECT( reflect_layer_1, (b)(n) );
|
||||
FC_REFLECT( reflect_layer_2, (l1)(d) );
|
||||
FC_REFLECT( reflect_layer_3, (l2)(i) );
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( fc_reflection )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( reflection_static_tests )
|
||||
{
|
||||
// These are all compile-time tests, nothing actually happens here at runtime
|
||||
using base_reflection = fc::reflector<reflect_test_base>;
|
||||
using derived_reflection = fc::reflector<reflect_test_derived>;
|
||||
static_assert(fc::typelist::length<base_reflection::members>() == 2, "");
|
||||
static_assert(fc::typelist::length<derived_reflection::members>() == 3, "");
|
||||
static_assert(fc::typelist::at<derived_reflection::members, 0>::is_derived, "");
|
||||
static_assert(std::is_same<fc::typelist::at<derived_reflection::members, 0>::field_container,
|
||||
reflect_test_base>::value, "");
|
||||
static_assert(fc::typelist::at<derived_reflection::members, 1>::is_derived, "");
|
||||
static_assert(std::is_same<fc::typelist::at<derived_reflection::members, 1>::field_container,
|
||||
reflect_test_base>::value, "");
|
||||
static_assert(fc::typelist::at<derived_reflection::members, 2>::is_derived == false, "");
|
||||
static_assert(std::is_same<fc::typelist::slice<fc::typelist::list<int, bool, char>, 0, 1>,
|
||||
fc::typelist::list<int>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::slice<fc::typelist::list<int, bool, char>, 0, 2>,
|
||||
fc::typelist::list<int, bool>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::slice<fc::typelist::list<int, bool, char>, 0, 3>,
|
||||
fc::typelist::list<int, bool, char>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::slice<fc::typelist::list<int, bool, char>, 1, 3>,
|
||||
fc::typelist::list<bool, char>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::slice<fc::typelist::list<int, bool, char>, 2, 3>,
|
||||
fc::typelist::list<char>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::slice<fc::typelist::list<int, bool, char>, 1, 2>,
|
||||
fc::typelist::list<bool>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::slice<fc::typelist::list<int, bool, char>, 1>,
|
||||
fc::typelist::list<bool, char>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::make_sequence<0>, fc::typelist::list<>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::make_sequence<1>,
|
||||
fc::typelist::list<std::integral_constant<size_t, 0>>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::make_sequence<2>,
|
||||
fc::typelist::list<std::integral_constant<size_t, 0>,
|
||||
std::integral_constant<size_t, 1>>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::make_sequence<3>,
|
||||
fc::typelist::list<std::integral_constant<size_t, 0>,
|
||||
std::integral_constant<size_t, 1>,
|
||||
std::integral_constant<size_t, 2>>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::zip<fc::typelist::list<>, fc::typelist::list<>>,
|
||||
fc::typelist::list<>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::zip<fc::typelist::list<bool>, fc::typelist::list<char>>,
|
||||
fc::typelist::list<fc::typelist::list<bool, char>>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::zip<fc::typelist::list<int, bool>, fc::typelist::list<char, double>>,
|
||||
fc::typelist::list<fc::typelist::list<int, char>,
|
||||
fc::typelist::list<bool, double>>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::index<fc::typelist::list<>>, fc::typelist::list<>>::value, "");
|
||||
static_assert(std::is_same<fc::typelist::index<fc::typelist::list<int, bool, char, double>>,
|
||||
fc::typelist::list<fc::typelist::list<std::integral_constant<size_t, 0>, int>,
|
||||
fc::typelist::list<std::integral_constant<size_t, 1>, bool>,
|
||||
fc::typelist::list<std::integral_constant<size_t, 2>, char>,
|
||||
fc::typelist::list<std::integral_constant<size_t, 3>, double>>
|
||||
>::value, "");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( typelist_dispatch_test )
|
||||
{
|
||||
using list = fc::typelist::list<float, bool, char>;
|
||||
auto get_name = [](auto t) -> std::string { return fc::get_typename<typename decltype(t)::type>::name(); };
|
||||
BOOST_CHECK_EQUAL(fc::typelist::runtime::dispatch(list(), 0ul, get_name), "float");
|
||||
BOOST_CHECK_EQUAL(fc::typelist::runtime::dispatch(list(), 1ul, get_name), "bool");
|
||||
BOOST_CHECK_EQUAL(fc::typelist::runtime::dispatch(list(), 2ul, get_name), "char");
|
||||
}
|
||||
|
||||
// Helper template to use fc::typelist::at without a comma, for macro friendliness
|
||||
template<typename T> struct index_from { template<std::size_t idx> using at = fc::typelist::at<T, idx>; };
|
||||
BOOST_AUTO_TEST_CASE( reflection_get_test )
|
||||
{ try {
|
||||
reflect_test_derived derived;
|
||||
reflect_test_base& base = derived;
|
||||
|
||||
using base_reflector = fc::reflector<reflect_test_base>;
|
||||
using derived_reflector = fc::reflector<reflect_test_derived>;
|
||||
|
||||
BOOST_CHECK(index_from<base_reflector::members>::at<0>::get(base) == 1);
|
||||
BOOST_CHECK(index_from<base_reflector::members>::at<1>::get(base) == 'a');
|
||||
|
||||
fc::typelist::at<base_reflector::members, 0>::get(base) = 5;
|
||||
fc::typelist::at<base_reflector::members, 1>::get(base) = 'q';
|
||||
|
||||
BOOST_CHECK(index_from<base_reflector::members>::at<0>::get(base) == 5);
|
||||
BOOST_CHECK(index_from<base_reflector::members>::at<1>::get(base) == 'q');
|
||||
|
||||
BOOST_CHECK(index_from<derived_reflector::members>::at<0>::get(derived) == 5);
|
||||
BOOST_CHECK(index_from<derived_reflector::members>::at<1>::get(derived) == 'q');
|
||||
BOOST_CHECK(index_from<derived_reflector::members>::at<2>::get(derived) == 3.14);
|
||||
|
||||
fc::typelist::at<derived_reflector::members, 1>::get(derived) = 'X';
|
||||
|
||||
BOOST_CHECK(index_from<base_reflector::members>::at<1>::get(base) == 'X');
|
||||
|
||||
reflect_layer_3 l3;
|
||||
BOOST_CHECK(index_from<index_from<index_from<index_from<fc::reflector<reflect_layer_3>::members>::at<0>
|
||||
::reflector::members>::at<0>::reflector::members>::at<0>::reflector::members>::at<1>::get(l3.l2.l1.b)
|
||||
== 'a');
|
||||
BOOST_CHECK(index_from<index_from<index_from<fc::reflector<reflect_layer_3>::members>::at<0>::reflector::members>
|
||||
::at<1>::reflector::members>::at<1>::get(l3.l2.d) == 'a');
|
||||
BOOST_CHECK(index_from<index_from<index_from<fc::reflector<reflect_layer_3>::members>::at<0>::reflector::members>
|
||||
::at<1>::reflector::members>::at<2>::get(l3.l2.d) == 3.14);
|
||||
} FC_CAPTURE_LOG_AND_RETHROW( (0) ) }
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ "$#" != 1 ]; then
|
||||
echo "Usage: $0 <boost-unit-test-executable>" 1>&2
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "Usage: $0 <boost-unit-test-executable> [arguments]" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ fi
|
|||
|
||||
if [ "$BOOST_VERSION" = "" -o "$BOOST_VERSION" -lt 105900 ]; then
|
||||
echo "Boost version '$BOOST_VERSION' - executing tests serially"
|
||||
"$1"
|
||||
"$@"
|
||||
else
|
||||
"$1" --list_content 2>&1 \
|
||||
| grep '\*$' \
|
||||
|
|
@ -26,5 +26,5 @@ else
|
|||
*) pre="$t"; ;;
|
||||
esac
|
||||
done \
|
||||
| parallel echo Running {}\; "$1" -t {}
|
||||
| parallel echo Running {}\; "$@" -t {}
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ namespace fc { namespace test {
|
|||
inline bool operator < ( const item& a, const item& b )
|
||||
{ return ( std::tie( a.level, a.w ) < std::tie( b.level, b.w ) ); }
|
||||
|
||||
|
||||
} } // namespace fc::test
|
||||
|
||||
FC_REFLECT( fc::test::item_wrapper, (v) );
|
||||
|
|
|
|||
|
|
@ -64,17 +64,20 @@ public:
|
|||
BOOST_AUTO_TEST_CASE(static_variant_depth_test)
|
||||
{
|
||||
int64_t i = 1;
|
||||
fc::static_variant<uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t> test(i);
|
||||
fc::static_variant<std::string,std::vector<uint8_t>,std::vector<uint16_t>,std::vector<uint32_t>,
|
||||
uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t> test(i);
|
||||
|
||||
std::string stacktrace = test.visit( _svdt_visitor() );
|
||||
//std::cerr << stacktrace << "\n";
|
||||
std::cerr << stacktrace << "\n";
|
||||
std::vector<std::string> lines;
|
||||
boost::split( lines, stacktrace, boost::is_any_of("\n") );
|
||||
int count = 0;
|
||||
for( const auto& line : lines )
|
||||
if( line.find("_svdt_visitor") != std::string::npos ) count++;
|
||||
BOOST_CHECK_LT( 2, count ); // test.visit(), static_variant::visit, function object, visitor
|
||||
BOOST_CHECK_GT( 8, count ); // some is implementation-dependent
|
||||
BOOST_CHECK_LT( 1, count ); // test.visit(), static_variant::visit, function object, visitor.
|
||||
// The actual count depends on compiler and optimization settings.
|
||||
BOOST_CHECK_GT( 10, count ); // It *should* be less than the number of static variant components.
|
||||
// some is implementation-dependent
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
namespace fc { namespace test {
|
||||
|
||||
struct thread_config {
|
||||
thread_config() {
|
||||
for( int i = 0; i < boost::unit_test::framework::master_test_suite().argc - 1; ++i )
|
||||
|
|
@ -42,13 +44,51 @@ struct thread_config {
|
|||
{
|
||||
uint16_t threads = atoi(boost::unit_test::framework::master_test_suite().argv[++i]);
|
||||
std::cout << "Using " << threads << " pool threads\n";
|
||||
fc::asio::default_io_service_scope::set_num_threads(threads);
|
||||
asio::default_io_service_scope::set_num_threads(threads);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_GLOBAL_FIXTURE( thread_config );
|
||||
const std::string TEXT = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"$%&/()=?,.-#+´{[]}`*'_:;<>|";
|
||||
|
||||
template<typename Hash>
|
||||
class hash_test {
|
||||
public:
|
||||
std::string _hashname = get_typename<Hash>::name();
|
||||
|
||||
void run_single_threaded() {
|
||||
const std::string first = Hash::hash(TEXT).str();
|
||||
time_point start = time_point::now();
|
||||
for( int i = 0; i < 1000; i++ )
|
||||
BOOST_CHECK_EQUAL( first, Hash::hash(TEXT).str() );
|
||||
time_point end = time_point::now();
|
||||
ilog( "${c} single-threaded ${h}'s in ${t}µs", ("c",1000)("h",_hashname)("t",end-start) );
|
||||
}
|
||||
|
||||
void run_multi_threaded() {
|
||||
const std::string first = Hash::hash(TEXT).str();
|
||||
std::vector<future<std::string>> results;
|
||||
results.reserve( 10000 );
|
||||
time_point start = time_point::now();
|
||||
for( int i = 0; i < 10000; i++ )
|
||||
results.push_back( do_parallel( [] () { return Hash::hash(TEXT).str(); } ) );
|
||||
for( auto& result: results )
|
||||
BOOST_CHECK_EQUAL( first, result.wait() );
|
||||
time_point end = time_point::now();
|
||||
ilog( "${c} multi-threaded ${h}'s in ${t}µs", ("c",10000)("h",_hashname)("t",end-start) );
|
||||
}
|
||||
|
||||
void run() {
|
||||
run_single_threaded();
|
||||
run_multi_threaded();
|
||||
}
|
||||
};
|
||||
|
||||
}} // fc::test
|
||||
|
||||
using namespace fc::test;
|
||||
|
||||
BOOST_GLOBAL_FIXTURE( thread_config );
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(parallel_tests)
|
||||
|
||||
|
|
@ -96,41 +136,6 @@ BOOST_AUTO_TEST_CASE( do_something_parallel )
|
|||
}
|
||||
}
|
||||
|
||||
const std::string TEXT = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"$%&/()=?,.-#+´{[]}`*'_:;<>|";
|
||||
|
||||
template<typename Hash>
|
||||
class hash_test {
|
||||
public:
|
||||
std::string _hashname = fc::get_typename<Hash>::name();
|
||||
|
||||
void run_single_threaded() {
|
||||
const std::string first = Hash::hash(TEXT).str();
|
||||
fc::time_point start = fc::time_point::now();
|
||||
for( int i = 0; i < 1000; i++ )
|
||||
BOOST_CHECK_EQUAL( first, Hash::hash(TEXT).str() );
|
||||
fc::time_point end = fc::time_point::now();
|
||||
ilog( "${c} single-threaded ${h}'s in ${t}µs", ("c",1000)("h",_hashname)("t",end-start) );
|
||||
}
|
||||
|
||||
void run_multi_threaded() {
|
||||
const std::string first = Hash::hash(TEXT).str();
|
||||
std::vector<fc::future<std::string>> results;
|
||||
results.reserve( 10000 );
|
||||
fc::time_point start = fc::time_point::now();
|
||||
for( int i = 0; i < 10000; i++ )
|
||||
results.push_back( fc::do_parallel( [] () { return Hash::hash(TEXT).str(); } ) );
|
||||
for( auto& result: results )
|
||||
BOOST_CHECK_EQUAL( first, result.wait() );
|
||||
fc::time_point end = fc::time_point::now();
|
||||
ilog( "${c} multi-threaded ${h}'s in ${t}µs", ("c",10000)("h",_hashname)("t",end-start) );
|
||||
}
|
||||
|
||||
void run() {
|
||||
run_single_threaded();
|
||||
run_multi_threaded();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( hash_parallel )
|
||||
{
|
||||
hash_test<fc::ripemd160>().run();
|
||||
|
|
|
|||
2
vendor/websocketpp
vendored
2
vendor/websocketpp
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 4543c5f9860333e9c73552362ae74239f98e80fe
|
||||
Subproject commit 969c9939112cd9f8a99e9d051cadc406ee634140
|
||||
Loading…
Reference in a new issue