FC Updates from BitShares and myself #21

Closed
nathanielhourt wants to merge 687 commits from dapp-support into latest-fc
314 changed files with 10097 additions and 14972 deletions

170
.github/workflows/build-and-test.yml vendored Normal file
View file

@ -0,0 +1,170 @@
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 Ubuntu, 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 Ubuntu, 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_
test-macos:
name: Build and run tests in macOS
runs-on: macos-latest
steps:
- name: Install dependencies
run: |
brew install autoconf automake libtool
brew install ccache
brew search boost
brew install boost@1.60
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Configure
run: |
mkdir -p _build
pushd _build
cmake -D CMAKE_BUILD_TYPE=Release \
-D CMAKE_C_COMPILER_LAUNCHER=ccache \
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
-D BOOST_ROOT=/usr/local/opt/boost@1.60 \
-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl \
..
popd
- name: Load Cache
uses: actions/cache@v1
with:
path: ccache
key: ccache-osx-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ccache-osx-${{ github.ref }}-
ccache-osx-
- name: Build
run: |
export CCACHE_DIR="$GITHUB_WORKSPACE/ccache"
mkdir -p "$CCACHE_DIR"
make -j 2 -C _build
df -h
- name: Unit-Tests
run: |
pushd _build/tests
./all_tests -l message
./bloom_test -- README.md
./ecc_test README.md
./hmac_test
./task_cancel_test

2
.gitignore vendored Executable file → Normal file
View file

@ -36,7 +36,7 @@ Release/
CMakeCache.txt
CMakeFiles
Makefile
*.cmake
cmake_install.cmake
*.cbp
libfc.a

View file

@ -1,10 +0,0 @@
include:
- template: Jobs/Code-Quality.gitlab-ci.yml
stages:
- test
trigger_build_peerplays:
stage: test
script:
- "curl -X POST -F token=$CI_JOB_TOKEN -F ref=$REF_NAME https://gitlab.com/api/v4/projects/10735589/trigger/pipeline"

3
.gitmodules vendored Executable file → Normal file
View file

@ -1,3 +1,6 @@
[submodule "vendor/diff-match-patch-cpp-stl"]
path = vendor/diff-match-patch-cpp-stl
url = https://github.com/leutloff/diff-match-patch-cpp-stl
[submodule "vendor/secp256k1-zkp"]
path = vendor/secp256k1-zkp
url = https://github.com/bitshares/secp256k1-zkp.git

37
.travis.yml Normal file
View file

@ -0,0 +1,37 @@
language: c++
cache: ccache
git:
depth: 1
dist: xenial
sudo: true
install:
- sudo apt-get install --allow-unauthenticated 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 cmake parallel
addons:
sonarcloud:
organization: "flwyiq7go36p6lipr64tbesy5jayad3q"
token:
secure: "Y0DhI1Fn7QXqdYF5kCUFV0l0XUOp5iYp+kHYVAWpt1HSYN5889GTO3SgsZoT7+Cmo1HLAe2P8tSCzz3lECDI0rWMuk7wxFRMVmnxBpbR5P61+Mhe4t/LhSGzuT3PAscttFNPexpDmePKO0EgTY7PemMtXR8LZ2O/RngAMWWfH0Wmyngy68Bm9CvpWfW9aQ8ZUMsjpbDmbaE9dN6FLABE1YZzVL+9SA07gOSQzry/SLbRY19+g9OicaAoCdQCdvIem6af1qIy0x5uDFfz4x1Sows9awBOsAOf6V5WmFlV21YwR1RhT+4WffB+VrMYOF8YpzoUrS+CPmPWlkDDN3fuKsqRGYpbBIxyqBQ+rahDtXfoD5ZbGY1UYTbrHGD8VTNVbvdqAsVEfgZ8ci7NxBnIL3VDduxP1qb46chTJb9KeeIETtN8qTdfsZyudveZLKmULKah8uaOkMX2bJT6oikluVXJnI0OybHQrrMwHula/qmEj3FnC3KKPmL84F/6DSPiiojx+qsMa0STQE9ZwzeJPc8KjllsTYKL492IDQJDXkWGS+PwlOXResr2Dhu/rfYKy6qpHQJzreoPcIRmeM7rFamJZHkqdaldJGm+iQacX2byKJ/tT93IM6hW0BEi4Haucwn1f0Ig5tzE8mzro1/Rj35a9ti2jmO0NWjyeBwnCVo="
env:
global:
- CCACHE_COMPRESS=exists_means_true
- CCACHE_MAXSIZE=1Gi
- CCACHE_SLOPPINESS=include_file_ctime,include_file_mtime,time_macros
script:
- ccache -s
- 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 -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'
- 'which sonar-scanner && sonar-scanner || true'
- ccache -s

252
CMakeLists.txt Executable file → Normal file
View file

@ -1,8 +1,19 @@
#
# Defines fc library target.
CMAKE_MINIMUM_REQUIRED( VERSION 3.2 FATAL_ERROR )
PROJECT( fc )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8.12 )
set( CMAKE_CXX_STANDARD 14 )
SET( CMAKE_CXX_STANDARD_REQUIRED ON )
set( FC_BUILD_DYNAMIC_LIBRARIES OFF CACHE BOOL "Whether FC should build as a dynamic library rather than static" )
if( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" )
set( CMAKE_CXX_EXTENSIONS ON ) # for __int128 support
else( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" )
set( CMAKE_CXX_EXTENSIONS OFF )
endif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang|GNU$" )
MESSAGE(STATUS "Configuring project fc located in: ${CMAKE_CURRENT_SOURCE_DIR}")
SET( CMAKE_AUTOMOC OFF )
@ -12,9 +23,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)
get_git_head_revision(GIT_REFSPEC FC_GIT_REVISION_SHA)
get_git_unix_timestamp(FC_GIT_REVISION_UNIX_TIMESTAMP)
@ -24,38 +34,23 @@ SET( DEFAULT_LIBRARY_INSTALL_DIR lib/ )
SET( DEFAULT_EXECUTABLE_INSTALL_DIR bin/ )
SET( CMAKE_DEBUG_POSTFIX _debug )
SET( BUILD_SHARED_LIBS NO )
SET( ECC_IMPL secp256k1 CACHE STRING "secp256k1 or openssl or mixed" )
SET( FC_USE_FULL_ZLIB FALSE CACHE BOOL "TRUE to try to use full zlib for compression, FALSE to use miniz.c")
if( FC_USE_FULL_ZLIB )
find_package( ZLIB REQUIRED )
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFC_USE_FULL_ZLIB")
endif()
set(platformBitness 32)
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 signals serialization chrono unit_test_framework context locale iostreams)
LIST(APPEND BOOST_COMPONENTS coroutine thread date_time filesystem system program_options serialization chrono unit_test_framework context iostreams regex)
# boost::endian is also required, but FindBoost can't handle header-only libs
if(${FC_BUILD_DYNAMIC_LIBRARIES})
SET( Boost_USE_STATIC_LIBS OFF CACHE STRING "ON or OFF" )
else()
SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" )
IF( ECC_IMPL STREQUAL openssl )
SET( ECC_REST src/crypto/elliptic_impl_pub.cpp )
ELSE( ECC_IMPL STREQUAL openssl )
SET( ECC_LIB secp256k1 )
IF( ECC_IMPL STREQUAL mixed )
SET( ECC_REST src/crypto/elliptic_impl_priv.cpp src/crypto/elliptic_impl_pub.cpp )
ELSE( ECC_IMPL STREQUAL mixed )
SET( ECC_REST src/crypto/elliptic_impl_priv.cpp )
ENDIF( ECC_IMPL STREQUAL mixed )
ENDIF( ECC_IMPL STREQUAL openssl )
endif()
# 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" )
@ -71,27 +66,24 @@ 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 )
if( CMAKE_POSITION_INDEPENDENT_CODE )
set( SECP_USE_PIC --with-pic )
else( CMAKE_POSITION_INDEPENDENT_CODE )
set( SECP_USE_PIC "" )
endif()
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
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp --with-bignum=no ${SECP_USE_PIC}
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
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp --with-bignum=no
BUILD_COMMAND make
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
@ -104,56 +96,41 @@ else ( MSVC )
set_property(TARGET secp256k1 PROPERTY IMPORTED_LOCATION ${binary_dir}/.libs/libsecp256k1${CMAKE_STATIC_LIBRARY_SUFFIX})
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 )
if (${FC_BUILD_DYNAMIC_LIBRARIES})
FILE(GLOB SECP_SHARED ${binary_dir}/.libs/libsecp256k1.so*)
endif()
install( FILES ${binary_dir}/.libs/libsecp256k1${CMAKE_STATIC_LIBRARY_SUFFIX} ${SECP_SHARED} DESTINATION lib/cryptonomex )
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 )
ExternalProject_Add( project_editline
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline --host=x86_64-w64-mingw32
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline CFLAGS=-fPIC
BUILD_COMMAND make
INSTALL_COMMAND true
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/src/.libs/libeditline.a
)
else ( MINGW )
ExternalProject_Add( project_editline
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
BUILD_COMMAND make
INSTALL_COMMAND true
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
)
endif ( MINGW )
ExternalProject_Add_Step(project_editline autogen
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/autogen.sh
DEPENDERS configure
)
ExternalProject_Get_Property(project_editline binary_dir)
add_library(editline STATIC IMPORTED)
set_property(TARGET editline PROPERTY IMPORTED_LOCATION ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX})
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 ( MSVC )
if (${FC_BUILD_DYNAMIC_LIBRARIES})
FILE(GLOB EDITLINE_SHARED ${binary_dir}/src/.libs/libeditline.so*)
endif()
install( FILES ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX} ${EDITLINE_SHARED} DESTINATION lib/cryptonomex )
endif ( NOT WIN32 )
# End configure editline
IF( WIN32 )
@ -162,57 +139,44 @@ IF( WIN32 )
set( RPCRT4 rpcrt4 )
#boost
if ($ENV{BOOST_ROOT})
SET(BOOST_ROOT $ENV{BOOST_ROOT})
# set(Boost_USE_DEBUG_PYTHON ON)
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)
set( 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}")
ENDIF()
IF( LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB )
LIST( APPEND PLATFORM_SPECIFIC_LIBS atomic )
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/uint128.cpp
src/real128.cpp
src/popcount.cpp
src/variant.cpp
src/exception.cpp
src/variant_object.cpp
@ -224,10 +188,11 @@ set( fc_sources
src/thread/spin_lock.cpp
src/thread/spin_yield_lock.cpp
src/thread/mutex.cpp
src/thread/parallel.cpp
src/thread/non_preemptable_scope_check.cpp
src/asio.cpp
src/string.cpp
src/shared_ptr.cpp
src/stacktrace.cpp
src/time.cpp
src/utf8.cpp
src/io/iostream.cpp
@ -237,17 +202,11 @@ set( fc_sources
src/io/sstream.cpp
src/io/json.cpp
src/io/varint.cpp
src/io/console.cpp
src/filesystem.cpp
src/interprocess/signals.cpp
src/interprocess/file_mapping.cpp
src/interprocess/mmap_struct.cpp
src/interprocess/file_mutex.cpp
src/rpc/cli.cpp
src/rpc/http_api.cpp
src/rpc/json_connection.cpp
src/rpc/state.cpp
src/rpc/bstate.cpp
src/rpc/websocket_api.cpp
src/log/log_message.cpp
src/log/logger.cpp
@ -261,34 +220,29 @@ set( fc_sources
src/crypto/aes.cpp
src/crypto/crc.cpp
src/crypto/city.cpp
src/crypto/base36.cpp
src/crypto/base58.cpp
src/crypto/base64.cpp
src/crypto/bigint.cpp
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
src/crypto/md5.cpp
src/crypto/dh.cpp
src/crypto/blowfish.cpp
src/crypto/elliptic_common.cpp
${ECC_REST}
src/crypto/elliptic_${ECC_IMPL}.cpp
src/crypto/elliptic_impl_priv.cpp
src/crypto/elliptic_secp256k1.cpp
src/crypto/rand.cpp
src/network/tcp_socket.cpp
src/network/udp_socket.cpp
src/network/http/http_connection.cpp
src/network/http/http_server.cpp
src/network/http/websocket.cpp
src/network/ip.cpp
src/network/ntp.cpp
src/network/rate_limiting.cpp
src/network/resolve.cpp
src/network/url.cpp
src/compress/smaz.cpp
src/compress/zlib.cpp
)
@ -304,7 +258,13 @@ list(APPEND sources ${fc_headers})
add_subdirectory( vendor/websocketpp EXCLUDE_FROM_ALL )
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC )
if (NOT ${FC_BUILD_DYNAMIC_LIBRARIES} )
add_library( fc ${sources} )
else()
add_library( fc SHARED ${sources} )
endif()
install( TARGETS fc LIBRARY DESTINATION lib ARCHIVE DESTINATION lib )
install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include )
# begin editline stuff
@ -316,10 +276,6 @@ else(WIN32)
endif(WIN32)
# end editline stuff
if( NOT CPP_STANDARD )
set( CPP_STANDARD "-std=c++11" )
endif()
IF(WIN32)
target_compile_definitions(fc PUBLIC WIN32 NOMINMAX _WIN32_WINNT=0x0501 _CRT_SECURE_NO_WARNINGS
_SCL_SERCURE_NO_WARNINGS
@ -341,12 +297,12 @@ ELSE()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall")
IF(APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CPP_STANDARD} -stdlib=libc++ -Wall")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wall")
ELSE()
if( NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
target_compile_options(fc PUBLIC ${CPP_STANDARD} -Wall -fnon-call-exceptions)
target_compile_options(fc PUBLIC -Wall -fnon-call-exceptions)
endif()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CPP_STANDARD} -Wall -fnon-call-exceptions")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fnon-call-exceptions")
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
if( CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.0.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0.0 )
@ -368,6 +324,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" )
@ -404,18 +361,21 @@ target_include_directories(fc
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
)
#target_link_libraries( fc PUBLIC ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${ECC_LIB} )
IF(NOT WIN32)
set(LINK_USR_LOCAL_LIB -L/usr/local/lib)
ENDIF()
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${editline_libraries} ${ECC_LIB} )
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${Boost_LIBRARIES}
${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library}
${editline_libraries} secp256k1 ${CMAKE_REQUIRED_LIBRARIES} )
if(MSVC)
if(WIN32 AND MSVC)
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
endif(MSVC)
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)$" OR FC_BUILD_DYNAMIC_LIBRARIES)
IF(MSVC)
add_definitions(/DBOOST_TEST_DYN_LINK)
ELSE(MSVC)
@ -427,18 +387,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)
@ -507,30 +459,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()
SET(OPENSSL_CONF_SOURCE "${OPENSSL_ROOT_DIR}/ssl/openssl.cnf")
IF(MINGW)
SET(OPENSSL_CONF_SOURCE "${OPENSSL_ROOT_DIR}/openssl.cnf")
ENDIF(MINGW)
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...")

View file

@ -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 )

View 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 ()

View file

@ -0,0 +1,55 @@
# Taken from https://chromium.googlesource.com/chromium/llvm-project/libcxx/+/refs/heads/master/cmake/Modules/CheckLibcxxAtomic.cmake
# Apache License v2.0 with LLVM Exceptions
INCLUDE(CheckCXXSourceCompiles)
# Sometimes linking against libatomic is required for atomic ops, if
# the platform doesn't support lock-free atomics.
function(check_cxx_atomics varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
if (${LIBCXX_GCC_TOOLCHAIN})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} --gcc-toolchain=${LIBCXX_GCC_TOOLCHAIN}")
endif()
if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all")
endif()
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*,boost::lockfree::capacity<5>> q;
int main(int, char**) {
uint32_t* a;
uint32_t* b;
q.push(a);
q.pop(b);
}
" ${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.
check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it.
if(NOT LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB)
check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB)
if(LIBCXX_HAS_ATOMIC_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB)
if (NOT LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB)
message(WARNING "Host compiler must support std::atomic!")
endif()
else()
message(WARNING "Host compiler appears to require libatomic, but cannot find it.")
endif()
endif()

File diff suppressed because it is too large Load diff

View file

@ -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)

View file

@ -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)

View file

@ -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 )

View file

@ -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 )

View file

@ -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 )

2362
Doxyfile Normal file

File diff suppressed because it is too large Load diff

2
GitVersionGen/GetGitRevisionDescription.cmake Executable file → Normal file
View file

@ -58,7 +58,7 @@ function(get_git_head_revision _refspecvar _hashvar)
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${GIT_DIR_RELATIVE} ABSOLUTE BASE_DIR ${SUBMODULE_DIR})
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")

0
GitVersionGen/GetGitRevisionDescription.cmake.in Executable file → Normal file
View file

52
LICENSE.md Normal file
View 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.

0
README-ecc.md Executable file → Normal file
View file

3
README.md Executable file → Normal file
View file

