Updating FC with changes from phoenix-int

This commit is contained in:
Daniel Larimer 2013-06-05 15:19:00 -04:00
parent 9909ef83b5
commit 59a121d64b
370 changed files with 13676 additions and 66345 deletions

View file

@ -3,31 +3,47 @@ PROJECT( fc )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8.0 )
SET( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}" )
SET( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}" )
INCLUDE( VersionMacros )
INCLUDE( SetupTargetMacros )
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} )
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include )
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/vendor/boost_1_51/include )
SET( DEFAULT_HEADER_INSTALL_DIR include/\${target} )
SET( DEFAULT_LIBRARY_INSTALL_DIR lib/ )
SET( DEFAULT_EXECUTABLE_INSTALL_DIR bin/ )
SET( CMAKE_DEBUG_POSTFIX _debug )
#SET( BUILD_SHARED_LIBS NO )
SET( BUILD_SHARED_LIBS NO )
SET(Boost_USE_STATIC_LIBS ON)
FIND_PACKAGE(Boost 1.51 COMPONENTS thread date_time system filesystem program_options signals serialization chrono unit_test_framework context )
if( WIN32 )
set( RPCRT4 Rpcrt4 )
set( OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl" )
if ( NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/lib" )
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/out32dll" DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/cmakefun")
file(RENAME "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/cmakefun/out32dll" "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/lib")
endif( NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/lib" )
endif( WIN32 )
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} )
LINK_DIRECTORIES( ${Boost_LIBRARY_DIRS} )
IF( WIN32 )
ADD_DEFINITIONS( -DWIN32 )
ADD_DEFINITIONS( -DBOOST_CONTEXT_NO_LIB )
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
ADD_DEFINITIONS( -D_WIN32_WINNT=0x0501 )
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
ADD_DEFINITIONS( -DBOOST_ALL_NO_LIB -DBOOST_THREAD_BUILD_LIB)
ADD_DEFINITIONS( -DWIN32)
# Activate C++ exception handling
IF (NOT CMAKE_CXX_FLAGS MATCHES "/EHsc")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
ENDIF()
ELSE(WIN32)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wno-unused-local-typedefs -fmax-errors=3" )
ENDIF(WIN32)
if( UNIX )
@ -40,82 +56,144 @@ endif()
option( UNITY_BUILD OFF )
FIND_PACKAGE( OpenSSL )
FIND_PACKAGE( ZLIB )
include_directories( vendor/zlib-1.2.7/)
include_directories( vendor/libssh2-1.4.2/include )
include_directories( vendor/boost_1.51/include )
include_directories( ${Boost_INCLUDE_DIR} )
include_directories( ${OPENSSL_INCLUDE_DIR} )
include_directories( include )
set( sources
src/logger.cpp
src/console_appender.cpp
src/file_appender.cpp
src/appender.cpp
src/logger_config.cpp
src/ssh.cpp
src/url.cpp
src/process.cpp
src/http_connection.cpp
src/http_server.cpp
src/json_rpc_connection.cpp
src/json_rpc_stream_connection.cpp
src/json_rpc_tcp_connection.cpp
src/json_rpc_tcp_server.cpp
src/json_rpc_error_object.cpp
src/error_report.cpp
src/value.cpp
src/lexical_cast.cpp
src/spin_lock.cpp
src/spin_yield_lock.cpp
src/task.cpp
src/future.cpp
src/shared_ptr.cpp
src/string.cpp
src/json.cpp
src/log.cpp
src/time.cpp
src/iostream.cpp
src/fstream.cpp
src/sstream.cpp
src/exception.cpp
src/thread.cpp
src/hex.cpp
src/sha1.cpp
src/sha256.cpp
src/filesystem.cpp
src/ip.cpp
src/bigint.cpp
src/mutex.cpp
src/pke.cpp
src/base64.cpp
src/base58.cpp
src/blowfish.cpp
src/dh.cpp
src/udp_socket.cpp
src/tcp_socket.cpp
src/asio.cpp
src/super_fast_hash.cpp
src/file_mapping.cpp
src/reflect.cpp
# src/program_options.cpp
SET( ALL_OPENSSL_LIBRARIES
${OPENSSL_LIBRARIES}
${SSL_EAY_RELEASE}
${LIB_EAY_RELEASE}
)
set( fc_sources
src/variant.cpp
src/exception.cpp
src/variant_object.cpp
src/thread/thread.cpp
src/thread/future.cpp
src/thread/task.cpp
src/thread/spin_lock.cpp
src/thread/spin_yield_lock.cpp
src/thread/mutex.cpp
src/asio.cpp
src/string.cpp
src/shared_ptr.cpp
src/time.cpp
src/io/iostream.cpp
src/io/datastream.cpp
src/io/buffered_iostream.cpp
src/io/fstream.cpp
src/io/sstream.cpp
src/io/json.cpp
src/io/varint.cpp
src/filesystem.cpp
src/interprocess/process.cpp
src/interprocess/file_mapping.cpp
src/rpc/json_connection.cpp
src/log/log_message.cpp
src/log/logger.cpp
src/log/appender.cpp
src/log/console_appender.cpp
src/log/file_appender.cpp
src/log/logger_config.cpp
src/crypto/base36.cpp
src/crypto/bigint.cpp
src/crypto/base64.cpp
src/crypto/base58.cpp
src/crypto/hex.cpp
src/crypto/sha1.cpp
src/crypto/sha256.cpp
src/crypto/dh.cpp
src/crypto/blowfish.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/ip.cpp
src/network/resolve.cpp
src/network/url.cpp
# src/ssh/client.cpp
# src/ssh/process.cpp
)
IF( UNIX )
IF( ENABLE_ARM )
SET_PROPERTY( SOURCE
vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S
PROPERTY LANGUAGE C)
SET( boost_context_sources vendor/boost_1.51/libs/context/protected_stack_posix.cpp
vendor/boost_1.51/libs/context/stack_helper_posix.cpp
vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S
)
ELSE()
IF( APPLE )
SET_PROPERTY( SOURCE
vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S
PROPERTY LANGUAGE C)
SET( boost_context_sources vendor/boost_1.51/libs/context/stack_utils_posix.cpp
vendor/boost_1.51/libs/context/stack_allocator_posix.cpp
vendor/boost_1.51/libs/context/fcontext.cpp
vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S
)
ELSE (APPLE)
IF( CMAKE_SIZEOF_VOID_P EQUAL 4 )
SET_PROPERTY( SOURCE
vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S
PROPERTY LANGUAGE C)
SET( fcontext_asm vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S )
ELSE( )
SET( fcontext_asm vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S )
SET_PROPERTY( SOURCE
vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S
PROPERTY LANGUAGE C)
ENDIF( )
SET( boost_context_sources vendor/boost_1.51/libs/context/stack_utils_posix.cpp
vendor/boost_1.51/libs/context/stack_allocator_posix.cpp
vendor/boost_1.51/libs/context/fcontext.cpp
${fcontext_asm}
)
ENDIF(APPLE)
ENDIF()
ENDIF( UNIX )
IF( WIN32 )
ENABLE_LANGUAGE(ASM_MASM)
# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHa" )
SET( boost_context_sources vendor/boost_1.51/libs/context/fcontext.cpp
vendor/boost_1.51/libs/context/seh.cpp
vendor/boost_1.51/libs/context/stack_allocator_windows.cpp
vendor/boost_1.51/libs/context/stack_utils_windows.cpp
vendor/boost_1.51/libs/context/seh.cpp
)
IF( CMAKE_SIZEOF_VOID_P EQUAL 8 )
SET( boost_context_sources ${boost_context_sources}
vendor/boost_1.51/libs/context/asm/fcontext_x86_64_ms_pe_masm.asm )
ELSE() # 32bit
SET( boost_context_sources ${boost_context_sources}
vendor/boost_1.51/libs/context/asm/fcontext_i386_ms_pe_masm.asm )
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO" )
message(STATUS "")
message(STATUS "Note for Visual Studio 2012 projects:")
message(STATUS " Each time CMake regenerates your projects, you will need to:")
message(STATUS " Right-click on the 'fc' project and select 'Build Customizations', and")
message(STATUS " check the 'masm' customization.")
message(STATUS " then, go to the 'Properties' for the fcontext*.asm file, and change its ")
message(STATUS " item type from 'Does not participate in build' to 'Microsoft Macro Assembler'")
ENDIF()
ENDIF(WIN32)
set( sources
${fc_sources}
${boost_context_sources}
)
add_subdirectory(vendor)
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC )
#add_executable( date t.cpp )
#target_link_libraries( date fc ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ${Boost_DATE_TIME_LIBRARY})
setup_library( fc SOURCES ${sources} )
#setup_executable( json_rpc_test SOURCES tests/json_rpc_test.cpp LIBRARIES fc ${ZLIB_LIBRARY} ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ${Boost_DATE_TIME_LIBRARY})
setup_executable( ssh_test SOURCES tests/ssh.cpp LIBRARIES fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ssh2 ${OPENSSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_LIBRARY})
setup_executable( logger_test SOURCES tests/logger.cpp LIBRARIES fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ssh2 ${OPENSSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_LIBRARY})
#add_executable( test_vec tests/vector_test.cpp )
#target_link_libraries( test_vec fc ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} )
#add_executable( unit_tests tests/unit.cpp )
#target_link_libraries( unit_tests fc ${Boost_CHRONO_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} )

123
CMakeModules/FindVLD.cmake Normal file
View file

@ -0,0 +1,123 @@
# 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,25 +0,0 @@
# Fast Compiliing C++ Library
-----------------------------------------
In my prior attempts at developing MACE what I discovered is that compile times
would explode to unreasonable levels that hinder the rate of development more
than what can be saved by reduced typing. So I began a quest to get C++ to compile
as quickly as Java or C# and the result is this library.
One of the major drawbacks to templates is that they place everything in header and
must be compiled with every run and generate a lot of object code. With Link Time Optimization,
the benefit of inline methods mostly disapears, leaving only static vs dynamic polymorphism.
For the vast majority of applications, a virtual method call is not the bottleneck and the
increased compile times costs more than is otherwise justified; therefore, the Fast Compiling C++
library opts for virtual interfaces to handle reflection instead of template interfaces. One could
argue that both types of reflection could be useful.
Another source of slowness was the standard template library itself. Most standard template library
classes cannot be forward declared and import thousands of lines of code into every compilation unit.
Another source of slowness is the need to include headers simply because the 'size' of the object must
be known. A new utility class allows you to 'forward declare' the size required for certain types which
allows you to remove their inclusion from the header file.

View file

@ -1,92 +0,0 @@
#ifndef _FC_ABSTRACT_TYPES_HPP_
#define _FC_ABSTRACT_TYPES_HPP_
#include <fc/utility.hpp>
#include <fc/log.hpp>
namespace fc {
struct abstract_type {
virtual ~abstract_type(){}
virtual size_t size_of()const = 0;
/*
* @brief Inplace destructor (does not free memory) ((T*)dst)->~T();
*/
virtual void destructor( void* dst )const = 0;
/** @brief 'delete T' */
virtual void destroy( void* dst )const = 0;
};
template<typename T>
struct type : virtual abstract_type {
virtual size_t size_of()const { return sizeof(T); }
virtual void destructor( void* dst )const { ((T*)dst)->~T(); }
virtual void destroy( void* dst )const { delete ((T*)dst); }
};
struct abstract_moveable_type : virtual abstract_type {
virtual void move_construct( void* dst, void* src )const = 0;
virtual void move( void* dst, void* src )const = 0;
};
template<typename T>
struct moveable_type : virtual type<T>, virtual abstract_moveable_type {
static abstract_moveable_type& instance() { static moveable_type<T> inst; return inst; }
virtual void destruct( void* dst )const { ((T*)dst)->~T(); }
virtual void move_construct( void* dst, void* src )const { slog( "move construct" ); new ((char*)dst) T( fc::move(*((T*)src)) ); }
virtual void move( void* dst, void* src )const { *((T*)dst) = fc::move(*((T*)src)); }
};
struct abstract_value_type : virtual abstract_moveable_type {
virtual void construct( void* dst )const = 0;
virtual void copy_construct( void* dst, const void* src )const = 0;
virtual void assign( void* dst, const void* src )const = 0;
};
/**
* Default constructable, moveable, copyable, assignable.
*/
template<typename T>
struct value_type : virtual moveable_type<T>, virtual abstract_value_type {
static abstract_value_type& instance() { static value_type<T> inst; return inst; }
virtual void construct( void* dst )const { new ((char*)dst) T(); }
virtual void copy_construct( void* dst, const void* src )const { new ((char*)dst) T( *((const T*)src) ); }
virtual void assign( void* dst, const void* src )const { *((T*)dst) = *((const T*)src); }
};
struct abstract_less_than_comparable_type {
virtual bool less_than( const void* left, const void* right )const = 0;
};
template<typename T>
struct less_than_comparable_type : abstract_less_than_comparable_type {
virtual bool less_than( const void* left, const void* right )const {
return *((const T*)left) < *((const T*)right);
}
};
struct abstract_equal_comparable_type {
virtual bool equal( const void* left, const void* right )const = 0;
};
template<typename T>
struct equal_comparable_type : abstract_equal_comparable_type {
virtual bool equal( const void* left, const void* right )const {
return *((const T*)left) == *((const T*)right);
}
};
struct abstract_callable_type {
virtual void call( const void* self )const = 0;
};
template<typename T>
struct callable_type : virtual abstract_callable_type, virtual value_type<T> {
virtual void call( const void* self )const { (*((const T*)self))(); }
};
} // namespace fc
#endif

View file

@ -1,6 +1,6 @@
#pragma once
#include <fc/ptr.hpp>
#include <fc/thread.hpp>
#include <fc/thread/thread.hpp>
namespace fc {

View file

@ -1,5 +1,4 @@
#ifndef _FC_ALIGNED_HPP_
#define _FC_ALIGNED_HPP_
#pragma once
namespace fc {
template<unsigned int S, typename T=double>
@ -13,4 +12,3 @@ namespace fc {
};
}
#endif // _FC_ALIGNED_HPP_

View file

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

View file

@ -1,5 +1,6 @@
#ifndef _FC_ARRAY_HPP_
#define _FC_ARRAY_HPP_
#pragma once
#include <fc/crypto/base64.hpp>
#include <fc/variant.hpp>
namespace fc {
@ -9,6 +10,27 @@ namespace fc {
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 ); }
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 ); }
#endif // _FC_ARRAY_HPP_
template<typename T, size_t N>
void to_variant( const array<T,N>& bi, variant& v )
{
v = fc::vector<char>( (const char*)&bi, ((const char*)&bi) + sizeof(bi) );
}
template<typename T, size_t N>
void from_variant( const variant& v, array<T,N>& bi )
{
fc::vector<char> ve = v.as< vector<char> >();
if( ve.size() )
{
memcpy(&bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}
else
memset( &bi, char(0), sizeof(bi) );
}
}

View file

@ -5,9 +5,8 @@
#pragma once
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <fc/future.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/combine.hpp>
#include <fc/thread/future.hpp>
#include <fc/io/iostream.hpp>
namespace fc {
/**
@ -53,7 +52,7 @@ namespace 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();
boost::asio::io_service& default_io_service(bool cleanup = false);
/**
* @brief wraps boost::asio::async_read
@ -62,18 +61,6 @@ namespace asio {
*/
template<typename AsyncReadStream, typename MutableBufferSequence>
size_t read( AsyncReadStream& s, const MutableBufferSequence& buf ) {
detail::non_blocking<AsyncReadStream> non_blocking;
// TODO: determine if non_blocking query results in a system call that
// will slow down every read...
if( non_blocking(s) || non_blocking(s,true) ) {
boost::system::error_code ec;
size_t r = boost::asio::read( s, buf, ec );
if( !ec ) return r;
if( ec != boost::asio::error::would_block )
BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
}
promise<size_t>::ptr p(new promise<size_t>("fc::asio::read"));
boost::asio::async_read( s, buf, boost::bind( detail::read_write_handler, p, _1, _2 ) );
return p->wait();
@ -92,39 +79,27 @@ namespace asio {
* @return the number of bytes read.
*/
template<typename AsyncReadStream, typename MutableBufferSequence>
size_t read_some( AsyncReadStream& s, const MutableBufferSequence& buf ) {
detail::non_blocking<AsyncReadStream> non_blocking;
// TODO: determine if non_blocking query results in a system call that
// will slow down every read...
if( non_blocking(s) || non_blocking(s,true) ) {
boost::system::error_code ec;
size_t r = s.read_some( buf, ec );
if( !ec ) return r;
if( ec != boost::asio::error::would_block )
BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
}
promise<size_t>::ptr p(new promise<size_t>("fc::asio::read_some"));
size_t read_some( AsyncReadStream& s, const MutableBufferSequence& buf )
{
promise<size_t>::ptr p(new promise<size_t>("fc::asio::async_read_some"));
s.async_read_some( buf, boost::bind( detail::read_write_handler, p, _1, _2 ) );
return p->wait();
}
template<typename AsyncReadStream>
size_t read_some( AsyncReadStream& s, boost::asio::streambuf& buf )
{
char buffer[1024];
size_t bytes_read = read_some( s, boost::asio::buffer( buffer, sizeof(buffer) ) );
buf.sputn( buffer, bytes_read );
return bytes_read;
}
/** @brief wraps boost::asio::async_write
* @return the number of bytes written
*/
template<typename AsyncWriteStream, typename ConstBufferSequence>
size_t write( AsyncWriteStream& s, const ConstBufferSequence& buf ) {
detail::non_blocking<AsyncWriteStream> non_blocking;
if( non_blocking(s) || non_blocking(s,true) ) {
boost::system::error_code ec;
size_t r = boost::asio::write( s, buf, ec );
if( !ec ) return r;
if( ec != boost::asio::error::would_block) {
BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
}
}
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write"));
boost::asio::async_write(s, buf, boost::bind( detail::read_write_handler, p, _1, _2 ) );
return p->wait();
@ -137,81 +112,11 @@ namespace asio {
*/
template<typename AsyncWriteStream, typename ConstBufferSequence>
size_t write_some( AsyncWriteStream& s, const ConstBufferSequence& buf ) {
detail::non_blocking<AsyncWriteStream> non_blocking;
if( non_blocking(s) || non_blocking(s,true) ) {
boost::system::error_code ec;
size_t r = s.write_some( buf, ec );
if( !ec ) return r;
if( ec != boost::asio::error::would_block) {
BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
}
}
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write_some"));
s.async_write_some( buf, boost::bind( detail::read_write_handler, p, _1, _2 ) );
return p->wait();
}
template<typename AsyncWriteStream>
class sink : public boost::iostreams::sink {
public:
// struct category : boost::iostreams::sink::category {};
typedef char type;
sink( AsyncWriteStream& p ):m_stream(p){}
std::streamsize write( const char* s, std::streamsize n ) {
return fc::asio::write( m_stream, boost::asio::const_buffers_1(s,n) );
}
void close() { m_stream.close(); }
private:
AsyncWriteStream& m_stream;
};
template<typename AsyncReadStream>
class source : public boost::iostreams::source {
public:
// struct category : boost::iostreams::sink::category {};
typedef char type;
source( AsyncReadStream& p ):m_stream(p){}
std::streamsize read( char* s, std::streamsize n ) {
return fc::asio::read_some( m_stream, boost::asio::buffer(s,n) );
}
void close() { m_stream.close(); }
private:
AsyncReadStream& m_stream;
};
template<typename AsyncStream>
class io_device {
public:
typedef boost::iostreams::bidirectional_device_tag category;
typedef char char_type;
io_device( AsyncStream& p ):m_stream(p){}
std::streamsize write( const char* s, std::streamsize n ) {
return fc::asio::write( m_stream, boost::asio::const_buffers_1(s,static_cast<size_t>(n)) );
}
std::streamsize read( char* s, std::streamsize n ) {
try {
return fc::asio::read_some( m_stream, boost::asio::buffer(s,n) );
} catch ( const boost::system::system_error& e ) {
if( e.code() == boost::asio::error::eof )
return -1;
throw;
}
}
void close() { m_stream.close(); }
private:
AsyncStream& m_stream;
};
namespace tcp {
typedef boost::asio::ip::tcp::endpoint endpoint;
typedef boost::asio::ip::tcp::resolver::iterator resolver_iterator;
@ -228,7 +133,6 @@ namespace asio {
promise<boost::system::error_code>::ptr p( new promise<boost::system::error_code>("fc::asio::tcp::accept") );
acc.async_accept( sock, boost::bind( fc::asio::detail::error_handler, p, _1 ) );
auto ec = p->wait();
if( !ec ) sock.non_blocking(true);
if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
}
@ -241,23 +145,53 @@ namespace asio {
promise<boost::system::error_code>::ptr p(new promise<boost::system::error_code>("fc::asio::tcp::connect"));
sock.async_connect( ep, boost::bind( fc::asio::detail::error_handler, p, _1 ) );
auto ec = p->wait();
if( !ec ) sock.non_blocking(true);
if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
}
typedef boost::iostreams::stream<fc::asio::sink<boost::asio::ip::tcp::socket> > ostream;
typedef boost::iostreams::stream<fc::asio::source<boost::asio::ip::tcp::socket> > istream;
typedef boost::iostreams::stream<fc::asio::io_device<boost::asio::ip::tcp::socket> > iostream;
}
namespace udp {
typedef boost::asio::ip::udp::endpoint endpoint;
typedef boost::asio::ip::udp::resolver::iterator resolver_iterator;
typedef boost::asio::ip::udp::resolver resolver;
/// @brief resolve all udp::endpoints for hostname:port
std::vector<endpoint> resolve( resolver& r, const std::string& hostname, const std::string& port );
std::vector<endpoint> resolve( resolver& r, const std::string& hostname,
const std::string& port );
}
template<typename AsyncReadStream>
class istream : public virtual fc::istream
{
public:
istream( std::shared_ptr<AsyncReadStream> str )
:_stream( fc::move(str) ){}
virtual size_t readsome( char* buf, size_t len )
{
auto r = fc::asio::read_some(*_stream, boost::asio::buffer(buf, len) );
return r;
}
private:
std::shared_ptr<AsyncReadStream> _stream;
};
template<typename AsyncWriteStream>
class ostream : public virtual fc::ostream
{
public:
ostream( std::shared_ptr<AsyncWriteStream> str )
:_stream( fc::move(str) ){}
virtual size_t writesome( const char* buf, size_t len )
{
return fc::asio::write_some(*_stream, boost::asio::const_buffers_1(buf, len) );
}
virtual void close(){ _stream->close(); }
virtual void flush() {}
private:
std::shared_ptr<AsyncWriteStream> _stream;
};
} } // namespace fc::asio

View file

@ -1,42 +0,0 @@
#ifndef _FC_BIGINT_HPP
#define _FC_BIGINT_HPP
#include <stdint.h>
#include <fc/string.hpp>
struct bignum_st;
typedef bignum_st BIGNUM;
namespace fc {
class bigint {
public:
bigint( const char* bige, uint32_t l );
bigint( unsigned long i = 0 );
bigint( const bigint& c );
bigint( bigint&& c );
~bigint();
bool is_negative()const;
int64_t to_int64()const;
int64_t log2()const;
bool operator < ( const bigint& c )const;
bool operator > ( const bigint& c )const;
bool operator >= ( const bigint& c )const;
bool operator == ( const bigint& c )const;
bigint operator + ( const bigint& a )const;
bigint operator * ( const bigint& a )const;
bigint operator / ( const bigint& a )const;
bigint operator - ( const bigint& a )const;
bigint& operator = ( const bigint& a );
bigint& operator = ( bigint&& a );
operator fc::string()const;
private:
BIGNUM* n;
};
} // namespace fc
#endif

View file

@ -1,21 +0,0 @@
#ifndef _FC_BUFFER_HPP_
#define _FC_BUFFER_HPP_
namespace fc {
struct const_buffer {
const_buffer( const char* const c = 0, size_t l = 0 )
:data(c),size(l){}
const char* const data;
size_t size;
};
struct mutable_buffer {
mutable_buffer( char* c = 0, size_t l = 0 )
:data(c),size(l){}
char* data;
size_t size;
};
}
#endif // _FC_BUFFER_HPP_

View file

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

View file

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

View file

@ -0,0 +1,8 @@
#pragma once
#include <string>
namespace fc {
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
std::string base64_encode( const std::string& enc );
std::string base64_decode( const std::string& encoded_string);
} // namespace fc

View file

@ -0,0 +1,70 @@
#pragma once
#include <stdint.h>
#include <fc/string.hpp>
#include <fc/vector.hpp>
struct bignum_st;
typedef bignum_st BIGNUM;
namespace fc {
class bigint {
public:
bigint( const fc::vector<char>& bige );
bigint( const char* bige, uint32_t l );
bigint( unsigned long i = 0 );
bigint( const bigint& c );
bigint( bigint&& c );
explicit bigint( BIGNUM* n );
~bigint();
bigint& operator = ( const bigint& a );
bigint& operator = ( bigint&& a );
operator bool()const;
bool is_negative()const;
int64_t to_int64()const;
int64_t log2()const;
bigint exp( const bigint& c )const;
static bigint random( uint32_t bits, int t, int );
bool operator < ( const bigint& c )const;
bool operator > ( const bigint& c )const;
bool operator >= ( const bigint& c )const;
bool operator == ( const bigint& c )const;
bool operator != ( const bigint& c )const;
bigint operator + ( const bigint& a )const;
bigint operator * ( const bigint& a )const;
bigint operator / ( const bigint& a )const;
bigint operator % ( const bigint& a )const;
bigint operator /= ( const bigint& a );
bigint operator - ( const bigint& a )const;
bigint operator++(int);
bigint& operator++();
bigint operator--(int);
bigint& operator--();
operator fc::string()const;
// returns bignum as bigendian bytes
operator fc::vector<char>()const;
BIGNUM* dup()const;
BIGNUM* get()const { return n; }
private:
BIGNUM* n;
};
class variant;
/** encodes the big int as base64 string, or a number */
void to_variant( const bigint& bi, variant& v );
/** decodes the big int as base64 string, or a number */
void from_variant( const variant& v, bigint& bi );
} // namespace fc

View file

@ -120,8 +120,7 @@ E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA
*/
#ifndef __FC_BLOWFISH_HPP__
#define __FC_BLOWFISH_HPP__
#pragma once
#include <stdint.h>
namespace fc {
@ -150,12 +149,12 @@ public:
void reset_chain() { m_oChain = m_oChain0; }
// encrypt/decrypt Buffer in Place
void encrypt(unsigned char* buf, uint64_t n, int iMode=ECB);
void decrypt(unsigned char* buf, uint64_t n, int iMode=ECB);
void encrypt(unsigned char* buf, uint64_t n, int iMode=CBC);
void decrypt(unsigned char* buf, uint64_t n, int iMode=CBC);
// encrypt/decrypt from Input Buffer to Output Buffer
void encrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=ECB);
void decrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=ECB);
void encrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=CBC);
void decrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=CBC);
//Private Functions
private:
@ -176,5 +175,4 @@ private:
} // namespace fc
#endif // __BLOWFISH_H__

View file

@ -1,7 +1,5 @@
#ifndef _FC_DH_HPP_
#define _FC_DH_HPP_
//#include <fc/vector.hpp>
#include <vector>
#pragma once
#include <fc/vector.hpp>
#include <stdint.h>
namespace fc {
@ -11,13 +9,13 @@ namespace fc {
bool generate_params( int s, uint8_t g );
bool generate_pub_key();
bool compute_shared_key( const char* buf, uint32_t s );
bool compute_shared_key( const std::vector<char>& pubk);
bool compute_shared_key( const vector<char>& pubk);
bool validate();
std::vector<char> p;
std::vector<char> pub_key;
std::vector<char> priv_key;
std::vector<char> shared_key;
vector<char> p;
vector<char> pub_key;
vector<char> priv_key;
vector<char> shared_key;
bool valid;
uint8_t g;
};
@ -25,4 +23,3 @@ namespace fc {
} // namespace fc
#endif

View file

@ -0,0 +1,61 @@
#pragma once
#include <fc/crypto/bigint.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
#include <fc/fwd.hpp>
#include <fc/array.hpp>
namespace fc { namespace ecc {
namespace detail
{
class public_key_impl;
class private_key_impl;
}
typedef fc::array<char,72> signature;
typedef fc::array<unsigned char,65> compact_signature;
class public_key
{
public:
public_key();
~public_key();
bool verify( const fc::sha256& digest, const signature& sig );
std::vector<char> serialize();
public_key( const std::vector<char>& v );
public_key( const compact_signature& c, const fc::sha256& digest );
private:
friend class private_key;
fc::fwd<detail::public_key_impl,8> my;
};
class private_key
{
public:
private_key();
private_key( std::vector<char> k );
~private_key();
static private_key generate();
static private_key regenerate( const fc::sha256& secret );
fc::sha256 get_secret()const; // get the private key secret
/**
* Given a public key, calculatse a 512 bit shared secret between that
* key and this private key.
*/
fc::sha512 get_shared_secret( const public_key& pub );
signature sign( const fc::sha256& digest );
compact_signature sign_compact( const fc::sha256& digest );
bool verify( const fc::sha256& digest, const signature& sig );
public_key get_public_key()const;
private:
fc::fwd<detail::private_key_impl,8> my;
};
} } // fc::ecc

113
include/fc/crypto/pke.hpp Normal file
View file

@ -0,0 +1,113 @@
#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)
{
bytes ser;
fc::raw::unpack(s,ser);
pk = fc::public_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::public_key& pk)
{
fc::raw::pack( s, pk.serialize() );
}
template<typename Stream>
void unpack( Stream& s, fc::private_key& pk)
{
bytes ser;
fc::raw::unpack(s,ser);
pk = fc::private_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::private_key& pk)
{
fc::raw::pack( s, pk.serialize() );
}
}
class variant;
void to_variant( const public_key& bi, variant& v );
void from_variant( const variant& v, public_key& bi );
void to_variant( const private_key& bi, variant& v );
void from_variant( const variant& v, private_key& bi );
} // fc

View file

@ -0,0 +1,67 @@
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
namespace fc{
class sha1
{
public:
sha1();
explicit sha1( const string& hex_str );
string str()const;
operator string()const;
char* data()const;
static sha1 hash( const char* d, uint32_t dlen );
static sha1 hash( const string& );
template<typename T>
static sha1 hash( const T& t )
{
sha1::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();
sha1 result();
private:
struct impl;
fc::fwd<impl,96> my;
};
template<typename T>
inline friend T& operator<<( T& ds, const sha1& ep ) {
ds.write( ep.data(), sizeof(ep) );
return ds;
}
template<typename T>
inline friend T& operator>>( T& ds, sha1& ep ) {
ds.read( ep.data(), sizeof(ep) );
return ds;
}
friend sha1 operator << ( const sha1& h1, uint32_t i );
friend bool operator == ( const sha1& h1, const sha1& h2 );
friend bool operator != ( const sha1& h1, const sha1& h2 );
friend sha1 operator ^ ( const sha1& h1, const sha1& h2 );
friend bool operator >= ( const sha1& h1, const sha1& h2 );
friend bool operator > ( const sha1& h1, const sha1& h2 );
friend bool operator < ( const sha1& h1, const sha1& h2 );
uint32_t _hash[5];
};
} // namespace fc

View file

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

View file

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

View file

@ -1,36 +0,0 @@
#pragma once
#include <fc/string.hpp>
namespace fc {
struct future_wait_timeout: public std::exception{
future_wait_timeout( const fc::string& msg = "" ):m_msg(msg){}
~future_wait_timeout()throw() {}
const char* what()const throw() { return m_msg.c_str(); }
private:
fc::string m_msg;
};
struct task_canceled: public std::exception{};
struct thread_quit: public std::exception{};
struct wait_any_error: public std::exception{};
struct pke_exception : public std::exception {};
struct invalid_buffer_length : public pke_exception {};
struct invalid_key_length : public pke_exception {};
struct generic_exception : public std::exception {
generic_exception( const fc::string& msg = "" ):m_msg(msg){}
~generic_exception()throw() {}
const char* what()const throw() { return m_msg.c_str(); }
private:
fc::string m_msg;
};
struct bad_cast: public std::exception{
const char* what()const throw(){ return "bad cast"; }
};
struct range_error: public std::exception{
const char* what()const throw(){ return "range error"; }
};
}

View file

@ -1,76 +0,0 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
#include <fc/value.hpp>
#include <fc/optional.hpp>
#include <fc/exception.hpp>
namespace fc {
/**
* Represents one stack frame within an error_report.
*/
class error_frame {
public:
error_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value m );
error_frame( bool detail, const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value m );
error_frame():file("unknown-file"),line(0){}
error_frame(const error_frame& );
error_frame(error_frame&& );
error_frame& operator=(const error_frame& );
error_frame& operator=(error_frame&& );
fc::string to_string()const;
fc::string to_detail_string()const;
fc::string desc;
fc::string file;
int64_t line;
fc::string method;
fc::optional<fc::value> meta;
fc::string time;
bool detail;
};
typedef fc::vector<error_frame> error_context;
/**
* This class is used for rich error reporting that captures relevant errors the
* whole way up the stack. By using FC_THROW_REPORT(...) and FC_REPORT_PUSH( e, ...)
* you can capture the file, line, and method where the error was caught / rethrown.
*/
class error_report {
public:
error_report();
error_report( const fc::string& desc, fc::value meta = fc::value() );
error_report( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta = fc::value() );
error_frame& current();
error_report& pop_frame();
error_report& push_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta = fc::value() );
error_report& push_frame( bool detail, const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta = fc::value() );
error_report& append( const error_report& e );
fc::string to_string()const;
fc::string to_detail_string()const;
error_context stack; ///< Human readable stack of what we were atempting to do.
fc::exception_ptr copy_exception();
};
fc::string substitute( const fc::string& format, const fc::value& keys );
fc::value recursive_substitute( const value& in, const fc::value& keys );
} // namespace fc
#include <fc/reflect.hpp>
FC_REFLECT( fc::error_frame, (desc)(file)(line)(method)(time)(meta)(detail) )
FC_REFLECT( fc::error_report, (stack) )
#define FC_IDENT(...) __VA_ARGS__
#define FC_REPORT( X, ... ) fc::error_report X( __FILE__, __LINE__, __func__, __VA_ARGS__ )
#define FC_THROW_REPORT( ... ) FC_THROW( fc::error_report( __FILE__, __LINE__, __func__, __VA_ARGS__ ))
#define FC_REPORT_CURRENT(ER, ... ) (ER).pop_frame().push_frame( __FILE__, __LINE__, __func__, __VA_ARGS__ )
#define FC_REPORT_PUSH( ER, ... ) (ER).push_frame( __FILE__, __LINE__, __func__, __VA_ARGS__ );
#define FC_REPORT_PUSH_DETAIL( ER, ... ) (ER).push_frame( true, __FILE__, __LINE__, __func__, __VA_ARGS__ )
#define FC_REPORT_POP(ER) (ER).pop_frame()

View file

@ -1,12 +0,0 @@
#ifndef _EXAMPLE_HPP_
#define _EXAMPLE_HPP_
#include <fc/reflect_fwd.hpp>
struct example {
int a;
int b;
};
FC_REFLECTABLE( example )
#endif // _EXAMPLE_HPP_

View file

@ -1,107 +0,0 @@
#ifndef _FC_EXCEPTION_HPP_
#define _FC_EXCEPTION_HPP_
#include <fc/shared_ptr.hpp>
#include <fc/string.hpp>
#include <boost/current_function.hpp>
// TODO: Remove boost exception dependency here!!
// TODO: Remove boost format dependency here!!
// provided for easy integration with boost.
namespace boost { class exception_ptr; }
namespace fc {
/**
* Simply including boost/exception_ptr.hpp is enough to significantly
* lengthen compile times. This header defines an 'opaque' exception
* type that provides the most 'general' exception handling needs without
* requiring a significant amount of code to be included.
*/
class exception_ptr {
public:
exception_ptr();
exception_ptr( const boost::exception_ptr& c );
exception_ptr( boost::exception_ptr&& c );
exception_ptr( const exception_ptr& c );
exception_ptr( exception_ptr&& c );
~exception_ptr();
exception_ptr& operator=(const boost::exception_ptr& c);
exception_ptr& operator=(boost::exception_ptr&& c);
exception_ptr& operator=(const exception_ptr& c);
exception_ptr& operator=(exception_ptr&& c);
fc::string diagnostic_information()const;
operator bool()const;
operator const boost::exception_ptr& ()const;
operator boost::exception_ptr& ();
private:
char my[sizeof(void*)*2];
};
exception_ptr current_exception();
template<typename T>
inline exception_ptr copy_exception( T&& e ) {
try { throw e; } catch (...) { return current_exception(); }
return exception_ptr();
}
void rethrow_exception( const exception_ptr& e );
void throw_exception( const char* func, const char* file, int line, const char* msg );
void throw_exception_( const char* func, const char* file, int line, const char* msg,
const fc::string& a1 );
void throw_exception_( const char* func, const char* file, int line, const char* msg,
const fc::string& a1, const fc::string& a2 );
void throw_exception_( const char* func, const char* file, int line, const char* msg,
const fc::string& a1, const fc::string& a2, const fc::string& a3 );
void throw_exception_( const char* func, const char* file, int line, const char* msg,
const fc::string& a1, const fc::string& a2, const fc::string& a3, const fc::string& a4 );
template<typename T>
fc::string to_string( T&& v ) { return fc::string(fc::forward<T>(v)); }
fc::string to_string( char v ); // { return fc::string(&v,1); }
fc::string to_string( uint64_t v );
fc::string to_string( int64_t v );
fc::string to_string( double v );
fc::string to_string( float v );
fc::string to_string( int8_t v );
fc::string to_string( uint8_t v );
fc::string to_string( int32_t v );
fc::string to_string( uint32_t v );
fc::string to_string( int16_t v );
fc::string to_string( uint16_t v );
// fc::string to_string( size_t v );
// fc::string to_string( long int v );
template<typename T>
void throw_exception( const char* func, const char* file, int line, const char* msg, T&& a1 ) {
throw_exception_( func, file, line, msg, to_string(fc::forward<T>(a1) ) );
}
template<typename T1, typename T2>
void throw_exception( const char* func, const char* file, int line, const char* msg, T1&& a1, T2&& a2 ) {
throw_exception_( func, file, line, msg, to_string(fc::forward<T1>(a1) ), to_string( fc::forward<T2>(a2) ) );
}
template<typename T1, typename T2, typename T3>
void throw_exception( const char* func, const char* file, int line, const char* msg, T1&& a1, T2&& a2, T3&& a3 ) {
throw_exception_( func, file, line, msg, to_string(fc::forward<T1>(a1) ), to_string( fc::forward<T2>(a2) ), to_string( fc::forward<T3>(a3) ) );
}
template<typename T1, typename T2, typename T3, typename T4>
void throw_exception( const char* func, const char* file, int line, const char* msg, T1&& a1, T2&& a2, T3&& a3, T4&& a4 ) {
throw_exception_( func, file, line, msg, to_string(fc::forward<T1>(a1) ), to_string( fc::forward<T2>(a2) ), to_string( fc::forward<T3>(a3) ), to_string( fc::forward<T4>(a4) ) );
}
fc::string except_str();
} // namespace fc
#define FC_THROW(X) throw X
#define FC_THROW_MSG( ... ) \
do { \
fc::throw_exception( BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, __VA_ARGS__ ); \
} while(0)
#endif // _FC_EXCEPTION_HPP_