@ -1,6 +1,9 @@
fc
==
[![](https://travis-ci.org/bitshares/bitshares-fc.svg?branch=master)](https://travis-ci.org/bitshares/bitshares-fc)
[![](https://github.com/bitshares/bitshares-fc/workflows/Github%20Autobuild/badge.svg?branch=master)](https://github.com/bitshares/bitshares-fc/actions?query=branch%3Amaster)
**NOTE:** This fork reverts upstream commit a421e280488385cab26a42153f7ce3c8d5b6281f to avoid changing the BitShares API.
FC stands for fast-compiling c++ library and provides a set of utility libraries useful

6
fc.natvis Executable file → Normal file
View file

@ -31,12 +31,6 @@
</Expand>
</Type>
<Type Name="fc::string">
<DisplayString>{my}</DisplayString>
<Expand>
<ExpandedItem>my</ExpandedItem>
</Expand>
</Type>
<Type Name="fc::optional&lt;*&gt;">
<DisplayString Condition="!_valid">invalid</DisplayString>

View file

@ -1,65 +0,0 @@
#pragma once
#include <fc/api.hpp>
#include <fc/thread/thread.hpp>
namespace fc {
namespace detail {
struct actor_member {
#if 1 // BOOST_NO_VARIADIC_TEMPLATES
#define RPC_MEMBER_FUNCTOR(z,n,IS_CONST) \
template<typename R, typename C, typename P BOOST_PP_ENUM_TRAILING_PARAMS( n, typename A)> \
static std::function<fc::future<R>( BOOST_PP_ENUM_PARAMS(n,A) ) > \
functor( P p, R (C::*mem_func)(BOOST_PP_ENUM_PARAMS(n,A)) IS_CONST, fc::thread* c = 0) { \
return [=](BOOST_PP_ENUM_BINARY_PARAMS(n,A,a))->fc::future<R>{ \
return c->async( [=](){ return (p->*mem_func)(BOOST_PP_ENUM_PARAMS(n,a)); } ); }; \
}
BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, const )
BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, BOOST_PP_EMPTY() )
#undef RPC_MEMBER_FUNCTOR
#else // g++ has a bug that prevents lambdas and varidic templates from working together (G++ Bug 41933)
template<typename R, typename C, typename P, typename... Args>
static std::function<fc::future<R>(Args...)> functor( P&& p, R (C::*mem_func)(Args...), fc::thread* c ) {
return [=](Args... args)->fc::future<R>{ c->async( [=]()->R { return p->*mem_func( fc::forward<Args>(args)... ); } ) };
}
template<typename R, typename C, typename P, typename... Args>
static std::function<fc::future<R>(Args...)> functor( P&& p, R (C::*mem_func)(Args...)const, fc::thread* c ){
return [=](Args... args)->fc::future<R>{ c->async( [=]()->R { return p->*mem_func( fc::forward<Args>(args)... ); } ) };
}
#endif
};
template<typename ThisPtr>
struct actor_vtable_visitor {
template<typename U>
actor_vtable_visitor( fc::thread* t, U&& u ):_thread(t),_this( fc::forward<U>(u) ){}
template<typename Function, typename MemberPtr>
void operator()( const char* name, Function& memb, MemberPtr m )const {
memb = actor_member::functor( _this, m, _thread );
}
fc::thread* _thread;
ThisPtr _this;
};
}
/**
* Posts all method calls to another thread and
* returns a future.
*/
template<typename Interface>
class actor : public api<Interface, detail::actor_member> {
public:
actor(){}
template<typename InterfaceType>
actor( InterfaceType* p, fc::thread* t = &fc::thread::current() )
{
this->_vtable.reset(new detail::vtable<Interface,detail::actor_member>() );
this->_vtable->template visit<InterfaceType>( detail::actor_vtable_visitor<InterfaceType*>(t, p) );
}
};
} // namespace fc

View file

@ -1,14 +0,0 @@
#pragma once
namespace fc {
template<unsigned int S, typename T=double>
struct aligned {
union {
T _align;
char _data[S];
} _store;
operator char*() { return _store._data; }
operator const char*()const { return _store._data; }
};
}

View file

@ -1,7 +0,0 @@
#pragma once
#include <boost/any.hpp>
namespace fc {
// TODO: define this without using boost
typedef boost::any any;
}

94
include/fc/api.hpp Executable file → Normal file
View file

@ -1,7 +1,7 @@
#pragma once
#include <fc/thread/future.hpp>
#include <fc/any.hpp>
#include <functional>
#include <boost/any.hpp>
#include <boost/config.hpp>
// ms visual c++ (as of 2013) doesn't accept the standard syntax for calling a
@ -13,11 +13,89 @@
#endif
namespace fc {
struct identity_member {
namespace detail {
/// This metafunction determines whether its template argument is an instantiation of fc::optional
template<typename T> struct is_optional : public std::false_type {};
template<typename T> struct is_optional<fc::optional<T>> : public std::true_type {};
/// This metafunction determines whether all of its template arguments are instantiations of fc::optional
template<typename... Ts> struct all_optionals;
template<> struct all_optionals<> : public std::true_type {};
template<typename T, typename... Ts> struct all_optionals<T, Ts...> : public std::false_type {};
template<typename T, typename... Ts> struct all_optionals<fc::optional<T>, Ts...> : public all_optionals<Ts...> {};
/// A wrapper of std::function allowing callers to omit the last several arguments if those arguments are
/// fc::optional types. i.e. given a function taking (int, double, bool, fc::optional<string>, fc::optional<char>),
/// whereas normally the last two arguments must be provided, this template allows them to be omitted.
/// Note that this only applies to trailing optional arguments, i.e. given a callable taking
/// (fc::optional<int>, int, fc::optional<int>), only the last argument can be omitted.
///
/// A discussion of how exactly this works is available here:
/// https://github.com/bitshares/bitshares-fc/pull/126#issuecomment-490566060
template<typename R, typename... Parameters>
struct optionals_callable : public std::function<R(Parameters...)> {
using std::function<R(Parameters...)>::operator();
template<typename... CutList>
struct short_pack {};
/// This metafunction removes the first several types from a variadic parameter pack of types.
/// The first parameter is the number of arguments to remove from the beginning of the pack.
/// All subsequent parameters are types in the list to be cut
/// The result pack_cutter<...>::type is a short_pack<RemainingTypes>
template<unsigned RemoveCount, typename... Types>
struct pack_cutter;
template<unsigned RemoveCount, typename, typename... Types>
struct pack_cutter_impl;
template<typename... Types>
struct pack_cutter_impl<0, void, Types...> {
static_assert(all_optionals<Types...>::value, "All omitted arguments must correspond to optional parameters.");
using type = short_pack<Types...>;
};
template<unsigned RemoveCount, typename T, typename... Types>
struct pack_cutter_impl<RemoveCount, std::enable_if_t<RemoveCount != 0>, T, Types...>
: public pack_cutter_impl<RemoveCount - 1, void, Types...> {};
template<unsigned RemoveCount, typename... Types>
struct pack_cutter : public pack_cutter_impl<RemoveCount, void, Types...> {};
template<unsigned RemoveCount, typename... Types>
using pack_cutter_t = typename pack_cutter<RemoveCount, Types...>::type;
template<typename F, typename... OptionalTypes>
R call_function(F&& f, short_pack<OptionalTypes...>) {
return f(OptionalTypes()...);
}
/// Overload the function call operator, enabled if the caller provides fewer arguments than there are parameters.
/// Pads out the provided arguments with default-constructed optionals, checking that they are indeed optional types
template<class... Args>
std::enable_if_t<sizeof...(Args) < sizeof...(Parameters), R> operator()(Args... args) {
// Partially apply with the arguments provided
auto partial_function = [this, &args...](auto&&... rest) {
return (*this)(std::forward<decltype(args)>(args)..., std::move(rest)...);
};
// Cut the provided arguments' types out of the Parameters list, and store the rest in a dummy type
pack_cutter_t<sizeof...(Args), std::decay_t<Parameters>...> dummy;
// Pass the partially applied function and the dummy type to another function which can deduce the optional
// types and call the function with default instantiations of those types
return call_function(std::move(partial_function), dummy);
}
};
}
// This is no longer used and probably no longer can be used without generalizing the infrastructure around it, but I
// kept it because it is informative.
// struct identity_member {
// template<typename R, typename C, typename P, typename... Args>
// static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...) );
// template<typename R, typename C, typename P, typename... Args>
// static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...)const );
// };
/// Used as the Transform template parameter for APIs, this type has two main purposes: first, it reads the argument
/// list and return type of a method into template parameters; and second, it uses those types in conjunction with the
/// optionals_callable template above to create a function pointer which supports optional arguments.
struct identity_member_with_optionals {
template<typename R, typename C, typename P, typename... Args>
static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...) );
static detail::optionals_callable<R, Args...> functor( P&& p, R (C::*mem_func)(Args...) );
template<typename R, typename C, typename P, typename... Args>
static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...)const );
static detail::optionals_callable<R, Args...> functor( P&& p, R (C::*mem_func)(Args...)const );
};
template< typename Interface, typename Transform >
@ -57,13 +135,13 @@ namespace fc {
// defined in api_connection.hpp
template< typename T >
api<T, identity_member> as();
api<T, identity_member_with_optionals> as();
};
typedef std::shared_ptr< api_base > api_ptr;
class api_connection;
template<typename Interface, typename Transform = identity_member >
template<typename Interface, typename Transform = identity_member_with_optionals >
class api : public api_base {
public:
typedef vtable<Interface,Transform> vtable_type;
@ -75,7 +153,7 @@ namespace fc {
api( const T& p )
:_vtable( std::make_shared<vtable_type>() )
{
_data = std::make_shared<fc::any>(p);
_data = std::make_shared<boost::any>(p);
T& ptr = boost::any_cast<T&>(*_data);
auto& pointed_at = *ptr;
typedef typename std::remove_reference<decltype(pointed_at)>::type source_vtable_type;
@ -95,7 +173,7 @@ namespace fc {
protected:
std::shared_ptr<vtable_type> _vtable;
std::shared_ptr<fc::any> _data;
std::shared_ptr<boost::any> _data;
};
} // namespace fc

View file

@ -1,147 +0,0 @@
#pragma once
#include <fc/crypto/base64.hpp>
#include <fc/variant.hpp>
#include <fc/reflect/reflect.hpp>
namespace fc {
/**
* Provides a fixed size array that is easier for templates to specialize
* against or overload than T[N].
*/
template<typename T, size_t N>
class array {
public:
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
T& at( size_t pos ) { assert( pos < N); return data[pos]; }
const T& at( size_t pos )const { assert( pos < N); return data[pos]; }
///@}
T& operator[]( size_t pos ) { assert( pos < N); return data[pos]; }
const T& operator[]( size_t pos )const { assert( pos < N); return data[pos]; }
const T* begin()const { return &data[0]; }
const T* end()const { return &data[N]; }
T* begin() { return &data[0]; }
T* end() { return &data[N]; }
size_t size()const { return N; }
T data[N];
};
/** provided for default 0 init */
template<size_t N>
class array<unsigned char,N>
{
public:
typedef unsigned char T;
array(){ memset( data, 0, sizeof(data) ); }
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
T& at( size_t pos ) { assert( pos < N); return data[pos]; }
const T& at( size_t pos )const { assert( pos < N); return data[pos]; }
///@}
T* begin() { return &data[0]; }
const T* begin()const { return &data[0]; }
const T* end()const { return &data[N]; }
size_t size()const { return N; }
T data[N];
};
/** provided for default 0 init */
template<size_t N>
class array<char,N>
{
public:
typedef char T;
array(){ memset( data, 0, sizeof(data) ); }
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
T& at( size_t pos ) { assert( pos < N); return data[pos]; }
const T& at( size_t pos )const { assert( pos < N); return data[pos]; }
///@}
T* begin() { return &data[0]; }
const T* begin()const { return &data[0]; }
const T* end()const { return &data[N]; }
size_t size()const { return N; }
T data[N];
};
template<typename T, size_t N>
bool operator == ( const array<T,N>& a, const array<T,N>& b )
{ return 0 == memcmp( a.data, b.data, N*sizeof(T) ); }
template<typename T, size_t N>
bool operator < ( const array<T,N>& a, const array<T,N>& b )
{ return memcmp( a.data, b.data, N*sizeof(T) ) < 0 ; }
template<typename T, size_t N>
bool operator > ( const array<T,N>& a, const array<T,N>& b )
{ return memcmp( a.data, b.data, N*sizeof(T) ) > 0 ; }
template<typename T, size_t N>
bool operator != ( const array<T,N>& a, const array<T,N>& b )
{ return 0 != memcmp( a.data, b.data, N*sizeof(T) ); }
template<typename T, size_t N>
void to_variant( const array<T,N>& bi, variant& v, uint32_t max_depth = 1 )
{
to_variant( std::vector<char>( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ), v, 1 );
}
template<typename T, size_t N>
void from_variant( const variant& v, array<T,N>& bi, uint32_t max_depth = 1 )
{
std::vector<char> ve = v.as< std::vector<char> >( 1 );
if( ve.size() )
{
memcpy(&bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}
else
for (size_t i = 0; i < bi.size(); i++) {
bi.data[i] = 0;
}
}
template<typename T,size_t N> struct get_typename< fc::array<T,N> >
{
static const char* name()
{
static std::string _name = std::string("fc::array<")+std::string(fc::get_typename<T>::name())+","+ fc::to_string(N) + ">";
return _name.c_str();
}
};
}
#include <unordered_map>
#include <fc/crypto/city.hpp>
namespace std
{
template<typename T, size_t N>
struct hash<fc::array<T,N> >
{
size_t operator()( const fc::array<T,N>& e )const
{
return fc::city_hash_size_t( (char*)&e, sizeof(e) );
}
};
}

61
include/fc/asio.hpp Executable file → Normal file
View file

@ -5,6 +5,8 @@
#pragma once
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <vector>
#include <fc/thread/future.hpp>
#include <fc/io/iostream.hpp>
@ -17,7 +19,6 @@ namespace asio {
* @brief internal implementation types/methods for fc::asio
*/
namespace detail {
using namespace fc;
class read_write_handler
{
@ -39,8 +40,17 @@ namespace asio {
std::shared_ptr<const char> _buffer;
};
//void read_write_handler( const promise<size_t>::ptr& p,
// const boost::system::error_code& ec,
// size_t bytes_transferred );
void read_write_handler_ec( promise<size_t>* p,
boost::system::error_code* oec,
const boost::system::error_code& ec,
size_t bytes_transferred );
void error_handler( const promise<void>::ptr& p,
const boost::system::error_code& ec );
void error_handler_ec( promise<boost::system::error_code>* p,
const boost::system::error_code& ec );
template<typename C>
struct non_blocking {
@ -56,14 +66,34 @@ namespace asio {
bool operator()( C&, bool ) { return false; }
};
#endif
}
} // end of namespace detail
/***
* A structure for holding the boost io service and associated
* threads
*/
class default_io_service_scope
{
public:
default_io_service_scope();
~default_io_service_scope();
static void set_num_threads(uint16_t num_threads);
static uint16_t get_num_threads();
boost::asio::io_service* io;
private:
std::vector<boost::thread*> asio_threads;
boost::asio::io_service::work* the_work;
protected:
static uint16_t num_io_threads; // marked protected to help with testing
};
/**
* @return the default boost::asio::io_service for use with fc::asio
*
* This IO service is automatically running in its own thread to service asynchronous
* requests without blocking any other threads.
*/
boost::asio::io_service& default_io_service(bool cleanup = false);
boost::asio::io_service& default_io_service();
/**
* @brief wraps boost::asio::async_read
@ -72,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();
}
@ -92,7 +122,7 @@ namespace asio {
template<typename AsyncReadStream, typename MutableBufferSequence>
future<size_t> read_some(AsyncReadStream& s, const MutableBufferSequence& buf)
{
promise<size_t>::ptr completion_promise(new promise<size_t>("fc::asio::async_read_some"));
promise<size_t>::ptr completion_promise = promise<size_t>::create("fc::asio::async_read_some");
s.async_read_some(buf, detail::read_write_handler(completion_promise));
return completion_promise;//->wait();
}
@ -100,7 +130,7 @@ namespace asio {
template<typename AsyncReadStream>
future<size_t> read_some(AsyncReadStream& s, char* buffer, size_t length, size_t offset = 0)
{
promise<size_t>::ptr completion_promise(new promise<size_t>("fc::asio::async_read_some"));
promise<size_t>::ptr completion_promise = promise<size_t>::create("fc::asio::async_read_some");
s.async_read_some(boost::asio::buffer(buffer + offset, length),
detail::read_write_handler(completion_promise));
return completion_promise;//->wait();
@ -109,7 +139,7 @@ namespace asio {
template<typename AsyncReadStream>
future<size_t> read_some(AsyncReadStream& s, const std::shared_ptr<char>& buffer, size_t length, size_t offset)
{
promise<size_t>::ptr completion_promise(new promise<size_t>("fc::asio::async_read_some"));
promise<size_t>::ptr completion_promise = promise<size_t>::create("fc::asio::async_read_some");
s.async_read_some(boost::asio::buffer(buffer.get() + offset, length),
detail::read_write_handler_with_buffer(completion_promise, buffer));
return completion_promise;//->wait();
@ -149,7 +179,7 @@ namespace asio {
*/
template<typename AsyncWriteStream, typename ConstBufferSequence>
size_t write( AsyncWriteStream& s, const ConstBufferSequence& buf ) {
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write"));
promise<size_t>::ptr p = promise<size_t>::create("fc::asio::write");
boost::asio::async_write(s, buf, detail::read_write_handler(p));
return p->wait();
}
@ -161,7 +191,7 @@ namespace asio {
*/
template<typename AsyncWriteStream, typename ConstBufferSequence>
future<size_t> write_some( AsyncWriteStream& s, const ConstBufferSequence& buf ) {
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write_some"));
promise<size_t>::ptr p = promise<size_t>::create("fc::asio::write_some");
s.async_write_some( buf, detail::read_write_handler(p));
return p; //->wait();
}
@ -169,7 +199,7 @@ namespace asio {
template<typename AsyncWriteStream>
future<size_t> write_some( AsyncWriteStream& s, const char* buffer,
size_t length, size_t offset = 0) {
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write_some"));
promise<size_t>::ptr p = promise<size_t>::create("fc::asio::write_some");
s.async_write_some( boost::asio::buffer(buffer + offset, length), detail::read_write_handler(p));
return p; //->wait();
}
@ -177,7 +207,7 @@ namespace asio {
template<typename AsyncWriteStream>
future<size_t> write_some( AsyncWriteStream& s, const std::shared_ptr<const char>& buffer,
size_t length, size_t offset ) {
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write_some"));
promise<size_t>::ptr p = promise<size_t>::create("fc::asio::write_some");
s.async_write_some( boost::asio::buffer(buffer.get() + offset, length), detail::read_write_handler_with_buffer(p, buffer));
return p; //->wait();
}
@ -219,8 +249,7 @@ 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( new promise<void>("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();
//if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
@ -232,7 +261,7 @@ namespace asio {
*/
template<typename AsyncSocket, typename EndpointType>
void connect( AsyncSocket& sock, const EndpointType& ep ) {
promise<void>::ptr p(new promise<void>("fc::asio::tcp::connect"));
promise<void>::ptr p = promise<void>::create("fc::asio::tcp::connect");
sock.async_connect( ep, boost::bind( fc::asio::detail::error_handler, p, _1 ) );
p->wait();
//if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
@ -252,7 +281,7 @@ namespace asio {
{
public:
istream( std::shared_ptr<AsyncReadStream> str )
:_stream( fc::move(str) ){}
:_stream( std::move(str) ){}
virtual size_t readsome( char* buf, size_t len )
{
@ -272,7 +301,7 @@ namespace asio {
{
public:
ostream( std::shared_ptr<AsyncWriteStream> str )
:_stream( fc::move(str) ){}
:_stream( std::move(str) ){}
virtual size_t writesome( const char* buf, size_t len )
{

View file

@ -1,28 +0,0 @@
#pragma once
#include <stdint.h>
namespace fc {
inline uint64_t endian_reverse_u64( uint64_t x )
{
return (((x >> 0x38) & 0xFF) )
| (((x >> 0x30) & 0xFF) << 0x08)
| (((x >> 0x28) & 0xFF) << 0x10)
| (((x >> 0x20) & 0xFF) << 0x18)
| (((x >> 0x18) & 0xFF) << 0x20)
| (((x >> 0x10) & 0xFF) << 0x28)
| (((x >> 0x08) & 0xFF) << 0x30)
| (((x ) & 0xFF) << 0x38)
;
}
inline uint32_t endian_reverse_u32( uint32_t x )
{
return (((x >> 0x18) & 0xFF) )
| (((x >> 0x10) & 0xFF) << 0x08)
| (((x >> 0x08) & 0xFF) << 0x10)
| (((x ) & 0xFF) << 0x18)
;
}
} // namespace fc

140
include/fc/bloom_filter.hpp Executable file → Normal file
View file

@ -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 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
@ -57,6 +57,20 @@ public:
random_seed(0xA5A5A5A55A5A5A5AULL)
{}
bloom_parameters(unsigned long long int projected_element_count,
double false_positive_probability,
unsigned long long int maximum_size) :
minimum_size(1),
maximum_size(maximum_size),
minimum_number_of_hashes(1),
maximum_number_of_hashes(std::numeric_limits<unsigned int>::max()),
projected_element_count(projected_element_count),
false_positive_probability(false_positive_probability),
random_seed(0xA5A5A5A55A5A5A5AULL)
{
compute_optimal_parameters();
}
virtual ~bloom_parameters()
{}
@ -73,11 +87,11 @@ 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;
@ -87,8 +101,8 @@ public:
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.
// 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;
@ -121,26 +135,30 @@ public:
double min_m = std::numeric_limits<double>::infinity();
double min_k = 0.0;
double curr_m = 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)
@ -164,13 +182,13 @@ 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),
random_seed_(0),
@ -185,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)
@ -205,13 +221,13 @@ public:
return
(salt_count_ == f.salt_count_ ) &&
(table_size_ == f.table_size_ ) &&
(raw_table_size_ == f.raw_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());
(bit_table_ == f.bit_table_ ) ;
}
else
return true;
@ -228,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_;
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
{
@ -251,7 +268,7 @@ 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;
}
@ -259,11 +276,14 @@ public:
{
std::size_t bit_index = 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);
bit_table_[bit_index / bits_per_char] |= bit_mask[bit];
}
++inserted_element_count_;
}
@ -276,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)
@ -288,6 +308,7 @@ public:
inline void insert(const InputIterator begin, const InputIterator end)
{
InputIterator itr = begin;
while (end != itr)
{
insert(*(itr++));
@ -298,14 +319,17 @@ public:
{
std::size_t bit_index = 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);
if ((bit_table_[bit_index / bits_per_char] & bit_mask[bit]) != bit_mask[bit])
{
return false;
}
}
return true;
}
@ -329,14 +353,17 @@ public:
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;
}
@ -344,14 +371,17 @@ public:
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;
}
@ -360,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_;
}
@ -386,11 +416,12 @@ public:
(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;
}
@ -403,11 +434,12 @@ public:
(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;
}
@ -420,11 +452,12 @@ public:
(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;
}
@ -455,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,
@ -496,7 +530,8 @@ 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:
@ -510,11 +545,16 @@ protected:
else
{
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);
@ -527,43 +567,58 @@ protected:
{
const unsigned char* itr = begin;
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;
}
@ -572,9 +627,8 @@ public:
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 inserted_element_count_;
unsigned long long int random_seed_;
double desired_false_positive_probability_;
};
@ -603,17 +657,15 @@ inline bloom_filter operator ^ (const bloom_filter& a, const bloom_filter& b)
} // namespace fc
#endif
FC_REFLECT( fc::bloom_filter, (salt_)(bit_table_)(salt_count_)(table_size_)(raw_table_size_)(projected_element_count_)(inserted_element_count_)(random_seed_)(desired_false_positive_probability_) )
FC_REFLECT( fc::bloom_parameters::optimal_parameters_t, (number_of_hashes)(table_size) )
FC_REFLECT( fc::bloom_parameters, (minimum_size)(maximum_size)(minimum_number_of_hashes)(maximum_number_of_hashes)(projected_element_count)(false_positive_probability)(random_seed)(optimal_parameters) )
/*
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

View file

@ -1,9 +0,0 @@
#pragma once
#include <string>
namespace fc {
std::string smaz_compress( const std::string& in );
std::string smaz_decompress( const std::string& compressed );
} // namespace fc

10
include/fc/compress/zlib.hpp Executable file → Normal file
View file

@ -1,16 +1,10 @@
#pragma once
#include <fc/string.hpp>
#ifdef FC_USE_FULL_ZLIB
# include <fc/filesystem.hpp>
#endif
#include <string>
namespace fc
{
string zlib_compress(const string& in);
#ifdef FC_USE_FULL_ZLIB
void gzip_compress_file(const path& input_filename, const path& output_filename);
#endif
std::string zlib_compress(const std::string& in);
} // namespace fc

View file

@ -7,3 +7,8 @@
// how many levels of nested objects are displayed in log messages
#define FC_MAX_LOG_OBJECT_DEPTH 200
#endif
#ifndef FC_MAX_PREALLOC_SIZE
// how many elements will be reserve()d when deserializing vectors
#define FC_MAX_PREALLOC_SIZE (256UL)
#endif

View file

@ -1,12 +0,0 @@
#pragma once
#include <deque>
#include <fc/io/raw.hpp>
namespace fc {
namespace raw {
} // namespace raw
} // namespace fc

View file

@ -1,14 +0,0 @@
#pragma once
#include <fc/config.hpp>
#include <deque>
namespace fc {
namespace raw {
template<typename Stream, typename T>
void pack( Stream& s, const std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T>
void unpack( Stream& s, std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
}
} // namespace fc

39
include/fc/container/flat.hpp Executable file → Normal file
View file

@ -7,11 +7,11 @@
namespace fc {
namespace raw {
template<typename Stream, typename T>
inline void pack( Stream& s, const flat_set<T>& value, uint32_t _max_depth ) {
template<typename Stream, typename T, typename... A>
inline void pack( Stream& s, const flat_set<T, A...>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
pack( s, unsigned_int(value.size()), _max_depth );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
@ -19,14 +19,13 @@ namespace fc {
++itr;
}
}
template<typename Stream, typename T>
inline void unpack( Stream& s, flat_set<T>& value, uint32_t _max_depth ) {
template<typename Stream, typename T, typename... A>
inline void unpack( Stream& s, flat_set<T, A...>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
unsigned_int size; unpack( s, size, _max_depth );
value.clear();
FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE );
value.reserve(size.value);
value.reserve( std::min( size.value, static_cast<uint64_t>(FC_MAX_PREALLOC_SIZE) ) );
for( uint32_t i = 0; i < size.value; ++i )
{
T tmp;
@ -38,7 +37,7 @@ namespace fc {
inline void pack( Stream& s, const flat_map<K,V...>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
pack( s, unsigned_int(value.size()), _max_depth );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
@ -53,8 +52,7 @@ namespace fc {
--_max_depth;
unsigned_int size; unpack( s, size, _max_depth );
value.clear();
FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE );
value.reserve(size.value);
value.reserve( std::min( size.value, static_cast<uint64_t>(FC_MAX_PREALLOC_SIZE) ) );
for( uint32_t i = 0; i < size.value; ++i )
{
std::pair<K,V> tmp;
@ -67,7 +65,7 @@ namespace fc {
void pack( Stream& s, const bip::vector<T,A>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
pack( s, unsigned_int(value.size()), _max_depth );
if( !std::is_fundamental<T>::value ) {
auto itr = value.begin();
auto end = value.end();
@ -86,11 +84,16 @@ namespace fc {
--_max_depth;
unsigned_int size;
unpack( s, size, _max_depth );
value.resize( size );
if( !std::is_fundamental<T>::value ) {
for( auto& item : value )
unpack( s, item, _max_depth );
value.resize( std::min( size.value, static_cast<uint64_t>(FC_MAX_PREALLOC_SIZE) ) );
for( uint64_t i = 0; i < size; i++ )
{
if( i >= value.size() )
value.resize( std::min( static_cast<uint64_t>(2*value.size()), size.value ) );
unpack( s, value[i], _max_depth );
}
} else {
value.resize( size );
s.read( (char*)value.data(), value.size() );
}
}
@ -98,8 +101,8 @@ namespace fc {
} // namespace raw
template<typename T>
void to_variant( const flat_set<T>& var, variant& vo, uint32_t _max_depth )
template<typename T, typename... A>
void to_variant( const flat_set<T, A...>& var, variant& vo, uint32_t _max_depth )
{
FC_ASSERT( _max_depth > 0 );
--_max_depth;
@ -109,8 +112,8 @@ namespace fc {
vars[i++] = variant( item, _max_depth );
vo = vars;
}
template<typename T>
void from_variant( const variant& var, flat_set<T>& vo, uint32_t _max_depth )
template<typename T, typename... A>
void from_variant( const variant& var, flat_set<T, A...>& vo, uint32_t _max_depth )
{
FC_ASSERT( _max_depth > 0 );
--_max_depth;

8
include/fc/container/flat_fwd.hpp Executable file → Normal file
View file

@ -11,10 +11,10 @@ namespace fc {
namespace bip = boost::interprocess;
namespace raw {
template<typename Stream, typename T>
void pack( Stream& s, const flat_set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T>
void unpack( Stream& s, flat_set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T, typename... A>
void pack( Stream& s, const flat_set<T, A...>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T, typename... A>
void unpack( Stream& s, flat_set<T, A...>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename K, typename... V>
void pack( Stream& s, const flat_map<K,V...>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename K, typename V, typename... A>

View file

@ -0,0 +1,87 @@
/*
* 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 {
#if defined(__clang__)
// Fix: https://github.com/bitshares/bitshares-core/issues/2197
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmismatched-tags"
#endif
template< typename T, size_t N >
class tuple_size< fc::zero_initialized_array< T, N > > : public tuple_size< array< T, N > > {};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}

10
include/fc/crypto/aes.hpp Executable file → Normal file
View file

@ -1,8 +1,10 @@
#pragma once
#include <fc/crypto/sha512.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/uint128.hpp>
#include <fc/fwd.hpp>
#include <fc/uint128.hpp>
#include <vector>
namespace fc {
@ -14,9 +16,8 @@ namespace fc {
aes_encoder();
~aes_encoder();
void init( const fc::sha256& key, const fc::uint128& init_value );
void init( const fc::sha256& key, const uint128_t& init_value );
uint32_t encode( const char* plaintxt, uint32_t len, char* ciphertxt );
// uint32_t final_encode( char* ciphertxt );
private:
struct impl;
@ -28,9 +29,8 @@ namespace fc {
aes_decoder();
~aes_decoder();
void init( const fc::sha256& key, const fc::uint128& init_value );
void init( const fc::sha256& key, const uint128_t& init_value );
uint32_t decode( const char* ciphertxt, uint32_t len, char* plaintext );
// uint32_t final_decode( char* plaintext );
private:
struct impl;

View file

@ -1,10 +0,0 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
namespace fc
{
std::vector<char> from_base36( const fc::string& b36 );
fc::string to_base36( const std::vector<char>& vec );
fc::string to_base36( const char* data, size_t len );
}

2
include/fc/crypto/base58.hpp Executable file → Normal file
View file

@ -1,5 +1,5 @@
#pragma once
#include <fc/string.hpp>
#include <string>
#include <vector>
namespace fc {

0
include/fc/crypto/base64.hpp Executable file → Normal file
View file

6
include/fc/crypto/bigint.hpp Executable file → Normal file
View file

@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include <fc/string.hpp>
#include <fc/vector.hpp>
#include <string>
#include <vector>
struct bignum_st;
typedef bignum_st BIGNUM;
@ -55,7 +55,7 @@ namespace fc {
bigint operator--(int);
bigint& operator--();
operator fc::string()const;
operator std::string()const;
// returns bignum as bigendian bytes
operator std::vector<char>()const;

View file

@ -1,178 +0,0 @@
////////////////////////////////////////////////////////////////////////////
///
// Blowfish.h Header File
//
// BLOWFISH ENCRYPTION ALGORITHM
//
// encryption and decryption of Byte Strings using the Blowfish encryption Algorithm.
// Blowfish is a block cipher that encrypts data in 8-byte blocks. The algorithm consists
// of two parts: a key-expansion part and a data-ancryption part. Key expansion converts a
// variable key of at least 1 and at most 56 bytes into several subkey arrays totaling
// 4168 bytes. Blowfish has 16 rounds. Each round consists of a key-dependent permutation,
// and a key and data-dependent substitution. All operations are XORs and additions on 32-bit words.
// The only additional operations are four indexed array data lookups per round.
// Blowfish uses a large number of subkeys. These keys must be precomputed before any data
// encryption or decryption. The P-array consists of 18 32-bit subkeys: P0, P1,...,P17.
// There are also four 32-bit S-boxes with 256 entries each: S0,0, S0,1,...,S0,255;
// S1,0, S1,1,...,S1,255; S2,0, S2,1,...,S2,255; S3,0, S3,1,...,S3,255;
//
// The Electronic Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback modes
// are used:
//
// In ECB mode if the same block is encrypted twice with the same key, the resulting
// ciphertext blocks are the same.
//
// In CBC Mode a ciphertext block is obtained by first xoring the
// plaintext block with the previous ciphertext block, and encrypting the resulting value.
//
// In CFB mode a ciphertext block is obtained by encrypting the previous ciphertext block
// and xoring the resulting value with the plaintext
//
// The previous ciphertext block is usually stored in an Initialization Vector (IV).
// An Initialization Vector of zero is commonly used for the first block, though other
// arrangements are also in use.
/*
http://www.counterpane.com/vectors.txt
Test vectors by Eric Young. These tests all assume Blowfish with 16
rounds.
All data is shown as a hex string with 012345 loading as
data[0]=0x01;
data[1]=0x23;
data[2]=0x45;
ecb test data (taken from the DES validation tests)
key bytes clear bytes cipher bytes
0000000000000000 0000000000000000 4EF997456198DD78
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 51866FD5B85ECB8A
3000000000000000 1000000000000001 7D856F9A613063F2 ???
1111111111111111 1111111111111111 2466DD878B963C9D
0123456789ABCDEF 1111111111111111 61F9C3802281B096
1111111111111111 0123456789ABCDEF 7D0CC630AFDA1EC7
0000000000000000 0000000000000000 4EF997456198DD78
FEDCBA9876543210 0123456789ABCDEF 0ACEAB0FC6A0A28D
7CA110454A1A6E57 01A1D6D039776742 59C68245EB05282B
0131D9619DC1376E 5CD54CA83DEF57DA B1B8CC0B250F09A0
07A1133E4A0B2686 0248D43806F67172 1730E5778BEA1DA4
3849674C2602319E 51454B582DDF440A A25E7856CF2651EB
04B915BA43FEB5B6 42FD443059577FA2 353882B109CE8F1A
0113B970FD34F2CE 059B5E0851CF143A 48F4D0884C379918
0170F175468FB5E6 0756D8E0774761D2 432193B78951FC98
43297FAD38E373FE 762514B829BF486A 13F04154D69D1AE5
07A7137045DA2A16 3BDD119049372802 2EEDDA93FFD39C79
04689104C2FD3B2F 26955F6835AF609A D887E0393C2DA6E3
37D06BB516CB7546 164D5E404F275232 5F99D04F5B163969
1F08260D1AC2465E 6B056E18759F5CCA 4A057A3B24D3977B
584023641ABA6176 004BD6EF09176062 452031C1E4FADA8E
025816164629B007 480D39006EE762F2 7555AE39F59B87BD
49793EBC79B3258F 437540C8698F3CFA 53C55F9CB49FC019
4FB05E1515AB73A7 072D43A077075292 7A8E7BFA937E89A3
49E95D6D4CA229BF 02FE55778117F12A CF9C5D7A4986ADB5
018310DC409B26D6 1D9D5C5018F728C2 D1ABB290658BC778
1C587F1C13924FEF 305532286D6F295A 55CB3774D13EF201
0101010101010101 0123456789ABCDEF FA34EC4847B268B2
1F1F1F1F0E0E0E0E 0123456789ABCDEF A790795108EA3CAE
E0FEE0FEF1FEF1FE 0123456789ABCDEF C39E072D9FAC631D
0000000000000000 FFFFFFFFFFFFFFFF 014933E0CDAFF6E4
FFFFFFFFFFFFFFFF 0000000000000000 F21E9A77B71C49BC
0123456789ABCDEF 0000000000000000 245946885754369A
FEDCBA9876543210 FFFFFFFFFFFFFFFF 6B5C5A9C5D9E0A5A
set_key test data
data[8]= FEDCBA9876543210
c=F9AD597C49DB005E k[ 1]=F0
c=E91D21C1D961A6D6 k[ 2]=F0E1
c=E9C2B70A1BC65CF3 k[ 3]=F0E1D2
c=BE1E639408640F05 k[ 4]=F0E1D2C3
c=B39E44481BDB1E6E k[ 5]=F0E1D2C3B4
c=9457AA83B1928C0D k[ 6]=F0E1D2C3B4A5
c=8BB77032F960629D k[ 7]=F0E1D2C3B4A596
c=E87A244E2CC85E82 k[ 8]=F0E1D2C3B4A59687
c=15750E7A4F4EC577 k[ 9]=F0E1D2C3B4A5968778
c=122BA70B3AB64AE0 k[10]=F0E1D2C3B4A596877869
c=3A833C9AFFC537F6 k[11]=F0E1D2C3B4A5968778695A
c=9409DA87A90F6BF2 k[12]=F0E1D2C3B4A5968778695A4B
c=884F80625060B8B4 k[13]=F0E1D2C3B4A5968778695A4B3C
c=1F85031C19E11968 k[14]=F0E1D2C3B4A5968778695A4B3C2D
c=79D9373A714CA34F k[15]=F0E1D2C3B4A5968778695A4B3C2D1E ???
c=93142887EE3BE15C k[16]=F0E1D2C3B4A5968778695A4B3C2D1E0F
c=03429E838CE2D14B k[17]=F0E1D2C3B4A5968778695A4B3C2D1E0F00
c=A4299E27469FF67B k[18]=F0E1D2C3B4A5968778695A4B3C2D1E0F0011
c=AFD5AED1C1BC96A8 k[19]=F0E1D2C3B4A5968778695A4B3C2D1E0F001122
c=10851C0E3858DA9F k[20]=F0E1D2C3B4A5968778695A4B3C2D1E0F00112233
c=E6F51ED79B9DB21F k[21]=F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344
c=64A6E14AFD36B46F k[22]=F0E1D2C3B4A5968778695A4B3C2D1E0F001122334455
c=80C7D7D45A5479AD k[23]=F0E1D2C3B4A5968778695A4B3C2D1E0F00112233445566
c=05044B62FA52D080 k[24]=F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344556677
chaining mode test data
key[16] = 0123456789ABCDEFF0E1D2C3B4A59687
iv[8] = FEDCBA9876543210
data[29] = "7654321 Now is the time for " (includes trailing '\0')
data[29] = 37363534333231204E6F77206973207468652074696D6520666F722000
cbc cipher text
cipher[32]= 6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC
cfb64 cipher text cipher[29]=
E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3
ofb64 cipher text cipher[29]=
E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA
*/
#pragma once
#include <stdint.h>
namespace fc {
//Block Structure
struct sblock
{
//Constructors
sblock(unsigned int l=0, unsigned int r=0) : m_uil(l), m_uir(r) {}
//Copy Constructor
sblock(const sblock& roBlock) : m_uil(roBlock.m_uil), m_uir(roBlock.m_uir) {}
sblock& operator^=(sblock& b) { m_uil ^= b.m_uil; m_uir ^= b.m_uir; return *this; }
unsigned int m_uil, m_uir;
};
class blowfish
{
public:
enum { ECB=0, CBC=1, CFB=2 };
//Constructor - Initialize the P and S boxes for a given Key
blowfish();
void start(unsigned char* ucKey, uint64_t n, const sblock& roChain = sblock(0UL,0UL));
//Resetting the chaining block
void reset_chain() { m_oChain = m_oChain0; }
// encrypt/decrypt Buffer in Place
void encrypt(unsigned char* buf, uint64_t n, int iMode=CFB);
void decrypt(unsigned char* buf, uint64_t n, int iMode=CFB);
// encrypt/decrypt from Input Buffer to Output Buffer
void encrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=CFB);
void decrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=CFB);
//Private Functions
private:
unsigned int F(unsigned int ui);
void encrypt(sblock&);
void decrypt(sblock&);
private:
//The Initialization Vector, by default {0, 0}
sblock m_oChain0;
sblock m_oChain;
unsigned int m_auiP[18];
unsigned int m_auiS[4][256];
static const unsigned int scm_auiInitP[18];
static const unsigned int scm_auiInitS[4][256];
};
} // namespace fc

19
include/fc/crypto/city.hpp Executable file → Normal file
View file

@ -41,36 +41,25 @@
// doesn't hold for any hash functions in this file.
#pragma once
#include <fc/uint128.hpp>
#include <stdlib.h> // for size_t.
#include <stdint.h>
#include <utility>
namespace fc {
template<typename T, size_t N>
class array;
class uint128;
// Hash function for a byte array.
uint64_t city_hash64(const char *buf, size_t len);
uint32_t city_hash32(const char *buf, size_t len);
#if SIZE_MAX > UINT32_MAX
inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash64(buf, len); }
#else
uint32_t city_hash32(const char *buf, size_t len);
inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash32(buf, len); }
#endif
// Hash function for a byte array.
uint128 city_hash128(const char *s, size_t len);
// Hash function for a byte array.
uint64_t city_hash_crc_64(const char *buf, size_t len);
// Hash function for a byte array.
uint128 city_hash_crc_128(const char *s, size_t len);
array<uint64_t,4> city_hash_crc_256(const char *s, size_t len);
uint128_t city_hash_crc_128(const char *s, size_t len);
} // namespace fc

0
include/fc/crypto/dh.hpp Executable file → Normal file
View file

0
include/fc/crypto/digest.hpp Executable file → Normal file
View file

33
include/fc/crypto/elliptic.hpp Executable file → Normal file
View file

@ -1,12 +1,14 @@
#pragma once
#include <fc/container/zeroed_array.hpp>
#include <fc/crypto/bigint.hpp>
#include <fc/crypto/openssl.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
#include <fc/fwd.hpp>
#include <fc/array.hpp>
#include <fc/io/raw_fwd.hpp>
#include <array>
namespace fc {
namespace ecc {
@ -17,14 +19,14 @@ namespace fc {
}
typedef fc::sha256 blind_factor_type;
typedef fc::array<char,33> commitment_type;
typedef fc::array<char,33> public_key_data;
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 fc::array<char,65> public_key_point_data; ///< the full non-compressed version of the ECC point
typedef fc::array<char,72> signature;
typedef fc::array<unsigned char,65> compact_signature;
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 fc::array<char,78> extended_key_data;
typedef zero_initialized_array<unsigned char,78> extended_key_data;
/**
* @class public_key
@ -117,9 +119,7 @@ namespace fc {
*/
fc::sha512 get_shared_secret( const public_key& pub )const;
// signature sign( const fc::sha256& digest )const;
compact_signature sign_compact( const fc::sha256& digest, bool require_canonical = true )const;
// bool verify( const fc::sha256& digest, const signature& sig );
public_key get_public_key()const;
@ -155,9 +155,9 @@ namespace fc {
extended_key_data serialize_extended() const;
static extended_public_key deserialize( const extended_key_data& data );
fc::string str() const;
fc::string to_base58() const { return str(); }
static extended_public_key from_base58( const fc::string& base58 );
std::string str() const;
std::string to_base58() const { return str(); }
static extended_public_key from_base58( const std::string& base58 );
private:
sha256 c;
@ -179,16 +179,15 @@ namespace fc {
extended_key_data serialize_extended() const;
static extended_private_key deserialize( const extended_key_data& data );
fc::string str() const;
fc::string to_base58() const { return str(); }
static extended_private_key from_base58( const fc::string& base58 );
static extended_private_key generate_master( const fc::string& seed );
std::string str() const;
std::string to_base58() const { return str(); }
static extended_private_key from_base58( const std::string& base58 );
static extended_private_key generate_master( const std::string& seed );
static extended_private_key generate_master( const char* seed, uint32_t seed_len );
private:
extended_private_key private_derive_rest( const fc::sha512& hash,
int num ) const;
sha256 c;
int child_num, parent_fp;
uint8_t depth;

View 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:
struct 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);
}
};
}

8
include/fc/crypto/hex.hpp Executable file → Normal file
View file

@ -1,15 +1,15 @@
#pragma once
#include <fc/string.hpp>
#include <fc/utility.hpp>
#include <stdint.h>
#include <string>
#include <vector>
namespace fc {
uint8_t from_hex( char c );
fc::string to_hex( const char* d, uint32_t s );
std::string to_hex( const char* d, uint32_t s );
std::string to_hex( const std::vector<char>& data );
/**
* @return the number of bytes decoded
*/
size_t from_hex( const fc::string& hex_str, char* out_data, size_t out_data_len );
size_t from_hex( const std::string& hex_str, char* out_data, size_t out_data_len );
}

0
include/fc/crypto/hmac.hpp Executable file → Normal file
View file

View file

@ -1,76 +0,0 @@
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
namespace fc
{
class md5
{
public:
md5();
explicit md5( const string& hex_str );
string str()const;
operator string()const;
char* data()const;
size_t data_size()const { return 128 / 8; }
static md5 hash( const char* d, uint32_t dlen );
static md5 hash( const string& );
template<typename T>
static md5 hash( const T& t )
{
md5::encoder e;
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();
md5 result();
private:
struct impl;
fc::fwd<impl,216> my;
};
template<typename T>
inline friend T& operator<<( T& ds, const md5& ep ) {
ds.write( ep.data(), sizeof(ep) );
return ds;
}
template<typename T>
inline friend T& operator>>( T& ds, md5& ep ) {
ds.read( ep.data(), sizeof(ep) );
return ds;
}
friend md5 operator << ( const md5& h1, uint32_t i );
friend bool operator == ( const md5& h1, const md5& h2 );
friend bool operator != ( const md5& h1, const md5& h2 );
friend md5 operator ^ ( const md5& h1, const md5& h2 );
friend bool operator >= ( const md5& h1, const md5& h2 );
friend bool operator > ( const md5& h1, const md5& h2 );
friend bool operator < ( const md5& h1, const md5& h2 );
uint64_t _hash[2];
};
class variant;
void to_variant( const md5& bi, variant& v, uint32_t max_depth = 1 );
void from_variant( const variant& v, md5& bi, uint32_t max_depth = 1 );
} // fc
#include <fc/reflect/reflect.hpp>
FC_REFLECT_TYPENAME( fc::md5 )

27
include/fc/crypto/openssl.hpp Executable file → Normal file
View file

@ -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>

View file

@ -1,117 +0,0 @@
#pragma once
#include <memory>
#include <vector>
#include <fc/crypto/sha1.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/array.hpp>
namespace fc {
namespace detail { class pke_impl; }
class private_key;
class public_key;
void generate_key_pair( public_key&, private_key& );
typedef std::vector<char> bytes;
typedef bytes signature;
class public_key
{
public:
public_key();
explicit public_key( const bytes& d );
public_key( const public_key& k );
public_key( public_key&& k );
~public_key();
operator bool()const;
public_key& operator=(const public_key& p );
public_key& operator=(public_key&& p );
bool verify( const sha1& digest, const array<char,2048/8>& sig )const;
bool verify( const sha1& digest, const signature& sig )const;
bool verify( const sha256& digest, const signature& sig )const;
bytes encrypt( const char* data, size_t len )const;
bytes encrypt( const bytes& )const;
bytes decrypt( const bytes& )const;
bytes serialize()const;
friend void generate_key_pair( public_key&, private_key& );
private:
std::shared_ptr<detail::pke_impl> my;
};
class private_key
{
public:
private_key();
explicit private_key( const bytes& d );
private_key( const private_key& k );
private_key( private_key&& k );
~private_key();
operator bool()const;
private_key& operator=(const private_key& p );
private_key& operator=(private_key&& p );
void sign( const sha1& digest, array<char,2048/8>& sig )const;
signature sign( const sha1& digest )const;
signature sign( const sha256& digest )const;
bytes decrypt( const char* bytes, size_t len )const;
bytes decrypt( const bytes& )const;
bytes encrypt( const bytes& )const;
bytes serialize()const;
friend void generate_key_pair( public_key&, private_key& );
private:
std::shared_ptr<detail::pke_impl> my;
};
bool operator==( const private_key& a, const private_key& b );
namespace raw
{
template<typename Stream>
void unpack( Stream& s, fc::public_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
{
FC_ASSERT( _max_depth > 0 );
bytes ser;
fc::raw::unpack( s, ser, _max_depth - 1 );
pk = fc::public_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::public_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
{
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, pk.serialize(), _max_depth - 1 );
}
template<typename Stream>
void unpack( Stream& s, fc::private_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
{
FC_ASSERT( _max_depth > 0 );
bytes ser;
fc::raw::unpack( s, ser, _max_depth - 1 );
pk = fc::private_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::private_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
{
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, pk.serialize(), _max_depth - 1 );
}
}
class variant;
void to_variant( const public_key& bi, variant& v, uint32_t max_depth = 1 );
void from_variant( const variant& v, public_key& bi, uint32_t max_depth = 1 );
void to_variant( const private_key& bi, variant& v, uint32_t max_depth = 1 );
void from_variant( const variant& v, private_key& bi, uint32_t max_depth = 1 );
} // fc

1
include/fc/crypto/rand.hpp Executable file → Normal file
View file

@ -4,5 +4,4 @@ namespace fc {
/* provides access to the OpenSSL random number generator */
void rand_bytes(char* buf, int count);
//void rand_pseudo_bytes(char* buf, int count);
} // namespace fc

22
include/fc/crypto/ripemd160.hpp Executable file → Normal file
View file

@ -1,5 +1,5 @@
#pragma once
#include <boost/endian/buffers.hpp>
#include <fc/fwd.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/reflect/typename.hpp>
@ -18,7 +18,7 @@ class ripemd160
explicit operator string()const;
char* data()const;
size_t data_size()const { return 160/8; }
static constexpr size_t data_size() { return 160/8; }
static ripemd160 hash( const fc::sha512& h );
static ripemd160 hash( const fc::sha256& h );
@ -45,7 +45,7 @@ class ripemd160
ripemd160 result();
private:
struct impl;
class impl;
fc::fwd<impl,96> my;
};
@ -68,9 +68,23 @@ class ripemd160
friend bool operator > ( const ripemd160& h1, const ripemd160& h2 );
friend bool operator < ( const ripemd160& h1, const ripemd160& h2 );
uint32_t _hash[5];
boost::endian::little_uint32_buf_t _hash[5];
};
namespace raw {
template<typename T>
inline void pack( T& ds, const ripemd160& ep, uint32_t _max_depth ) {
ds << ep;
}
template<typename T>
inline void unpack( T& ds, ripemd160& ep, uint32_t _max_depth ) {
ds >> ep;
}
}
class variant;
void to_variant( const ripemd160& bi, variant& v, uint32_t max_depth );
void from_variant( const variant& v, ripemd160& bi, uint32_t max_depth );

34
include/fc/crypto/sha1.hpp Executable file → Normal file
View file

@ -1,6 +1,9 @@
#pragma once
#include <boost/endian/buffers.hpp>
#include <fc/fwd.hpp>
#include <fc/string.hpp>
#include <functional>
#include <string>
namespace fc{
@ -8,16 +11,16 @@ class sha1
{
public:
sha1();
explicit sha1( const string& hex_str );
explicit sha1( const std::string& hex_str );
string str()const;
operator string()const;
std::string str()const;
operator std::string()const;
char* data()const;
size_t data_size()const { return 20; }
static constexpr size_t data_size() { return 20; }
static sha1 hash( const char* d, uint32_t dlen );
static sha1 hash( const string& );
static sha1 hash( const std::string& );
template<typename T>
static sha1 hash( const T& t )
@ -62,9 +65,23 @@ class sha1
friend bool operator > ( const sha1& h1, const sha1& h2 );
friend bool operator < ( const sha1& h1, const sha1& h2 );
uint32_t _hash[5];
boost::endian::little_uint32_buf_t _hash[5];
};
namespace raw {
template<typename T>
inline void pack( T& ds, const sha1& ep, uint32_t _max_depth ) {
ds << ep;
}
template<typename T>
inline void unpack( T& ds, sha1& ep, uint32_t _max_depth ) {
ds >> ep;
}
}
class variant;
void to_variant( const sha1& bi, variant& v, uint32_t max_depth );
void from_variant( const variant& v, sha1& bi, uint32_t max_depth );
@ -82,3 +99,6 @@ namespace std
}
};
}
#include <fc/reflect/reflect.hpp>
FC_REFLECT_TYPENAME( fc::sha1 )