View file

@ -0,0 +1,238 @@
#pragma once
/**
* @file exception.hpp
* @brief Defines exception's used by fc
*/
#include <fc/log/log_message.hpp>
#include <fc/optional.hpp>
#include <exception>
namespace fc
{
namespace detail { class exception_impl; }
/**
* @brief Used to generate a useful error report when an exception is thrown.
* @ingroup serializable
*
* At each level in the stack where the exception is caught and rethrown a
* new log_message is added to the exception.
*
* exception's are designed to be serialized to a variant and
* deserialized from an variant.
*
* @see FC_THROW_EXCEPTION
* @see FC_RETHROW_EXCEPTION
* @see FC_RETHROW_EXCEPTIONS
*/
class exception
{
public:
exception();
exception( log_message&& );
exception( const exception& e );
exception( exception&& e );
~exception();
virtual const char* what()const throw() { return "exception"; }
/**
* @return a reference to log messages that have
* been added to this log.
*/
const log_messages& get_log()const;
void append_log( log_message m );
/**
* Generates a detailed string including file, line, method,
* and other information that is generally only useful for
* developers.
*/
string to_detail_string( log_level ll = log_level::all )const;
/**
* Generates a user-friendly error report.
*/
string to_string( log_level ll = log_level::info )const;
/**
* Throw this exception as its most derived type.
*
* @note does not return.
*/
virtual NO_RETURN void dynamic_rethrow_exception()const;
/**
* This is equivalent to:
* @code
* try { throwAsDynamic_exception(); }
* catch( ... ) { return std::current_exception(); }
* @endcode
*/
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
protected:
friend void to_variant( const exception& e, variant& v );
friend void from_variant( const variant& e, exception& ll );
virtual void from_variant( const variant& ){}
virtual void to_variant( variant& ){}
std::unique_ptr<detail::exception_impl> my;
};
void to_variant( const exception& e, variant& v );
void from_variant( const variant& e, exception& ll );
typedef std::shared_ptr<exception> exception_ptr;
typedef optional<exception> oexception;
/**
* @brief re-thrown whenever an unhandled exception is caught.
* @ingroup serializable
* Any exceptions thrown by 3rd party libraries that are not
* caught get wrapped in an unhandled_exception exception.
*
* The original exception is captured as a std::exception_ptr
* which may be rethrown. The std::exception_ptr does not
* propgate across process boundaries.
*/
class unhandled_exception : public exception
{
public:
unhandled_exception( log_message&& m, std::exception_ptr e = std::current_exception() );
unhandled_exception( log_messages );
unhandled_exception( const exception& );
virtual const char* what()const throw() { return "Unhandled _exception"; }
std::exception_ptr get_inner_exception()const;
virtual NO_RETURN void dynamic_rethrow_exception()const;
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
private:
std::exception_ptr _inner;
};
template<typename T>
fc::exception_ptr copy_exception( T&& e )
{
#if defined(_MSC_VER) && (_MSC_VER < 1700)
return std::make_shared<unhandled_exception>( log_message(), std::copy_exception(fc::forward<T>(e)) );
#else
return std::make_shared<unhandled_exception>( log_message(), std::make_exception_ptr(fc::forward<T>(e)) );
#endif
}
/**
* @brief wraps unhanlded std::exception's
* @ingroup serializable
*
* This exception allows the 'what' field of unhandled std::exceptions
* to be propagated across process boundaries.
*/
class std_exception : public unhandled_exception
{
public:
std_exception( log_message&& m, std::exception_ptr e, const char* w );
std_exception( log_messages );
std_exception( const exception& c);
virtual const char* what()const throw() { return _what.c_str(); }
protected:
void from_variant( const variant& v );
void to_variant( variant& v );
private:
string _what;
};
#define FC_DECLARE_EXCEPTION( TYPE, WHAT ) \
class TYPE : public exception \
{ \
public: \
TYPE( log_message&& m ); \
TYPE( log_messages ); \
TYPE( const TYPE& c ); \
TYPE(); \
virtual const char* what()const throw() { return WHAT; } \
};
FC_DECLARE_EXCEPTION( timeout_exception, "Timeout" );
FC_DECLARE_EXCEPTION( file_not_found_exception, "File Not Found" );
/**
* @brief report's parse errors
*/
FC_DECLARE_EXCEPTION( parse_error_exception, "Parse Error" );
FC_DECLARE_EXCEPTION( invalid_arg_exception, "Invalid Argument" );
/**
* @brief reports when a key, guid, or other item is not found.
*/
FC_DECLARE_EXCEPTION( key_not_found_exception, "Key Not Found" );
FC_DECLARE_EXCEPTION( bad_cast_exception, "Bad Cast" );
FC_DECLARE_EXCEPTION( out_of_range_exception, "Out of Range" );
/** @brief if an operation is unsupported or not valid this may be thrown */
FC_DECLARE_EXCEPTION( invalidOperation_exception, "Invalid Operation" );
/**
* @brief used to report a canceled Operation
*/
FC_DECLARE_EXCEPTION( canceled_exception, "Canceled" );
/**
* @brief used inplace of assert() to report violations of pre conditions.
*/
FC_DECLARE_EXCEPTION( assert_exception, "Assert Exception" );
FC_DECLARE_EXCEPTION( eof_exception, "End Of File" );
fc::string except_str();
} // namespace fc
/**
* @brief Checks a condition and throws an assert_exception if the test is FALSE
*/
#define FC_ASSERT( TEST, ... ) \
if( !(TEST) ) { FC_THROW_EXCEPTION( assert_exception, #TEST __VA_ARGS__ ); }
#define FC_THROW( FORMAT, ... ) \
throw fc::exception( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
#define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \
fc::EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
/**
* @def FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... )
* @param EXCEPTION a class in the Phoenix::Athena::API namespace that inherits
* @param format - a const char* string with "${keys}"
*/
#define FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... ) \
throw fc::EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
/**
* @def FC_RETHROW_EXCEPTION(ER,LOG_LEVEL,FORMAT,...)
* @brief Appends a log_message to the exception ER and rethrows it.
*/
#define FC_RETHROW_EXCEPTION( ER, LOG_LEVEL, FORMAT, ... ) \
do { \
er.append_log( FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, __VA_ARGS__ ) ); \
throw;\
} while(false)
/**
* @def FC_RETHROW_EXCEPTIONS(LOG_LEVEL,FORMAT,...)
* @brief Catchs all exception's, std::exceptions, and ... and rethrows them after
* appending the provided log message.
*/
#define FC_RETHROW_EXCEPTIONS( LOG_LEVEL, FORMAT, ... ) \
catch( fc::exception& er ) { \
FC_RETHROW_EXCEPTION( er, LOG_LEVEL, FORMAT, __VA_ARGS__ ); \
} catch( const std::exception& e ) { \
throw fc::std_exception( \
FC_LOG_MESSAGE( LOG_LEVEL, FORMAT,__VA_ARGS__), \
std::current_exception(), \
e.what() ) ; \
} catch( ... ) { \
throw fc::unhandled_exception( \
FC_LOG_MESSAGE( LOG_LEVEL, FORMAT,__VA_ARGS__), \
std::current_exception() ); \
}

View file

@ -1,6 +1,8 @@
#pragma once
#include <utility>
#include <fc/string.hpp>
#include <fc/typename.hpp>
#include <fc/reflect/typename.hpp>
#include <fc/optional.hpp>
#include <fc/fwd.hpp>
namespace boost {
@ -60,6 +62,9 @@ namespace fc {
bool is_relative()const;
bool is_absolute()const;
static char separator_char;
private:
fwd<boost::filesystem::path,32> _p;
};
@ -104,20 +109,64 @@ namespace fc {
void create_directories( const path& p );
void remove_all( const path& p );
path absolute( const path& p );
path make_relative(const path& from, const path& to);
path canonical( const path& p );
uint64_t file_size( const path& p );
bool remove( const path& p );
void copy( const path& from, const path& to );
void rename( const path& from, const path& to );
void create_hard_link( const path& from, const path& to );
path unique_path();
path temp_directory_path();
class value;
void pack( fc::value& , const fc::path& );
void unpack( const fc::value& , fc::path& );
class variant;
void to_variant( const fc::path&, fc::variant& );
void from_variant( const fc::variant& , fc::path& );
template<> struct get_typename<path> { static const char* name() { return "path"; } };
/**
* Class which creates a temporary directory inside an existing temporary directory.
*/
class temp_file_base
{
public:
inline ~temp_file_base() { remove(); }
inline operator bool() const { return _path; }
inline bool operator!() const { return !_path; }
const fc::path& path() const;
void remove();
void release();
protected:
typedef fc::optional<fc::path> path_t;
inline temp_file_base(const path_t& path) : _path(path) {}
inline temp_file_base(path_t&& path) : _path(std::move(path)) {}
path_t _path;
};
/**
* Class which creates a temporary directory inside an existing temporary directory.
*/
class temp_file : public temp_file_base
{
public:
temp_file(temp_file&& other);
temp_file& operator=(temp_file&& other);
temp_file(const fc::path& tempFolder = fc::temp_directory_path(), bool create = false);
};
/**
* Class which creates a temporary directory inside an existing temporary directory.
*/
class temp_directory : public temp_file_base
{
public:
temp_directory(temp_directory&& other);
temp_directory& operator=(temp_directory&& other);
temp_directory(const fc::path& tempFolder = fc::temp_directory_path());
};
}

View file

@ -1,112 +0,0 @@
#if 0
#pragma once
#include <fc/utility.hpp>
#include <fc/shared_ptr.hpp>
namespace fc {
template<typename R,typename ... Args>
class function {
public:
function(){}
template<typename Functor>
function( Functor&& f )
:func( new impl<Functor>( fc::forward<Functor>(f) ) ){};
function( const function& c ):func(c.func){}
function( function&& c ) { fc::swap( func, c.func); }
~function(){}
template<typename Functor>
function& operator=( Functor&& f ) {
func.reset( new impl<Functor>( fc::forward<Functor>(f) ) );
return *this;
}
function& operator=( const function& c ) { func = c.func; return *this; }
function& operator=( function&& c ) { fc::swap(func,c.func); return *this; }
R operator()( Args... args)const { return func->call(args...); }
bool operator!()const { return !func; }
protected:
struct impl_base : public fc::retainable {
virtual ~impl_base(){}
virtual R call(Args...)const = 0;
};
template<typename Functor>
struct impl : impl_base {
template<typename U>
impl( U&& u ):func( fc::forward<U>(u) ){}
virtual R call(Args... args)const { return func(args...); }
Functor func;
};
function( const fc::shared_ptr<impl_base>& f ):func(f){}
function( fc::shared_ptr<impl_base>&& f ):func(fc::move(f)){}
fc::shared_ptr<impl_base> func;
};
/**
* Provides functionality similar to boost::function.
*
* Functions have 'reference semantics', meaning that copies will all
* refer to the same underlying function.
*
* TODO: Small functions are allocated on the stack, large functors are
* allocated on the heap.
*
* Simply including boost/function adds an additional 0.6 seconds to every
* object file compared to using fc/function.
*
* Including <functional> on the other hand adds a mere 0.05
* seconds to every object file compared to fc/function.
*/
template<typename R>
class function<R()> : public function<R> {
public:
function(){}
template<typename U>
function( U&& u ) { *this = fc::forward<U>(u); }
using function<R>::operator=;
};
template<typename R,typename A1>
class function<R(A1)> : public function<R,A1> {
public:
function(){}
function( const function<R,A1>& u ):function<R,A1>(u){}
function( function<R,A1>&& u ):function<R,A1>(u){}
function( const function& u ):function<R,A1>(u.func){}
function( function&& u ):function<R,A1>(fc::move(u.func)){}
using function<R,A1>::operator=;
};
template<typename R,typename A1,typename A2>
class function<R(A1,A2)> : public function<R,A1,A2> {
public:
function(){}
template<typename U>
function( U&& u ):function<R,A1,A2>( fc::forward<U>(u) ){}
function( const function& c ):function<R,A1,A2>(c.func){}
using function<R,A1,A2>::operator=;
};
template<typename R,typename A1,typename A2, typename A3>
class function<R(A1,A2,A3)> : public function<R,A1,A2,A3> {
public:
function(){}
template<typename U>
function( U&& u ):function<R,A1,A2,A3>( fc::forward<U>(u) ){}
function( const function& c ):function<R,A1,A2,A3>(c.func){}
using function<R,A1,A2,A3>::operator=;
};
}
#endif

View file

@ -1,5 +1,4 @@
#ifndef _FC_FWD_IMPL_HPP_
#define _FC_FWD_IMPL_HPP_
#pragma once
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
@ -134,4 +133,3 @@ namespace fc {
} // namespace fc
#endif //_FC_FWD_IMPL_HPP_

View file

@ -1,21 +0,0 @@
#ifndef _FC_FWD_REFLECT_HPP_
#define _FC_FWD_REFLECT_HPP_
#include <fc/reflect.hpp>
#include <fc/fwd.hpp>
namespace fc {
template<typename T,unsigned int S>
class reflector<fwd<T,S>> : public detail::reflector_impl<fwd<T,S>, reflector<fwd<T,S>> >{
public:
virtual const char* name()const { return instance().name(); }
virtual void visit( void* s, const abstract_visitor& v )const {
instance().visit(s,v);
}
virtual void visit( const void* s, const abstract_const_visitor& v )const {
instance().visit(s,v);
}
static reflector<T>& instance() { return reflector<T>::instance(); }
};
} // namespace fc
#endif //_FC_FWD_REFLECT_HPP_

View file

@ -1,64 +0,0 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
#include <fc/shared_impl.hpp>
namespace fc {
namespace ip { class endpoint; }
class tcp_socket;
namespace http {
struct header {
header( fc::string k, fc::string v )
:key(fc::move(k)),val(fc::move(v)){}
header(){}
fc::string key;
fc::string val;
};
struct reply {
enum status_code {
OK = 200,
RecordCreated = 201,
NotFound = 404,
Found = 302,
InternalServerError = 500
};
reply( status_code c = OK):status(c){}
int status;
fc::vector<header> headers;
fc::vector<char> body;
};
struct request {
fc::string get_header( const fc::string& key )const;
fc::string method;
fc::string domain;
fc::string path;
fc::vector<header> headers;
fc::vector<char> body;
};
fc::vector<header> parse_urlencoded_params( const fc::string& f );
/**
* Connections have reference semantics, all copies refer to the same
* underlying socket.
*/
class connection {
public:
// 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 );
// used for servers
fc::tcp_socket& get_socket()const;
http::request read_request()const;
FC_REFERENCE_TYPE(connection)
};
} } // fc::http

View file

@ -25,7 +25,7 @@ namespace fc {
};
class mapped_region {
public:
mapped_region( const file_mapping& fm, mode_t m, size_t start, size_t size );
mapped_region( const file_mapping& fm, mode_t m, uint64_t start, size_t size );
mapped_region( const file_mapping& fm, mode_t m );
~mapped_region();
void flush();

View file

@ -0,0 +1,66 @@
#pragma once
#include <fc/thread/future.hpp>
#include <fc/io/buffered_iostream.hpp>
#include <fc/vector.hpp>
#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,
};
virtual ~iprocess(){}
/**
*
* @return *this
*/
virtual iprocess& exec( const fc::path& exe, vector<string> args,
const fc::path& work_dir = fc::path(), exec_opts opts = open_all ) = 0;
/**
* @return blocks until the process exits
*/
virtual int result() = 0;
/**
* Forcefully kills the process.
*/
virtual void kill() = 0;
/**
* @brief returns a stream that writes to the process' stdin
*/
virtual fc::buffered_ostream_ptr in_stream() = 0;
/**
* @brief returns a stream that reads from the process' stdout
*/
virtual fc::buffered_istream_ptr out_stream() = 0;
/**
* @brief returns a stream that reads from the process' stderr
*/
virtual fc::buffered_istream_ptr err_stream() = 0;
};
typedef std::shared_ptr<iprocess> iprocess_ptr;
} // namespace fc

View file

@ -0,0 +1,36 @@
#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,
vector<string> args,
const fc::path& work_dir = fc::path(),
exec_opts opts = open_all );
virtual int result();
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

View file

@ -1,17 +0,0 @@
#ifndef _FC_INVOKEABLE_HPP_
#define _FC_INVOKEABLE_HPP_
namespace fc {
class invokeable {
public:
virtual ~invokeable(){};
virtual void invoke( const promise::ptr& prom, const string& name, size_t num_params, reflect::cref* params );
void invoke( const std::string& name ) { invoke( promise::ptr(), name, 0, 0 ); }
};
}
#endif // _FC_INVOKEABLE_HPP_

13
include/fc/io/base16.hpp Normal file
View file

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

8
include/fc/io/base58.hpp Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#include <fc/string.hpp>
namespace fc {
fc::string to_base58( const char* d, size_t s );
fc::vector<char> from_base58( const fc::string& base58_str );
size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_data_len );
}

View file

@ -0,0 +1,71 @@
#pragma once
#include <fc/io/iostream.hpp>
namespace fc
{
namespace detail
{
class buffered_istream_impl;
class buffered_ostream_impl;
}
/**
* @brief Reads data from an unbuffered stream
* and enables peek functionality.
*/
class buffered_istream : public virtual istream
{
public:
buffered_istream( istream_ptr is );
buffered_istream( buffered_istream&& o );
buffered_istream& operator=( buffered_istream&& i );
virtual ~buffered_istream();
/** read at least 1 byte or throw, if no data is available
* this method should block cooperatively until data is
* available or fc::eof_exception is thrown.
*
* @pre len > 0
* @pre buf != nullptr
* @throws fc::eof if at least 1 byte cannot be read
**/
virtual std::size_t readsome( char* buf, std::size_t len );
/**
* This method may block until at least 1 character is
* available.
*/
char peek()const;
private:
std::unique_ptr<detail::buffered_istream_impl> my;
};
typedef std::shared_ptr<buffered_istream> buffered_istream_ptr;
/**
*
*/
class buffered_ostream : public virtual ostream
{
public:
buffered_ostream( ostream_ptr o, size_t bufsize = 4096 );
buffered_ostream( buffered_ostream&& m );
~buffered_ostream();
buffered_ostream& operator=( buffered_ostream&& m );
/**
* This method will return immediately unless the buffer
* is full, in which case it will flush which may block.
*/
virtual size_t writesome( const char* buf, size_t len );
virtual void close();
virtual void flush();
private:
std::unique_ptr<detail::buffered_ostream_impl> my;
};
typedef std::shared_ptr<buffered_ostream> buffered_ostream_ptr;
}

View file

@ -0,0 +1,182 @@
#pragma once
#include <fc/utility.hpp>
#include <string.h>
#include <stdint.h>
namespace fc {
namespace detail
{
NO_RETURN void throw_datastream_range_error( const char* file, size_t len, size_t over );
}
/**
* 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( "read", _end-_start, int64_t(-((_end-_pos) - 1)));
}
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( "write", _end-_start, int64_t(-((_end-_pos) - 1)));
}
inline bool put(char c) {
if( _pos < _end ) {
*_pos = c;
++_pos;
return true;
}
detail::throw_datastream_range_error( "put", _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( "get", _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* ,size_t s ) { _size += s; return true; }
inline bool put(char ) { ++_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

View file

@ -1,6 +1,5 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/error_report.hpp>
#include <string.h>
#include <stdint.h>
@ -14,96 +13,78 @@ namespace fc {
* actually packing it after doing a single allocation.
*/
template<typename T>
struct datastream {
class datastream {
public:
datastream( T start, size_t s )
:m_start(start),m_pos(start),m_end(start+s){};
:_start(start),_pos(start),_end(start+s){};
inline void skip( size_t s ){ m_pos += s; }
inline void skip( size_t s ){ _pos += s; }
inline bool read( char* d, size_t s ) {
if( size_t(m_end - m_pos) >= (size_t)s ) {
memcpy( d, m_pos, s );
m_pos += s;
if( size_t(_end - _pos) >= (size_t)s ) {
memcpy( d, _pos, s );
_pos += s;
return true;
}
FC_THROW_REPORT( "Attempt to read ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ",
fc::value("bytes_past",int64_t(-((m_end-m_pos) - s)))
("buffer_size", int64_t(m_end-m_start)) );
detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1)))
return false;
}
inline bool write( const char* d, size_t s ) {
if( m_end - m_pos >= (int32_t)s ) {
memcpy( m_pos, d, s );
m_pos += s;
if( _end - _pos >= (int32_t)s ) {
memcpy( _pos, d, s );
_pos += s;
return true;
}
FC_THROW_REPORT( "Attempt to write ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ",
fc::value("bytes_past",int64_t(-((m_end-m_pos) - s)))
("buffer_size", int64_t(m_end-m_start)) );
detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1)))
return false;
}
inline bool put(char c) {
if( m_pos < m_end ) {
*m_pos = c;
++m_pos;
if( _pos < _end ) {
*_pos = c;
++_pos;
return true;
}
FC_THROW_REPORT( "Attempt to write ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ",
fc::value("bytes_past",int64_t(-((m_end-m_pos) - 1)))
("buffer_size", int64_t(m_end-m_start)) );
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( m_pos < m_end ) {
c = *m_pos;
++m_pos;
if( _pos < _end ) {
c = *_pos;
++_pos;
return true;
}
FC_THROW_REPORT( "Attempt to read ${bytes_past} bytes beyond end of buffer of size ${buffer_size} ",
fc::value("bytes_past",int64_t(-((m_end-m_pos) - 1)))
("buffer_size", int64_t(m_end-m_start)) );
detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1)))
}
T pos()const { return m_pos; }
inline bool valid()const { return m_pos <= m_end && m_pos >= m_start; }
inline bool seekp(size_t p) { m_pos = m_start + p; return m_pos <= m_end; }
inline size_t tellp()const { return m_pos - m_start; }
inline size_t remaining()const { return m_end - m_pos; }
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 m_start;
T m_pos;
T m_end;
T _start;
T _pos;
T _end;
};
template<>
struct datastream<size_t> {
datastream( size_t init_size = 0):m_size(init_size){};
inline bool skip( size_t s ) { m_size += s; return true; }
inline bool write( const char* d,size_t s ) { m_size += s; return true; }
inline bool put(char c) { ++m_size; return true; }
inline bool valid()const { return true; }
inline bool seekp(size_t p) { m_size = p; return true; }
inline size_t tellp()const { return m_size; }
inline size_t remaining()const { return 0; }
private:
size_t m_size;
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 size_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return *this;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, size_t& d) {
ds.read((char*)&d, sizeof(d) );
return *this;
}
*/
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int32_t& d) {
ds.write( (const char*)&d, sizeof(d) );

View file

@ -1,7 +1,7 @@
#pragma once
#include <fc/shared_ptr.hpp>
#include <fc/filesystem.hpp>
#include <fc/iostream.hpp>
#include <fc/io/iostream.hpp>
namespace fc {
class path;
@ -13,7 +13,7 @@ namespace fc {
~ofstream();
void open( const fc::path& file, int m = binary );
ofstream& write( const char* buf, size_t len );
size_t writesome( const char* buf, size_t len );
void put( char c );
void close();
void flush();

View file

@ -0,0 +1,81 @@
#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;
};
}

View file

@ -0,0 +1,98 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/string.hpp>
#include <memory>
namespace fc {
/**
* Provides a fc::thread friendly cooperatively multi-tasked stream that
* will block 'cooperatively' instead of hard blocking.
*/
class istream
{
public:
virtual ~istream(){};
/** read at least 1 byte or throw, if no data is available
* this method should block cooperatively until data is
* available or fc::eof is thrown.
*
* @throws fc::eof if at least 1 byte cannot be read
**/
virtual size_t readsome( char* buf, size_t len ) = 0;
/** read len bytes or throw, this method is implemented
* in terms of readsome.
*
* @throws fc::eof_exception if len bytes cannot be read
**/
istream& read( char* buf, size_t len );
char get();
};
typedef std::shared_ptr<istream> istream_ptr;
/**
* Provides a fc::thread friendly cooperatively multi-tasked stream that
* will block 'cooperatively' instead of hard blocking.
*/
class ostream
{
public:
virtual ~ostream(){};
virtual size_t writesome( const char* buf, size_t len ) = 0;
virtual void close() = 0;
virtual void flush() = 0;
void put( char c ) { write(&c,1); }
/** implemented in terms of writesome, guarantees len bytes are sent
* but not flushed.
**/
ostream& write( const char* buf, size_t len );
};
typedef std::shared_ptr<ostream> ostream_ptr;
class iostream : public virtual ostream, public virtual istream {};
fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' );
template<size_t N>
ostream& operator<<( ostream& o, char (&array)[N] )
{
return o.write( array, N );
}
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 double& v );
ostream& operator<<( ostream& o, const float& v );
ostream& operator<<( ostream& o, const int64_t& v );
ostream& operator<<( ostream& o, const uint64_t& v );
ostream& operator<<( ostream& o, const int32_t& v );
ostream& operator<<( ostream& o, const uint32_t& v );
ostream& operator<<( ostream& o, const int16_t& v );
ostream& operator<<( ostream& o, const uint16_t& v );
ostream& operator<<( ostream& o, const int8_t& v );
ostream& operator<<( ostream& o, const uint8_t& v );
#ifndef _MSC_VER
ostream& operator<<( ostream& o, const size_t& v );
#endif
istream& operator>>( istream& o, std::string& v );
istream& operator>>( istream& o, fc::string& v );
istream& operator>>( istream& o, char& v );
istream& operator>>( istream& o, double& v );
istream& operator>>( istream& o, float& v );
istream& operator>>( istream& o, int64_t& v );
istream& operator>>( istream& o, uint64_t& v );
istream& operator>>( istream& o, int32_t& v );
istream& operator>>( istream& o, uint32_t& v );
istream& operator>>( istream& o, int16_t& v );
istream& operator>>( istream& o, uint16_t& v );
istream& operator>>( istream& o, int8_t& v );
istream& operator>>( istream& o, uint8_t& v );
}

56
include/fc/io/json.hpp Normal file
View file

@ -0,0 +1,56 @@
#pragma once
#include <fc/variant.hpp>
namespace fc
{
class path;
class ostream;
class buffered_istream;
/**
* Provides interface for json serialization.
*
* json strings are always UTF8
*/
class json
{
public:
static ostream& to_stream( ostream& out, const fc::string& );
static ostream& to_stream( ostream& out, const variant& v );
static ostream& to_stream( ostream& out, const variants& v );
static ostream& to_stream( ostream& out, const variant_object& v );
static variant from_stream( buffered_istream& in );
static variant from_string( const string& utf8_str );
static string to_string( const variant& v );
static string to_pretty_string( const variant& v );
static void save_to_file( const variant& v, const string& fi, bool pretty = true );
static variant from_file( const fc::path& p );
template<typename T>
static T from_file( const fc::path& p )
{
return json::from_file(p).as<T>();
}
template<typename T>
static string to_string( const T& v )
{
return to_string( variant(v) );
}
template<typename T>
static string to_pretty_string( const T& v )
{
return to_pretty_string( variant(v) );
}
template<typename T>
static void save_to_file( const T& v, const string& p, bool pretty = true )
{
save_to_file( variant(v), p, pretty );
}
};
} // fc

View file