22
include/fc/crypto/sha224.hpp Executable file → Normal file
View file

@ -1,8 +1,7 @@
#pragma once
#include <unordered_map>
#include <boost/endian/buffers.hpp>
#include <fc/fwd.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/string.hpp>
namespace fc
{
@ -17,7 +16,7 @@ class sha224
operator string()const;
char* data()const;
size_t data_size()const { return 224 / 8; }
static constexpr size_t data_size() { return 224 / 8; }
static sha224 hash( const char* d, uint32_t dlen );
static sha224 hash( const string& );
@ -65,11 +64,24 @@ class sha224
friend bool operator >= ( const sha224& h1, const sha224& h2 );
friend bool operator > ( const sha224& h1, const sha224& h2 );
friend bool operator < ( const sha224& h1, const sha224& h2 );
friend std::size_t hash_value( const sha224& v ) { return uint64_t(v._hash[1])<<32 | v._hash[2]; }
uint32_t _hash[7];
boost::endian::little_uint32_buf_t _hash[7];
};
namespace raw {
template<typename T>
inline void pack( T& ds, const sha224& ep, uint32_t _max_depth ) {
ds << ep;
}
template<typename T>
inline void unpack( T& ds, sha224& ep, uint32_t _max_depth ) {
ds >> ep;
}
}
class variant;
void to_variant( const sha224& bi, variant& v, uint32_t max_depth );
void from_variant( const variant& v, sha224& bi, uint32_t max_depth );

46
include/fc/crypto/sha256.hpp Executable file → Normal file
View file

@ -1,7 +1,7 @@
#pragma once
#include <boost/endian/buffers.hpp>
#include <fc/fwd.hpp>
#include <fc/string.hpp>
#include <fc/platform_independence.hpp>
#include <fc/io/raw_fwd.hpp>
namespace fc
@ -18,7 +18,7 @@ class sha256
operator string()const;
char* data()const;
size_t data_size()const { return 256 / 8; }
static constexpr size_t data_size() { return 256 / 8; }
static sha256 hash( const char* d, uint32_t dlen );
static sha256 hash( const string& );
@ -68,35 +68,22 @@ class sha256
friend bool operator > ( const sha256& h1, const sha256& h2 );
friend bool operator < ( const sha256& h1, const sha256& h2 );
uint32_t pop_count()const
{
return (uint32_t)(__builtin_popcountll(_hash[0]) +
__builtin_popcountll(_hash[1]) +
__builtin_popcountll(_hash[2]) +
__builtin_popcountll(_hash[3]));
boost::endian::little_uint64_buf_t _hash[4];
};
namespace raw {
template<typename T>
inline void pack( T& ds, const sha256& ep, uint32_t _max_depth ) {
ds << ep;
}
/**
* Count leading zero bits
*/
uint16_t clz()const;
template<typename T>
inline void unpack( T& ds, sha256& ep, uint32_t _max_depth ) {
ds >> ep;
}
/**
* Approximate (log_2(x) + 1) * 2**24.
*
* Detailed specs:
* - Return 0 when x == 0.
* - High 8 bits of result simply counts nonzero bits.
* - Low 24 bits of result are the 24 bits of input immediately after the most significant 1 in the input.
* - If above would require reading beyond the end of the input, zeros are used instead.
*/
uint32_t approx_log_32()const;
void set_to_inverse_approx_log_32( uint32_t x );
static double inverse_approx_log_32_double( uint32_t x );
uint64_t _hash[4];
};
}
typedef sha256 uint256;
@ -104,8 +91,6 @@ class sha256
void to_variant( const sha256& bi, variant& v, uint32_t max_depth );
void from_variant( const variant& v, sha256& bi, uint32_t max_depth );
uint64_t hash64(const char* buf, size_t len);
} // fc
namespace std
{
@ -119,6 +104,5 @@ namespace std
};
}
#include <fc/reflect/reflect.hpp>
FC_REFLECT_TYPENAME( fc::sha256 )

29
include/fc/crypto/sha512.hpp Executable file → Normal file
View file