@ -1,52 +1,55 @@
#pragma once
#include <fc/reflect.hpp>
#include <fc/datastream.hpp>
#include <fc/varint.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/io/datastream.hpp>
#include <fc/io/varint.hpp>
#include <fc/optional.hpp>
#include <fc/vector.hpp>
#include <fc/fwd.hpp>
#include <fc/array.hpp>
#include <fc/time.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/variant_object.hpp>
#include <fc/variant.hpp>
#include <fc/exception/exception.hpp>
#include <fc/log/logger.hpp>
namespace fc {
class value;
namespace raw {
template<typename Stream>
inline void pack( Stream& s, const variant_object& v );
template<typename Stream>
inline void unpack( Stream& s, variant_object& v );
template<typename Stream, typename T>
void unpack( Stream& s, fc::optional<T>& v );
template<typename Stream, typename T>
void pack( Stream& s, const fc::optional<T>& v );
template<typename Stream>
inline void pack( Stream& s, const variant& v );
template<typename Stream>
inline void unpack( Stream& s, variant& v );
template<typename Stream>
void unpack( Stream& s, fc::value& );
template<typename Stream>
void pack( Stream& s, const fc::value& );
inline void pack( Stream& s, const fc::time_point& tp )
{
uint64_t usec = tp.time_since_epoch().count();
s.write( (const char*)&usec, sizeof(usec) );
}
template<typename Stream>
void unpack( Stream& s, fc::string& );
template<typename Stream>
void pack( Stream& s, const fc::string& );
template<typename Stream, typename T>
inline void pack( Stream& s, const T& v );
template<typename Stream, typename T>
inline void unpack( Stream& s, T& v );
template<typename Stream, typename T>
inline void pack( Stream& s, const fc::vector<T>& v );
template<typename Stream, typename T>
inline void unpack( Stream& s, fc::vector<T>& v );
inline void unpack( Stream& s, fc::time_point& tp )
{
uint64_t usec;
s.read( (char*)&usec, sizeof(usec) );
tp = fc::time_point() + fc::microseconds(usec);
}
template<typename Stream, typename T, size_t N>
inline void pack( Stream& s, const fc::array<T,N>& v) {
s.write((const char*)&v.data[0],N*sizeof(T));
}
template<typename Stream, typename T, size_t N>
inline void unpack( Stream& s, fc::array<T,N>& v) {
s.read((char*)&v.data[0],N*sizeof(T));
}
template<typename Stream> inline void pack( Stream& s, const signed_int& v ) {
uint32_t val = (v.value<<1) ^ (v.value>>31);
do {
@ -239,12 +242,152 @@ namespace fc {
fc::raw::detail::if_reflected< typename fc::reflector<T>::is_defined >::unpack(s,v);
}
template<typename Stream>
class variant_packer : public variant::visitor
{
public:
variant_packer( Stream& _s ):s(_s){}
virtual void handle()const { }
virtual void handle( const int64_t& v )const
{
fc::raw::pack( s, v );
}
virtual void handle( const uint64_t& v )const
{
fc::raw::pack( s, v );
}
virtual void handle( const double& v )const
{
fc::raw::pack( s, v );
}
virtual void handle( const bool& v )const
{
fc::raw::pack( s, v );
}
virtual void handle( const string& v )const
{
fc::raw::pack( s, v );
}
virtual void handle( const variant_object& v)const
{
fc::raw::pack( s, v );
}
virtual void handle( const variants& v)const
{
fc::raw::pack( s, v );
}
Stream& s;
};
template<typename Stream>
inline void pack( Stream& s, const variant& v )
{
pack( s, uint8_t(v.get_type()) );
v.visit( variant_packer<Stream>(s) );
}
template<typename Stream>
inline void unpack( Stream& s, variant& v )
{
uint8_t t;
unpack( s, t );
switch( t )
{
case variant::null_type:
return;
case variant::int64_type:
{
int64_t val;
raw::unpack(s,val);
v = val;
return;
}
case variant::uint64_type:
{
uint64_t val;
raw::unpack(s,val);
v = val;
return;
}
case variant::double_type:
{
double val;
raw::unpack(s,val);
v = val;
return;
}
case variant::bool_type:
{
bool val;
raw::unpack(s,val);
v = val;
return;
}
case variant::string_type:
{
fc::string val;
raw::unpack(s,val);
v = fc::move(val);
return;
}
case variant::array_type:
{
variants val;
raw::unpack(s,val);
v = fc::move(val);
return;
}
case variant::object_type:
{
variant_object val;
raw::unpack(s,val);
v = fc::move(val);
return;
}
default:
FC_THROW_EXCEPTION( parse_error_exception, "Unknown Variant Type ${t}", ("t", t) );
}
}
template<typename Stream>
inline void pack( Stream& s, const variant_object& v )
{
unsigned_int vs = v.size();
pack( s, vs );
for( auto itr = v.begin(); itr != v.end(); ++itr )
{
pack( s, itr->key() );
pack( s, itr->value() );
}
wlog( "------------ done pack -------------" );
}
template<typename Stream>
inline void unpack( Stream& s, variant_object& v )
{
unsigned_int vs;
unpack( s, vs );
mutable_variant_object mvo;
mvo.reserve(vs.value);
for( auto i = 0; i < vs.value; ++i )
{
fc::string key;
fc::variant value;
fc::raw::unpack(s,key);
fc::raw::unpack(s,value);
mvo.set( fc::move(key), fc::move(value) );
}
v = fc::move(mvo);
}
template<typename T>
inline fc::vector<char> pack( const T& v ) {
datastream<size_t> ps;
raw::pack(ps,v );
fc::vector<char> vec(ps.tellp());
if( vec.size() ) {
datastream<char*> ds( vec.data(), size_t(vec.size()) );
raw::pack(ds,v);
@ -275,6 +418,12 @@ namespace fc {
raw::unpack(ds,v);
return v;
}
template<typename T>
inline void unpack( const char* d, uint32_t s, T& v ) {
datastream<const char*> ds( d, s );
raw::unpack(ds,v);
return v;
}
} } // namespace fc::raw

38
include/fc/io/raw_fwd.hpp Normal file
View file

@ -0,0 +1,38 @@
#pragma once
#include <fc/io/varint.hpp>
#include <fc/array.hpp>
namespace fc { namespace raw {
template<typename Stream, typename T> void unpack( Stream& s, fc::optional<T>& v );
template<typename Stream, typename T> void pack( Stream& s, const fc::optional<T>& v );
template<typename Stream> void unpack( Stream& s, fc::string& );
template<typename Stream> void pack( Stream& s, const fc::string& );
template<typename Stream, typename T> inline void pack( Stream& s, const T& v );
template<typename Stream, typename T> inline void unpack( Stream& s, T& v );
template<typename Stream, typename T> inline void pack( Stream& s, const fc::vector<T>& v );
template<typename Stream, typename T> inline void unpack( Stream& s, fc::vector<T>& v );
template<typename Stream> inline void pack( Stream& s, const signed_int& v );
template<typename Stream> inline void unpack( Stream& s, signed_int& vi );
template<typename Stream> inline void pack( Stream& s, const unsigned_int& v );
template<typename Stream> inline void unpack( Stream& s, unsigned_int& vi );
template<typename Stream> inline void pack( Stream& s, const char* v );
template<typename Stream> inline void pack( Stream& s, const fc::vector<char>& value );
template<typename Stream> inline void unpack( Stream& s, fc::vector<char>& value );
template<typename Stream, typename T, size_t N> inline void pack( Stream& s, const fc::array<T,N>& v);
template<typename Stream, typename T, size_t N> inline void unpack( Stream& s, fc::array<T,N>& v);
template<typename Stream> inline void pack( Stream& s, const bool& v );
template<typename Stream> inline void unpack( Stream& s, bool& v );
template<typename T> inline fc::vector<char> pack( const T& v );
template<typename T> inline T unpack( const fc::vector<char>& s );
template<typename T> inline T unpack( const char* d, uint32_t s );
template<typename T> inline void unpack( const char* d, uint32_t s, T& v );
} }

View file

@ -0,0 +1,24 @@
#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) );
}
}
}

31
include/fc/io/sstream.hpp Normal file
View file

@ -0,0 +1,31 @@
#pragma once
#include <fc/io/iostream.hpp>
#include <fc/fwd.hpp>
namespace fc {
class stringstream : virtual public iostream {
public:
stringstream();
stringstream( fc::string& s);
stringstream( const fc::string& s);
~stringstream();
fc::string str();
void str(const fc::string& s);
void clear();
virtual bool eof()const;
virtual size_t writesome( const char* buf, size_t len );
virtual size_t readsome( char* buf, size_t len );
virtual void close();
virtual void flush();
char peek();
private:
class impl;
fwd<impl,368> my;
};
}

36
include/fc/io/stdio.hpp Normal file
View file

@ -0,0 +1,36 @@
#pragma once
#include <fc/io/iostream.hpp>
namespace fc
{
class cout_t : virtual public ostream {
public:
virtual size_t writesome( const char* buf, size_t len );
virtual void close();
virtual void flush();
};
class cerr_t : virtual public ostream {
public:
virtual size_t writesome( const char* buf, size_t len );
virtual void close();
virtual void flush();
};
class cin_t : virtual public istream {
public:
~cin_t();
virtual size_t readsome( char* buf, size_t len );
virtual istream& read( char* buf, size_t len );
virtual bool eof()const;
};
extern cout_t& cout;
extern cerr_t& cerr;
extern cin_t& cin;
extern std::shared_ptr<cin_t> cin_ptr;
extern std::shared_ptr<cout_t> cout_ptr;
extern std::shared_ptr<cerr_t> cerr_ptr;
}

View file

@ -1,5 +1,4 @@
#ifndef _FC_VARINT_HPP_
#define _FC_VARINT_HPP_
#pragma once
#include <stdint.h>
namespace fc {
@ -24,7 +23,13 @@ struct signed_int {
int32_t value;
};
class variant;
void to_variant( const signed_int& var, variant& vo );
void from_variant( const variant& var, signed_int& vo );
void to_variant( const unsigned_int& var, variant& vo );
void from_variant( const variant& var, unsigned_int& vo );
} // namespace fc
#endif

View file

@ -1,80 +0,0 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/lexical_cast.hpp>
#include <fc/string.hpp>
namespace fc {
class istream {
public:
virtual ~istream(){};
virtual size_t readsome( char* buf, size_t len ) = 0;
virtual istream& read( char* buf, size_t len ) = 0;
virtual bool eof()const = 0;
};
class ostream {
public:
virtual ~ostream(){};
virtual ostream& write( const char* buf, size_t len ) = 0;
virtual void close(){}
virtual void flush(){}
};
class iostream : public virtual ostream, public virtual istream {};
struct cout_t : virtual public ostream {
virtual ostream& write( const char* buf, size_t len );
virtual void close();
virtual void flush();
virtual ostream& write( const fc::string& );
};
struct cerr_t : virtual public ostream {
virtual ostream& write( const char* buf, size_t len );
virtual void close();
virtual void flush();
virtual ostream& write( const fc::string& );
};
struct cin_t : virtual public istream {
~cin_t();
virtual size_t readsome( char* buf, size_t len );
virtual istream& read( char* buf, size_t len );
virtual bool eof()const;
};
fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' );
extern cout_t cout;
extern cerr_t cerr;
extern cin_t cin;
template<typename T>
ostream& operator<<( ostream& o, const T& v ) {
auto str = fc::lexical_cast<fc::string>(v);
o.write( str.c_str(), static_cast<size_t>(str.size()) );
return o;
}
ostream& operator<<( ostream& o, const char* v );
template<typename T>
ostream& operator<<( ostream& o, const fc::string& str ) {
o.write( str.c_str(), static_cast<size_t>(str.size()) );
return o;
}
template<typename T>
istream& operator>>( istream& o, T& v ) {
fc::string str;
getline( o, str, ' ' );
v = fc::lexical_cast<T>(str);
return o;
}
}

View file

@ -1,118 +0,0 @@
#pragma once
#include <fc/iostream.hpp>
#include <fc/shared_ptr.hpp>
#include <fc/log.hpp>
namespace fc {
/**
* Used to wrap references to other streams
*/
class ostream_wrapper : public ostream {
public:
template<typename Stream>
ostream_wrapper( Stream& s )
:my( new impl<Stream>(s) ){}
virtual ~ostream_wrapper(){};
virtual ostream& write( const char* buf, size_t len ) {
my->write(buf,len);
return *this;
}
virtual void close() {
// TODO: move to cpp
my->close();
}
virtual void flush() {
my->flush();
}
protected:
virtual ostream& write( const fc::string& s ) {
return write( s.c_str(), s.size() );
}
struct impl_base : public fc::retainable {
virtual ~impl_base(){}
virtual void write( const char* buf, size_t len ) = 0;
virtual void close() = 0;
virtual void flush() = 0;
};
template<typename T>
struct impl : public impl_base {
impl(T& i):st(i){}
virtual void write( const char* buf, size_t len ) {
st.write(buf,len);
}
virtual void close() { st.close(); }
virtual void flush() { st.flush(); }
T& st;
};
fc::shared_ptr<impl_base> my;
};
/**
* Used to wrap references to other streams
*/
class istream_wrapper : public istream {
public:
template<typename Stream>
istream_wrapper( Stream& s )
:my( new impl<Stream>(s) ){}
virtual ~istream_wrapper(){};
virtual size_t readsome( char* buf, size_t len ) {
return my->readsome(buf,len);
}
virtual istream& read( char* buf, size_t len ) {
// slog( "%p %lld", my.get(), len );
my->read(buf,len);
return *this;
}
virtual void close() { }
virtual bool eof()const{ return my->eof(); }
/*
virtual istream& read( int64_t& ) { return *this; }
virtual istream& read( uint64_t& ) { return *this; }
virtual istream& read( int32_t& ) { return *this; }
virtual istream& read( uint32_t& ) { return *this; }
virtual istream& read( int16_t& ) { return *this; }
virtual istream& read( uint16_t& ) { return *this; }
virtual istream& read( int8_t& ) { return *this; }
virtual istream& read( uint8_t& ) { return *this; }
virtual istream& read( float& ) { return *this; }
virtual istream& read( double& ) { return *this; }
virtual istream& read( bool& ) { return *this; }
virtual istream& read( char& ) { return *this; }
virtual istream& read( fc::string& ) { return *this; }
*/
protected:
struct impl_base : public fc::retainable {
virtual ~impl_base(){}
virtual void read( char* buf, size_t len )=0;
virtual size_t readsome( char* buf, size_t len )=0;
virtual bool eof()const=0;
};
template<typename T>
struct impl : public impl_base {
impl(T& i):st(i){}
virtual size_t readsome( char* buf, size_t len ) { return size_t(st.readsome(buf,len)); }
virtual void read( char* buf, size_t len ) {
st.read(buf,len);
}
virtual bool eof()const { return st.eof() || !st.good(); }
T& st;
};
fc::shared_ptr<impl_base> my;
};
} // namespace fc

View file

@ -1,54 +0,0 @@
#pragma once
#include <fc/string.hpp>
#include <fc/value.hpp>
#include <fc/value_cast.hpp>
#include <fc/vector_fwd.hpp>
namespace fc {
class istream;
class ostream;
class path;
namespace json {
string to_string( const value& o );
string to_pretty_string( const value& v );
value from_string( const string& s );
value from_string( const char* s, const char* e );
value from_string( const fc::vector<char>& v );
string escape_string( const string& );
string unescape_string( const string& );
void write( ostream& out, const value& val );
template<typename T>
void write( ostream& out, const T& val ) {
write( out, value(val) );
}
template<typename T>
string to_string( const T& o ) {
return json::to_string(value(o));
}
template<typename T>
string to_pretty_string( const T& o ) {
return json::to_pretty_string(value(o));
}
template<typename T>
T from_string( const string& s ) {
return value_cast<T>( from_string(s) );
}
value from_file( const fc::path& s );
template<typename T>
T from_file( const fc::path& s ) {
return value_cast<T>( fc::json::from_file(s) );
}
} // namespace json
} // fc

View file

@ -1,74 +0,0 @@
#pragma once
#include <fc/actor.hpp>
#include <fc/json_rpc_connection.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
namespace fc { namespace json {
namespace detail {
struct rpc_member {
#ifdef 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, R (C::*mem_func)(BOOST_PP_ENUM_PARAMS(n,A)) IS_CONST, \
const rpc_connection::ptr& c = rpc_connection::ptr(), const char* name = nullptr ) { \
return [=](BOOST_PP_ENUM_BINARY_PARAMS(n,A,a))->fc::future<R>{ \
return c->invoke<R>( name, make_tuple(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
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 rpc_connection::ptr& c = rpc_connection::ptr(), const char* name = nullptr ) {
return [=](Args... args)->fc::future<R>{
return c->invoke<R>( name, make_tuple(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,
const rpc_connection::ptr& c = rpc_connection::ptr(), const char* name = nullptr ) {
return [=](Args... args)->fc::future<R>{
return c->invoke<R>( name, make_tuple(args...) ); };
}
#endif
};
struct vtable_visitor {
vtable_visitor( rpc_connection::ptr& c ):_con(c){}
template<typename Function, typename MemberPtr>
void operator()( const char* name, Function& memb, MemberPtr m )const {
memb = rpc_member::functor( nullptr, m, _con, name );
}
rpc_connection::ptr& _con;
};
};
template<typename InterfaceType>
class rpc_client : public actor<InterfaceType> { //ptr<InterfaceType,fc::json::detail::rpc_member> {
public:
rpc_client(){}
rpc_client( const rpc_connection::ptr& c ){ set_connection(c); }
//rpc_client( const rpc_client& c ):_con(c._con){}
void set_connection( const rpc_connection::ptr& c ) {
_con = c;
this->_vtable.reset(new fc::detail::vtable<InterfaceType,fc::detail::actor_member>() );
this->_vtable->template visit_other<InterfaceType>( fc::json::detail::vtable_visitor(_con) );
}
const rpc_connection::ptr& connection()const { return _con; }
private:
rpc_connection::ptr _con;
};
} } // fc::json

View file

@ -1,196 +0,0 @@
#pragma once
#include <fc/json_rpc_error_object.hpp>
#include <fc/json.hpp>
#include <fc/future.hpp>
#include <fc/function.hpp>
#include <fc/ptr.hpp>
namespace fc { namespace json {
class rpc_connection;
class error_object;
struct rpc_server_method : public fc::retainable {
typedef fc::shared_ptr<rpc_server_method> ptr;
virtual value call( const value& v ) = 0;
};
namespace detail {
struct pending_result : virtual public promise_base {
typedef shared_ptr<pending_result> ptr;
virtual void handle_result( const fc::value& ) = 0;
void handle_error( const fc::string& );
int64_t id;
pending_result::ptr next;
protected:
~pending_result(){}
};
template<typename T>
struct pending_result_impl : virtual public promise<T>, virtual public pending_result {
virtual void handle_result( const fc::value& s ) {
this->set_value( value_cast<T>(s) );
}
protected:
~pending_result_impl(){}
};
template<>
struct pending_result_impl<void> : virtual public promise<void>, virtual public pending_result {
virtual void handle_result( const fc::value& ) {
set_value();
}
protected:
~pending_result_impl(){}
};
template<typename T>
struct named_param {
typedef fc::false_type type;
static T cast( const value& v ) { return fc::value_cast<T>(v); }
template<typename X>
static value to_value( X&& x ) { return value(fc::forward<X>(x)); }
};
#define FC_JSON_NAMED_PARAMS( T ) \
namespace fc { namespace json {namespace detail { \
template<> \
struct named_param< fc::tuple<T> > { \
typedef fc::true_type type; \
static tuple<T> cast( const value& v ) { return make_tuple(fc::value_cast<T>(v)); } \
template<typename X> \
static value to_value( X&& x ) { return value( x.a0 ); }\
}; \
} } }
template<typename R, typename ArgsTuple, typename Signature>
struct rpc_server_method_impl : public rpc_server_method {
rpc_server_method_impl( const std::function<Signature>& f ):func(f){}
virtual value call( const value& v ) {
return value( fc::call_fused(func, named_param<typename deduce<ArgsTuple>::type>::cast(v) ) );
}
std::function<Signature> func;
};
template<typename ArgsTuple, typename Signature>
struct rpc_server_method_impl<void,ArgsTuple,Signature> : public rpc_server_method {
rpc_server_method_impl( const std::function<Signature>& f ):func(f){}
virtual value call( const value& v ) {
fc::call_fused(func, named_param<typename deduce<ArgsTuple>::type>::cast(v) );
return value();
}
std::function<Signature> func;
};
template<typename InterfaceType>
struct add_method_visitor {
public:
add_method_visitor( const fc::ptr<InterfaceType>& p, fc::json::rpc_connection& c ):_ptr(p),_con(c){}
template<typename R>
void operator()( const char* name, std::function<R()>& meth);
template<typename R, typename A1>
void operator()( const char* name, std::function<R(A1)>& meth);
template<typename R, typename A1, typename A2>
void operator()( const char* name, std::function<R(A1,A2)>& meth);
template<typename R, typename A1, typename A2, typename A3>
void operator()( const char* name, std::function<R(A1,A2,A3)>& meth);
const fc::ptr<InterfaceType>& _ptr;
fc::json::rpc_connection& _con;
};
}
/**
* This is the base JSON RPC connection that handles the protocol
* level issues. It does not implement a transport which should
* be provided separately and use the handle_message and set_send_delegate
* methods to manage the protocol.
*/
class rpc_connection : public fc::retainable {
public:
rpc_connection();
rpc_connection(const rpc_connection&);
rpc_connection(rpc_connection&&);
~rpc_connection();
rpc_connection& operator=(const rpc_connection&);
rpc_connection& operator=(rpc_connection&&);
typedef fc::shared_ptr<rpc_connection> ptr;
void cancel_pending_requests();
template<typename R, typename Args >
future<R> invoke( const fc::string& method, Args&& a = nullptr ){
auto r = new detail::pending_result_impl<R>();
typename promise<R>::ptr rtn( r, true );
invoke( detail::pending_result::ptr(r), method,
value(detail::named_param<typename fc::deduce<Args>::type>::to_value(a)) );
return rtn;
}
template<typename Args >
void notice( const fc::string& method, Args&& a = nullptr ){
send_notice( method,
value(detail::named_param<typename fc::deduce<Args>::type>::to_value(a)) );
}
template<typename InterfaceType>
void add_interface( const fc::ptr<InterfaceType>& it ) {
it->TEMPLATE visit( detail::add_method_visitor<InterfaceType>( it, *this ) );
}
void add_method( const fc::string& name, const fc::json::rpc_server_method::ptr& func );
virtual void close(){};
protected:
void handle_message( const value& m );
virtual void send_notice( const fc::string& m, value&& param ) = 0;
virtual void send_invoke( uint64_t id, const fc::string& m, value&& param ) = 0;
virtual void send_error( uint64_t id, const error_object& e ) = 0;
virtual void send_result( uint64_t id, value&& r ) = 0;
private:
void invoke( detail::pending_result::ptr&& p, const fc::string& m, value&& param );
void add_method( const fc::string& name, rpc_server_method::ptr&& m );
template<typename InterfaceType>
friend struct detail::add_method_visitor;
class impl;
fc::shared_ptr<class impl> my;
};
namespace detail {
template<typename InterfaceType>
template<typename R, typename A1>
void add_method_visitor<InterfaceType>::operator()( const char* name,
std::function<R(A1)>& meth) {
_con.add_method( name, rpc_server_method::ptr(
new rpc_server_method_impl<R,tuple<A1>,R(A1) >(meth) ) );
}
template<typename InterfaceType>
template<typename R, typename A1, typename A2>
void add_method_visitor<InterfaceType>::operator()( const char* name,
std::function<R(A1,A2)>& meth) {
_con.add_method( name, rpc_server_method::ptr(
new rpc_server_method_impl<R,tuple<A1,A2>,R(A1,A2) >(meth) ) );
}
template<typename InterfaceType>
template<typename R, typename A1, typename A2, typename A3>
void add_method_visitor<InterfaceType>::operator()( const char* name,
std::function<R(A1,A2,A3)>& meth) {
_con.add_method( name, rpc_server_method::ptr(
new rpc_server_method_impl<R,tuple<A1,A2,A3>,R(A1,A2,A3) >(meth) ) );
}
template<typename InterfaceType>
template<typename R>
void add_method_visitor<InterfaceType>::operator()( const char* name,
std::function<R()>& meth) {
_con.add_method( name, rpc_server_method::ptr(
new rpc_server_method_impl<R,tuple<>,R() >(meth) ) );
}
} // namespace detail
} } // fc::json

View file

@ -1,27 +0,0 @@
#pragma once
#include <fc/string.hpp>
#include <fc/optional.hpp>
#include <fc/value.hpp>
#include <fc/reflect.hpp>
namespace fc {
class value;
namespace json {
class error_object {
public:
error_object( const fc::string& msg, const fc::value& v , int64_t c = -32000);
error_object( const fc::string& msg=fc::string(), int64_t c = -32000 );
error_object( const error_object& e );
~error_object();
int64_t code;
fc::string message;
fc::optional<fc::value> data;
};
} }
FC_REFLECT( fc::json::error_object, (code)(message)(data) )

View file

@ -1,54 +0,0 @@
#pragma once
#include <fc/json_rpc_client.hpp>
#include <fc/json_rpc_stream_connection.hpp>
#include <fc/process.hpp>
#include <fc/filesystem.hpp>
namespace fc { namespace json {
template<typename InterfaceType>
class rpc_process_client : public ptr<InterfaceType,fc::json::detail::rpc_member> {
public:
fc::future<int> exec( const fc::path& exe, int opt = fc::process::open_all ) {
return exec( exe, fc::path("."), opt );
}
fc::future<int> exec( const fc::path& exe, const fc::path& wd,
int opt = fc::process::open_all ) {
return exec( exe, fc::vector<fc::string>(), wd, opt );
}
fc::future<int> exec( const fc::path& exe, fc::vector<fc::string>&& args ,
int opt = fc::process::open_all ) {
return exec( exe, fc::move(args), fc::path("."), opt );
}
fc::future<int> exec( const fc::path& exe, fc::vector<fc::string>&& args,
const fc::path& wd, int opt = fc::process::open_all ) {
auto r = _proc.exec( canonical(exe), fc::move(args), wd, opt );
_con.reset( new fc::json::rpc_stream_connection( _proc.out_stream(), _proc.in_stream() ) );
this->_vtable.reset(new fc::detail::vtable<InterfaceType,fc::json::detail::rpc_member>() );
rpc_connection::ptr p(_con);
this->_vtable->template visit_other<InterfaceType>( fc::json::detail::vtable_visitor(p) );
return r;
}
void kill() { _con->close(); _proc.kill(); }
/**
* @brief returns a stream that reads from the process' stderr
*/
fc::istream& err_stream() { return _proc.err_stream(); }
template<typename T>
void on_close( T&& f) { _con->on_close( fc::forward<T>(f) ); }
const fc::json::rpc_stream_connection::ptr& connection()const { return _con; }
~rpc_process_client() {
if(_con)
_con->close();
}
private:
fc::process _proc;
fc::json::rpc_stream_connection::ptr _con;
};
} }

View file

@ -1,33 +0,0 @@
#pragma once
#include <fc/json_rpc_client.hpp>
#include <fc/json_rpc_stream_connection.hpp>
#include <fc/ssh/process.hpp>
namespace fc { namespace json {
template<typename InterfaceType>
class rpc_ssh_process_client : public rpc_client<InterfaceType> {
public:
rpc_ssh_process_client(){}
bool valid()const { return proc.valid(); }
rpc_ssh_process_client( const fc::ssh::process& proc )
:rpc_client<InterfaceType>(rpc_connection::ptr(new fc::json::rpc_stream_connection( proc.out_stream(), proc.in_stream() ) ) ){}
rpc_ssh_process_client& operator = ( const fc::ssh::process& proc ) {
this->set_connection( rpc_connection::ptr(new fc::json::rpc_stream_connection( proc.out_stream(), proc.in_stream() ) ) );
return *this;
}
/**
* @brief returns a stream that reads from the process' stderr
*/
fc::istream& err_stream() { return proc.err_stream(); }
fc::ssh::process& get_ssh_process() { return proc; }
private:
fc::ssh::process proc;
fc::json::rpc_stream_connection::ptr _con;
};
} }

View file

@ -1,40 +0,0 @@
#pragma once
#include <fc/json_rpc_connection.hpp>
namespace fc {
class istream;
class ostream;
namespace json {
class rpc_stream_connection : public rpc_connection {
public:
typedef fc::shared_ptr<rpc_stream_connection> ptr;
rpc_stream_connection( fc::istream&, fc::ostream& );
rpc_stream_connection(const rpc_stream_connection& );
rpc_stream_connection();
// the life of the streams must exceed the life of all copies
// of this rpc_stream_connection
void open( fc::istream&, fc::ostream& );
// cancels all pending requests, closes the ostream
// results on_close() being called if the stream is not already closed.
virtual void close();
/**
* When the connection is closed, call the given method
*/
void on_close( const std::function<void()>& );
protected:
~rpc_stream_connection();
virtual void send_invoke( uint64_t id, const fc::string& m, value&& param );
virtual void send_notice( const fc::string& m, value&& param );
virtual void send_error( uint64_t id, const error_object& eo );
virtual void send_result( uint64_t id, value&& r );
private:
class impl;
fc::shared_ptr<impl> my;
};
} } // fc::json

View file

@ -1,28 +0,0 @@
#pragma once
#include <fc/json_rpc_stream_connection.hpp>
namespace fc {
class tcp_socket;
namespace ip { class endpoint; }
namespace json {
class rpc_tcp_connection : public rpc_stream_connection {
public:
typedef fc::shared_ptr<rpc_tcp_connection> ptr;
rpc_tcp_connection();
rpc_tcp_connection( const rpc_tcp_connection& c );
~rpc_tcp_connection();
void connect_to( const fc::ip::endpoint& e );
void start();
tcp_socket& get_socket()const;
virtual void close();
private:
class impl;
fc::shared_ptr<impl> my;
};
} // json
} // fc

View file

@ -1,42 +0,0 @@
#pragma once
#include <fc/json_rpc_connection.hpp>
namespace fc {
namespace json {
class rpc_tcp_server {
private:
template<typename Interface>
struct add_method_visitor {
add_method_visitor( fc::ptr<Interface>& p, rpc_connection& s ):_ptr(p),_rpcc(s) { }
template<typename Functor>
void operator()( const char* name, Functor& fun ) {
_rpcc.add_method( name, fun );
}
fc::ptr<Interface>& _ptr;
rpc_connection& _rpcc;
};
public:
rpc_tcp_server();
~rpc_tcp_server();
template<typename Interface>
void add_interface( const fc::ptr<Interface>& ptr ) {
on_new_connection( [=]( rpc_connection& c ) {
ptr->visit( detail::add_method_visitor<Interface>( ptr, c ) );
});
}
void on_new_connection( const std::function<void(rpc_connection&)>& c );
void listen( uint16_t port );
private:
class impl;
impl* my;
};
}
}

View file

@ -1,98 +0,0 @@
#pragma once
#include <fc/string.hpp>
namespace fc {
namespace detail {
template<typename T, typename R>
struct lexical_cast { };
double to_double( const fc::string& s );
inline double to_double( double d ) { return d; }
int64_t to_int64( const fc::string& s );
inline int64_t to_int64( double d ) { return static_cast<int64_t>(d); }
inline int64_t to_int64( int64_t d ) { return d; }
uint64_t to_uint64( const fc::string& s );
inline uint64_t to_uint64( double d ) { return static_cast<uint64_t>(d); }
inline uint64_t to_uint64( uint64_t d ) { return d; }
fc::string to_string( double d );
fc::string to_string( size_t d );
fc::string to_string( uint64_t d );
fc::string to_string( uint32_t d );
fc::string to_string( uint16_t d );
fc::string to_string( uint8_t d );
fc::string to_string( int64_t d );
fc::string to_string( int32_t d );
fc::string to_string( int16_t d );
fc::string to_string( int8_t d );
fc::string to_string( char d );
inline fc::string to_string( const char* d ) { return d; }
inline fc::string to_string( fc::string s ) { return s; }
template<typename R>
struct lexical_cast<double, R> {
static double cast( const R& v ) { return to_double( v ); }
};
template<typename R>
struct lexical_cast<fc::string, R> {
static fc::string cast( const R& v ) { return to_string( v ); }
};
template<typename R>
struct lexical_cast<std::string, R> {
static std::string cast( const R& v ) { return to_string( v ); }
};
template<typename R>
struct lexical_cast<uint64_t, R> {
static uint64_t cast( const R& v ) { return to_uint64( v ); }
};
template<typename R>
struct lexical_cast<int64_t, R> { static int64_t cast( const R& v ) { return static_cast<int64_t>(to_int64( v )); } };
template<typename R>
struct lexical_cast<int32_t, R> { static int32_t cast( const R& v ) { return static_cast<int32_t>(to_int64( v )); } };
template<typename R>
struct lexical_cast<int16_t, R> { static int16_t cast( const R& v ) { return static_cast<int16_t>(to_int64( v )); } };
template<typename R>
struct lexical_cast<int8_t, R> { static int8_t cast( const R& v ) { return static_cast<int8_t>(to_int64( v )); } };
template<typename R>
struct lexical_cast<uint32_t, R> { static uint32_t cast( const R& v ) { return static_cast<uint32_t>(to_uint64( v )); } };
template<typename R>
struct lexical_cast<uint16_t, R> { static uint16_t cast( const R& v ) { return static_cast<uint16_t>(to_uint64( v )); } };
template<typename R>
struct lexical_cast<uint8_t, R> { static uint8_t cast( const R& v ) { return static_cast<uint8_t>(to_uint64( v )); } };
template<typename R>
struct lexical_cast<bool, R> { static bool cast( const R& v ) { return v != 0; } };
template<>
struct lexical_cast<char, fc::string> { static char cast( const fc::string& v )
{ return v[0]; } };// TODO: check string len
template<>
struct lexical_cast<bool, fc::string> { static bool cast( const fc::string& v ) { return v == "true"; } };
template<>
struct lexical_cast<fc::string,bool> { static fc::string cast( const bool& v ) { return v ? "true" : "false";} };
template<typename R>
struct lexical_cast<float, R> { static float cast( const R& v ) { return static_cast<float>(to_double( v )); } };
}
template<typename T, typename R>
T lexical_cast( const R& v ) {
return detail::lexical_cast<T,R>::cast(v);
}
}

View file

@ -1,31 +0,0 @@
#pragma once
#include <fc/utility.hpp>
namespace boost { class mutex; }
namespace fc {
/** wrapper on printf */
void log( const char* color, const char* file_name, size_t line_num, const char* method_name, const char* format, ... );
/** used to add extra fields to be printed (thread,fiber,time,etc) */
void add_log_field( void (*f)() );
void remove_log_field( void (*f)() );
boost::mutex& log_mutex();
}
#ifndef __func__
#define __func__ __FUNCTION__
#endif
#ifndef WIN32
#define COLOR_CONSOLE 1
#endif
#include <fc/console_defines.h>
#define dlog(...) do { fc::log( CONSOLE_DEFAULT, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false)
#define slog(...) do { fc::log( CONSOLE_DEFAULT, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false)
#define wlog(...) do { fc::log( CONSOLE_BROWN, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false)
#define elog(...) do { fc::log( CONSOLE_RED, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false)

View file

@ -4,22 +4,22 @@
namespace fc {
class appender;
class log_message;
class value;
class string;
class variant;
class appender_factory : public fc::retainable {
public:
typedef fc::shared_ptr<appender_factory> ptr;
virtual ~appender_factory(){};
virtual fc::shared_ptr<appender> create( const value& args ) = 0;
virtual fc::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 value& args ) {
virtual fc::shared_ptr<appender> create( const variant& args ) {
return fc::shared_ptr<appender>(new T(args));
}
};
@ -34,7 +34,7 @@ namespace fc {
return register_appender( type, new detail::appender_factory_impl<T>() );
}
static appender::ptr create( const fc::string& name, const fc::string& type, const value& args );
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 );

View file

@ -1,11 +1,14 @@
#pragma once
#include <fc/appender.hpp>
#include <fc/logger.hpp>
#include <fc/log/appender.hpp>
#include <fc/log/logger.hpp>
namespace fc {
class console_appender : public appender {
namespace fc
{
class console_appender : public appender
{
public:
struct color {
struct color
{
enum type {
red,
green,
@ -17,20 +20,23 @@ namespace fc {
console_default,
};
};
struct stream { enum type { std_out, std_error }; };
struct level_color {
level_color( log_level::type l=log_level::all,
struct level_color
{
level_color( log_level l=log_level::all,
color::type c=color::console_default )
:level(l),color(c){}
log_level::type level;
log_level level;
console_appender::color::type color;
};
struct config {
struct config
{
config()
:format( "${when} ${thread} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
:format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
stream(console_appender::stream::std_error),flush(true){}
fc::string format;
@ -40,16 +46,17 @@ namespace fc {
};
console_appender( const value& args );
const char* get_color( log_level::type l )const;
console_appender( const variant& args );
const char* get_color( log_level l )const;
virtual void log( const log_message& m );
private:
config cfg;
color::type lc[log_level::off+1];
};
} // namespace fc
#include <fc/reflect.hpp>
#include <fc/reflect/reflect.hpp>
FC_REFLECT_ENUM( fc::console_appender::stream::type, (std_out)(std_error) )
FC_REFLECT_ENUM( fc::console_appender::color::type, (red)(green)(brown)(blue)(magenta)(cyan)(white)(console_default) )
FC_REFLECT( fc::console_appender::level_color, (level)(color) )

View file

@ -1,10 +1,12 @@
#pragma once
#include <fc/appender.hpp>
#include <fc/logger.hpp>
#include <fc/log/appender.hpp>
#include <fc/log/logger.hpp>
#include <fc/filesystem.hpp>
namespace fc {
class varaint;
class file_appender : public appender {
public:
struct config {
@ -15,7 +17,7 @@ class file_appender : public appender {
bool flush;
bool truncate;
};
file_appender( const value& args );
file_appender( const variant& args );
~file_appender();
virtual void log( const log_message& m );
@ -25,5 +27,5 @@ class file_appender : public appender {
};
} // namespace fc
#include <fc/reflect.hpp>
#include <fc/reflect/reflect.hpp>
FC_REFLECT( fc::file_appender::config, (format)(filename)(flush)(truncate) )

View file

@ -0,0 +1,159 @@
#pragma once
/**
* @file log_message.hpp
* @brief Defines types and helper macros necessary for generating log messages.
*/
#include <fc/time.hpp>
#include <fc/variant_object.hpp>
#include <fc/shared_ptr.hpp>
#include <memory>
namespace fc
{
namespace detail
{
class log_context_impl;
class log_message_impl;
}
/**
* Named scope for log_level enumeration.
*/
class log_level
{
public:
/**
* @brief Define's the various log levels for reporting.
*
* Each log level includes all higher levels such that
* Debug includes Error, but Error does not include Debug.
*/
enum values
{
all,
debug,
info,
warn,
error,
off
};
log_level( values v = off ):value(v){}
explicit log_level( int v ):value( static_cast<values>(v)){}
operator int()const { return value; }
values value;
};
void to_variant( log_level e, variant& v );
void from_variant( const variant& e, log_level& ll );
/**
* @brief provides information about where and when a log message was generated.
* @ingroup AthenaSerializable
*
* @see FC_LOG_CONTEXT
*/
class log_context
{
public:
log_context();
log_context( log_level ll,
const char* file,
uint64_t line,
const char* method );
~log_context();
explicit log_context( const variant& v );
variant to_variant()const;
string get_file()const;
uint64_t get_line_number()const;
string get_method()const;
string get_thread_name()const;
string get_host_name()const;
time_point get_timestamp()const;
log_level get_log_level()const;
string get_context()const;
void append_context( const fc::string& c );
string to_string()const;
private:
std::shared_ptr<detail::log_context_impl> my;
};
void to_variant( const log_context& l, variant& v );
void from_variant( const variant& l, log_context& c );
/**
* @brief aggregates a message along with the context and associated meta-information.
* @ingroup AthenaSerializable
*
* @note log_message has reference semantics, all copies refer to the same log message
* and the message is read-only after construction.
*
* When converted to JSON, log_message has the following form:
* @code
* {
* "context" : { ... },
* "format" : "string with ${keys}",
* "data" : { "keys" : "values" }
* }
* @endcode
*
* @see FC_LOG_MESSAGE
*/
class log_message
{
public:
log_message();
/**
* @param ctx - generally provided using the FC_LOG_CONTEXT(LEVEL) macro
*/
log_message( log_context ctx, const char* format, variant_object args = variant_object() );
~log_message();
log_message( const variant& v );
variant to_variant()const;
string get_message()const;
log_context get_context()const;
string get_format()const;
variant_object get_data()const;
private:
std::shared_ptr<detail::log_message_impl> my;
};
void to_variant( const log_message& l, variant& v );
void from_variant( const variant& l, log_message& c );
typedef fc::vector<log_message> log_messages;
} // namespace fc
#ifndef __func__
#define __func__ __FUNCTION__
#endif
/**
* @def FC_LOG_CONTEXT(LOG_LEVEL)
* @brief Automatically captures the File, Line, and Method names and passes them to
* the constructor of fc::log_context along with LOG_LEVEL
* @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__ )
/**
* @def FC_LOG_MESSAGE(LOG_LEVEL,FORMAT,...)
*
* @brief A helper method for generating log messages.
*
* @param LOG_LEVEL a valid log_level::Enum name to be passed to the log_context
* @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( LOG_LEVEL, FORMAT, ... ) \
fc::log_message( FC_LOG_CONTEXT(LOG_LEVEL), FORMAT, fc::mutable_variant_object()__VA_ARGS__ )

137
include/fc/log/logger.hpp Normal file
View file

@ -0,0 +1,137 @@
#pragma once
#include <fc/string.hpp>
#include <fc/time.hpp>
#include <fc/shared_ptr.hpp>
#include <fc/log/log_message.hpp>
namespace fc
{
class appender;
/**
*
*
@code
void my_class::func()
{
fc_dlog( my_class_logger, "Format four: ${arg} five: ${five}", ("arg",4)("five",5) );
}
@endcode
*/
class logger
{
public:
static logger get( const fc::string& name = "default");
logger();
logger( const string& name, const logger& parent = nullptr );
logger( std::nullptr_t );
logger( const logger& c );
logger( logger&& c );
~logger();
logger& operator=(const logger&);
logger& operator=(logger&&);
friend bool operator==( const logger&, nullptr_t );
friend bool operator!=( const logger&, 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 add_appender( const fc::shared_ptr<appender>& a );
bool is_enabled( log_level e )const;
void log( log_message m );
private:
class impl;
fc::shared_ptr<impl> my;
};
} // namespace fc
#define fc_dlog( LOGGER, FORMAT, ... ) \
do { \
if( (LOGGER).is_enabled( fc::log_level::debug ) ) { \
(LOGGER).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
} \
} while (0)
#define fc_ilog( LOGGER, FORMAT, ... ) \
do { \
if( (LOGGER).is_enabled( fc::log_level::info ) ) { \
(LOGGER).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
} \
} while (0)
#define fc_wlog( LOGGER, FORMAT, ... ) \
do { \
if( (LOGGER).is_enabled( fc::log_level::warn ) ) { \
(LOGGER).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
} \
} while (0)
#define fc_elog( LOGGER, FORMAT, ... ) \
do { \
if( (LOGGER).is_enabled( fc::log_level::error ) ) { \
(LOGGER).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
} \
} while (0)
#define dlog( FORMAT, ... ) \
do { \
if( (fc::logger::get()).is_enabled( fc::log_level::debug ) ) { \
(fc::logger::get()).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
} \
} while (0)
#define ilog( FORMAT, ... ) \
do { \
if( (fc::logger::get()).is_enabled( fc::log_level::info ) ) { \
(fc::logger::get()).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
} \
} while (0)
#define wlog( FORMAT, ... ) \
do { \
if( (fc::logger::get()).is_enabled( fc::log_level::warn ) ) { \
(fc::logger::get()).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
} \
} while (0)
#define elog( FORMAT, ... ) \
do { \
if( (fc::logger::get()).is_enabled( fc::log_level::error ) ) { \
(fc::logger::get()).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
} \
} while (0)
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/punctuation/paren.hpp>
#define FC_FORMAT_ARG(r, unused, base) \
BOOST_PP_STRINGIZE(base) ": ${" BOOST_PP_STRINGIZE( base ) "} "
#define FC_FORMAT_ARGS(r, unused, base) \
BOOST_PP_LPAREN() BOOST_PP_STRINGIZE(base),fc::variant(base) BOOST_PP_RPAREN()
#define FC_FORMAT( SEQ )\
BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARG, v, SEQ )
#define FC_FORMAT_ARG_PARAMS( SEQ )\
BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARGS, v, SEQ )
#define idump( SEQ ) \
ilog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )

View file

@ -1,15 +1,15 @@
#pragma once
#include <fc/logger.hpp>
#include <fc/log/logger.hpp>
namespace fc {
class path;
struct appender_config {
appender_config(const fc::string& n="",const fc::string& t="", const value& a=value())
:name(n),type(t),args(a),enabled(true){}
string name;
string type;
value args;
bool enabled;
appender_config(const fc::string& n="",const fc::string& t="", variant a=variant())
:name(n),type(t),args(fc::move(a)),enabled(true){}
string name;
string type;
variant args;
bool enabled;
};
struct logger_config {
@ -17,7 +17,7 @@ namespace fc {
string name;
ostring parent;
/// if not set, then parents level is used.
fc::optional<log_level::type> level;
fc::optional<log_level> level;
bool enabled;
/// if any appenders are sepecified, then parent's appenders are not set.
bool additivity;
@ -37,7 +37,7 @@ namespace fc {
bool configure_logging( const logging_config& l );
}
#include <fc/reflect.hpp>
#include <fc/reflect/reflect.hpp>
FC_REFLECT( fc::appender_config, (name)(type)(args)(enabled) )
FC_REFLECT( fc::logger_config, (name)(parent)(level)(enabled)(additivity)(appenders) )
FC_REFLECT( fc::logging_config, (includes)(appenders)(loggers) )

View file

@ -1,144 +0,0 @@
#pragma once
#include <fc/value.hpp>
#include <fc/string.hpp>
#include <fc/time.hpp>
#include <fc/shared_ptr.hpp>
namespace fc {
struct log_level {
enum type {
all, trace, debug, info, warn, error, fatal, off
};
};
struct log_message {
log_message(log_level::type, const string& file, int line, const string& func, const string& format );
log_message();
otime_point when;
log_level::type level;
ostring context;
ostring thread;
ostring fiber;
ostring host;
string file;
int line;
string method;
string format;
value args;
ovalue meta;
// key based args
template<typename T>
log_message& operator()( const string& arg, const T& v ) {
return (*this)(arg,value(v));
}
log_message& operator()( const string& arg, value&& v );
log_message& operator()( const string& arg, const value& v );
// position based args...
log_message& operator()( value&& v );
log_message& operator()( const value& v );
};
class appender;
/**
*
*
@code
void my_class::func()
{
fc_dlog( my_class_logger, "Format four: ${arg} five: ${five}", ("arg",4)("five",5) );
}
@endcode
*/
class logger {
public:
static logger get( const fc::string& name = "default");
logger();
logger( const string& name, const logger& parent = nullptr );
logger( std::nullptr_t );
logger( const logger& c );
logger( logger&& c );
~logger();
logger& operator=(const logger&);
logger& operator=(logger&&);
friend bool operator==( const logger&, std::nullptr_t );
friend bool operator!=( const logger&, std::nullptr_t );
logger& set_log_level( log_level::type e );
log_level::type 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 add_appender( const fc::shared_ptr<appender>& a );
bool is_enabled( log_level::type e )const;
void log( log_message m );
private:
class impl;
fc::shared_ptr<impl> my;
};
/**
* This helper class is used to automatically print a log message
* once upon construction, and again upon destruction and is therefore
* helpful in catching scope changes.
struct tracer {
tracer( const logger::ptr& lgr );
~tracer();
void set_message( log_message&& ms g);
private:
logger::ptr logger;
log_message msg;
};
*/
} // namespace fc
#include <fc/reflect.hpp>
FC_REFLECT( fc::log_message, (when)(level)(context)(thread)(fiber)(host)(method)(file)(line)(format)(args)(meta) )
FC_REFLECT_ENUM( fc::log_level::type, (all)(trace)(debug)(info)(warn)(error)(fatal)(off) )
#define fc_scope_log( LOGGER, FORMAT, ... ) \
fc::tracer __tracer; \
if( (LOGGER).is_enabled( fc::log_level::trace ) ) { \
__tracer.set_message( fc::log_message( fc::log_level::trace, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\
}
#define fc_dlog( LOGGER, FORMAT, ... ) \
if( (LOGGER).is_enabled( fc::log_level::debug ) ) { \
(LOGGER).log( fc::log_message( fc::log_level::debug, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\
}
#define fc_ilog( LOGGER, FORMAT, ... ) \
if( (LOGGER).is_enabled( fc::log_level::info ) ) { \
(LOGGER).log( fc::log_message( fc::log_level::info, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\
}
#define fc_wlog( LOGGER, FORMAT, ... ) \
if( (LOGGER).is_enabled( fc::log_level::warn ) ) { \
(LOGGER).log( fc::log_message( fc::log_level::warn, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\
}
#define fc_elog( LOGGER, FORMAT, ... ) \
if( (LOGGER).is_enabled( fc::log_level::error ) ) { \
(LOGGER).log( fc::log_message( fc::log_level::error, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\
}
#define fc_flog( LOGGER, FORMAT, ... ) \
if( (LOGGER).is_enabled( fc::log_level::fatal ) ) { \
(LOGGER).log( fc::log_message( fc::log_level::fatal, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\
}

View file

@ -4,23 +4,23 @@
namespace fc {
template<typename R>
fc::function<R, fc::tuple<> > make_fused( const fc::function<R>& f ) {
std::function<R, fc::tuple<> > make_fused( const std::function<R>& f ) {
return [=]( fc::tuple<> ){ return f(); };
}
template<typename R,typename A>
fc::function<R(fc::tuple<A>) > make_fused( const fc::function<R(A)>& f ) {
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>
fc::function<R(fc::tuple<A,B>) > make_fused( const fc::function<R(A,B)>& f ) {
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>
fc::function<R(fc::tuple<A,B,C>) > make_fused( const fc::function<R(A,B,C)>& f ) {
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>
fc::function<R(fc::tuple<A,B,C,D>) > make_fused( const fc::function<R(A,B,C,D)>& f ) {
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); };
}
}

View file

@ -1,18 +0,0 @@
#ifndef _FC_MAP_HPP_
namespace fc {
namespace detail {
class map_impl {
public:
};
}
template<typename K, typename V>
class map : public map_impl {
};
}

View file

@ -0,0 +1,76 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
#include <memory>
namespace fc {
namespace ip { class endpoint; }
class tcp_socket;
namespace http {
struct header
{
header( fc::string k, fc::string v )
:key(fc::move(k)),val(fc::move(v)){}
header(){}
fc::string key;
fc::string val;
};
typedef fc::vector<header> headers;
struct reply
{
enum status_code {
OK = 200,
RecordCreated = 201,
NotFound = 404,
Found = 302,
InternalServerError = 500
};
reply( status_code c = OK):status(c){}
int status;
fc::vector<header> headers;
fc::vector<char> body;
};
struct request
{
fc::string get_header( const fc::string& key )const;
fc::string method;
fc::string domain;
fc::string path;
fc::vector<header> headers;
fc::vector<char> body;
};
fc::vector<header> parse_urlencoded_params( const fc::string& f );
/**
* Connections have reference semantics, all copies refer to the same
* underlying socket.
*/
class connection
{
public:
connection();
~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, const headers& = headers());
// used for servers
fc::tcp_socket& get_socket()const;
http::request read_request()const;
class impl;
private:
std::unique_ptr<impl> my;
};
typedef std::shared_ptr<connection> connection_ptr;
} } // fc::http

View file

@ -1,7 +1,8 @@
#pragma once
#include <fc/http/connection.hpp>
#include <fc/network/http/connection.hpp>
#include <fc/shared_ptr.hpp>
#include <functional>
#include <memory>
namespace fc { namespace http {
@ -11,18 +12,18 @@ namespace fc { namespace http {
* function for every http request.
*
*/
class server {
class server
{
public:
server();
server( uint16_t port );
server( const server& s );
server( server&& s );
~server();
server& operator=(const server& s);
server& operator=(server&& s);
class response {
class response
{
public:
class impl;
@ -53,8 +54,8 @@ namespace fc { namespace http {
private:
class impl;
fc::shared_ptr<impl> my;
std::unique_ptr<impl> my;
};
typedef std::shared_ptr<server> server_ptr;
} }

View file

@ -46,7 +46,10 @@ namespace fc {
address _ip;
};
}
class value;
void pack( fc::value& , const fc::ip::endpoint& );
void unpack( const fc::value& , fc::ip::endpoint& );
class variant;
void to_variant( const ip::endpoint& var, variant& vo );
void from_variant( const variant& var, ip::endpoint& vo );
void to_variant( const ip::address& var, variant& vo );
void from_variant( const variant& var, ip::address& vo );
}

View file

@ -1,11 +1,12 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
#include <fc/iostream.hpp>
#include <fc/io/iostream.hpp>
namespace fc {
namespace ip { class endpoint; }
class tcp_socket : public iostream {
class tcp_socket : public virtual iostream
{
public:
tcp_socket();
~tcp_socket();
@ -15,13 +16,12 @@ namespace fc {
/// istream interface
/// @{
virtual size_t readsome( char* buffer, size_t max );
virtual istream& read( char* buffer, size_t s );
virtual bool eof()const;
/// @}
/// ostream interface
/// @{
virtual ostream& write( const char* buffer, size_t len );
virtual size_t writesome( const char* buffer, size_t len );
virtual void flush();
virtual void close();
/// @}
@ -33,8 +33,11 @@ namespace fc {
class impl;
fc::fwd<impl,0x44> my;
};
typedef std::shared_ptr<tcp_socket> tcp_socket_ptr;
class tcp_server {
class tcp_server
{
public:
tcp_server();
~tcp_server();

106
include/fc/network/url.hpp Normal file
View file

@ -0,0 +1,106 @@
#pragma once
#include <fc/string.hpp>
#include <fc/optional.hpp>
#include <stdint.h>
#include <fc/filesystem.hpp>
#include <fc/variant_object.hpp>
#include <memory>
namespace fc {
typedef fc::optional<fc::string> ostring;
typedef fc::optional<fc::path> opath;
typedef fc::optional<fc::variant_object> ovariant_object;
namespace detail { class url_impl; }
class mutable_url;
/**
* Used to pass an immutable URL and
* query its parts.
*/
class url
{
public:
url();
explicit url( const string& u );
url( const url& c );
url( url&& c );
url( mutable_url&& c );
url( const mutable_url& c );
~url();
url& operator=( const url& c );
url& operator=( url&& c );
url& operator=( const mutable_url& c );
url& operator=( mutable_url&& c );
bool operator==( const url& cmp )const;
operator string()const;
//// file, ssh, tcp, http, ssl, etc...
string proto()const;
ostring host()const;
ostring user()const;
ostring pass()const;
opath path()const;
ovariant_object args()const;
fc::optional<uint16_t> port()const;
private:
friend class mutable_url;
std::shared_ptr<detail::url_impl> my;
};
void to_variant( const url& u, fc::variant& v );
void from_variant( const fc::variant& v, url& u );
/**
* Used to create / manipulate a URL
*/
class mutable_url
{
public:
mutable_url();
explicit mutable_url( const string& mutable_url );
mutable_url( const mutable_url& c );
mutable_url( const url& c );
mutable_url( mutable_url&& c );
~mutable_url();
mutable_url& operator=( const url& c );
mutable_url& operator=( const mutable_url& c );
mutable_url& operator=( mutable_url&& c );
bool operator==( const mutable_url& cmp )const;
bool operator==( const url& cmp )const;
operator string()const;
//// file, ssh, tcp, http, ssl, etc...
string proto()const;
ostring host()const;
ostring user()const;
ostring pass()const;
opath path()const;
ovariant_object args()const;
fc::optional<uint16_t> port()const;
void set_proto( string );
void set_host( string );
void set_user( string );
void set_pass( string );
void set_path( fc::path p );
void set_args( variant_object );
void set_port( uint16_t );
private:
friend class url;
std::unique_ptr<detail::url_impl> my;
};
} // namespace fc

View file

@ -1,9 +0,0 @@
#pragma once
namespace fc {
template<typename T, typename R>
T numeric_cast( const R& v ) {
// TODO: do something smarter here, check ranges, etc
return static_cast<T>(v);
}
}

View file

@ -8,6 +8,12 @@ namespace fc {
* Simply including boost::optional adds 35,000 lines to each object file, using
* fc::optional adds less than 400.
*/
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4521) /* multiple copy ctors */
#endif
template<typename T>
class optional {
public:
@ -20,6 +26,12 @@ namespace fc {
_valid = o._valid;
}
optional( optional& o )
:_valid(false) {
if( o._valid ) new (&**this) T( *o );
_valid = o._valid;
}
optional( optional&& o )
:_valid(false) {
if( o._valid ) new (&**this) T( fc::move(*o) );
@ -39,23 +51,36 @@ namespace fc {
new (&**this) T( fc::forward<U>(u) );
_valid = true;
} else {
**this = fc::forward<U>(u);
**this = static_cast<T>(fc::forward<U>(u));
}
return *this;
}
optional& operator=( const optional& o ) {
if( _valid && o._valid ) { **this = *o; }
else if( !_valid && o._valid ) {
*this = *o;
} // else !_valid && !o._valid == same!
if (this != &o) {
if( _valid && o._valid ) {
**this = *o;
} else if( !_valid && o._valid ) {
*this = *o;
} else if (_valid) {
(**this).~T();
_valid = false;
}
}
return *this;
}
optional& operator=( optional&& o ) {
if( _valid && o._valid ) { **this = fc::move(*o); }
else if( !_valid && o._valid ) {
*this = fc::move(*o);
}
if (this != &o) {
if( _valid && o._valid ) {
**this = fc::move(*o);
} else if ( !_valid && o._valid ) {
*this = fc::move(*o);
} else if (_valid) {
(**this).~T();
_valid = false;
}
}
return *this;
}
@ -91,5 +116,9 @@ namespace fc {
return !left || *left != u;
}
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // namespace fc

View file

@ -1,155 +0,0 @@
#pragma once
#include <fc/sha1.hpp>
#include <fc/vector.hpp>
#include <fc/reflect.hpp>
/**
* Define common crypto methods and data types to abstract underlying implementation.
*/
namespace fc {
template<uint32_t KeySize=2048>
struct signature {
char data[KeySize/8];
template<typename T,uint32_t KS>
friend T& operator<<( T& ds, const fc::signature<KS>& sig )
{
ds.write(sig.data, KS/8 );
return ds;
}
template<typename T,uint32_t KS>
friend T& operator>>( T& ds, fc::signature<KS>& sig )
{
ds.read(sig.data, KS/8 );
return ds;
}
bool operator != ( const signature& s )const {
return memcmp( s.data, data, sizeof(data) ) != 0;
}
bool operator == ( const signature& s )const {
return memcmp( s.data, data, sizeof(data) ) == 0;
}
};
bool verify_data( const char* key, uint32_t key_size, uint32_t pe, const sha1& hc, const char* sig );
bool sign_data( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const sha1& hc, char* sig );
bool public_encrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out );
bool public_decrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out );
bool private_encrypt( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out );
bool private_decrypt( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out );
bool generate_keys( char* pubkey, fc::vector<char>& privkey, uint32_t key_size, uint32_t pe );
template<uint32_t KeySize = 2048, uint32_t PublicExponent = 65537>
struct private_key;
template<uint32_t KeySize = 2048, uint32_t PublicExponent = 65537>
struct public_key {
public_key() { memset( key, 0, sizeof(key) ); }
public_key( const public_key& pk ) { memcpy( key, pk.key, sizeof(key) ); }
bool verify( const sha1& digest, const signature<KeySize>& sig )const {
return verify_data( key, sizeof(key), PublicExponent, digest, sig.data );
}
bool encrypt( const fc::vector<char>& in, fc::vector<char>& out )const {
return public_encrypt( key, KeySize, PublicExponent, in, out );
}
bool decrypt( const fc::vector<char>& in, fc::vector<char>& out )const {
return public_decrypt( key, KeySize, PublicExponent, in, out );
}
public_key& operator = ( const public_key& pk ) {
memcpy( key, pk.key, sizeof(key) );
return *this;
}
bool operator == ( const public_key& pk )const {
return 0 == memcmp( key, pk.key, sizeof(key) );
}
bool operator != ( const public_key& pk )const {
return 0 != memcmp( key, pk.key, sizeof(key) );
}
bool operator > ( const public_key& pk )const {
return memcmp( key, pk.key, sizeof(key) ) > 0;
}
bool operator < ( const public_key& pk )const {
return memcmp( key, pk.key, sizeof(key) ) < 0;
}
template<typename T,uint32_t KS, uint32_t PE>
inline friend T& operator<<( T& ds, const fc::public_key<KS,PE>& pk ) {
ds.write(pk.key, KS/8 );
return ds;
}
template<typename T,uint32_t KS, uint32_t PE>
inline friend T& operator>>( T& ds, fc::public_key<KS,PE>& pk ) {
ds.read( pk.key, KS/8 );
return ds;
}
private:
template<uint32_t KS, uint32_t PE>
friend void generate_keys( public_key<KS,PE>& pub, private_key<KS,PE>& priv );
char key[KeySize/8];
};
template<uint32_t KeySize, uint32_t PublicExponent>
struct private_key {
bool encrypt( const fc::vector<char>& in, fc::vector<char>& out )const {
return private_encrypt( key, KeySize, PublicExponent, in, out );
}
bool decrypt( const fc::vector<char>& in, fc::vector<char>& out )const {
return private_decrypt( key, KeySize, PublicExponent, in, out );
}
bool sign( const sha1& digest, signature<KeySize>& sig )const {
return sign_data( key, KeySize, PublicExponent, digest, sig.data );
}
template<typename T,uint32_t KS, uint32_t PE>
friend T& operator<<( T& ds, const fc::private_key<KS,PE>& pk ) {
uint16_t s = pk.key.size();
ds.write( (const char*)&s, sizeof(s) );
ds.write( pk.key.data(), pk.key.size() );
return ds;
}
template<typename T,uint32_t KS, uint32_t PE>
friend T& operator>>( T& ds, fc::private_key<KS,PE>& pk ) {
uint16_t s;
ds.read((char*)&s,sizeof(s) );
pk.key.resize(s);
ds.read( pk.key.data(), pk.key.size() );
return ds;
}
private:
template<uint32_t KS, uint32_t PE>
friend void generate_keys( public_key<KS,PE>& pub, private_key<KS,PE>& priv );
fc::vector<char> key;
};
template<uint32_t KeySize, uint32_t PublicExponent>
void generate_keys( public_key<KeySize,PublicExponent>& pub, private_key<KeySize,PublicExponent>& priv ) {
generate_keys( pub.key, priv.key, KeySize, PublicExponent );
}
/*
template<uint32_t KeySize>
inline std::ostream& operator<< ( std::ostream& os, const signature<KeySize>& s ) {
for( uint32_t i = 0; i < KeySize; ++i )
os << std::hex << int(s.data[i]) << ' ';
return os;
}
*/
typedef public_key<> public_key_t;
typedef private_key<> private_key_t;
typedef signature<> signature_t;
class value;
void pack( fc::value& , const fc::signature_t& );
void unpack( const fc::value& , fc::signature_t& );
void pack( fc::value& , const fc::public_key_t& );
void unpack( const fc::value& , fc::private_key_t& );
void pack( fc::value& , const fc::private_key_t& );
void unpack( const fc::value& , fc::public_key_t& );
} // namespace fc

View file

@ -1,59 +0,0 @@
#pragma once
#include <fc/shared_impl.hpp>
#include <fc/future.hpp>
#include <fc/string.hpp>
namespace fc {
class istream;
class ostream;
class path;
template<typename> class vector;
fc::path find_executable_in_path( const fc::string name );
/**
* @brief start and manage an external process
*
* @note this class implements reference semantics.
*/
class process {
public:
enum exec_opts {
open_none = 0,
open_stdin = 0x01,
open_stdout = 0x02,
open_stderr = 0x04,
open_all = open_stdin|open_stdout|open_stderr,
};
/**
* Return a new process executing the specified exe with the specified args.
*/
fc::future<int> exec( const fc::path& exe, int opt = open_all );
fc::future<int> exec( const fc::path& exe, const fc::path& wd, int opt = open_all );
fc::future<int> exec( const fc::path& exe, fc::vector<fc::string>&& args , int opt = open_all );
fc::future<int> exec( const fc::path& exe, fc::vector<fc::string>&& args, const fc::path& wd, int opt = open_all );
/**
* Forcefully kills the process.
*/
void kill();
/**
* @brief returns a stream that writes to the process' stdin
*/
fc::ostream& in_stream();
/**
* @brief returns a stream that reads from the process' stdout
*/
fc::istream& out_stream();
/**
* @brief returns a stream that reads from the process' stderr
*/
fc::istream& err_stream();
FC_REFERENCE_TYPE(process)
};
} // namespace fc

View file

@ -1,64 +0,0 @@
#ifndef _FC_PROGRAM_OPTIONS_HPP_
#define _FC_PROGRAM_OPTIONS_HPP_
#include <fc/optional.hpp>
#include <fc/string.hpp>
#include <vector>
#include <string>
#include <fc/fwd.hpp>
namespace boost {
namespace program_options {
class variables_map;
}
}
namespace fc {
class ostream;
namespace program_options {
template<typename T>
class value {
public:
value( T* v ):_v(v){}
value& default_value( const T& d ) { _default = d; }
T* get()const { return _v; }
private:
fc::optional<T> _default;
T* _v;
};
class options_description {
public:
options_description( const char* c );
~options_description();
options_description& add_options();
options_description& operator()( const char* o, const char* desc );
options_description& operator()( const char* o, const value<fc::string>&, const char* desc );
options_description& operator()( const char* o, const value<uint16_t>&, const char* desc );
options_description& operator()( const char* o, const value<std::vector<std::string> >&, const char* desc );
private:
class impl;
fwd<impl,104> my;
friend class variables_map;
friend fc::ostream& operator<<( fc::ostream& o, const options_description& );
};
class variables_map {
public:
variables_map();
~variables_map();
void parse_command_line( int argc, char** argv, const options_description& d );
int count( const char* opt );
private:
class impl;
fwd<impl,160> my;
};
}
}
#endif // _FC_PROGRAM_OPTIONS_HPP_

View file

@ -1,12 +1,10 @@
#pragma once
/**
* @file fc/reflect.hpp
*
* @brief Defines types and macros used to provide reflection.
*
*/
#ifndef _FC_REFLECT_HPP_
#define _FC_REFLECT_HPP_
#include <fc/utility.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
@ -16,8 +14,7 @@
#include <boost/preprocessor/stringize.hpp>
#include <stdint.h>
#include <fc/exception.hpp>
#include <fc/typename.hpp>
#include <fc/reflect/typename.hpp>
namespace fc {
@ -41,7 +38,7 @@ struct reflector{
*
* @code
* struct functor {
* template<typename MemberPtr, MemberPtr m>
* template<typename Member, class Class, Member (Class::*member)>
* void operator()( const char* name )const;
* };
* @endcode
@ -90,7 +87,7 @@ void throw_bad_enum_cast( const char* k, const char* e );
#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \
OP fc::reflector<elem>::member_count
OP fc::reflector<elem>::total_member_count
#define FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
template<typename Visitor>\
@ -207,4 +204,3 @@ template<> struct reflector<TYPE> {\
#endif

View file

@ -0,0 +1,99 @@
#pragma once
#include <fc/reflect/reflect.hpp>
#include <fc/variant_object.hpp>
namespace fc
{
template<typename T>
void to_variant( const T& o, variant& v );
template<typename T>
void from_variant( const variant& v, T& o );
template<typename T>
class to_variant_visitor
{
public:
to_variant_visitor( mutable_variant_object& mvo, const T& v )
:vo(mvo),val(v){}
template<typename Member, class Class, Member (Class::*member)>
void operator()( const char* name )const
{
vo(name,(val.*member));
}
mutable_variant_object& vo;
const T& val;
};
template<typename T>
class from_variant_visitor
{
public:
from_variant_visitor( const variant_object& _vo, T& v )
:vo(_vo),val(v){}
template<typename Member, class Class, Member (Class::*member)>
void operator()( const char* name )const
{
auto itr = vo.find(name);
if( itr != vo.end() )
from_variant( itr->value(), val.*member );
}
const variant_object& vo;
T& val;
};
template<typename IsReflected=fc::false_type>
struct if_enum
{
template<typename T>
static inline void to_variant( const T& v, fc::variant& vo )
{
mutable_variant_object mvo;
fc::reflector<T>::visit( to_variant_visitor<T>( mvo, v ) );
vo = fc::move(mvo);
}
template<typename T>
static inline void from_variant( const fc::variant& v, T& o )
{
const variant_object& vo = v.get_object();
fc::reflector<T>::visit( from_variant_visitor<T>( vo, o ) );
}
};
template<>
struct if_enum<fc::true_type>
{
template<typename T>
static inline void to_variant( const T& o, fc::variant& v )
{
v = fc::reflector<T>::to_string(o);
}
template<typename T>
static inline void from_variant( const fc::variant& v, T& o )
{
if( v.is_string() )
o = fc::reflector<T>::from_string( v.get_string().c_str() );
else
// throw if invalid int, by attempting to convert to string
fc::reflector<T>::to_string( o = static_cast<T>(v.as_int64()) );
}
};
template<typename T>
void to_variant( const T& o, variant& v )
{
if_enum<typename fc::reflector<T>::is_enum>::to_variant( o, v );
}
template<typename T>
void from_variant( const variant& v, T& o )
{
if_enum<typename fc::reflector<T>::is_enum>::from_variant( v, o );
}
}

View file

@ -0,0 +1,140 @@
#pragma once
#include <fc/io/buffered_iostream.hpp>
#include <fc/variant_object.hpp>
#include <fc/thread/future.hpp>
#include <fc/log/logger.hpp>
#include <functional>
namespace fc { namespace rpc {
namespace detail { class json_connection_impl; }
/**
* @brief Implements JSON-RPC 2.0 over a set of io streams
*
* Each JSON RPC message is expected to be on its own line, violators
* will be prosecuted to the fullest extent of the law.
*/
class json_connection
{
public:
typedef std::function<variant(const variants&)> method;
typedef std::function<variant(const variant_object&)> named_param_method;
json_connection( fc::buffered_istream_ptr in, fc::buffered_ostream_ptr out );
~json_connection();
/**
* Starts processing messages from input
*/
future<void> exec();
logger get_logger()const;
void set_logger( const logger& l );
/**
* @name server interface
*
* Adding methods to the interface allows the remote side
* to call them.
*/
///@{
void add_method( const fc::string& name, method );
void add_method( const fc::string& name, named_param_method );
void remove_method( const fc::string& name );
//@}
/**
* @name client interface
*/
///@{
void notice( const fc::string& method );
void notice( const fc::string& method, const variants& args );
void notice( const fc::string& method, const variant_object& named_args );
/// args will be handled as named params
future<variant> async_call( const fc::string& method,
const variant_object& args );
future<variant> async_call( const fc::string& method, mutable_variant_object args );
/// Sending in an array of variants will be handled as positional arguments
future<variant> async_call( const fc::string& method,
const variants& args );
future<variant> async_call( const fc::string& method );
future<variant> async_call( const fc::string& method,
const variant& a1 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3 );
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
variant_object a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, fc::move(a1) ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
mutable_variant_object a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, variant_object( fc::move(a1) ) ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method, microseconds timeout = microseconds::maximum() )
{
return async_call( method ).wait(timeout).as<Result>();
}
/// Sending in a variant_object will be issued as named parameters
variant call( const fc::string& method, const variant_object& named_args );
///@}
private:
std::unique_ptr<detail::json_connection_impl> my;
};
typedef std::shared_ptr<json_connection> json_connection_ptr;
}} // fc::rpc

View file

@ -0,0 +1,140 @@
#pragma once
#include <fc/io/buffered_iostream.hpp>
#include <fc/variant_object.hpp>
#include <fc/thread/future.hpp>
#include <fc/log/logger.hpp>
#include <functional>
namespace fc { namespace rpc {
namespace detail { class variant_connection_impl; }
/**
* @brief Implements JSON-RPC 2.0 over a set of io streams
*
* Each JSON RPC message is expected to be on its own line, violators
* will be prosecuted to the fullest extent of the law.
*/
class variant_connection
{
public:
typedef std::function<variant(const variants&)> method;
typedef std::function<variant(const variant_object&)> named_param_method;
variant_connection( fc::variant_stream::ptr in, fc::variant_stream::ptr out );
~variant_connection();
/**
* Starts processing messages from input
*/
future<void> exec();
logger get_logger()const;
void set_logger( const logger& l );
/**
* @name server interface
*
* Adding methods to the interface allows the remote side
* to call them.
*/
///@{
void add_method( const fc::string& name, method );
void add_method( const fc::string& name, named_param_method );
void remove_method( const fc::string& name );
//@}
/**
* @name client interface
*/
///@{
void notice( const fc::string& method );
void notice( const fc::string& method, const variants& args );
void notice( const fc::string& method, const variant_object& named_args );
/// args will be handled as named params
future<variant> async_call( const fc::string& method,
const variant_object& args );
future<variant> async_call( const fc::string& method, mutable_variant_object args );
/// Sending in an array of variants will be handled as positional arguments
future<variant> async_call( const fc::string& method,
const variants& args );
future<variant> async_call( const fc::string& method );
future<variant> async_call( const fc::string& method,
const variant& a1 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3 );
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
variant_object a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, fc::move(a1) ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
mutable_variant_object a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, variant_object( fc::move(a1) ) ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method, microseconds timeout = microseconds::maximum() )
{
return async_call( method ).wait(timeout).as<Result>();
}
/// Sending in a variant_object will be issued as named parameters
variant call( const fc::string& method, const variant_object& named_args );
///@}
private:
std::unique_ptr<detail::variant_connection_impl> my;
};
typedef std::shared_ptr<variant_connection> variant_connection_ptr;
}} // fc::rpc

View file

@ -0,0 +1,36 @@
#pragma once
namespace fc
{
/**
* Thread-safe, circular buffer for passing variants
* between threads.
*/
class variant_stream
{
public:
variant_stream( size_t s );
~variant_stream();
/** producer api */
int64_t free(); // number of spaces available
int64_t claim( int64_t num );
int64_t publish( int64_t pos );
int64_t wait_free(); // wait for free space
// producer/consumer api
variant& get( int64_t pos );
/** consumer api */
int64_t begin(); // returns the first index ready to be read
int64_t end(); // returns the first index that cannot be read
int64_t wait(); // wait for variants to be posted
private:
std::vector<variant> _variants;
uint64_t _read_pos;
uint64_t _write_pos;
};
}

View file

@ -1,27 +0,0 @@
class istream {
public:
template<typename T>
istream( T& s ) {
}
istream& read( char* buf, uint64_t s );
int64_t readsome( char* buf, uint64_t s );
bool eof()const;
private:
struct vtable {
void* (*read)(void*, char* buf, uint64_t s );
int64_t (*readsome)(void*, char* buf, uint64_t s );
bool (*eof)(void* )
};
vtable& _vtable;
void* _stream;
};

View file

@ -1,69 +0,0 @@
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
#include <fc/reflect.hpp>
namespace fc {
class path;
class sha1 {
public:
sha1();
explicit sha1( const fc::string& hex_str );
fc::string str()const;
operator fc::string()const;
char* data()const;
static sha1 hash( const char* d, uint32_t dlen );
static sha1 hash( const fc::string& );
static sha1 hash( const fc::path& );
template<typename T>
static sha1 hash( const T& t ) { sha1::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();
sha1 result();
private:
struct impl;
fwd<impl,96> my;
};
template<typename T>
inline friend T& operator<<( T& ds, const sha1& ep ) {
ds.write( ep.data(), sizeof(ep) );
return ds;
}
template<typename T>
inline friend T& operator>>( T& ds, sha1& ep ) {
ds.read( ep.data(), sizeof(ep) );
return ds;
}
friend sha1 operator << ( const sha1& h1, uint32_t i );
friend bool operator == ( const sha1& h1, const sha1& h2 );
friend bool operator != ( const sha1& h1, const sha1& h2 );
friend sha1 operator ^ ( const sha1& h1, const sha1& h2 );
friend bool operator >= ( const sha1& h1, const sha1& h2 );
friend bool operator > ( const sha1& h1, const sha1& h2 );
friend bool operator < ( const sha1& h1, const sha1& h2 );
uint32_t _hash[5];
};
class value;
void pack( fc::value& , const fc::sha1& );
void unpack( const fc::value& , fc::sha1& );
}

View file

@ -1,69 +0,0 @@
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
#include <fc/reflect.hpp>
namespace fc {
class path;
class sha256 {
public:
sha256();
explicit sha256( const fc::string& hex_str );
fc::string str()const;
operator fc::string()const;
char* data()const;
static sha256 hash( const char* d, uint32_t dlen );
static sha256 hash( const fc::string& );
static sha256 hash( const fc::path& );
template<typename T>
static sha256 hash( const T& t ) { sha256::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();
sha256 result();
private:
struct impl;
fwd<impl,96> my;
};
template<typename T>
inline friend T& operator<<( T& ds, const sha256& ep ) {
ds.write( ep.data(), sizeof(ep) );
return ds;
}
template<typename T>
inline friend T& operator>>( T& ds, sha256& ep ) {
ds.read( ep.data(), sizeof(ep) );
return ds;
}
friend sha256 operator << ( const sha256& h1, uint32_t i );
friend bool operator == ( const sha256& h1, const sha256& h2 );
friend bool operator != ( const sha256& h1, const sha256& h2 );
friend sha256 operator ^ ( const sha256& h1, const sha256& h2 );
friend bool operator >= ( const sha256& h1, const sha256& h2 );
friend bool operator > ( const sha256& h1, const sha256& h2 );
friend bool operator < ( const sha256& h1, const sha256& h2 );
uint64_t _hash[4];
};
class value;
void pack( fc::value& , const fc::sha256& );
void unpack( const fc::value& , fc::sha256& );
}

View file

@ -1,84 +0,0 @@
#pragma once
#include <fc/shared_impl.hpp>
namespace fc {
template<typename T>
typename shared_impl<T>::impl& shared_impl<T>::operator* ()const { return *_impl; }
template<typename T>
typename shared_impl<T>::impl* shared_impl<T>::operator-> ()const { return _impl.get(); }
template<typename T>
template<typename U>
shared_impl<T>::shared_impl( U&& u ):_impl(fc::forward<U>(u)){}
template<typename T>
shared_impl<T>::shared_impl( const shared_impl<T>& u ):_impl(u._impl){}
//template<typename T>
//shared_impl<T>::shared_impl( shared_impl<T>& u ):_impl(u._impl){}
template<typename T>
shared_impl<T>::shared_impl( shared_impl<T>&& u ):_impl(fc::move(u._impl)){}
template<typename T>
shared_impl<T>& shared_impl<T>::operator=( shared_impl<T>&& u ) {
fc_swap(_impl,u._impl);
return *this;
}
template<typename T>
shared_impl<T>& shared_impl<T>::operator=( const shared_impl<T>& u ) {
_impl = u._impl;
return *this;
}
template<typename T>
bool shared_impl<T>::operator !()const { return !_impl; }
template<typename T>
shared_impl<T>::~shared_impl(){}
}
#define FC_REFERENCE_TYPE_IMPL( TYPE ) \
template<typename A1> \
TYPE::TYPE( A1&& a1 ) \
:my( new typename fc::shared_impl<TYPE>::impl( fc::forward<A1>(a1) ) ){}\
template<typename A1,typename A2> \
TYPE::TYPE( A1&& a1, A2&& a2 ) \
:my( new typename fc::shared_impl<TYPE>::impl( fc::forward<A1>(a1), fc::forward<A2>(a2) ) ){}\
template<typename A1,typename A2, typename A3> \
TYPE::TYPE( A1&& a1, A2&& a2, A3&& a3 ) \
:my( new fc::shared_impl<TYPE>::impl( fc::forward<A1>(a1), fc::forward<A2>(a2), fc::forward<A3>(a3) ) ){}\
TYPE::TYPE( shared_impl<TYPE>::impl* m ) \
:my(m){}\
TYPE::TYPE( TYPE* c )\
:my(fc::move(c->my)){ delete c; }\
TYPE::TYPE( TYPE&& c )\
:my(fc::move(c.my)){}\
TYPE::TYPE( const TYPE& c )\
:my(c.my){}\
TYPE::TYPE() \
:my( new fc::shared_impl<TYPE>::impl( ) ){}\
TYPE::~TYPE(){}\
bool TYPE::operator !()const { return !my; }\
TYPE& TYPE::operator = ( const TYPE& c ) {\
my = c.my;\
return *this;\
}\
TYPE& TYPE::operator = ( TYPE&& c ) {\
fc_swap( my._impl, c.my._impl );\
return *this;\
}\
TYPE& TYPE::operator = ( TYPE* c ) {\
fc_swap( my._impl, c->my._impl );\
delete c;\
return *this;\
} \
bool operator==( const TYPE& a, const TYPE& b ) {\
return a.my._impl.get() == b.my._impl.get(); \
} \
bool operator!=( const TYPE& a, const TYPE& b ) {\
return a.my._impl.get() != b.my._impl.get(); \
}

View file

@ -1,163 +0,0 @@
#pragma once
#include <fc/shared_ptr.hpp>
namespace fc {
/**
* @class shared_impl<T>
* @brief used to create types with reference semantics
*
* A type with reference semantics is effectively a shared pointer except that
* it is used like a Java or C# type using '.' notation instead of -> notation.
*
* It is ideal for use with classes that almost always get managed by a shared
* pointer (sockets and long-lived resources). These types are rarely, if ever
* copied by value and often by-value copy or 'deep-copy' has no real meaning.
*
* An additional feature of shared_impl<T> is that your classes implementation
* should be private and defined entirely in your source file. There should be
* no member variables defined in your types header.
*
* To make this design pattern work requires a lot of 'boiler-plate' code for
* handling assignments, moves, copies, etc that cannot be provided via tradtional
* means such as templates or base classes.
*
* To create a new type with reference semantics you place FC_REFERENCE_TYPE(type)
* inside the private section of 'type'. Then in your source file you will
* need to define your 'private' data.
*
* @code
* #include <your_type.hpp>
*
* FC_START_SHARED_IMPL( your_namespace::your_type )
* impl( int x, int y ); // custom constructor
*
* ...
* int member_variable;
* your private member variables / methods go here.
* ...
* FC_END_SHARED_IMPL
* #include <fc/shared_impl.cpp>
* @endcode
*
*
* Lastly, you will need to provide the implementation your class below. This
* implementation will need to provide the matching implementations for the
* methods declared by FC_REFERENCE_TYPE(type) in your header. To do this
* use the FC_REFERENCE_TYPE_IMPL(type)
*
* @code
* namespace your_namespace {
* FC_REFERENCE_TYPE(your_type)
* ... your methods here...
* }
* @endcode
*
* Within the body of your methods you can access your private data and members
* via using 'my->member_variable'
*
* If you want to define custom constructors for your reference type, you will
* need to implement them inside the FC_START_SHARED_IMPL block using the pattern:
*
* @code
* FC_START_SHARED_IMPL( your_namespace::your_type )
* impl( int x, int y ){} // custom constructor
* FC_END_SHARED_IMPL
* @code
*
* A limited number (3) of arguments are supported for custom constructors.
*
* Once you have defined your reference type you can use it like so:
*
* @code
* your_type val = nullptr; // create a null type
* your_type val2 = new your_type(...); // construct a new instance, unnecessary temporary heap alloc
* your_type val3(...); // constructs a new instance, more effecient
*
* val2.your_method();
* val2 = nullptr; // reset val2 to a null object
*
* val2 = val3; // val2 and val3 now reference the same data
* if( !!val2 ){} // val2 is not null
* else{} // val2 is null
* @endcode
*
* As you can see, when creating types with this method your code will
* look and act like a Java or C# garbage collected type.
*
* Often times your private methods will need to call your public methods, to achieve
* this you can use the following techinque:
*
* @code
* FC_START_SHARED_IMPL( your_namespace::your_type )
* void private_method( int x, int y ){
* auto s = self();
* s.public_method();
* }
* FC_END_SHARED_IMPL
* @code
*
* For performance reasons, it is best to only call 'self()' once and save the
* result to avoid unnecessary copies of shared pointers which require atomic
* operations.
*
*/
template<typename T>
struct shared_impl {
class impl;
impl& operator* ()const;
impl* operator-> ()const;
bool operator !()const;
template<typename U>
explicit shared_impl( U&& u );
shared_impl( const shared_impl& u );
// shared_impl( shared_impl& u );
shared_impl( shared_impl&& u );
shared_impl& operator=( shared_impl&& u );
shared_impl& operator=( const shared_impl& u );
~shared_impl();
fc::shared_ptr<typename shared_impl<T>::impl> _impl;
};
}
#define FC_REFERENCE_TYPE( TYPE ) \
public:\
TYPE(); \
TYPE( std::nullptr_t ); \
TYPE( TYPE* ); \
TYPE( TYPE&& ); \
TYPE( const TYPE& ); \
template<typename A1> \
TYPE( A1&& ); \
template<typename A1,typename A2> \
TYPE( A1&&, A2&& ); \
template<typename A1,typename A2, typename A3> \
TYPE( A1&&, A2&&, A3&& ); \
~TYPE(); \
bool operator !()const; \
friend bool operator==( const TYPE& a, const TYPE& b ); \
friend bool operator!=( const TYPE& a, const TYPE& b ); \
TYPE& operator = ( const TYPE& ); \
TYPE& operator = ( TYPE&& );\
TYPE& operator = ( TYPE* );\
TYPE& operator = ( std::nullptr_t );\
private: \
friend class shared_impl<TYPE>::impl; \
TYPE( shared_impl<TYPE>::impl* m ); \
shared_impl<TYPE> my;
#define FC_START_SHARED_IMPL( SCOPED_TYPE ) \
namespace fc { \
template<> \
class fc::shared_impl<SCOPED_TYPE>::impl : public fc::retainable { \
public:\
SCOPED_TYPE self() { return SCOPED_TYPE(this); } \
#define FC_END_SHARED_IMPL }; }

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