@ -1,6 +1,7 @@
#pragma once
#include <boost/endian/buffers.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/fwd.hpp>
#include <fc/string.hpp>
namespace fc
{
@ -9,16 +10,16 @@ class sha512
{
public:
sha512();
explicit sha512( const string& hex_str );
explicit sha512( const std::string& hex_str );
string str()const;
operator string()const;
std::string str()const;
operator std::string()const;
char* data()const;
size_t data_size()const { return 512 / 8; }
static constexpr size_t data_size() { return 512 / 8; }
static sha512 hash( const char* d, uint32_t dlen );
static sha512 hash( const string& );
static sha512 hash( const std::string& );
template<typename T>
static sha512 hash( const T& t )
@ -63,9 +64,23 @@ class sha512
friend bool operator > ( const sha512& h1, const sha512& h2 );
friend bool operator < ( const sha512& h1, const sha512& h2 );
uint64_t _hash[8];
boost::endian::little_uint64_buf_t _hash[8];
};
namespace raw {
template<typename T>
inline void pack( T& ds, const sha512& ep, uint32_t _max_depth ) {
ds << ep;
}
template<typename T>
inline void unpack( T& ds, sha512& ep, uint32_t _max_depth ) {
ds >> ep;
}
}
typedef fc::sha512 uint512;
class variant;

144
include/fc/exception/exception.hpp Executable file → Normal file
View file

@ -35,7 +35,8 @@ namespace fc
aes_error_code = 18,
overflow_code = 19,
underflow_code = 20,
divide_by_zero_code = 21
divide_by_zero_code = 21,
method_not_found_exception_code = 22
};
/**
@ -105,7 +106,7 @@ namespace fc
*
* @note does not return.
*/
virtual NO_RETURN void dynamic_rethrow_exception()const;
[[noreturn]] virtual void dynamic_rethrow_exception()const;
/**
* This is equivalent to:
@ -154,7 +155,7 @@ namespace fc
std::exception_ptr get_inner_exception()const;
virtual NO_RETURN void dynamic_rethrow_exception()const;
[[noreturn]] virtual void dynamic_rethrow_exception()const;
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
private:
std::exception_ptr _inner;
@ -165,10 +166,10 @@ namespace fc
{
#if defined(_MSC_VER) && (_MSC_VER < 1700)
return std::make_shared<unhandled_exception>( log_message(),
std::copy_exception(fc::forward<T>(e)) );
std::copy_exception(std::forward<T>(e)) );
#else
return std::make_shared<unhandled_exception>( log_message(),
std::make_exception_ptr(fc::forward<T>(e)) );
std::make_exception_ptr(std::forward<T>(e)) );
#endif
}
@ -178,13 +179,13 @@ namespace fc
public:
struct base_exception_builder
{
virtual NO_RETURN void rethrow( const exception& e )const = 0;
[[noreturn]] virtual void rethrow( const exception& e )const = 0;
};
template<typename T>
struct exception_builder : public base_exception_builder
{
virtual NO_RETURN void rethrow( const exception& e )const override
[[noreturn]] virtual void rethrow( const exception& e )const override
{
throw T( e );
}
@ -200,7 +201,7 @@ namespace fc
_registered_exceptions[T::code_value] = &builder;
}
void NO_RETURN rethrow( const exception& e )const;
[[noreturn]] void rethrow( const exception& e )const;
static exception_factory& instance()
{
@ -222,81 +223,98 @@ namespace fc
}(); \
#define FC_DECLARE_DERIVED_EXCEPTION( TYPE, BASE, CODE, WHAT ) \
#define FC_DECLARE_DERIVED_EXCEPTION( TYPE, BASE, CODE ) \
class TYPE : public BASE \
{ \
public: \
enum code_enum { \
code_value = CODE, \
}; \
explicit TYPE( int64_t code, const std::string& name_value, const std::string& what_value ) \
:BASE( code, name_value, what_value ){} \
explicit TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \
:BASE( std::move(m), code, name_value, what_value ){} \
explicit TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value )\
:BASE( std::move(m), code, name_value, what_value ){}\
explicit TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value )\
:BASE( m, code, name_value, what_value ){}\
TYPE( const std::string& what_value, const fc::log_messages& m ) \
:BASE( m, CODE, BOOST_PP_STRINGIZE(TYPE), what_value ){} \
TYPE( fc::log_message&& m ) \
:BASE( fc::move(m), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ){}\
TYPE( fc::log_messages msgs ) \
:BASE( fc::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
TYPE( const TYPE& c ) \
:BASE(c){} \
TYPE( const BASE& c ) \
:BASE(c){} \
TYPE():BASE(CODE, BOOST_PP_STRINGIZE(TYPE), WHAT){}\
explicit TYPE( int64_t code, const std::string& name_value, const std::string& what_value ); \
explicit TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ); \
explicit TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value );\
explicit TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value );\
explicit TYPE( const std::string& what_value, const fc::log_messages& m ); \
explicit TYPE( fc::log_message&& m ); \
explicit TYPE( fc::log_messages msgs ); \
TYPE( TYPE&& c ) = default; \
TYPE( const TYPE& c ); \
TYPE( const BASE& c ); \
explicit TYPE();\
\
virtual std::shared_ptr<fc::exception> dynamic_copy_exception()const\
{ return std::make_shared<TYPE>( *this ); } \
virtual NO_RETURN void dynamic_rethrow_exception()const \
{ if( code() == CODE ) throw *this;\
else fc::exception::dynamic_rethrow_exception(); \
} \
virtual std::shared_ptr<fc::exception> dynamic_copy_exception()const;\
[[noreturn]] virtual void dynamic_rethrow_exception()const; \
};
#define FC_DECLARE_EXCEPTION( TYPE, CODE, WHAT ) \
FC_DECLARE_DERIVED_EXCEPTION( TYPE, fc::exception, CODE, WHAT )
#define FC_IMPLEMENT_DERIVED_EXCEPTION( TYPE, BASE, CODE, WHAT ) \
TYPE::TYPE( int64_t code, const std::string& name_value, const std::string& what_value ) \
: BASE( code, name_value, what_value ) {} \
TYPE::TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \
: BASE( std::move(m), code, name_value, what_value ) {} \
TYPE::TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \
: BASE( std::move(m), code, name_value, what_value ) {} \
TYPE::TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value ) \
: BASE( m, code, name_value, what_value ) {} \
TYPE::TYPE( const std::string& what_value, const fc::log_messages& m ) \
: BASE( m, CODE, BOOST_PP_STRINGIZE(TYPE), what_value ) {} \
TYPE::TYPE( fc::log_message&& m ) \
: BASE( std::move(m), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
TYPE::TYPE( fc::log_messages msgs ) \
: BASE( std::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
TYPE::TYPE( const TYPE& c ) : BASE(c) {} \
TYPE::TYPE( const BASE& c ) : BASE(c) {} \
TYPE::TYPE() : BASE(CODE, BOOST_PP_STRINGIZE(TYPE), WHAT) {} \
\
std::shared_ptr<fc::exception> TYPE::dynamic_copy_exception()const \
{ \
return std::make_shared<TYPE>( *this ); \
} \
[[noreturn]] void TYPE::dynamic_rethrow_exception()const \
{ \
if( code() == CODE ) throw *this;\
else fc::exception::dynamic_rethrow_exception(); \
}
FC_DECLARE_EXCEPTION( timeout_exception, timeout_exception_code, "Timeout" );
FC_DECLARE_EXCEPTION( file_not_found_exception, file_not_found_exception_code, "File Not Found" );
#define FC_DECLARE_EXCEPTION( TYPE, CODE ) \
FC_DECLARE_DERIVED_EXCEPTION( TYPE, fc::exception, CODE )
#define FC_IMPLEMENT_EXCEPTION( TYPE, CODE, WHAT ) \
FC_IMPLEMENT_DERIVED_EXCEPTION( TYPE, fc::exception, CODE, WHAT )
FC_DECLARE_EXCEPTION( timeout_exception, timeout_exception_code );
FC_DECLARE_EXCEPTION( file_not_found_exception, file_not_found_exception_code );
/**
* @brief report's parse errors
* @brief reports parse errors
*/
FC_DECLARE_EXCEPTION( parse_error_exception, parse_error_exception_code, "Parse Error" );
FC_DECLARE_EXCEPTION( invalid_arg_exception, invalid_arg_exception_code, "Invalid Argument" );
FC_DECLARE_EXCEPTION( parse_error_exception, parse_error_exception_code );
FC_DECLARE_EXCEPTION( invalid_arg_exception, invalid_arg_exception_code );
/**
* @brief reports when a key, guid, or other item is not found.
*/
FC_DECLARE_EXCEPTION( key_not_found_exception, key_not_found_exception_code, "Key Not Found" );
FC_DECLARE_EXCEPTION( bad_cast_exception, bad_cast_exception_code, "Bad Cast" );
FC_DECLARE_EXCEPTION( out_of_range_exception, out_of_range_exception_code, "Out of Range" );
FC_DECLARE_EXCEPTION( key_not_found_exception, key_not_found_exception_code );
FC_DECLARE_EXCEPTION( bad_cast_exception, bad_cast_exception_code );
FC_DECLARE_EXCEPTION( out_of_range_exception, out_of_range_exception_code );
FC_DECLARE_EXCEPTION( method_not_found_exception, method_not_found_exception_code );
/** @brief if an operation is unsupported or not valid this may be thrown */
FC_DECLARE_EXCEPTION( invalid_operation_exception,
invalid_operation_exception_code,
"Invalid Operation" );
FC_DECLARE_EXCEPTION( invalid_operation_exception, invalid_operation_exception_code );
/** @brief if an host name can not be resolved this may be thrown */
FC_DECLARE_EXCEPTION( unknown_host_exception,
unknown_host_exception_code,
"Unknown Host" );
FC_DECLARE_EXCEPTION( unknown_host_exception, unknown_host_exception_code );
/**
* @brief used to report a canceled Operation
*/
FC_DECLARE_EXCEPTION( canceled_exception, canceled_exception_code, "Canceled" );
FC_DECLARE_EXCEPTION( canceled_exception, canceled_exception_code );
/**
* @brief used inplace of assert() to report violations of pre conditions.
*/
FC_DECLARE_EXCEPTION( assert_exception, assert_exception_code, "Assert Exception" );
FC_DECLARE_EXCEPTION( eof_exception, eof_exception_code, "End Of File" );
FC_DECLARE_EXCEPTION( null_optional, null_optional_code, "null optional" );
FC_DECLARE_EXCEPTION( aes_exception, aes_error_code, "AES error" );
FC_DECLARE_EXCEPTION( overflow_exception, overflow_code, "Integer Overflow" );
FC_DECLARE_EXCEPTION( underflow_exception, underflow_code, "Integer Underflow" );
FC_DECLARE_EXCEPTION( divide_by_zero_exception, divide_by_zero_code, "Integer Divide By Zero" );
FC_DECLARE_EXCEPTION( assert_exception, assert_exception_code );
FC_DECLARE_EXCEPTION( eof_exception, eof_exception_code );
FC_DECLARE_EXCEPTION( null_optional, null_optional_code );
FC_DECLARE_EXCEPTION( aes_exception, aes_error_code );
FC_DECLARE_EXCEPTION( overflow_exception, overflow_code );
FC_DECLARE_EXCEPTION( underflow_exception, underflow_code );
FC_DECLARE_EXCEPTION( divide_by_zero_exception, divide_by_zero_code );
std::string except_str();
@ -446,11 +464,11 @@ namespace fc
catch( fc::exception& er ) { \
FC_RETHROW_EXCEPTION( er, LOG_LEVEL, FORMAT, __VA_ARGS__ ); \
} catch( const std::exception& e ) { \
fc::exception fce( \
BOOST_PP_EXPAND(FC_LOG_MESSAGE( LOG_LEVEL, "${what}: " FORMAT,__VA_ARGS__("what",e.what()))), \
throw fc::exception( \
FC_LOG_MESSAGE( LOG_LEVEL, "${what}: " FORMAT,__VA_ARGS__("what",e.what())), \
fc::std_exception_code,\
typeid(e).name(), \
e.what() ) ; throw fce;\
e.what() ) ;\
} catch( ... ) { \
throw fc::unhandled_exception( \
FC_LOG_MESSAGE( LOG_LEVEL, FORMAT,__VA_ARGS__), \
@ -461,11 +479,11 @@ namespace fc
catch( fc::exception& er ) { \
FC_RETHROW_EXCEPTION( er, warn, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ); \
} catch( const std::exception& e ) { \
fc::exception fce( \
throw fc::exception( \
FC_LOG_MESSAGE( warn, "${what}: ",FC_FORMAT_ARG_PARAMS(__VA_ARGS__)("what",e.what())), \
fc::std_exception_code,\
typeid(e).name(), \
e.what() ) ; throw fce;\
e.what() ) ;\
} catch( ... ) { \
throw fc::unhandled_exception( \
FC_LOG_MESSAGE( warn, "",FC_FORMAT_ARG_PARAMS(__VA_ARGS__)), \

33
include/fc/filesystem.hpp Executable file → Normal file
View file

@ -2,7 +2,6 @@
#include <utility>
#include <memory>
#include <fc/string.hpp>
#include <fc/reflect/typename.hpp>
#include <fc/optional.hpp>
#include <fc/fwd.hpp>
@ -228,37 +227,5 @@ namespace fc {
temp_directory(const fc::path& tempFolder = fc::temp_directory_path());
};
#if !defined(__APPLE__)
// this code is known to work on linux and windows. It may work correctly on mac,
// or it may need slight tweaks or extra includes. It's disabled now to avoid giving
// a false sense of security.
# define FC_HAS_SIMPLE_FILE_LOCK
#endif
#ifdef FC_HAS_SIMPLE_FILE_LOCK
/** simple class which only allows one process to open any given file.
* approximate usage:
* int main() {
* fc::simple_file_lock instance_lock("~/.my_app/.lock");
* if (!instance_lock.try_lock()) {
* elog("my_app is already running");
* return 1;
* }
* // do stuff here, file will be unlocked when instance_lock goes out of scope
* }
*/
class simple_lock_file
{
public:
simple_lock_file(const path& lock_file_path);
~simple_lock_file();
bool try_lock();
void unlock();
private:
class impl;
std::unique_ptr<impl> my;
};
#endif // FC_HAS_SIMPLE_FILE_LOCK
}

View file

@ -1,143 +0,0 @@
#pragma once
#include <fc/io/raw_fwd.hpp>
namespace fc {
/**
* This class is designed to offer in-place memory allocation of a string up to Length equal to
* sizeof(Storage).
*
* The string will serialize the same way as std::string for variant and raw formats
* The string will sort according to the comparison operators defined for Storage, this enables effecient
* sorting.
*/
template<typename Storage = std::pair<uint64_t,uint64_t> >
class fixed_string {
public:
fixed_string(){}
fixed_string( const fixed_string& c ):data(c.data){}
fixed_string( const std::string& str ) {
if( str.size() <= sizeof(data) )
memcpy( (char*)&data, str.c_str(), str.size() );
else {
memcpy( (char*)&data, str.c_str(), sizeof(data) );
}
}
fixed_string( const char* str ) {
auto l = strlen(str);
if( l <= sizeof(data) )
memcpy( (char*)&data, str, l );
else {
memcpy( (char*)&data, str, sizeof(data) );
}
}
operator std::string()const {
const char* self = (const char*)&data;
return std::string( self, self + size() );
}
uint32_t size()const {
if( *(((const char*)&data)+sizeof(data) - 1) )
return sizeof(data);
return strnlen( (const char*)&data, sizeof(data) );
}
uint32_t length()const { return size(); }
fixed_string& operator=( const fixed_string& str ) {
data = str.data;
return *this;
}
fixed_string& operator=( const char* str ) {
return *this = fixed_string(str);
}
fixed_string& operator=( const std::string& str ) {
if( str.size() <= sizeof(data) ) {
data = Storage();
memcpy( (char*)&data, str.c_str(), str.size() );
}
else {
memcpy( (char*)&data, str.c_str(), sizeof(data) );
}
return *this;
}
friend std::string operator + ( const fixed_string& a, const std::string& b ) {
return std::string(a) + b;
}
friend std::string operator + ( const std::string& a, const fixed_string& b ) {
return a + std::string(b);
}
friend bool operator < ( const fixed_string& a, const fixed_string& b ) {
return a.data < b.data;
}
friend bool operator <= ( const fixed_string& a, const fixed_string& b ) {
return a.data <= b.data;
}
friend bool operator > ( const fixed_string& a, const fixed_string& b ) {
return a.data > b.data;
}
friend bool operator >= ( const fixed_string& a, const fixed_string& b ) {
return a.data >= b.data;
}
friend bool operator == ( const fixed_string& a, const fixed_string& b ) {
return a.data == b.data;
}
friend bool operator != ( const fixed_string& a, const fixed_string& b ) {
return a.data != b.data;
}
//private:
Storage data;
};
namespace raw
{
template<typename Stream, typename Storage>
inline void pack( Stream& s, const fc::fixed_string<Storage>& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) {
FC_ASSERT( _max_depth > 0 );
unsigned_int size = u.size();
pack( s, size, _max_depth - 1 );
s.write( (const char*)&u.data, size );
}
template<typename Stream, typename Storage>
inline void unpack( Stream& s, fc::fixed_string<Storage>& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) {
FC_ASSERT( _max_depth > 0 );
unsigned_int size;
fc::raw::unpack( s, size, _max_depth - 1 );
if( size.value > 0 ) {
if( size.value > sizeof(Storage) ) {
s.read( (char*)&u.data, sizeof(Storage) );
char buf[1024];
size_t left = size.value - sizeof(Storage);
while( left >= 1024 )
{
s.read( buf, 1024 );
left -= 1024;
}
s.read( buf, left );
} else {
s.read( (char*)&u.data, size.value );
}
}
}
}
}
#include <fc/variant.hpp>
namespace fc {
template<typename Storage>
void to_variant( const fixed_string<Storage>& s, variant& v, uint32_t max_depth = 1 ) {
v = std::string(s);
}
template<typename Storage>
void from_variant( const variant& v, fixed_string<Storage>& s, uint32_t max_depth = 1 ) {
s = v.as_string();
}
}

3
include/fc/fwd.hpp Executable file → Normal file
View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/aligned.hpp>
namespace fc {
@ -37,7 +36,7 @@ class fwd {
~fwd();
private:
aligned<S,Align> _store;
alignas(Align) char _store[S];
};

30
include/fc/fwd_impl.hpp Executable file → Normal file
View file

@ -1,33 +1,35 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
#include <cstdint>
#include <new>
#include <type_traits>
#include <utility>
namespace fc {
namespace detail {
template<typename A, typename U>
struct add {
typedef decltype( *((A*)0) + *((typename fc::remove_reference<U>::type*)0) ) type;
typedef decltype( *((A*)0) + *((typename std::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct add_eq {
typedef decltype( *((A*)0) += *((typename fc::remove_reference<U>::type*)0) ) type;
typedef decltype( *((A*)0) += *((typename std::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct sub {
typedef decltype( *((A*)0) - *((typename fc::remove_reference<U>::type*)0) ) type;
typedef decltype( *((A*)0) - *((typename std::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct sub_eq {
typedef decltype( *((A*)0) -= *((typename fc::remove_reference<U>::type*)0) ) type;
typedef decltype( *((A*)0) -= *((typename std::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct insert_op {
typedef decltype( *((A*)0) << *((typename fc::remove_reference<U>::type*)0) ) type;
typedef decltype( *((A*)0) << *((typename std::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct extract_op {
@ -39,10 +41,10 @@ namespace fc {
template<typename T, unsigned int S, typename U, typename A>
auto operator + ( const fwd<T,S,A>& x, U&& u ) -> typename detail::add<T,U>::type { return *x+fc::forward<U>(u); }
auto operator + ( const fwd<T,S,A>& x, U&& u ) -> typename detail::add<T,U>::type { return *x+std::forward<U>(u); }
template<typename T, unsigned int S, typename U, typename A>
auto operator - ( const fwd<T,S,A>& x, U&& u ) -> typename detail::sub<T,U>::type { return *x-fc::forward<U>(u); }
auto operator - ( const fwd<T,S,A>& x, U&& u ) -> typename detail::sub<T,U>::type { return *x-std::forward<U>(u); }
template<typename T, unsigned int S, typename U, typename A>
auto operator << ( U& u, const fwd<T,S,A>& f ) -> typename detail::insert_op<U,T>::type { return u << *f; }
@ -61,20 +63,20 @@ namespace fc {
template<typename U>
fwd<T,S,A>::fwd( U&& u ) {
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::forward<U>(u) );
new (this) T( std::forward<U>(u) );
}
template<typename T,unsigned int S,typename A>
template<typename U,typename V>
fwd<T,S,A>::fwd( U&& u, V&& v ) {
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::forward<U>(u), fc::forward<V>(v) );
new (this) T( std::forward<U>(u), std::forward<V>(v) );
}
template<typename T,unsigned int S,typename A>
template<typename U,typename V,typename X,typename Y>
fwd<T,S,A>::fwd( U&& u, V&& v, X&& x, Y&& y ) {
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::forward<U>(u), fc::forward<V>(v), fc::forward<X>(x), fc::forward<Y>(y) );
new (this) T( std::forward<U>(u), std::forward<V>(v), std::forward<X>(x), std::forward<Y>(y) );
}
@ -91,7 +93,7 @@ namespace fc {
template<typename T,unsigned int S,typename A>
fwd<T,S,A>::fwd( fwd<T,S,A>&& f ){
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::move(*f) );
new (this) T( std::move(*f) );
}
@ -119,12 +121,12 @@ namespace fc {
template<typename T,unsigned int S, typename A>
template<typename U>
T& fwd<T,S,A>::operator = ( U&& u ) {
return **this = fc::forward<U>(u);
return **this = std::forward<U>(u);
}
template<typename T,unsigned int S, typename A>
T& fwd<T,S,A>::operator = ( fwd<T,S,A>&& u ) {
return **this = fc::move(*u);
return **this = std::move(*u);
}
template<typename T,unsigned int S, typename A>
T& fwd<T,S,A>::operator = ( const fwd<T,S,A>& u ) {

0
include/fc/git_revision.hpp Executable file → Normal file
View file

View file

@ -1,135 +0,0 @@
#pragma once
#include <fc/variant.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/flat_map.hpp>
#include <boost/interprocess/containers/set.hpp>
#include <boost/interprocess/containers/deque.hpp>
#include <fc/crypto/hex.hpp>
#include <fc/exception/exception.hpp>
#include <fc/io/raw_fwd.hpp>
namespace fc {
namespace bip = boost::interprocess;
template<typename... T >
void to_variant( const bip::deque< T... >& t, fc::variant& v, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
std::vector<variant> vars(t.size());
for( size_t i = 0; i < t.size(); ++i ) {
to_variant( t[i], vars[i], max_depth );
}
v = std::move(vars);
}
template<typename T, typename... A>
void from_variant( const fc::variant& v, bip::deque< T, A... >& d, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
const variants& vars = v.get_array();
d.clear();
d.resize( vars.size() );
for( uint32_t i = 0; i < vars.size(); ++i ) {
from_variant( vars[i], d[i], max_depth );
}
}
template<typename K, typename V, typename... T >
void to_variant( const bip::map< K, V, T... >& var, fc::variant& vo, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
std::vector< variant > vars(var.size());
size_t i = 0;
for( auto itr = var.begin(); itr != var.end(); ++itr, ++i )
vars[i] = fc::variant( *itr, max_depth );
vo = vars;
}
template<typename... T >
void to_variant( const bip::vector< T... >& t, fc::variant& v, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
std::vector<variant> vars(t.size());
for( size_t i = 0; i < t.size(); ++i ) {
to_variant( t[i], vars[i], max_depth );
}
v = std::move(vars);
}
template<typename T, typename... A>
void from_variant( const fc::variant& v, bip::vector< T, A... >& d, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
const variants& vars = v.get_array();
d.clear();
d.resize( vars.size() );
for( uint32_t i = 0; i < vars.size(); ++i ) {
from_variant( vars[i], d[i], max_depth );
}
}
template<typename... T >
void to_variant( const bip::set< T... >& t, fc::variant& v, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
std::vector<variant> vars;
vars.reserve(t.size());
for( const auto& item : t ) {
vars.emplace_back( variant( item, max_depth ) );
}
v = std::move(vars);
}
template<typename... A>
void to_variant( const bip::vector<char, A...>& t, fc::variant& v, uint32_t max_depth = 1 )
{
if( t.size() )
v = variant(fc::to_hex(t.data(), t.size()));
else
v = "";
}
template<typename... A>
void from_variant( const fc::variant& v, bip::vector<char, A...>& d, uint32_t max_depth = 1 )
{
auto str = v.as_string();
d.resize( str.size() / 2 );
if( d.size() )
{
size_t r = fc::from_hex( str, d.data(), d.size() );
FC_ASSERT( r == d.size() );
}
}
namespace raw {
namespace bip = boost::interprocess;
template<typename Stream, typename T, typename... A>
inline void pack( Stream& s, const bip::vector<T,A...>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
fc::raw::pack( s, *itr, _max_depth );
++itr;
}
}
template<typename Stream, typename T, typename... A>
inline void unpack( Stream& s, bip::vector<T,A...>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
unsigned_int size;
unpack( s, size, _max_depth );
value.clear(); value.resize(size);
for( auto& item : value )
fc::raw::unpack( s, item, _max_depth );
}
}
}

5
include/fc/interprocess/file_mapping.hpp Executable file → Normal file
View file

@ -1,6 +1,7 @@
#pragma once
#include <fc/fwd.hpp>
#include <fc/utility.hpp>
#include <cstdint>
#include <cstdlib>
namespace boost {
namespace interprocess {
@ -24,7 +25,7 @@ namespace fc {
#ifdef _WIN64
fc::fwd<boost::interprocess::file_mapping,0x38> my;
#else
fc::fwd<boost::interprocess::file_mapping,0x24> my;
fc::fwd<boost::interprocess::file_mapping,0x28> my;
#endif
};

View file

@ -1,44 +0,0 @@
#pragma once
#include <fc/time.hpp>
#include <fc/thread/spin_yield_lock.hpp>
#include <memory>
namespace fc {
class microseconds;
class time_point;
class path;
struct context;
namespace detail { class file_mutex_impl; }
/**
* The purpose of this class is to support synchronization of
* processes, threads, and coop-threads.
*
* Before grabbing the lock for a thread or coop, a file_mutex will first
* grab a process-level lock. After grabbing the process level lock, it will
* synchronize in the same way as a local process lock.
*/
class file_mutex {
public:
file_mutex( const fc::path& filename );
~file_mutex();
bool try_lock();
bool try_lock_for( const microseconds& rel_time );
bool try_lock_until( const time_point& abs_time );
void lock();
void unlock();
void lock_shared();
void unlock_shared();
bool try_lock_shared();
int readers()const;
private:
std::unique_ptr<detail::file_mutex_impl> my;
};
} // namespace fc

View file

@ -1,67 +0,0 @@
#pragma once
#include <fc/thread/future.hpp>
#include <fc/io/buffered_iostream.hpp>
#include <vector>
#include <fc/string.hpp>
#include <fc/filesystem.hpp>
namespace fc
{
/**
* @brief abstract interface for interacting with external processes
*
* At the very least we have ssh::process and direct child processes, and
* there may be other processes that need to implement this protocol.
*/
class iprocess
{
public:
enum exec_opts {
open_none = 0,
open_stdin = 0x01,
open_stdout = 0x02,
open_stderr = 0x04,
open_all = open_stdin|open_stdout|open_stderr,
suppress_console = 0x08
};
virtual ~iprocess(){}
/**
*
* @return *this
*/
virtual iprocess& exec( const path& exe, std::vector<std::string> args,
const path& work_dir = path(), int opts = open_all ) = 0;
/**
* @return blocks until the process exits
*/
virtual int result(const microseconds& timeout = microseconds::maximum()) = 0;
/**
* Forcefully kills the process.
*/
virtual void kill() = 0;
/**
* @brief returns a stream that writes to the process' stdin
*/
virtual buffered_ostream_ptr in_stream() = 0;
/**
* @brief returns a stream that reads from the process' stdout
*/
virtual buffered_istream_ptr out_stream() = 0;
/**
* @brief returns a stream that reads from the process' stderr
*/
virtual buffered_istream_ptr err_stream() = 0;
};
typedef std::shared_ptr<iprocess> iprocess_ptr;
} // namespace fc

View file

@ -1,59 +0,0 @@
#pragma once
#include <fc/interprocess/file_mapping.hpp>
#include <memory>
namespace fc
{
class path;
namespace detail
{
/**
* Base class used to hide common implementation details.
*/
class mmap_struct_base
{
public:
size_t size()const;
void flush();
protected:
void open( const fc::path& file, size_t s, bool create );
std::unique_ptr<fc::file_mapping> _file_mapping;
std::unique_ptr<fc::mapped_region> _mapped_region;
};
};
/**
* @class mmap_struct
* @brief A struct that has been mapped from a file.
*
* @note T must be POD
*/
template<typename T>
class mmap_struct : public detail::mmap_struct_base
{
public:
mmap_struct():_mapped_struct(nullptr){}
/**
* Create the file if it does not exist or is of the wrong size if create is true, then maps
* the file to memory.
*
* @throw an exception if the file does not exist or is the wrong size and create is false
*/
void open( const fc::path& file, bool create = false )
{
detail::mmap_struct_base::open( file, sizeof(T), create );
_mapped_struct = (T*)_mapped_region->get_address();
}
T* operator->() { return _mapped_struct; }
const T* operator->()const { return _mapped_struct; }
T& operator*() { return *_mapped_struct; }
const T& operator*()const { return *_mapped_struct; }
private:
T* _mapped_struct;
};
}

View file

@ -1,37 +0,0 @@
#pragma once
#include <fc/interprocess/iprocess.hpp>
namespace fc {
fc::path find_executable_in_path( const fc::string name );
/**
* @brief start and manage an local process
* @note this class implements reference semantics.
*/
class process : public iprocess
{
public:
process();
~process();
virtual iprocess& exec( const fc::path& exe,
std::vector<std::string> args,
const fc::path& work_dir = fc::path(),
int opts = open_all );
virtual int result(const microseconds& timeout = microseconds::maximum());
virtual void kill();
virtual fc::buffered_ostream_ptr in_stream();
virtual fc::buffered_istream_ptr out_stream();
virtual fc::buffered_istream_ptr err_stream();
class impl;
private:
std::unique_ptr<impl> my;
};
typedef std::shared_ptr<process> process_ptr;
} // namespace fc

7
include/fc/interprocess/signals.hpp Executable file → Normal file
View file

@ -1,8 +1,11 @@
#pragma once
#include <functional>
#include <boost/asio/signal_set.hpp>
namespace fc
{
/// handler will be called from ASIO thread
void set_signal_handler( std::function<void(int)> handler, int signal_num );
/// Set a handler to process an IPC (inter process communication) signal.
/// Handler will be called from ASIO thread.
/// @return shared pointer to the signal_set that holds the handler
std::shared_ptr<boost::asio::signal_set> set_signal_handler( std::function<void(int)> handler, int signal_num );
}

0
include/fc/io/buffered_iostream.hpp Executable file → Normal file
View file

View file

@ -1,8 +0,0 @@
#pragma once
namespace fc
{
/** enables / disables echoing of console input, useful for
* entering passwords on the console.
*/
void set_console_echo( bool enable_echo );
} // namespace fc

92
include/fc/io/datastream.hpp Executable file → Normal file
View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/utility.hpp>
#include <string.h>
#include <stdint.h>
@ -7,7 +6,7 @@ namespace fc {
namespace detail
{
NO_RETURN void throw_datastream_range_error( const char* file, size_t len, int64_t over );
[[noreturn]] void throw_datastream_range_error( const char* file, size_t len, int64_t over );
}
/**
@ -89,94 +88,5 @@ class datastream<size_t> {
size_t _size;
};
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
} // namespace fc

View file

@ -1,178 +0,0 @@
#pragma once
#include <fc/utility.hpp>
#include <string.h>
#include <stdint.h>
namespace fc {
/**
* The purpose of this datastream is to provide a fast, effecient, means
* of calculating the amount of data "about to be written" and then
* writing it. This means having two modes of operation, "test run" where
* you call the entire pack sequence calculating the size, and then
* actually packing it after doing a single allocation.
*/
template<typename T>
class datastream {
public:
datastream( T start, size_t s )
:_start(start),_pos(start),_end(start+s){};
inline void skip( size_t s ){ _pos += s; }
inline bool read( char* d, size_t s ) {
if( size_t(_end - _pos) >= (size_t)s ) {
memcpy( d, _pos, s );
_pos += s;
return true;
}
detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1)))
return false;
}
inline bool write( const char* d, size_t s ) {
if( _end - _pos >= (int32_t)s ) {
memcpy( _pos, d, s );
_pos += s;
return true;
}
detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1)))
return false;
}
inline bool put(char c) {
if( _pos < _end ) {
*_pos = c;
++_pos;
return true;
}
detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1)))
}
inline bool get( unsigned char& c ) { return get( *(char*)&c ); }
inline bool get( char& c ) {
if( _pos < _end ) {
c = *_pos;
++_pos;
return true;
}
detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1)))
}
T pos()const { return _pos; }
inline bool valid()const { return _pos <= _end && _pos >= _start; }
inline bool seekp(size_t p) { _pos = _start + p; return _pos <= _end; }
inline size_t tellp()const { return _pos - _start; }
inline size_t remaining()const { return _end - _pos; }
private:
T _start;
T _pos;
T _end;
};
template<>
class datastream<size_t> {
public:
datastream( size_t init_size = 0):_size(init_size){};
inline bool skip( size_t s ) { _size += s; return true; }
inline bool write( const char* d,size_t s ) { _size += s; return true; }
inline bool put(char c) { ++_size; return true; }
inline bool valid()const { return true; }
inline bool seekp(size_t p) { _size = p; return true; }
inline size_t tellp()const { return _size; }
inline size_t remaining()const { return 0; }
private:
size_t _size;
};
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
} // namespace fc

0
include/fc/io/enum_type.hpp Executable file → Normal file
View file

7
include/fc/io/fstream.hpp Executable file → Normal file
View file

@ -1,14 +1,13 @@
#pragma once
#include <fc/shared_ptr.hpp>
#include <fc/filesystem.hpp>
#include <fc/io/iostream.hpp>
#include <fstream>
#include <memory>
namespace fc {
class path;
class ofstream : virtual public ostream {
public:
enum mode { out, binary };
ofstream();
ofstream( const fc::path& file, std::ios_base::openmode m = std::ios_base::out | std::ios_base::binary );
~ofstream();
@ -22,7 +21,7 @@ namespace fc {
private:
class impl;
fc::shared_ptr<impl> my;
std::shared_ptr<impl> my;
};
class ifstream : virtual public istream {
@ -45,7 +44,7 @@ namespace fc {
bool eof()const;
private:
class impl;
fc::shared_ptr<impl> my;
std::shared_ptr<impl> my;
};
/**

View file

@ -1,81 +0,0 @@
#pragma once
#include <fc/io/iostream.hpp>
#include <fc/exception/exception.hpp>
namespace fc
{
/**
* Records the size, but discards the data.
*/
class size_stream : public virtual fc::ostream
{
public:
size_stream( size_t s = 0):_size(s){}
size_t size()const { return _size; }
size_t seek( size_t pos ) { return _size = pos; }
virtual size_t writesome( const char* /*ignored buf*/, size_t len )
{
_size += len;
return len;
}
virtual void close(){}
virtual void flush(){}
private:
size_t _size;
};
class iobuffer : public virtual fc::iostream
{
public:
iobuffer( size_t s )
:_data(s){}
size_t size()const { return _data.size(); }
size_t pos()const { return _pos; }
size_t seek( size_t pos )
{
return _pos = std::min<size_t>(_data.size(),pos);
}
virtual size_t readsome( char* buf, size_t len )
{
auto avail = std::min<size_t>( _data.size()-_pos, len );
if( avail == 0 ) throw fc::eof_exception();
memcpy( buf, _data.data()+_pos, avail );
_pos += avail;
return avail;
}
/**
* This method may block until at least 1 character is
* available.
*/
char peek()const
{
if( _pos == _data.size() ) throw fc::eof_exception();
return _data[_pos];
}
virtual size_t writesome( const char* buf, size_t len )
{
auto avail = std::max<size_t>( _data.size(), _pos + len );
_data.resize(avail);
memcpy( _data.data()+_pos, buf, len );
_pos += avail;
return avail;
}
char* data() { return _data.data(); }
virtual void close(){}
virtual void flush(){}
private:
std::vector<char> _data;
size_t _pos;
};
}

9
include/fc/io/iostream.hpp Executable file → Normal file
View file

@ -1,7 +1,6 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/string.hpp>
#include <memory>
#include <string>
namespace fc {
@ -61,7 +60,7 @@ namespace fc {
class iostream : public virtual ostream, public virtual istream {};
fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' );
fc::istream& getline( fc::istream&, std::string&, char delim = '\n' );
template<size_t N>
ostream& operator<<( ostream& o, char (&array)[N] )
@ -72,7 +71,7 @@ namespace fc {
ostream& operator<<( ostream& o, char );
ostream& operator<<( ostream& o, const char* v );
ostream& operator<<( ostream& o, const std::string& v );
ostream& operator<<( ostream& o, const fc::string& v );
ostream& operator<<( ostream& o, const std::string& v );
ostream& operator<<( ostream& o, const double& v );
ostream& operator<<( ostream& o, const float& v );
ostream& operator<<( ostream& o, const int64_t& v );
@ -88,7 +87,7 @@ namespace fc {
#endif
istream& operator>>( istream& o, std::string& v );
istream& operator>>( istream& o, fc::string& v );
istream& operator>>( istream& o, std::string& v );
istream& operator>>( istream& o, char& v );
istream& operator>>( istream& o, double& v );
istream& operator>>( istream& o, float& v );

4
include/fc/io/json.hpp Executable file → Normal file
View file

@ -30,12 +30,10 @@ namespace fc
enum output_formatting
{
stringify_large_ints_and_doubles = 0,
#ifdef WITH_EXOTIC_JSON_PARSERS
legacy_generator = 1
#endif
};
static ostream& to_stream( ostream& out, const fc::string& );
static ostream& to_stream( ostream& out, const std::string& );
static ostream& to_stream( ostream& out, const variant& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
static ostream& to_stream( ostream& out, const variants& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
static ostream& to_stream( ostream& out, const variant_object& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );

23
include/fc/io/json_relaxed.hpp Executable file → Normal file
View file

@ -10,7 +10,6 @@
#include <fc/io/fstream.hpp>
#include <fc/io/sstream.hpp>
#include <fc/log/logger.hpp>
#include <fc/string.hpp>
//#include <utfcpp/utf8.h>
#include <iostream>
#include <fstream>
@ -24,7 +23,7 @@ namespace fc { namespace json_relaxed
variant variant_from_stream( T& in, uint32_t max_depth );
template<typename T>
fc::string tokenFromStream( T& in )
std::string tokenFromStream( T& in )
{
fc::stringstream token;
try
@ -81,7 +80,7 @@ namespace fc { namespace json_relaxed
}
template<typename T, bool strict, bool allow_escape>
fc::string quoteStringFromStream( T& in )
std::string quoteStringFromStream( T& in )
{
fc::stringstream token;
try
@ -107,11 +106,11 @@ namespace fc { namespace json_relaxed
try
{
if( in.peek() != q )
return fc::string();
return std::string();
}
catch( const fc::eof_exception& e )
{
return fc::string();
return std::string();
}
// triple quote processing
@ -186,7 +185,7 @@ namespace fc { namespace json_relaxed
}
template<typename T, bool strict>
fc::string stringFromStream( T& in )
std::string stringFromStream( T& in )
{
try
{
@ -238,6 +237,8 @@ namespace fc { namespace json_relaxed
}
} FC_RETHROW_EXCEPTIONS( warn, "while parsing string" );
return {};
}
struct CharValueTable
@ -292,7 +293,7 @@ namespace fc { namespace json_relaxed
};
template<uint8_t base>
fc::variant parseInt( const fc::string& token, size_t start )
fc::variant parseInt( const std::string& token, size_t start )
{
static const CharValueTable ctbl;
static const uint64_t INT64_MAX_PLUS_ONE = static_cast<uint64_t>(INT64_MAX) + 1;
@ -334,7 +335,7 @@ namespace fc { namespace json_relaxed
}
template<bool strict, uint8_t base>
fc::variant maybeParseInt( const fc::string& token, size_t start )
fc::variant maybeParseInt( const std::string& token, size_t start )
{
try
{
@ -350,7 +351,7 @@ namespace fc { namespace json_relaxed
}
template<bool strict>
fc::variant parseNumberOrStr( const fc::string& token )
fc::variant parseNumberOrStr( const std::string& token )
{ try {
//ilog( (token) );
size_t i = 0, n = token.length();
@ -586,7 +587,7 @@ namespace fc { namespace json_relaxed
template<typename T, bool strict>
variant numberFromStream( T& in )
{ try {
fc::string token = tokenFromStream(in);
std::string token = tokenFromStream(in);
variant result = json_relaxed::parseNumberOrStr<strict>( token );
if( strict && !(result.is_int64() || result.is_uint64() || result.is_double()) )
FC_THROW_EXCEPTION( parse_error_exception, "expected: number" );
@ -596,7 +597,7 @@ namespace fc { namespace json_relaxed
template<typename T, bool strict>
variant wordFromStream( T& in )
{
fc::string token = tokenFromStream(in);
std::string token = tokenFromStream(in);
FC_ASSERT( token.length() > 0 );

348
include/fc/io/raw.hpp Executable file → Normal file
View file

@ -1,16 +1,14 @@
#pragma once
#include <boost/endian/buffers.hpp>
#include <fc/io/raw_variant.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/io/datastream.hpp>
#include <fc/io/varint.hpp>
#include <fc/optional.hpp>
#include <fc/fwd.hpp>
#include <fc/smart_ref_fwd.hpp>
#include <fc/array.hpp>
#include <fc/time.hpp>
#include <fc/filesystem.hpp>
#include <fc/exception/exception.hpp>
#include <fc/safe.hpp>
#include <fc/io/raw_fwd.hpp>
#include <algorithm>
#include <map>
@ -27,6 +25,22 @@ namespace fc {
pack( s, args..., _max_depth );
}
template<typename Stream>
inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth )
{
boost::endian::little_uint64_buf_at hilo[2];
hilo[0] = uint128_hi64( v );
hilo[1] = uint128_lo64( v );
s.write( (char*)hilo[0].data(), sizeof(hilo) );
}
template<typename Stream>
inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth )
{
boost::endian::little_uint64_buf_at hilo[2];
s.read( (char*) hilo, sizeof(hilo) );
v = uint128( hilo[0].value(), hilo[1].value() );
}
template<typename Stream>
inline void pack( Stream& s, const fc::exception& e, uint32_t _max_depth )
{
@ -51,7 +65,7 @@ namespace fc {
fc::raw::unpack( s, what, _max_depth );
fc::raw::unpack( s, msgs, _max_depth );
e = fc::exception( fc::move(msgs), code, name, what );
e = fc::exception( std::move(msgs), code, name, what );
}
template<typename Stream>
@ -90,52 +104,62 @@ namespace fc {
template<typename Stream>
inline void pack( Stream& s, const fc::time_point_sec& tp, uint32_t _max_depth )
{
uint32_t usec = tp.sec_since_epoch();
s.write( (const char*)&usec, sizeof(usec) );
pack( s, tp.sec_since_epoch(), _max_depth );
}
template<typename Stream>
inline void unpack( Stream& s, fc::time_point_sec& tp, uint32_t _max_depth )
{ try {
uint32_t sec;
s.read( (char*)&sec, sizeof(sec) );
unpack( s, sec, _max_depth );
tp = fc::time_point() + fc::seconds(sec);
} FC_RETHROW_EXCEPTIONS( warn, "" ) }
template<typename Stream>
inline void pack( Stream& s, const fc::time_point& tp, uint32_t _max_depth )
{
uint64_t usec = tp.time_since_epoch().count();
s.write( (const char*)&usec, sizeof(usec) );
pack( s, tp.time_since_epoch().count(), _max_depth );
}
template<typename Stream>
inline void unpack( Stream& s, fc::time_point& tp, uint32_t _max_depth )
{ try {
uint64_t usec;
s.read( (char*)&usec, sizeof(usec) );
unpack( s, usec, _max_depth );
tp = fc::time_point() + fc::microseconds(usec);
} FC_RETHROW_EXCEPTIONS( warn, "" ) }
template<typename Stream>
inline void pack( Stream& s, const fc::microseconds& usec, uint32_t _max_depth )
{
uint64_t usec_as_int64 = usec.count();
s.write( (const char*)&usec_as_int64, sizeof(usec_as_int64) );
pack( s, usec.count(), _max_depth );
}
template<typename Stream>
inline void unpack( Stream& s, fc::microseconds& usec, uint32_t _max_depth )
{ try {
uint64_t usec_as_int64;
s.read( (char*)&usec_as_int64, sizeof(usec_as_int64) );
unpack( s, usec_as_int64, _max_depth );
usec = fc::microseconds(usec_as_int64);
} FC_RETHROW_EXCEPTIONS( warn, "" ) }
template<typename Stream, typename T, size_t N>
inline void pack( Stream& s, const fc::array<T,N>& v, uint32_t _max_depth ) {
s.write((const char*)&v.data[0],N*sizeof(T));
template<typename Stream, size_t N>
inline void pack( Stream& s, const std::array<char,N>& v, uint32_t _max_depth ) {
s.write( v.data(), N );
}
template<typename Stream, size_t N>
inline void pack( Stream& s, const std::array<unsigned char,N>& v, uint32_t _max_depth ) {
s.write( (char*)v.data(), N );
}
template<typename Stream, size_t N>
inline void unpack( Stream& s, std::array<char,N>& v, uint32_t _max_depth ) { try {
s.read( v.data(), N );
} FC_RETHROW_EXCEPTIONS( warn, "std::array<char,${length}>", ("length",N) ) }
template<typename Stream, size_t N>
inline void unpack( Stream& s, std::array<unsigned char,N>& v, uint32_t _max_depth ) { try {
s.read( (char*)v.data(), N );
} FC_RETHROW_EXCEPTIONS( warn, "std::array<unsigned char,${length}>", ("length",N) ) }
template<typename Stream, typename T>
inline void pack( Stream& s, const std::shared_ptr<T>& v, uint32_t _max_depth )
@ -144,19 +168,29 @@ namespace fc {
fc::raw::pack( s, *v, _max_depth - 1 );
}
template<typename Stream, typename T, size_t N>
inline void unpack( Stream& s, fc::array<T,N>& v, uint32_t _max_depth )
{ try {
s.read((char*)&v.data[0],N*sizeof(T));
} FC_RETHROW_EXCEPTIONS( warn, "fc::array<type,length>", ("type",fc::get_typename<T>::name())("length",N) ) }
template<typename Stream, typename T>
inline void unpack( Stream& s, std::shared_ptr<T>& v, uint32_t _max_depth )
{ try {
FC_ASSERT( _max_depth > 0 );
v = std::make_shared<T>();
fc::raw::unpack( s, *v, _max_depth - 1 );
} FC_RETHROW_EXCEPTIONS( warn, "std::shared_ptr<T>", ("type",fc::get_typename<T>::name()) ) }
} FC_RETHROW_EXCEPTIONS( warn, "std::shared_ptr<${type}>", ("type",fc::get_typename<T>::name()) ) }
template<typename Stream, typename T>
inline void pack( Stream& s, const std::shared_ptr<const T>& v, uint32_t _max_depth )
{
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, *v, _max_depth - 1 );
}
template<typename Stream, typename T>
inline void unpack( Stream& s, std::shared_ptr<const T>& v, uint32_t _max_depth )
{ try {
FC_ASSERT( _max_depth > 0 );
T tmp;
fc::raw::unpack( s, tmp, _max_depth - 1 );
v = std::make_shared<const T>(std::move(tmp));
} FC_RETHROW_EXCEPTIONS( warn, "std::shared_ptr<const T>", ("type",fc::get_typename<T>::name()) ) }
template<typename Stream> inline void pack( Stream& s, const signed_int& v, uint32_t _max_depth ) {
uint32_t val = (v.value<<1) ^ (v.value>>31);
@ -184,7 +218,7 @@ namespace fc {
s.get(b);
v |= uint32_t(uint8_t(b) & 0x7f) << by;
by += 7;
} while( uint8_t(b) & 0x80 );
} while( (uint8_t(b) & 0x80) && by < 32 );
vi.value = ((v>>1) ^ (v>>31)) + (v&0x01);
vi.value = v&0x01 ? vi.value : -vi.value;
vi.value = -vi.value;
@ -193,10 +227,12 @@ namespace fc {
uint64_t v = 0; char b = 0; uint8_t by = 0;
do {
s.get(b);
v |= uint32_t(uint8_t(b) & 0x7f) << by;
if( by >= 64 || (by == 63 && uint8_t(b) > 1) )
FC_THROW_EXCEPTION( overflow_exception, "Invalid packed unsigned_int!" );
v |= uint64_t(uint8_t(b) & 0x7f) << by;
by += 7;
} while( uint8_t(b) & 0x80 );
vi.value = static_cast<uint32_t>(v);
vi.value = static_cast<uint64_t>(v);
}
template<typename Stream, typename T> inline void unpack( Stream& s, const T& vi, uint32_t _max_depth )
@ -210,7 +246,7 @@ namespace fc {
template<typename Stream> inline void pack( Stream& s, const char* v, uint32_t _max_depth )
{
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, fc::string(v), _max_depth - 1 );
fc::raw::pack( s, std::string(v), _max_depth - 1 );
}
template<typename Stream, typename T>
@ -238,19 +274,6 @@ namespace fc {
FC_ASSERT( _max_depth > 0 );
fc::raw::unpack( *v, _max_depth - 1 ); // TODO not sure about this
}
template<typename Stream, typename T>
void pack( Stream& s, const fc::smart_ref<T>& v, uint32_t _max_depth )
{
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, *v, _max_depth - 1 );
}
template<typename Stream, typename T>
void unpack( Stream& s, fc::smart_ref<T>& v, uint32_t _max_depth )
{
FC_ASSERT( _max_depth > 0 );
fc::raw::unpack( s, *v, _max_depth - 1 );
}
// optional
template<typename Stream, typename T>
@ -273,9 +296,9 @@ namespace fc {
// std::vector<char>
template<typename Stream> inline void pack( Stream& s, const std::vector<char>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 );
fc::raw::pack( s, unsigned_int(value.size()), _max_depth - 1 );
if( value.size() )
s.write( &value.front(), (uint32_t)value.size() );
s.write( &value.front(), value.size() );
}
template<typename Stream> inline void unpack( Stream& s, std::vector<char>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
@ -287,25 +310,25 @@ namespace fc {
}
// fc::string
template<typename Stream> inline void pack( Stream& s, const fc::string& v, uint32_t _max_depth ) {
template<typename Stream> inline void pack( Stream& s, const std::string& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, unsigned_int((uint32_t)v.size()), _max_depth - 1 );
fc::raw::pack( s, unsigned_int(v.size()), _max_depth - 1 );
if( v.size() ) s.write( v.c_str(), v.size() );
}
template<typename Stream> inline void unpack( Stream& s, fc::string& v, uint32_t _max_depth ) {
template<typename Stream> inline void unpack( Stream& s, std::string& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
std::vector<char> tmp; fc::raw::unpack( s, tmp, _max_depth - 1 );
if( tmp.size() )
v = fc::string( tmp.data(), tmp.data()+tmp.size() );
else v = fc::string();
v = std::string( tmp.data(), tmp.data()+tmp.size() );
else v = std::string();
}
// bool
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 )
{
@ -354,47 +377,162 @@ namespace fc {
const uint32_t max_depth;
};
template<typename IsClass=fc::true_type>
struct if_class{
template<typename Stream, typename T>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { s << v; }
template<typename Stream, typename T>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { s >> v; }
// Default pack/unpack functions for classes are removed due to recursion issue.
// Classes should implement pack/unpack functions explicitly.
template<typename T, typename Dummy = void>
struct if_class;
template<typename T>
struct if_class<T, std::enable_if_t<!std::is_class<T>::value>> {
template<typename Stream>
static inline void pack( Stream& s, const T v, uint32_t _max_depth ) = delete;
template<typename Stream>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) = delete;
};
template<>
struct if_class<fc::false_type> {
template<typename Stream, typename T>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
s.write( (char*)&v, sizeof(v) );
struct if_class<int64_t, void> {
template<typename Stream>
static inline void pack( Stream& s, const int64_t v, uint32_t _max_depth ) {
boost::endian::little_int64_buf_t tmp;
tmp = v;
s.write( (char*)&tmp, sizeof(tmp) );
}
template<typename Stream, typename T>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
s.read( (char*)&v, sizeof(v) );
template<typename Stream>
static inline void unpack( Stream& s, int64_t& v, uint32_t _max_depth ) {
boost::endian::little_int64_buf_t tmp;
s.read( (char*)&tmp, sizeof(tmp) );
v = tmp.value();
}
};
template<typename IsEnum=fc::false_type>
struct if_enum {
template<typename Stream, typename T>
template<>
struct if_class<uint64_t, void> {
template<typename Stream>
static inline void pack( Stream& s, const uint64_t v, uint32_t _max_depth ) {
boost::endian::little_uint64_buf_t tmp;
tmp = v;
s.write( (char*)&tmp, sizeof(tmp) );
}
template<typename Stream>
static inline void unpack( Stream& s, uint64_t& v, uint32_t _max_depth ) {
boost::endian::little_uint64_buf_t tmp;
s.read( (char*)&tmp, sizeof(tmp) );
v = tmp.value();
}
};
template<>
struct if_class<int32_t, void> {
template<typename Stream>
static inline void pack( Stream& s, const int32_t v, uint32_t _max_depth ) {
boost::endian::little_int32_buf_t tmp;
tmp = v;
s.write( (char*)&tmp, sizeof(tmp) );
}
template<typename Stream>
static inline void unpack( Stream& s, int32_t& v, uint32_t _max_depth ) {
boost::endian::little_int32_buf_t tmp;
s.read( (char*)&tmp, sizeof(tmp) );
v = tmp.value();
}
};
template<>
struct if_class<uint32_t, void> {
template<typename Stream>
static inline void pack( Stream& s, const uint32_t v, uint32_t _max_depth ) {
boost::endian::little_uint32_buf_t tmp;
tmp = v;
s.write( (char*)&tmp, sizeof(tmp) );
}
template<typename Stream>
static inline void unpack( Stream& s, uint32_t& v, uint32_t _max_depth ) {
boost::endian::little_uint32_buf_t tmp;
s.read( (char*)&tmp, sizeof(tmp) );
v = tmp.value();
}
};
template<>
struct if_class<int16_t, void> {
template<typename Stream>
static inline void pack( Stream& s, const int16_t v, uint32_t _max_depth ) {
boost::endian::little_int16_buf_t tmp;
tmp = v;
s.write( (char*)&tmp, sizeof(tmp) );
}
template<typename Stream>
static inline void unpack( Stream& s, int16_t& v, uint32_t _max_depth ) {
boost::endian::little_int16_buf_t tmp;
s.read( (char*)&tmp, sizeof(tmp) );
v = tmp.value();
}
};
template<>
struct if_class<uint16_t, void> {
template<typename Stream>
static inline void pack( Stream& s, const uint16_t v, uint32_t _max_depth ) {
boost::endian::little_uint16_buf_t tmp;
tmp = v;
s.write( (char*)&tmp, sizeof(tmp) );
}
template<typename Stream>
static inline void unpack( Stream& s, uint16_t& v, uint32_t _max_depth ) {
boost::endian::little_uint16_buf_t tmp;
s.read( (char*)&tmp, sizeof(tmp) );
v = tmp.value();
}
};
template<>
struct if_class<int8_t, void> {
template<typename Stream>
static inline void pack( Stream& s, const int8_t v, uint32_t _max_depth ) {
s.write( (char*)&v, 1 );
}
template<typename Stream>
static inline void unpack( Stream& s, int8_t& v, uint32_t _max_depth ) {
s.read( (char*)&v, 1 );
}
};
template<>
struct if_class<uint8_t, void> {
template<typename Stream>
static inline void pack( Stream& s, const uint8_t v, uint32_t _max_depth ) {
s.write( (char*)&v, 1 );
}
template<typename Stream>
static inline void unpack( Stream& s, uint8_t& v, uint32_t _max_depth ) {
s.read( (char*)&v, 1 );
}
};
template<typename T, typename Dummy=void>
struct if_enum;
template<typename T>
struct if_enum<T, std::enable_if_t<!std::is_enum<T>::value>> {
template<typename Stream>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
fc::reflector<T>::visit( pack_object_visitor<Stream,T>( v, s, _max_depth - 1 ) );
}
template<typename Stream, typename T>
template<typename Stream>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
fc::reflector<T>::visit( unpack_object_visitor<Stream,T>( v, s, _max_depth - 1 ) );
}
};
template<>
struct if_enum<fc::true_type> {
template<typename Stream, typename T>
template<typename T>
struct if_enum<T, std::enable_if_t<std::is_enum<T>::value>> {
template<typename Stream>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, signed_int((int64_t)v), _max_depth - 1 );
}
template<typename Stream, typename T>
template<typename Stream>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
signed_int temp;
@ -403,30 +541,30 @@ namespace fc {
}
};
template<typename IsReflected=fc::false_type>
template<typename IsReflected=std::false_type>
struct if_reflected {
template<typename Stream, typename T>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_class<typename fc::is_class<T>::type>::pack( s, v, _max_depth - 1 );
if_class<T>::pack( s, v, _max_depth - 1 );
}
template<typename Stream, typename T>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_class<typename fc::is_class<T>::type>::unpack( s, v, _max_depth - 1 );
if_class<T>::unpack( s, v, _max_depth - 1 );
}
};
template<>
struct if_reflected<fc::true_type> {
struct if_reflected<std::true_type> {
template<typename Stream, typename T>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_enum< typename fc::reflector<T>::is_enum >::pack( s, v, _max_depth - 1 );
if_enum<T>::pack( s, v, _max_depth - 1 );
}
template<typename Stream, typename T>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_enum< typename fc::reflector<T>::is_enum >::unpack( s, v, _max_depth - 1 );
if_enum<T>::unpack( s, v, _max_depth - 1 );
}
};
@ -436,7 +574,7 @@ namespace fc {
inline void pack( Stream& s, const std::unordered_set<T>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
fc::raw::pack( s, unsigned_int(value.size()), _max_depth );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
@ -450,8 +588,7 @@ namespace fc {
--_max_depth;
unsigned_int size; fc::raw::unpack( s, size, _max_depth );
value.clear();
FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE );
value.reserve(size.value);
value.reserve( std::min( size.value, static_cast<uint64_t>(FC_MAX_PREALLOC_SIZE) ) );
for( uint32_t i = 0; i < size.value; ++i )
{
T tmp;
@ -481,7 +618,7 @@ namespace fc {
inline void pack( Stream& s, const std::unordered_map<K,V>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
fc::raw::pack( s, unsigned_int(value.size()), _max_depth );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
@ -496,8 +633,7 @@ namespace fc {
--_max_depth;
unsigned_int size; fc::raw::unpack( s, size, _max_depth );
value.clear();
FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE );
value.reserve(size.value);
value.reserve( std::min( size.value, static_cast<uint64_t>(FC_MAX_PREALLOC_SIZE) ) );
for( uint32_t i = 0; i < size.value; ++i )
{
std::pair<K,V> tmp;
@ -509,7 +645,7 @@ namespace fc {
inline void pack( Stream& s, const std::map<K,V>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
fc::raw::pack( s, unsigned_int(value.size()), _max_depth );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
@ -524,7 +660,6 @@ namespace fc {
--_max_depth;
unsigned_int size; fc::raw::unpack( s, size, _max_depth );
value.clear();
FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE );
for( uint32_t i = 0; i < size.value; ++i )
{
std::pair<K,V> tmp;
@ -537,7 +672,7 @@ namespace fc {
inline void pack( Stream& s, const std::deque<T>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
fc::raw::pack( s, unsigned_int(value.size()), _max_depth );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
@ -551,13 +686,12 @@ namespace fc {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
unsigned_int size; fc::raw::unpack( s, size, _max_depth );
FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE );
value.resize(size.value);
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
fc::raw::unpack( s, *itr, _max_depth );
++itr;
value.resize( std::min( size.value, static_cast<uint64_t>(FC_MAX_PREALLOC_SIZE) ) );
for( uint64_t i = 0; i < size; i++ )
{
if( i >= value.size() )
value.resize( std::min( static_cast<uint64_t>(2*value.size()), size.value ) );
unpack( s, value[i], _max_depth );
}
}
@ -565,7 +699,7 @@ namespace fc {
inline void pack( Stream& s, const std::vector<T>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
fc::raw::pack( s, unsigned_int(value.size()), _max_depth );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
@ -579,13 +713,12 @@ namespace fc {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
unsigned_int size; fc::raw::unpack( s, size, _max_depth );
FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE );
value.resize(size.value);
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
fc::raw::unpack( s, *itr, _max_depth );
++itr;
value.resize( std::min( size.value, static_cast<uint64_t>(FC_MAX_PREALLOC_SIZE) ) );
for( uint64_t i = 0; i < size; i++ )
{
if( i >= value.size() )
value.resize( std::min( static_cast<uint64_t>(2*value.size()), size.value ) );
unpack( s, value[i], _max_depth );
}
}
@ -593,7 +726,7 @@ namespace fc {
inline void pack( Stream& s, const std::set<T>& value, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
--_max_depth;
fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth );
fc::raw::pack( s, unsigned_int(value.size()), _max_depth );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
@ -615,6 +748,18 @@ namespace fc {
}
}
template<typename Stream, boost::endian::order O, class T, std::size_t N, boost::endian::align A>
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( (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 )
{
FC_ASSERT( _max_depth > 0 );
s.read( (char*)&v, sizeof(v) );
}
template<typename Stream, typename T>
@ -713,7 +858,6 @@ namespace fc {
FC_ASSERT( _max_depth > 0 );
datastream<const char*> ds( d, s );
fc::raw::unpack( ds, v, _max_depth - 1 );
return v;
} FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename<T>::name() ) ) }
template<typename Stream>

67
include/fc/io/raw_fwd.hpp Executable file → Normal file
View file

@ -1,11 +1,15 @@
#pragma once
#include <boost/endian/buffers.hpp>
#include <fc/config.hpp>
#include <fc/container/flat_fwd.hpp>
#include <fc/container/deque_fwd.hpp>
#include <fc/io/varint.hpp>
#include <fc/array.hpp>
#include <fc/safe.hpp>
#include <fc/uint128.hpp>
#include <array>
#include <deque>
#include <memory>
#include <vector>
#include <string>
#include <unordered_set>
@ -22,25 +26,29 @@ namespace fc {
class path;
template<typename... Types> class static_variant;
class sha224;
class sha256;
class sha512;
class ripemd160;
template<typename IntType, typename EnumType> class enum_type;
namespace ip { class endpoint; }
namespace ecc { class public_key; class private_key; }
template<typename Storage> class fixed_string;
namespace raw {
template<typename T>
inline size_t pack_size( const T& v );
template<typename Stream, typename Storage> inline void pack( Stream& s, const fc::fixed_string<Storage>& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename Storage> inline void unpack( Stream& s, fc::fixed_string<Storage>& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename IntType, typename EnumType>
inline void pack( Stream& s, const fc::enum_type<IntType,EnumType>& tp, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename IntType, typename EnumType>
inline void unpack( Stream& s, fc::enum_type<IntType,EnumType>& tp, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream>
inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream>
inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void pack( Stream& s, const std::set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, std::set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
@ -53,8 +61,8 @@ namespace fc {
//template<typename Stream, typename T> inline void pack( Stream& s, const flat_set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
//template<typename Stream, typename T> inline void unpack( Stream& s, flat_set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
//template<typename Stream, typename T> inline void pack( Stream& s, const std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
//template<typename Stream, typename T> inline void unpack( Stream& s, std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void pack( Stream& s, const std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename K, typename V> inline void pack( Stream& s, const std::unordered_map<K,V>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename K, typename V> inline void unpack( Stream& s, std::unordered_map<K,V>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
@ -96,8 +104,17 @@ namespace fc {
template<typename Stream> void unpack( Stream& s, fc::ecc::private_key&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> void pack( Stream& s, const fc::ecc::private_key&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void pack( Stream& s, const T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void unpack( Stream& s, fc::sha224&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void pack( Stream& s, const fc::sha224&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void unpack( Stream& s, fc::sha256&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void pack( Stream& s, const fc::sha256&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void unpack( Stream& s, fc::sha512&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void pack( Stream& s, const fc::sha512&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void unpack( Stream& s, fc::ripemd160&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void pack( Stream& s, const fc::ripemd160&, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> void pack( Stream& s, const T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> void unpack( Stream& s, T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void pack( Stream& s, const std::vector<T>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, std::vector<T>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
@ -111,9 +128,33 @@ namespace fc {
template<typename Stream> inline void pack( Stream& s, const char* v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void pack( Stream& s, const std::vector<char>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void unpack( Stream& s, std::vector<char>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, boost::endian::order O, class T, std::size_t N, boost::endian::align A>
inline void pack( Stream& s, const boost::endian::endian_buffer<O,T,N,A>& v, uint32_t _max_depth );
template<typename Stream, boost::endian::order O, class T, std::size_t N, boost::endian::align A>
inline void unpack( Stream& s, boost::endian::endian_buffer<O,T,N,A>& v, uint32_t _max_depth );
template<typename Stream, typename T, size_t N> inline void pack( Stream& s, const fc::array<T,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T, size_t N> inline void unpack( Stream& s, fc::array<T,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH);
template<typename Stream, typename T, size_t N>
inline void pack( Stream& s, const std::array<T,N>& v, uint32_t _max_depth ) = delete;
template<typename Stream, typename T, size_t N>
inline void unpack( Stream& s, std::array<T,N>& v, uint32_t _max_depth ) = delete;
template<typename Stream, size_t N>
inline void pack( Stream& s, const std::array<char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, size_t N>
inline void unpack( Stream& s, std::array<char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH);
template<typename Stream, size_t N>
inline void pack( Stream& s, const std::array<unsigned char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, size_t N>
inline void unpack( Stream& s, std::array<unsigned char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH);
template<typename Stream, typename T> inline void pack( Stream& s, const std::shared_ptr<T>& v,
uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, std::shared_ptr<T>& v,
uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void pack( Stream& s, const std::shared_ptr<const T>& v,
uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, std::shared_ptr<const T>& v,
uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void pack( Stream& s, const bool& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void unpack( Stream& s, bool& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );

View file

@ -1,24 +0,0 @@
#pragma once
#include <fc/io/raw.hpp>
#include <fc/interprocess/file_mapping.hpp>
#include <fc/filesystem.hpp>
#include <fc/exception/exception.hpp>
namespace fc
{
namespace raw
{
template<typename T>
void unpack_file( const fc::path& filename, T& obj )
{
try {
fc::file_mapping fmap( filename.generic_string().c_str(), fc::read_only);
fc::mapped_region mapr( fmap, fc::read_only, 0, fc::file_size(filename) );
auto cs = (const char*)mapr.get_address();
fc::datastream<const char*> ds( cs, mapr.get_size() );
fc::raw::unpack(ds,obj);
} FC_RETHROW_EXCEPTIONS( info, "unpacking file ${file}", ("file",filename) );
}
}
}

27
include/fc/io/raw_variant.hpp Executable file → Normal file
View file

@ -1,4 +1,5 @@
#pragma once
#include <algorithm>
#include <fc/exception/exception.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/variant_object.hpp>
@ -25,7 +26,7 @@ namespace fc { namespace raw {
}
virtual void handle( const double& v )const
{
fc::raw::pack( s, v, max_depth );
FC_THROW_EXCEPTION( invalid_arg_exception, "Can't pack double!" );
}
virtual void handle( const bool& v )const
{
@ -85,10 +86,7 @@ namespace fc { namespace raw {
}
case variant::double_type:
{
double val;
raw::unpack( s, val, _max_depth );
v = val;
return;
FC_THROW_EXCEPTION( invalid_arg_exception, "Can't unpack double!" );
}
case variant::bool_type:
{
@ -99,23 +97,23 @@ namespace fc { namespace raw {
}
case variant::string_type:
{
fc::string val;
std::string val;
raw::unpack( s, val, _max_depth );
v = fc::move(val);
v = std::move(val);
return;
}
case variant::array_type:
{
variants val;
raw::unpack( s, val, _max_depth );
v = fc::move(val);
v = std::move(val);
return;
}
case variant::object_type:
{
variant_object val;
raw::unpack( s, val, _max_depth );
v = fc::move(val);
v = std::move(val);
return;
}
default:
@ -128,7 +126,7 @@ namespace fc { namespace raw {
{
FC_ASSERT( _max_depth > 0 );
--_max_depth;
unsigned_int vs = (uint32_t)v.size();
unsigned_int vs = v.size();
pack( s, vs, _max_depth );
for( auto itr = v.begin(); itr != v.end(); ++itr )
{
@ -143,18 +141,17 @@ namespace fc { namespace raw {
--_max_depth;
unsigned_int vs;
unpack( s, vs, _max_depth );
mutable_variant_object mvo;
mvo.reserve(vs.value);
mvo.reserve( std::min( vs.value, static_cast<uint64_t>(FC_MAX_PREALLOC_SIZE) ) );
for( uint32_t i = 0; i < vs.value; ++i )
{
fc::string key;
std::string key;
fc::variant value;
fc::raw::unpack( s, key, _max_depth );
fc::raw::unpack( s, value, _max_depth );
mvo.set( fc::move(key), fc::move(value) );
mvo.set( std::move(key), std::move(value) );
}
v = fc::move(mvo);
v = std::move(mvo);
}
} } // fc::raw

8
include/fc/io/sstream.hpp Executable file → Normal file
View file

@ -7,12 +7,12 @@ namespace fc {
class stringstream : virtual public iostream {
public:
stringstream();
stringstream( fc::string& s);
stringstream( const fc::string& s);
stringstream( std::string& s);
stringstream( const std::string& s);
~stringstream();
fc::string str();
void str(const fc::string& s);
std::string str();
void str(const std::string& s);
void clear();

0
include/fc/io/stdio.hpp Executable file → Normal file
View file

37
include/fc/io/varint.hpp Executable file → Normal file
View file

@ -4,35 +4,40 @@
namespace fc {
struct unsigned_int {
unsigned_int( uint32_t v = 0 ):value(v){}
unsigned_int( uint64_t v = 0 ):value(v){}
template<typename T>
unsigned_int( T v ):value(v){}
//operator uint32_t()const { return value; }
//operator uint64_t()const { return value; }
template<typename T>
operator T()const { return static_cast<T>(value); }
unsigned_int& operator=( int32_t v ) { value = v; return *this; }
unsigned_int& operator=( uint64_t v ) { value = v; return *this; }
uint32_t value;
uint64_t value;
friend bool operator==( const unsigned_int& i, const uint32_t& v ) { return i.value == v; }
friend bool operator==( const uint32_t& i, const unsigned_int& v ) { return i == v.value; }
friend bool operator==( const unsigned_int& i, const uint64_t& v ) { return i.value == v; }
friend bool operator==( const uint64_t& i, const unsigned_int& v ) { return i == v.value; }
friend bool operator==( const unsigned_int& i, const unsigned_int& v ) { return i.value == v.value; }
friend bool operator!=( const unsigned_int& i, const uint32_t& v ) { return i.value != v; }
friend bool operator!=( const uint32_t& i, const unsigned_int& v ) { return i != v.value; }
friend bool operator!=( const unsigned_int& i, const uint64_t& v ) { return i.value != v; }
friend bool operator!=( const uint64_t& i, const unsigned_int& v ) { return i != v.value; }
friend bool operator!=( const unsigned_int& i, const unsigned_int& v ) { return i.value != v.value; }
friend bool operator<( const unsigned_int& i, const uint32_t& v ) { return i.value < v; }
friend bool operator<( const uint32_t& i, const unsigned_int& v ) { return i < v.value; }
friend bool operator<( const unsigned_int& i, const uint64_t& v ) { return i.value < v; }
friend bool operator<( const uint64_t& i, const unsigned_int& v ) { return i < v.value; }
friend bool operator<( const unsigned_int& i, const unsigned_int& v ) { return i.value < v.value; }
friend bool operator>=( const unsigned_int& i, const uint32_t& v ) { return i.value >= v; }
friend bool operator>=( const uint32_t& i, const unsigned_int& v ) { return i >= v.value; }
friend bool operator<=( const unsigned_int& i, const uint64_t& v ) { return i.value <= v; }
friend bool operator<=( const uint64_t& i, const unsigned_int& v ) { return i <= v.value; }
friend bool operator<=( const unsigned_int& i, const unsigned_int& v ) { return i.value <= v.value; }
friend bool operator>( const unsigned_int& i, const uint64_t& v ) { return i.value > v; }
friend bool operator>( const uint64_t& i, const unsigned_int& v ) { return i > v.value; }
friend bool operator>( const unsigned_int& i, const unsigned_int& v ) { return i.value > v.value; }
friend bool operator>=( const unsigned_int& i, const uint64_t& v ) { return i.value >= v; }
friend bool operator>=( const uint64_t& i, const unsigned_int& v ) { return i >= v.value; }
friend bool operator>=( const unsigned_int& i, const unsigned_int& v ) { return i.value >= v.value; }
};
@ -93,9 +98,9 @@ namespace std
struct hash<fc::unsigned_int>
{
public:
size_t operator()(const fc::signed_int &a) const
size_t operator()(const fc::unsigned_int &a) const
{
return std::hash<uint32_t>()(a.value);
return std::hash<uint64_t>()(a.value);
}
};
}

29
include/fc/log/appender.hpp Executable file → Normal file
View file

@ -1,42 +1,43 @@
#pragma once
#include <fc/shared_ptr.hpp>
#include <fc/string.hpp>
#include <memory>
#include <string>
namespace fc {
class appender;
class log_message;
class variant;
class appender_factory : public fc::retainable {
class appender_factory {
public:
typedef fc::shared_ptr<appender_factory> ptr;
typedef std::shared_ptr<appender_factory> ptr;
virtual ~appender_factory(){};
virtual fc::shared_ptr<appender> create( const variant& args ) = 0;
virtual std::shared_ptr<appender> create( const variant& args ) = 0;
};
namespace detail {
template<typename T>
class appender_factory_impl : public appender_factory {
public:
virtual fc::shared_ptr<appender> create( const variant& args ) {
return fc::shared_ptr<appender>(new T(args));
virtual std::shared_ptr<appender> create( const variant& args ) {
return std::shared_ptr<appender>(new T(args));
}
};
}
class appender : public fc::retainable {
class appender {
public:
typedef fc::shared_ptr<appender> ptr;
typedef std::shared_ptr<appender> ptr;
template<typename T>
static bool register_appender(const fc::string& type) {
return register_appender( type, new detail::appender_factory_impl<T>() );
static bool register_appender(const std::string& type) {
return register_appender( type, appender_factory::ptr( new detail::appender_factory_impl<T>() ) );
}
static appender::ptr create( const fc::string& name, const fc::string& type, const variant& args );
static appender::ptr get( const fc::string& name );
static bool register_appender( const fc::string& type, const appender_factory::ptr& f );
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 );
virtual void log( const log_message& m ) = 0;
};

2
include/fc/log/console_appender.hpp Executable file → Normal file
View file

@ -40,7 +40,7 @@ namespace fc
:format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
stream(console_appender::stream::std_error),max_object_depth(FC_MAX_LOG_OBJECT_DEPTH),flush(true){}
fc::string format;
std::string format;
console_appender::stream::type stream;
std::vector<level_color> level_colors;
uint32_t max_object_depth;

9
include/fc/log/file_appender.hpp Executable file → Normal file
View file

@ -12,14 +12,13 @@ class file_appender : public appender {
struct config {
config( const fc::path& p = "log.txt" );
fc::string format;
std::string format;
fc::path filename;
bool flush = true;
bool rotate = false;
microseconds rotation_interval;
microseconds rotation_limit;
bool rotation_compression = false;
uint32_t max_object_depth;
uint32_t max_object_depth = FC_MAX_LOG_OBJECT_DEPTH;
};
file_appender( const variant& args );
~file_appender();
@ -27,10 +26,10 @@ class file_appender : public appender {
private:
class impl;
fc::shared_ptr<impl> my;
std::unique_ptr<impl> my;
};
} // namespace fc
#include <fc/reflect/reflect.hpp>
FC_REFLECT( fc::file_appender::config,
(format)(filename)(flush)(rotate)(rotation_interval)(rotation_limit)(rotation_compression)(max_object_depth) )
(format)(filename)(flush)(rotate)(rotation_interval)(rotation_limit)(max_object_depth) )

4
include/fc/log/gelf_appender.hpp Executable file → Normal file
View file

@ -15,7 +15,7 @@ namespace fc
{
string endpoint = "127.0.0.1:12201";
string host = "fc"; // the name of the host, source or application that sent this message (just passed through to GELF server)
uint32_t max_object_depth;
uint32_t max_object_depth = FC_MAX_LOG_OBJECT_DEPTH;
};
gelf_appender(const variant& args);
@ -24,7 +24,7 @@ namespace fc
private:
class impl;
fc::shared_ptr<impl> my;
std::unique_ptr<impl> my;
};
} // namespace fc

46
include/fc/log/log_message.hpp Executable file → Normal file
View file

@ -6,16 +6,8 @@
#include <fc/config.hpp>
#include <fc/time.hpp>
#include <fc/variant_object.hpp>
#include <fc/shared_ptr.hpp>
#include <memory>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/facilities/expand.hpp>
#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/seq/variadic_seq_to_seq.hpp>
#include <string>
namespace fc
{
@ -73,19 +65,19 @@ namespace fc
explicit log_context( const variant& v, uint32_t max_depth );
variant to_variant( uint32_t max_depth )const;
string get_file()const;
std::string get_file()const;
uint64_t get_line_number()const;
string get_method()const;
string get_thread_name()const;
string get_task_name()const;
string get_host_name()const;
std::string get_method()const;
std::string get_thread_name()const;
std::string get_task_name()const;
std::string get_host_name()const;
time_point get_timestamp()const;
log_level get_log_level()const;
string get_context()const;
std::string get_context()const;
void append_context( const fc::string& c );
void append_context( const std::string& c );
string to_string()const;
std::string to_string()const;
private:
std::shared_ptr<detail::log_context_impl> my;
};
@ -124,10 +116,10 @@ namespace fc
log_message( const variant& v, uint32_t max_depth );
variant to_variant(uint32_t max_depth)const;
string get_message()const;
std::string get_message()const;
log_context get_context()const;
string get_format()const;
std::string get_format()const;
variant_object get_data()const;
private:
@ -155,7 +147,7 @@ FC_REFLECT_TYPENAME( fc::log_message );
* @param LOG_LEVEL - a valid log_level::Enum name.
*/
#define FC_LOG_CONTEXT(LOG_LEVEL) \
fc::log_context( fc::log_level::LOG_LEVEL, __FILE__, __LINE__, __func__ )
fc::log_context( fc::log_level::LOG_LEVEL, (const char*)__FILE__, __LINE__, (const char*)__func__ )
/**
* @def FC_LOG_MESSAGE(LOG_LEVEL,FORMAT,...)
@ -166,14 +158,8 @@ FC_REFLECT_TYPENAME( fc::log_message );
* @param FORMAT A const char* string containing zero or more references to keys as "${key}"
* @param ... A set of key/value pairs denoted as ("key",val)("key2",val2)...
*/
#define FC_LOG_MESSAGE_GENERATE_PARAMETER_NAME(VALUE) BOOST_PP_LPAREN() BOOST_PP_STRINGIZE(VALUE), fc::variant(VALUE, FC_MAX_LOG_OBJECT_DEPTH) BOOST_PP_RPAREN()
#define FC_LOG_MESSAGE_DONT_GENERATE_PARAMETER_NAME(NAME, VALUE) BOOST_PP_LPAREN() NAME, fc::variant(VALUE, FC_MAX_LOG_OBJECT_DEPTH) BOOST_PP_RPAREN()
#define FC_LOG_MESSAGE_GENERATE_PARAMETER_NAMES_IF_NEEDED(r, data, PARAMETER_AND_MAYBE_NAME) BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE PARAMETER_AND_MAYBE_NAME,1),FC_LOG_MESSAGE_GENERATE_PARAMETER_NAME,FC_LOG_MESSAGE_DONT_GENERATE_PARAMETER_NAME)PARAMETER_AND_MAYBE_NAME
#define FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, ... ) \
fc::log_message( FC_LOG_CONTEXT(LOG_LEVEL), \
FORMAT, \
fc::limited_mutable_variant_object( FC_MAX_LOG_OBJECT_DEPTH, true )__VA_ARGS__ )
#define FC_LOG_MESSAGE_STRING_ONLY(LOG_LEVEL, FORMAT) \
fc::log_message(FC_LOG_CONTEXT(LOG_LEVEL), FORMAT, fc::variant_object())
#define FC_LOG_MESSAGE_WITH_SUBSTITUTIONS(LOG_LEVEL, FORMAT, ...) \
fc::log_message(FC_LOG_CONTEXT(LOG_LEVEL), FORMAT, fc::mutable_variant_object() BOOST_PP_SEQ_FOR_EACH(FC_LOG_MESSAGE_GENERATE_PARAMETER_NAMES_IF_NEEDED, _, BOOST_PP_VARIADIC_SEQ_TO_SEQ(__VA_ARGS__)))
#define FC_LOG_MESSAGE(LOG_LEVEL, ...) \
BOOST_PP_EXPAND(BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),1),FC_LOG_MESSAGE_STRING_ONLY,FC_LOG_MESSAGE_WITH_SUBSTITUTIONS)(LOG_LEVEL,__VA_ARGS__))

60
include/fc/log/logger.hpp Executable file → Normal file
View file

@ -1,15 +1,13 @@
#pragma once
#include <fc/config.hpp>
#include <fc/string.hpp>
#include <fc/time.hpp>
#include <fc/shared_ptr.hpp>
#include <fc/log/appender.hpp>
#include <fc/log/log_message.hpp>
#include <cstddef>
#include <memory>
namespace fc
{
class appender;
/**
*
*
@ -23,7 +21,7 @@ namespace fc
class logger
{
public:
static logger get( const fc::string& name = "default");
static logger get( const std::string& name = "default");
logger();
logger( const string& name, const logger& parent = nullptr );
@ -33,27 +31,27 @@ namespace fc
~logger();
logger& operator=(const logger&);
logger& operator=(logger&&);
friend bool operator==( const logger&, nullptr_t );
friend bool operator!=( const logger&, nullptr_t );
friend bool operator==( const logger&, std::nullptr_t );
friend bool operator!=( const logger&, std::nullptr_t );
logger& set_log_level( log_level e );
log_level get_log_level()const;
logger& set_parent( const logger& l );
logger get_parent()const;
void set_name( const fc::string& n );
const fc::string& name()const;
void set_name( const std::string& n );
const std::string& name()const;
void add_appender( const fc::shared_ptr<appender>& a );
std::vector<fc::shared_ptr<appender> > get_appenders()const;
void remove_appender( const fc::shared_ptr<appender>& a );
void add_appender( const appender::ptr& a );
std::vector<appender::ptr> get_appenders()const;
void remove_appender( const appender::ptr& a );
bool is_enabled( log_level e )const;
void log( log_message m );
private:
class impl;
fc::shared_ptr<impl> my;
std::shared_ptr<impl> my;
};
} // namespace fc
@ -156,6 +154,12 @@ namespace fc
#define FC_FORMAT_ARG_PARAMS( ... )\
BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARGS, v, __VA_ARGS__ )
#define FC_DUMP_FORMAT_ARG_NAME(r, unused, base) \
"(" BOOST_PP_STRINGIZE(base) ")"
#define FC_DUMP_FORMAT_ARG_NAMES( SEQ )\
BOOST_PP_SEQ_FOR_EACH( FC_DUMP_FORMAT_ARG_NAME, v, SEQ )
#define fc_ddump( LOGGER, SEQ ) \
fc_dlog( LOGGER, FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
#define fc_idump( LOGGER, SEQ ) \
@ -167,12 +171,34 @@ namespace fc
#define ddump( SEQ ) \
dlog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
// TODO FC_FORMAT_ARG_PARAMS(...) may throw exceptions when calling fc::variant(...) inside,
// as a quick-fix / workaround, we catch all exceptions here.
// However, to log as much info as possible, it's better to catch exceptions when processing each argument
#define idump( SEQ ) \
ilog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
{ \
try { \
ilog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ); \
} catch( ... ) { \
ilog ( "[ERROR: Got exception while trying to dump ( ${args} )]",("args",FC_DUMP_FORMAT_ARG_NAMES(SEQ)) ); \
} \
}
#define wdump( SEQ ) \
wlog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
{ \
try { \
wlog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ); \
} catch( ... ) { \
wlog ( "[ERROR: Got exception while trying to dump ( ${args} )]",("args",FC_DUMP_FORMAT_ARG_NAMES(SEQ)) ); \
} \
}
#define edump( SEQ ) \
elog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
{ \
try { \
elog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ); \
} catch( ... ) { \
elog ( "[ERROR: Got exception while trying to dump ( ${args} )]",("args",FC_DUMP_FORMAT_ARG_NAMES(SEQ)) ); \
} \
}
// this disables all normal logging statements -- not something you'd normally want to do,
// but it's useful if you're benchmarking something and suspect logging is causing

4
include/fc/log/logger_config.hpp Executable file → Normal file
View file

@ -9,7 +9,7 @@ namespace fc {
variant args = variant()) :
name(name),
type(type),
args(fc::move(args)),
args(std::move(args)),
enabled(true)
{}
string name;
@ -19,7 +19,7 @@ namespace fc {
};
struct logger_config {
logger_config(const fc::string& name = ""):name(name),enabled(true),additivity(false){}
logger_config(const std::string& name = ""):name(name),enabled(true),additivity(false){}
string name;
ostring parent;
/// if not set, then parents level is used.

View file

@ -1,26 +0,0 @@
#pragma once
#include <fc/tuple.hpp>
#include <fc/function.hpp>
namespace fc {
template<typename R>
std::function<R, fc::tuple<> > make_fused( const std::function<R>& f ) {
return [=]( fc::tuple<> ){ return f(); };
}
template<typename R,typename A>
std::function<R(fc::tuple<A>) > make_fused( const std::function<R(A)>& f ) {
return [f]( fc::tuple<A> t){ return f(t.a); };
}
template<typename R,typename A,typename B>
std::function<R(fc::tuple<A,B>) > make_fused( const std::function<R(A,B)>& f ) {
return [f]( fc::tuple<A,B> t){ return f(t.a,t.b); };
}
template<typename R,typename A,typename B,typename C>
std::function<R(fc::tuple<A,B,C>) > make_fused( const std::function<R(A,B,C)>& f ) {
return [f]( fc::tuple<A,B,C> t){ return f(t.a,t.b,t.c); };
}
template<typename R,typename A,typename B,typename C,typename D>
std::function<R(fc::tuple<A,B,C,D>) > make_fused( const std::function<R(A,B,C,D)>& f ) {
return [f]( fc::tuple<A,B,C> t){ return f(t.a,t.b,t.c,t.d); };
}
}

30
include/fc/network/http/connection.hpp Executable file → Normal file
View file

@ -1,7 +1,7 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
#include <memory>
#include <string>
#include <vector>
namespace fc {
namespace ip { class endpoint; }
@ -11,11 +11,11 @@ namespace fc {
struct header
{
header( fc::string k, fc::string v )
:key(fc::move(k)),val(fc::move(v)){}
header( std::string k, std::string v )
:key(std::move(k)),val(std::move(v)){}
header(){}
fc::string key;
fc::string val;
std::string key;
std::string val;
};
typedef std::vector<header> headers;
@ -25,6 +25,7 @@ namespace fc {
enum status_code {
OK = 200,
RecordCreated = 201,
NoContent = 204,
BadRequest = 400,
NotAuthorized = 401,
NotFound = 404,
@ -35,20 +36,21 @@ namespace fc {
int status;
std::vector<header> headers;
std::vector<char> body;
std::string body_as_string;
};
struct request
{
fc::string get_header( const fc::string& key )const;
fc::string remote_endpoint;
fc::string method;
fc::string domain;
fc::string path;
std::string get_header( const std::string& key )const;
std::string remote_endpoint;
std::string method;
std::string domain;
std::string path;
std::vector<header> headers;
std::vector<char> body;
};
std::vector<header> parse_urlencoded_params( const fc::string& f );
std::vector<header> parse_urlencoded_params( const std::string& f );
/**
* Connections have reference semantics, all copies refer to the same
@ -61,7 +63,7 @@ namespace fc {
~connection();
// used for clients
void connect_to( const fc::ip::endpoint& ep );
http::reply request( const fc::string& method, const fc::string& url, const fc::string& body = std::string(), const headers& = headers(), const fc::string& content_type = "application/json");
http::reply request( const std::string& method, const std::string& url, const std::string& body = std::string(), const headers& = headers());
// used for servers
fc::tcp_socket& get_socket()const;
@ -79,4 +81,4 @@ namespace fc {
#include <fc/reflect/reflect.hpp>
FC_REFLECT( fc::http::header, (key)(val) )
FC_REFLECT( fc::http::reply, (status)(headers)(body)(body_as_string) )

View file

@ -1,62 +0,0 @@
#pragma once
#include <fc/network/http/connection.hpp>
#include <fc/shared_ptr.hpp>
#include <functional>
#include <memory>
namespace fc { namespace http {
/**
* Listens on a given port for incomming http
* connections and then calls a user provided callback
* function for every http request.
*
*/
class server
{
public:
server();
server( uint16_t port );
server( server&& s );
~server();
server& operator=(server&& s);
class response
{
public:
class impl;
response();
response( const fc::shared_ptr<impl>& my);
response( const response& r);
response( response&& r );
~response();
response& operator=(const response& );
response& operator=( response&& );
void add_header( const fc::string& key, const fc::string& val )const;
void set_status( const http::reply::status_code& s )const;
void set_length( uint64_t s )const;
void write( const char* data, uint64_t len )const;
private:
fc::shared_ptr<impl> my;
};
void listen( const fc::ip::endpoint& p );
fc::ip::endpoint get_local_endpoint() const;
/**
* Set the callback to be called for every http request made.
*/
void on_request( const std::function<void(const http::request&, const server::response& s )>& cb );
private:
class impl;
std::unique_ptr<impl> my;
};
typedef std::shared_ptr<server> server_ptr;
} }

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