提交 fc709930 编写于 作者: B Bucky Kittinger

Merged master

......@@ -58,15 +58,22 @@ if( NOT ("${WASM_CLANG}" STREQUAL "" OR "${WASM_LLC}" STREQUAL "" OR "${WASM_LLV
set(WASM_TOOLCHAIN TRUE)
endif()
macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
macro(compile_wast)
cmake_parse_arguments(ARG "" "TARGET" "SOURCE_FILES;INCLUDE_FOLDERS" ${ARGN})
set(target ${ARG_TARGET})
# NOTE: Setting SOURCE_FILE and looping over it to avoid cmake issue with compilation ${target}.bc's rule colliding with
# linking ${target}.bc's rule
set(SOURCE_FILE ${target}.cpp)
# linking ${target}.bc's rule
if ("${ARG_SOURCE_FILES}" STREQUAL "")
set(SOURCE_FILES ${target}.cpp)
else()
set(SOURCE_FILES ${ARG_SOURCE_FILES})
endif()
set(outfiles "")
foreach(srcfile ${SOURCE_FILE})
foreach(srcfile ${SOURCE_FILES})
get_filename_component(outfile ${srcfile} NAME)
get_filename_component(extension ${srcfile} EXT)
get_filename_component(infile ${srcfile} ABSOLUTE)
# -ffreestanding
......@@ -89,12 +96,17 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
# -fno-exceptions
# Disable the generation of extra code needed to propagate exceptions
if ("${extension}" STREQUAL ".c")
set(STDFLAG -D_XOPEN_SOURCE=700)
else()
set(STDFLAG "--std=c++14")
endif()
set(WASM_COMMAND ${WASM_CLANG} -emit-llvm -O3 --std=c++14 --target=wasm32 -ffreestanding
-nostdlib -fno-threadsafe-statics -fno-rtti -fno-exceptions
set(WASM_COMMAND ${WASM_CLANG} -emit-llvm -O3 ${STDFLAG} --target=wasm32 -ffreestanding
-nostdlib -nostdlibinc -fno-threadsafe-statics -fno-rtti -fno-exceptions
-c ${infile} -o ${outfile}.bc
)
foreach(folder ${INCLUDE_FOLDERS})
foreach(folder ${ARG_INCLUDE_FOLDERS})
list(APPEND WASM_COMMAND -I ${folder})
endforeach()
......@@ -111,18 +123,51 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
endforeach(srcfile)
add_custom_command(OUTPUT ${target}.bc
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.bc)
endmacro(compile_wast)
macro(add_wast_library)
cmake_parse_arguments(ARG "" "TARGET;DESTINATION_FOLDER" "SOURCE_FILES;INCLUDE_FOLDERS" ${ARGN})
set(target ${ARG_TARGET})
compile_wast(TARGET ${ARG_TARGET} SOURCE_FILES ${ARG_SOURCE_FILES} INCLUDE_FOLDERS ${ARG_INCLUDE_FOLDERS})
get_filename_component("${ARG_TARGET}_BC_FILENAME" "${ARG_DESTINATION_FOLDER}/${ARG_TARGET}.bc" ABSOLUTE CACHE)
add_custom_target(${target} ALL DEPENDS ${${ARG_TARGET}_BC_FILENAME})
add_custom_command(OUTPUT ${${ARG_TARGET}_BC_FILENAME}
DEPENDS ${outfiles}
COMMAND ${WASM_LLVM_LINK} -o ${target}.bc ${outfiles}
COMMENT "Linking LLVM bitcode ${target}.bc"
COMMAND ${WASM_LLVM_LINK} -o ${${ARG_TARGET}_BC_FILENAME} ${outfiles}
COMMENT "Linking LLVM bitcode library ${target}.bc"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
)
endmacro(add_wast_library)
macro(add_wast_executable)
cmake_parse_arguments(ARG "" "TARGET;DESTINATION_FOLDER" "SOURCE_FILES;INCLUDE_FOLDERS;LIBRARIES" ${ARGN})
set(target ${ARG_TARGET})
set(DESTINATION_FOLDER ${ARG_DESTINATION_FOLDER})
compile_wast(TARGET ${ARG_TARGET} SOURCE_FILES ${ARG_SOURCE_FILES} INCLUDE_FOLDERS ${ARG_INCLUDE_FOLDERS})
foreach(lib ${ARG_LIBRARIES})
list(APPEND LIBRARIES ${${lib}_BC_FILENAME})
endforeach()
add_custom_command(OUTPUT ${target}.bc
DEPENDS ${outfiles} ${ARG_LIBRARIES} ${LIBRARIES}
COMMAND ${WASM_LLVM_LINK} -only-needed -o ${target}.bc ${outfiles} ${LIBRARIES}
COMMENT "Linking LLVM bitcode executable ${target}.bc"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
)
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.bc)
add_custom_command(OUTPUT ${target}.s
DEPENDS ${target}.bc
COMMAND ${WASM_LLC} -asm-verbose=false -o ${target}.s ${target}.bc
COMMAND ${WASM_LLC} -thread-model=single -asm-verbose=false -o ${target}.s ${target}.bc
COMMENT "Generating textual assembly ${target}.s"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
......@@ -132,7 +177,6 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.wast
DEPENDS ${target}.s
COMMAND ${BINARYEN_BIN}/s2wasm -o ${DESTINATION_FOLDER}/${target}.wast -s 4096 ${target}.s
COMMENT "Generating WAST ${target}.wast"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
......@@ -149,7 +193,7 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
VERBATIM
)
if (EXISTS ${DESTINATION_FOLDER}/${target}.abi )
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${target}.abi )
add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.abi.hpp
DEPENDS ${DESTINATION_FOLDER}/${target}.abi
COMMAND echo "const char* const ${TARGET_VARIABLE}_abi = R\"=====(" > ${DESTINATION_FOLDER}/${target}.abi.hpp
......@@ -163,13 +207,12 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
else()
endif()
add_custom_target(${target} ALL DEPENDS ${DESTINATION_FOLDER}/${target}.wast.hpp ${extra_target_dependency})
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${DESTINATION_FOLDER}/${target}.wast.hpp)
set_property(TARGET ${target} PROPERTY INCLUDE_DIRECTORIES ${INCLUDE_FOLDERS})
set_property(TARGET ${target} PROPERTY INCLUDE_DIRECTORIES ${ARG_INCLUDE_FOLDERS})
set(extra_target_dependency)
endmacro(add_wast_target)
endmacro(add_wast_executable)
set(STANDARD_INCLUDE_FOLDERS ${CMAKE_SOURCE_DIR}/contracts ${CMAKE_SOURCE_DIR}/contracts/libc++/include ${CMAKE_SOURCE_DIR}/contracts/musl/include)
add_subdirectory(eosiolib)
add_subdirectory(musl/src)
add_subdirectory(libc++/src)
add_subdirectory(eosio.system)
add_subdirectory(identity)
add_subdirectory(currency)
add_subdirectory(stltest)
#add_subdirectory(bancor)
#add_subdirectory(eosio.system)
add_subdirectory(asserter)
......@@ -13,6 +20,7 @@ add_subdirectory(test_api_mem)
#add_subdirectory(simpledb)
#add_subdirectory(storage)
#add_subdirectory(social)
add_subdirectory(test.system)
add_subdirectory(noop)
install( DIRECTORY eosiolib DESTINATION include/ )
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(asserter "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET asserter
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -29,9 +29,9 @@ extern "C" {
}
// maybe assert?
assert(def->condition, def->message);
eos_assert(def->condition, def->message);
} else if( action == N(provereset) ) {
assert(global_variable == 45, "Global Variable Initialized poorly");
eos_assert(global_variable == 45, "Global Variable Initialized poorly");
global_variable = 100;
}
}
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(bancor "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET bancor
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -82,7 +82,7 @@ namespace bancor {
save_and_send( trans.from, state, output, args.min_return );
}
else {
assert( false, "invalid to currency" );
eos_assert( false, "invalid to currency" );
}
}
......@@ -118,7 +118,7 @@ namespace bancor {
template<typename CurrencyType>
static void start_convert( const typename CurrencyType::transfer_memo& trans ) {
auto args = unpack<converter_args>( trans.memo );
assert( args.to_currency_type != trans.quantity.token_type(), "cannot convert to self" );
eos_assert( args.to_currency_type != trans.quantity.token_type(), "cannot convert to self" );
auto state = read_converter_state();
on_convert( trans, args, state );
......@@ -148,7 +148,7 @@ namespace bancor {
if( trans.to == converter_account ) {
start_convert( trans );
} else {
assert( trans.from == converter_account,
eos_assert( trans.from == converter_account,
"received unexpected notification of transfer" );
}
}
......@@ -159,7 +159,7 @@ namespace bancor {
converter_currency::issue,
first_currency::transfer,
second_currency::transfer ) {
assert( false, "received unexpected action" );
eos_assert( false, "received unexpected action" );
}
}
}; /// converter_contract
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(currency "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET currency
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -6,8 +6,8 @@
namespace dice {
void apply_offer( const offer_bet& offer ) {
assert( offer.amount > 0, "insufficient bet" );
assert( !hasOffer( offer.commitment ), "offer with this commitment already exist" );
eos_assert( offer.amount > 0, "insufficient bet" );
eos_assert( !hasOffer( offer.commitment ), "offer with this commitment already exist" );
require_auth( offer.player );
auto acnt = get_account( offer.player );
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(eosio.system "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET eosio.system
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -104,7 +104,7 @@ namespace eosiosystem {
if( !eosio::dispatch<contract, regproducer, regproxy, nonce>( code, act) ) {
if ( !eosio::dispatch<currency, typename currency::transfer, typename currency::issue>( code, act ) ) {
eosio::print("Unexpected action: ", act, "\n");
assert( false, "received unexpected action");
eos_assert( false, "received unexpected action");
}
}
} /// apply
......
add_wast_library(TARGET eosiolib
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -61,8 +61,8 @@ extern "C" {
* account_name code = current_receiver();
* print(Name(code)); // Output: eos
*
* assert(Name(current_receiver()) === "eos", "This action expects to be received by eos"); // Do nothing
* assert(Name(current_receiver()) === "inita", "This action expects to be received by inita"); // Throws exception and roll back transfer transaction
* eos_assert(Name(current_receiver()) === "eos", "This action expects to be received by eos"); // Do nothing
* eos_assert(Name(current_receiver()) === "inita", "This action expects to be received by inita"); // Throws exception and roll back transfer transaction
*
* print(now()); // Output: timestamp of last accepted block
*
......
......@@ -40,7 +40,7 @@ namespace eosio {
T current_action() {
T value;
auto read = read_action( &value, sizeof(value) );
assert( read >= sizeof(value), "action shorter than expected" );
eos_assert( read >= sizeof(value), "action shorter than expected" );
return value;
}
......
......@@ -51,7 +51,7 @@
if( action == N(transfer) )
currency::apply_currency_transfer( current_action< currency::transfer >() );
} else {
assert( false, "rejecting unexpected event" );
eos_assert( false, "rejecting unexpected event" );
}
}
}
......
......@@ -10,14 +10,14 @@ extern "C" {
*
* checksum calc_hash;
* sha256( data, length, &calc_hash );
* assert( calc_hash == hash, "invalid hash" );
* eos_assert( calc_hash == hash, "invalid hash" );
*
* This method is optimized to a NO-OP when in fast evaluation mode
*/
void assert_sha256( char* data, uint32_t length, const checksum* hash );
void eos_assert_sha256( char* data, uint32_t length, const checksum* hash );
/**
* Calculates sha256( data,length) and stores result in memory pointed to by hash
*/
void sha256( char* data, uint32_t length, checksum* hash );
}
\ No newline at end of file
}
......@@ -33,7 +33,7 @@ class datastream {
* @param s the number of bytes to read
*/
inline bool read( char* d, size_t s ) {
assert( size_t(_end - _pos) >= (size_t)s, "read" );
eos_assert( size_t(_end - _pos) >= (size_t)s, "read" );
memcpy( d, _pos, s );
_pos += s;
return true;
......@@ -46,7 +46,7 @@ class datastream {
* @param s The number of bytes to write
*/
inline bool write( const char* d, size_t s ) {
assert( _end - _pos >= (int32_t)s, "write" );
eos_assert( _end - _pos >= (int32_t)s, "write" );
memcpy( _pos, d, s );
_pos += s;
return true;
......@@ -58,7 +58,7 @@ class datastream {
* @param c byte to write
*/
inline bool put(char c) {
assert( _pos < _end, "put" );
eos_assert( _pos < _end, "put" );
*_pos = c;
++_pos;
return true;
......@@ -72,7 +72,7 @@ class datastream {
inline bool get( unsigned char& c ) { return get( *(char*)&c ); }
inline bool get( char& c )
{
assert( _pos < _end, "get" );
eos_assert( _pos < _end, "get" );
c = *_pos;
++_pos;
return true;
......@@ -428,5 +428,3 @@ bytes pack( const T& value ) {
}
......@@ -388,7 +388,7 @@ struct table {
* @return true if successful store.
*/
static bool store( const Record& r, uint64_t s = scope, uint64_t b = bta ) {
assert( impl::store( s, table_n, b, &r, sizeof(r) ), "error storing record" );
eos_assert( impl::store( s, table_n, b, &r, sizeof(r) ), "error storing record" );
return true;
}
......@@ -401,7 +401,7 @@ struct table {
* @return true if successful update.
*/
static bool update( const Record& r, uint64_t s = scope, uint64_t b = bta ) {
assert( impl::update( s, table_n, b, &r, sizeof(r) ), "error updating record" );
eos_assert( impl::update( s, table_n, b, &r, sizeof(r) ), "error updating record" );
return true;
}
......
#include "memory.hpp"
namespace eosio {
using ::memset;
using ::memcpy;
/**
* @defgroup memorycppapi Memory C++ API
* @brief Defines common memory functions
* @ingroup memoryapi
*
* @{
*/
class memory_manager // NOTE: Should never allocate another instance of memory_manager
{
friend void* ::malloc(size_t size);
friend void* ::calloc(size_t count, size_t size);
friend void* ::realloc(void* ptr, size_t size);
friend void ::free(void* ptr);
public:
memory_manager()
// NOTE: it appears that WASM has an issue with initialization lists if the object is globally allocated,
// and seems to just initialize members to 0
: _heaps_actual_size(0)
, _active_heap(0)
, _active_free_heap(0)
{
}
private:
class memory;
memory* next_active_heap()
{
memory* const current_memory = _available_heaps + _active_heap;
// make sure we will not exceed the 1M limit (needs to match wasm_interface.cpp _max_memory)
auto remaining = 1024 * 1024 - reinterpret_cast<int32_t>(sbrk(0));
if (remaining <= 0)
{
// ensure that any remaining unallocated memory gets cleaned up
current_memory->cleanup_remaining();
++_active_heap;
_heaps_actual_size = _active_heap;
return nullptr;
}
const uint32_t new_heap_size = remaining > _new_heap_size ? _new_heap_size : remaining;
char* new_memory_start = static_cast<char*>(sbrk(new_heap_size));
// if we can expand the current memory, keep working with it
if (current_memory->expand_memory(new_memory_start, new_heap_size))
return current_memory;
// ensure that any remaining unallocated memory gets cleaned up
current_memory->cleanup_remaining();
++_active_heap;
memory* const next = _available_heaps + _active_heap;
next->init(new_memory_start, new_heap_size);
return next;
}
void* malloc(uint32_t size)
{
if (size == 0)
return nullptr;
// see Note on ctor
if (_heaps_actual_size == 0)
_heaps_actual_size = _heaps_size;
adjust_to_mem_block(size);
// first pass of loop never has to initialize the slot in _available_heap
uint32_t needs_init = 0;
char* buffer = nullptr;
memory* current = nullptr;
// need to make sure
if (_active_heap < _heaps_actual_size)
{
memory* const start_heap = &_available_heaps[_active_heap];
// only heap 0 won't be initialized already
if(_active_heap == 0 && !start_heap->is_init())
{
start_heap->init(_initial_heap, _initial_heap_size);
}
current = start_heap;
}
while (current != nullptr)
{
buffer = current->malloc(size);
// done if we have a buffer
if (buffer != nullptr)
break;
current = next_active_heap();
}
if (buffer == nullptr)
{
const uint32_t end_free_heap = _active_free_heap;
do
{
buffer = _available_heaps[_active_free_heap].malloc_from_freed(size);
if (buffer != nullptr)
break;
if (++_active_free_heap == _heaps_actual_size)
_active_free_heap = 0;
} while (_active_free_heap != end_free_heap);
}
return buffer;
}
void* realloc(void* ptr, uint32_t size)
{
if (size == 0)
{
free(ptr);
return nullptr;
}
const uint32_t REMOVE = size;
adjust_to_mem_block(size);
char* realloc_ptr = nullptr;
uint32_t orig_ptr_size = 0;
if (ptr != nullptr)
{
char* const char_ptr = static_cast<char*>(ptr);
for (memory* realloc_heap = _available_heaps; realloc_heap < _available_heaps + _heaps_actual_size && realloc_heap->is_init(); ++realloc_heap)
{
if (realloc_heap->is_in_heap(char_ptr))
{
realloc_ptr = realloc_heap->realloc_in_place(char_ptr, size, &orig_ptr_size);
if (realloc_ptr != nullptr)
return realloc_ptr;
else
break;
}
}
}
char* new_alloc = static_cast<char*>(malloc(size));
if (new_alloc == nullptr)
return nullptr;
const uint32_t copy_size = (size < orig_ptr_size) ? size : orig_ptr_size;
if (copy_size > 0)
{
memcpy(new_alloc, ptr, copy_size);
free (ptr);
}
return new_alloc;
}
void free(void* ptr)
{
if (ptr == nullptr)
return;
char* const char_ptr = static_cast<char*>(ptr);
for (memory* free_heap = _available_heaps; free_heap < _available_heaps + _heaps_actual_size && free_heap->is_init(); ++free_heap)
{
if (free_heap->is_in_heap(char_ptr))
{
free_heap->free(char_ptr);
break;
}
}
}
void adjust_to_mem_block(uint32_t& size)
{
const uint32_t remainder = (size + _size_marker) & _rem_mem_block_mask;
if (remainder > 0)
{
size += _mem_block - remainder;
}
}
class memory
{
public:
memory()
: _heap_size(0)
, _heap(nullptr)
, _offset(0)
{
}
void init(char* const mem_heap, uint32_t size)
{
_heap_size = size;
_heap = mem_heap;
memset(_heap, 0, _heap_size);
}
uint32_t is_init() const
{
return _heap != nullptr;
}
uint32_t is_in_heap(const char* const ptr) const
{
const char* const end_of_buffer = _heap + _heap_size;
const char* const first_ptr_of_buffer = _heap + _size_marker;
return ptr >= first_ptr_of_buffer && ptr < end_of_buffer;
}
uint32_t is_capacity_remaining() const
{
return _offset + _size_marker < _heap_size;
}
char* malloc(uint32_t size)
{
uint32_t used_up_size = _offset + size + _size_marker;
if (used_up_size > _heap_size)
{
return nullptr;
}
buffer_ptr new_buff(&_heap[_offset + _size_marker], size, _heap + _heap_size);
_offset += size + _size_marker;
new_buff.mark_alloc();
return new_buff.ptr();
}
char* malloc_from_freed(uint32_t size)
{
eos_assert(_offset == _heap_size, "malloc_from_freed was designed to only be called after _heap was completely allocated");
char* current = _heap + _size_marker;
while (current != nullptr)
{
buffer_ptr current_buffer(current, _heap + _heap_size);
if (!current_buffer.is_alloc())
{
// done if we have enough contiguous memory
if (current_buffer.merge_contiguous(size))
{
current_buffer.mark_alloc();
return current;
}
}
current = current_buffer.next_ptr();
}
// failed to find any free memory
return nullptr;
}
char* realloc_in_place(char* const ptr, uint32_t size, uint32_t* orig_ptr_size)
{
const char* const end_of_buffer = _heap + _heap_size;
buffer_ptr orig_buffer(ptr, end_of_buffer);
*orig_ptr_size = orig_buffer.size();
// is the passed in pointer valid
char* const orig_buffer_end = orig_buffer.end();
if (orig_buffer_end > end_of_buffer)
{
*orig_ptr_size = 0;
return nullptr;
}
if (ptr > end_of_buffer - size)
{
// cannot resize in place
return nullptr;
}
const int32_t diff = size - *orig_ptr_size;
if (diff < 0)
{
// use a buffer_ptr to allocate the memory to free
char* const new_ptr = ptr + size + _size_marker;
buffer_ptr excess_to_free(new_ptr, -diff, _heap + _heap_size);
excess_to_free.mark_free();
return ptr;
}
// if ptr was the last allocated buffer, we can expand
else if (orig_buffer_end == &_heap[_offset])
{
orig_buffer.size(size);
_offset += diff;
return ptr;
}
if (-diff == 0)
return ptr;
if (!orig_buffer.merge_contiguous_if_available(size))
// could not resize in place
return nullptr;
orig_buffer.mark_alloc();
return ptr;
}
void free(char* ptr)
{
buffer_ptr to_free(ptr, _heap + _heap_size);
to_free.mark_free();
}
void cleanup_remaining()
{
if (_offset == _heap_size)
return;
// take the remaining memory and act like it was allocated
const uint32_t size = _heap_size - _offset - _size_marker;
buffer_ptr new_buff(&_heap[_offset + _size_marker], size, _heap + _heap_size);
_offset = _heap_size;
new_buff.mark_free();
}
bool expand_memory(char* exp_mem, uint32_t size)
{
if (_heap + _heap_size != exp_mem)
return false;
_heap_size += size;
return true;
}
private:
class buffer_ptr
{
public:
buffer_ptr(void* ptr, const char* const heap_end)
: _ptr(static_cast<char*>(ptr))
, _size(*reinterpret_cast<uint32_t*>(static_cast<char*>(ptr) - _size_marker) & ~_alloc_memory_mask)
, _heap_end(heap_end)
{
}
buffer_ptr(void* ptr, uint32_t buff_size, const char* const heap_end)
: _ptr(static_cast<char*>(ptr))
, _heap_end(heap_end)
{
size(buff_size);
}
uint32_t size() const
{
return _size;
}
char* next_ptr() const
{
char* const next = end() + _size_marker;
if (next >= _heap_end)
return nullptr;
return next;
}
void size(uint32_t val)
{
// keep the same state (allocated or free) as was set before
const uint32_t memory_state = *reinterpret_cast<uint32_t*>(_ptr - _size_marker) & _alloc_memory_mask;
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) = val | memory_state;
_size = val;
}
char* end() const
{
return _ptr + _size;
}
char* ptr() const
{
return _ptr;
}
void mark_alloc()
{
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) |= _alloc_memory_mask;
}
void mark_free()
{
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) &= ~_alloc_memory_mask;
}
bool is_alloc() const
{
return *reinterpret_cast<const uint32_t*>(_ptr - _size_marker) & _alloc_memory_mask;
}
bool merge_contiguous_if_available(uint32_t needed_size)
{
return merge_contiguous(needed_size, true);
}
bool merge_contiguous(uint32_t needed_size)
{
return merge_contiguous(needed_size, false);
}
private:
bool merge_contiguous(uint32_t needed_size, bool all_or_nothing)
{
// do not bother if there isn't contiguious space to allocate
if (all_or_nothing && _heap_end - _ptr < needed_size)
return false;
uint32_t possible_size = _size;
while (possible_size < needed_size && (_ptr + possible_size < _heap_end))
{
const uint32_t next_mem_flag_size = *reinterpret_cast<const uint32_t*>(_ptr + possible_size);
// if ALLOCed then done with contiguous free memory
if (next_mem_flag_size & _alloc_memory_mask)
break;
possible_size += (next_mem_flag_size & ~_alloc_memory_mask) + _size_marker;
}
if (all_or_nothing && possible_size < needed_size)
return false;
// combine
const uint32_t new_size = possible_size < needed_size ? possible_size : needed_size;
size(new_size);
if (possible_size > needed_size)
{
const uint32_t freed_size = possible_size - needed_size - _size_marker;
buffer_ptr freed_remainder(_ptr + needed_size + _size_marker, freed_size, _heap_end);
freed_remainder.mark_free();
}
return new_size == needed_size;
}
char* _ptr;
uint32_t _size;
const char* const _heap_end;
};
uint32_t _heap_size;
char* _heap;
uint32_t _offset;
};
static const uint32_t _size_marker = sizeof(uint32_t);
// allocate memory in 8 char blocks
static const uint32_t _mem_block = 8;
static const uint32_t _rem_mem_block_mask = _mem_block - 1;
static const uint32_t _initial_heap_size = 8192;//32768;
static const uint32_t _new_heap_size = 65536;
// if sbrk is not called outside of this file, then this is the max times we can call it
static const uint32_t _heaps_size = 16;
char _initial_heap[_initial_heap_size];
memory _available_heaps[_heaps_size];
uint32_t _heaps_actual_size;
uint32_t _active_heap;
uint32_t _active_free_heap;
static const uint32_t _alloc_memory_mask = 1 << 31;
};
memory_manager memory_heap;
}
extern "C" {
void* __dso_handle = 0;
void* malloc(size_t size)
{
return eosio::memory_heap.malloc(size);
}
void* calloc(size_t count, size_t size)
{
return eosio::memory_heap.malloc(count*size);
}
void* realloc(void* ptr, size_t size)
{
return eosio::memory_heap.realloc(ptr, size);
}
void free(void* ptr)
{
return eosio::memory_heap.free(ptr);
}
}
......@@ -41,7 +41,7 @@ namespace eosio {
template<typename DataStream>
friend DataStream& operator >> ( DataStream& ds, transfer& t ){
ds >> t.from >> t.to >> t.quantity;
assert( t.quantity.symbol== token_type::symbol, "unexpected asset type" );
eos_assert( t.quantity.symbol== token_type::symbol, "unexpected asset type" );
return ds;
}
};
......
......@@ -34,4 +34,4 @@ Welcome to the EOS.IO Documentation
- @ref transactionapi - Define API for sending transactions and inline messages
- @ref types - Specifies typedefs and aliases
\ No newline at end of file
......@@ -102,7 +102,7 @@ namespace eosio {
}
explicit operator uint64_t()const {
assert( !(value >> 64), "cast to 64 bit loss of precision" );
eos_assert( !(value >> 64), "cast to 64 bit loss of precision" );
return uint64_t(value);
}
......
......@@ -4,89 +4,5 @@
*/
#pragma once
#include <string.h>
#include <eosiolib/types.h>
/**
* @defgroup memoryapi Memory API
* @brief Defines common memory functions
* @ingroup contractdev
*/
extern "C" {
/**
* @defgroup memorycapi Memory C API
* @brief Defines common memory functions
* @ingroup memoryapi
*
* @{
*/
/**
* Allocate page(s) of memory to accommodate the
* requested number of bytes.
* @brief Allocate page memory
* @param num_bytes Number of bytes to add.
*
* @return void pointer to the previous end of allocated bytes
*
* Example:
* @code
* // allocate a whole new page, the returned offset is the pointer to the
* // newly allocated page
* char* new_page = static_cast<char*>(sbrk(65536));
* memset(new_page, 0, 65536);
* @endcode
*/
void* sbrk( uint32_t num_bytes );
/**
* Copy a block of memory from source to destination.
* @brief Copy a block of memory from source to destination.
* @param destination Pointer to the destination to copy to.
* @param source Pointer to the source for copy from.
* @param num Number of bytes to copy.
*
* @return the destination pointer
*
* Example:
* @code
* char dest[6] = { 0 };
* char source[6] = { 'H', 'e', 'l', 'l', 'o', '\0' };
* memcpy(dest, source, 6 * sizeof(char));
* prints(dest); // Output: Hello
* @endcode
*/
void* memcpy( void* destination, const void* source, uint32_t num );
/**
* Compare block of memory from source to destination.
* @brief Copy a block of memory from source to destination.
* @param ptr1 Pointer to first data to compare
* @param ptr2 Pointer to second data to compare
* @param num Number of bytes to compare.
*
* @return the destination pointer
*
*/
int32_t memcmp( void* ptr1, const void* ptr2, uint32_t num );
/**
* Fill block of memory.
* @brief Fill a block of memory with the provided value.
* @param ptr Pointer to memory to fill.
* @param value Value to set (it is passed as an int but converted to unsigned char).
* @param num Number of bytes to be set to the value.
*
* @return the destination pointer
*
* Example:
* @code
* char ptr[6] = { 'H', 'e', 'l', 'l', 'o', '\0' };
* memset(ptr, 'y', 6 * sizeof(char));
* prints(ptr); // Output: yyyyyy
* @endcode
*/
void* memset( void* ptr, uint32_t value, uint32_t num );
/// @}
} // extern "C"
......@@ -7,528 +7,16 @@
#include <eosiolib/memory.h>
#include <eosiolib/print.hpp>
namespace eosio {
#include <unistd.h>
using ::memset;
using ::memcpy;
extern "C" {
/**
* @defgroup memorycppapi Memory C++ API
* @brief Defines common memory functions
* @ingroup memoryapi
*
* @{
*/
void* malloc(size_t size);
class memory_manager // NOTE: Should never allocate another instance of memory_manager
{
friend void* malloc(uint32_t size);
friend void* realloc(void* ptr, uint32_t size);
friend void free(void* ptr);
public:
memory_manager()
// NOTE: it appears that WASM has an issue with initialization lists if the object is globally allocated,
// and seems to just initialize members to 0
: _heaps_actual_size(0)
, _active_heap(0)
, _active_free_heap(0)
{
}
void* calloc(size_t count, size_t size);
private:
class memory;
void* realloc(void* ptr, size_t size);
memory* next_active_heap()
{
memory* const current_memory = _available_heaps + _active_heap;
void free(void* ptr);
// make sure we will not exceed the 1M limit (needs to match wasm_interface.cpp _max_memory)
auto remaining = 1024 * 1024 - reinterpret_cast<int32_t>(sbrk(0));
if (remaining <= 0)
{
// ensure that any remaining unallocated memory gets cleaned up
current_memory->cleanup_remaining();
++_active_heap;
_heaps_actual_size = _active_heap;
return nullptr;
}
const uint32_t new_heap_size = remaining > _new_heap_size ? _new_heap_size : remaining;
char* new_memory_start = static_cast<char*>(sbrk(new_heap_size));
// if we can expand the current memory, keep working with it
if (current_memory->expand_memory(new_memory_start, new_heap_size))
return current_memory;
// ensure that any remaining unallocated memory gets cleaned up
current_memory->cleanup_remaining();
++_active_heap;
memory* const next = _available_heaps + _active_heap;
next->init(new_memory_start, new_heap_size);
return next;
}
void* malloc(uint32_t size)
{
if (size == 0)
return nullptr;
// see Note on ctor
if (_heaps_actual_size == 0)
_heaps_actual_size = _heaps_size;
adjust_to_mem_block(size);
// first pass of loop never has to initialize the slot in _available_heap
uint32_t needs_init = 0;
char* buffer = nullptr;
memory* current = nullptr;
// need to make sure
if (_active_heap < _heaps_actual_size)
{
memory* const start_heap = &_available_heaps[_active_heap];
// only heap 0 won't be initialized already
if(_active_heap == 0 && !start_heap->is_init())
{
start_heap->init(_initial_heap, _initial_heap_size);
}
current = start_heap;
}
while (current != nullptr)
{
buffer = current->malloc(size);
// done if we have a buffer
if (buffer != nullptr)
break;
current = next_active_heap();
}
if (buffer == nullptr)
{
const uint32_t end_free_heap = _active_free_heap;
do
{
buffer = _available_heaps[_active_free_heap].malloc_from_freed(size);
if (buffer != nullptr)
break;
if (++_active_free_heap == _heaps_actual_size)
_active_free_heap = 0;
} while (_active_free_heap != end_free_heap);
}
return buffer;
}
void* realloc(void* ptr, uint32_t size)
{
if (size == 0)
{
free(ptr);
return nullptr;
}
const uint32_t REMOVE = size;
adjust_to_mem_block(size);
char* realloc_ptr = nullptr;
uint32_t orig_ptr_size = 0;
if (ptr != nullptr)
{
char* const char_ptr = static_cast<char*>(ptr);
for (memory* realloc_heap = _available_heaps; realloc_heap < _available_heaps + _heaps_actual_size && realloc_heap->is_init(); ++realloc_heap)
{
if (realloc_heap->is_in_heap(char_ptr))
{
realloc_ptr = realloc_heap->realloc_in_place(char_ptr, size, &orig_ptr_size);
if (realloc_ptr != nullptr)
return realloc_ptr;
else
break;
}
}
}
char* new_alloc = static_cast<char*>(malloc(size));
if (new_alloc == nullptr)
return nullptr;
const uint32_t copy_size = (size < orig_ptr_size) ? size : orig_ptr_size;
if (copy_size > 0)
{
memcpy(new_alloc, ptr, copy_size);
free (ptr);
}
return new_alloc;
}
void free(void* ptr)
{
if (ptr == nullptr)
return;
char* const char_ptr = static_cast<char*>(ptr);
for (memory* free_heap = _available_heaps; free_heap < _available_heaps + _heaps_actual_size && free_heap->is_init(); ++free_heap)
{
if (free_heap->is_in_heap(char_ptr))
{
free_heap->free(char_ptr);
break;
}
}
}
void adjust_to_mem_block(uint32_t& size)
{
const uint32_t remainder = (size + _size_marker) & _rem_mem_block_mask;
if (remainder > 0)
{
size += _mem_block - remainder;
}
}
class memory
{
public:
memory()
: _heap_size(0)
, _heap(nullptr)
, _offset(0)
{
}
void init(char* const mem_heap, uint32_t size)
{
_heap_size = size;
_heap = mem_heap;
memset(_heap, 0, _heap_size);
}
uint32_t is_init() const
{
return _heap != nullptr;
}
uint32_t is_in_heap(const char* const ptr) const
{
const char* const end_of_buffer = _heap + _heap_size;
const char* const first_ptr_of_buffer = _heap + _size_marker;
return ptr >= first_ptr_of_buffer && ptr < end_of_buffer;
}
uint32_t is_capacity_remaining() const
{
return _offset + _size_marker < _heap_size;
}
char* malloc(uint32_t size)
{
uint32_t used_up_size = _offset + size + _size_marker;
if (used_up_size > _heap_size)
{
return nullptr;
}
buffer_ptr new_buff(&_heap[_offset + _size_marker], size, _heap + _heap_size);
_offset += size + _size_marker;
new_buff.mark_alloc();
return new_buff.ptr();
}
char* malloc_from_freed(uint32_t size)
{
assert(_offset == _heap_size, "malloc_from_freed was designed to only be called after _heap was completely allocated");
char* current = _heap + _size_marker;
while (current != nullptr)
{
buffer_ptr current_buffer(current, _heap + _heap_size);
if (!current_buffer.is_alloc())
{
// done if we have enough contiguous memory
if (current_buffer.merge_contiguous(size))
{
current_buffer.mark_alloc();
return current;
}
}
current = current_buffer.next_ptr();
}
// failed to find any free memory
return nullptr;
}
char* realloc_in_place(char* const ptr, uint32_t size, uint32_t* orig_ptr_size)
{
const char* const end_of_buffer = _heap + _heap_size;
buffer_ptr orig_buffer(ptr, end_of_buffer);
*orig_ptr_size = orig_buffer.size();
// is the passed in pointer valid
char* const orig_buffer_end = orig_buffer.end();
if (orig_buffer_end > end_of_buffer)
{
*orig_ptr_size = 0;
return nullptr;
}
if (ptr > end_of_buffer - size)
{
// cannot resize in place
return nullptr;
}
const int32_t diff = size - *orig_ptr_size;
if (diff < 0)
{
// use a buffer_ptr to allocate the memory to free
char* const new_ptr = ptr + size + _size_marker;
buffer_ptr excess_to_free(new_ptr, -diff, _heap + _heap_size);
excess_to_free.mark_free();
return ptr;
}
// if ptr was the last allocated buffer, we can expand
else if (orig_buffer_end == &_heap[_offset])
{
orig_buffer.size(size);
_offset += diff;
return ptr;
}
if (-diff == 0)
return ptr;
if (!orig_buffer.merge_contiguous_if_available(size))
// could not resize in place
return nullptr;
orig_buffer.mark_alloc();
return ptr;
}
void free(char* ptr)
{
buffer_ptr to_free(ptr, _heap + _heap_size);
to_free.mark_free();
}
void cleanup_remaining()
{
if (_offset == _heap_size)
return;
// take the remaining memory and act like it was allocated
const uint32_t size = _heap_size - _offset - _size_marker;
buffer_ptr new_buff(&_heap[_offset + _size_marker], size, _heap + _heap_size);
_offset = _heap_size;
new_buff.mark_free();
}
bool expand_memory(char* exp_mem, uint32_t size)
{
if (_heap + _heap_size != exp_mem)
return false;
_heap_size += size;
return true;
}
private:
class buffer_ptr
{
public:
buffer_ptr(void* ptr, const char* const heap_end)
: _ptr(static_cast<char*>(ptr))
, _size(*reinterpret_cast<uint32_t*>(static_cast<char*>(ptr) - _size_marker) & ~_alloc_memory_mask)
, _heap_end(heap_end)
{
}
buffer_ptr(void* ptr, uint32_t buff_size, const char* const heap_end)
: _ptr(static_cast<char*>(ptr))
, _heap_end(heap_end)
{
size(buff_size);
}
uint32_t size() const
{
return _size;
}
char* next_ptr() const
{
char* const next = end() + _size_marker;
if (next >= _heap_end)
return nullptr;
return next;
}
void size(uint32_t val)
{
// keep the same state (allocated or free) as was set before
const uint32_t memory_state = *reinterpret_cast<uint32_t*>(_ptr - _size_marker) & _alloc_memory_mask;
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) = val | memory_state;
_size = val;
}
char* end() const
{
return _ptr + _size;
}
char* ptr() const
{
return _ptr;
}
void mark_alloc()
{
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) |= _alloc_memory_mask;
}
void mark_free()
{
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) &= ~_alloc_memory_mask;
}
bool is_alloc() const
{
return *reinterpret_cast<const uint32_t*>(_ptr - _size_marker) & _alloc_memory_mask;
}
bool merge_contiguous_if_available(uint32_t needed_size)
{
return merge_contiguous(needed_size, true);
}
bool merge_contiguous(uint32_t needed_size)
{
return merge_contiguous(needed_size, false);
}
private:
bool merge_contiguous(uint32_t needed_size, bool all_or_nothing)
{
// do not bother if there isn't contiguious space to allocate
if (all_or_nothing && _heap_end - _ptr < needed_size)
return false;
uint32_t possible_size = _size;
while (possible_size < needed_size && (_ptr + possible_size < _heap_end))
{
const uint32_t next_mem_flag_size = *reinterpret_cast<const uint32_t*>(_ptr + possible_size);
// if ALLOCed then done with contiguous free memory
if (next_mem_flag_size & _alloc_memory_mask)
break;
possible_size += (next_mem_flag_size & ~_alloc_memory_mask) + _size_marker;
}
if (all_or_nothing && possible_size < needed_size)
return false;
// combine
const uint32_t new_size = possible_size < needed_size ? possible_size : needed_size;
size(new_size);
if (possible_size > needed_size)
{
const uint32_t freed_size = possible_size - needed_size - _size_marker;
buffer_ptr freed_remainder(_ptr + needed_size + _size_marker, freed_size, _heap_end);
freed_remainder.mark_free();
}
return new_size == needed_size;
}
char* _ptr;
uint32_t _size;
const char* const _heap_end;
};
uint32_t _heap_size;
char* _heap;
uint32_t _offset;
};
static const uint32_t _size_marker = sizeof(uint32_t);
// allocate memory in 8 char blocks
static const uint32_t _mem_block = 8;
static const uint32_t _rem_mem_block_mask = _mem_block - 1;
static const uint32_t _initial_heap_size = 8192;//32768;
static const uint32_t _new_heap_size = 65536;
// if sbrk is not called outside of this file, then this is the max times we can call it
static const uint32_t _heaps_size = 16;
char _initial_heap[_initial_heap_size];
memory _available_heaps[_heaps_size];
uint32_t _heaps_actual_size;
uint32_t _active_heap;
uint32_t _active_free_heap;
static const uint32_t _alloc_memory_mask = 1 << 31;
} memory_heap;
/**
* Allocate a block of memory.
* @brief Allocate a block of memory.
* @param size Size of memory block
*
* Example:
* @code
* uint64_t* int_buffer = malloc(500 * sizeof(uint64_t));
* @endcode
*/
inline void* malloc(uint32_t size)
{
return memory_heap.malloc(size);
}
/**
* Allocate a block of memory.
* @brief Allocate a block of memory.
* @param size Size of memory block
*
* Example:
* @code
* uint64_t* int_buffer = malloc(500 * sizeof(uint64_t));
* ...
* uint64_t* bigger_int_buffer = realloc(int_buffer, 600 * sizeof(uint64_t));
* @endcode
*/
inline void* realloc(void* ptr, uint32_t size)
{
return memory_heap.realloc(ptr, size);
}
/**
* Free a block of memory.
* @brief Free a block of memory.
* @param ptr Pointer to memory block to free.
*
* Example:
* @code
* uint64_t* int_buffer = malloc(500 * sizeof(uint64_t));
* ...
* free(int_buffer);
* @endcode
*/
inline void free(void* ptr)
{
return memory_heap.free(ptr);
}
/// @} /// mathcppapi
}
......@@ -3,7 +3,10 @@
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup consoleapi Console API
* @brief Enables applications to log/print text messages
......@@ -98,4 +101,6 @@ extern "C" {
void printhex( void* data, uint32_t datalen );
/// @}
#ifdef __cplusplus
}
#endif
......@@ -27,7 +27,7 @@ namespace eosio {
char temp[1024+8];
*reinterpret_cast<uint64_t *>(temp) = SingletonName;
auto read = load_i64( Code, scope, SingletonName, temp, sizeof(temp) );
assert( read > 0, "singleton does not exist" );
eos_assert( read > 0, "singleton does not exist" );
return unpack<T>( temp + sizeof(SingletonName), read );
}
......@@ -58,7 +58,7 @@ namespace eosio {
auto size = pack_size( value );
char buf[size+ sizeof(SingletonName)];
assert( sizeof(buf) <= 1024 + 8, "singleton too big to store" );
eos_assert( sizeof(buf) <= 1024 + 8, "singleton too big to store" );
datastream<char*> ds( buf, size + sizeof(SingletonName) );
ds << SingletonName;
......
#pragma once
// forward declarations, to be filled in by the compiler, for placement new.
extern "C" {
void* operator new(size_t, void*);
void* operator new[](size_t, void*);
}
// compatibility for things declared by the c++ standard libraries that compilers replace
namespace std {
// forward declaration of initializer_list
template<class E> class initializer_list {
public:
using value_type = E;
using reference = const E&;
using const_reference = const E&;
using size_type = size_t;
using iterator = const E*;
using const_iterator = const E*;
constexpr initializer_list() noexcept;
constexpr size_t size() const noexcept {
return _len;
}
constexpr const E* begin() const noexcept {
return _iter;
}
constexpr const E* end() const noexcept {
return _iter + _len;
}
private:
iterator _iter;
size_type _len;
constexpr initializer_list(const_iterator array, size_type len)
:_iter(array),_len(len)
{}
};
// initializer list range access
template<class E> constexpr const E* begin(initializer_list<E> il) noexcept;
template<class E> constexpr const E* end(initializer_list<E> il) noexcept;
}
\ No newline at end of file
#include <initializer_list>
#include <iterator>
#include <memory>
......@@ -198,12 +198,12 @@ namespace eosio {
* @return substring of the current string
*/
string substr(size_t offset, size_t substr_size, bool copy) {
assert((offset < size) && (offset + substr_size < size), "out of bound");
eos_assert((offset < size) && (offset + substr_size < size), "out of bound");
return string(data + offset, substr_size, copy);
}
char operator [] (const size_t index) {
assert(index < size, "index out of bound");
eos_assert(index < size, "index out of bound");
return *(data + index);
}
......@@ -238,7 +238,7 @@ namespace eosio {
}
string& operator += (const string& str){
assert((size + str.size > size) && (size + str.size > str.size), "overflow");
eos_assert((size + str.size > size) && (size + str.size > str.size), "overflow");
char* new_data;
size_t new_size;
......
......@@ -29,7 +29,7 @@ extern "C" {
* @param cstr - a null terminated action to explain the reason for failure
*/
void assert( uint32_t test, const char* cstr );
void eos_assert( uint32_t test, const char* cstr );
/**
* Returns the time in seconds from 1970 of the last accepted block (not the block including this action)
......@@ -37,7 +37,27 @@ extern "C" {
* @return time in seconds from 1970 of the last accepted block
*/
time now();
///@ } systemcapi
/**
* @defgroup privilegedapi Privileged API
* @ingroup systemapi
* @brief Defines an API for accessing configuration of the chain that can only be done by privileged accounts
*/
/**
* @defgroup privilegedcapi Privileged C API
* @ingroup privilegedapi
* @brief Define C Privileged API
*
* @{
*/
void set_resource_limits( account_name account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight, int64_t ignored);
void set_active_producers( char *producer_data, size_t producer_data_size );
///@ } privilegedcapi
}
......@@ -21,7 +21,7 @@ namespace eosio {
char temp[1024];
*reinterpret_cast<uint64_t *>(temp) = key;
auto read = load_i64( DefaultScope, scope , TableName, temp, sizeof(temp) );
assert( read > 0, "key does not exist" );
eos_assert( read > 0, "key does not exist" );
datastream<const char*> ds(temp, read);
T result;
......@@ -63,7 +63,7 @@ namespace eosio {
static void set( const T& value = T(), scope_name scope = DefaultScope, uint64_t bta = BillToAccount ) {
auto size = pack_size( value );
char buf[size];
assert( size <= 1024, "singleton too big to store" );
eos_assert( size <= 1024, "singleton too big to store" );
datastream<char*> ds( buf, size );
ds << value;
......
......@@ -41,7 +41,7 @@ namespace eosio {
operator asset()const { return asset( quantity, Symbol ); }
token( const asset& a ):quantity(a.amount) {
assert( a.symbol == Symbol, "attempt to construct token from asset with different symbol" );
eos_assert( a.symbol == Symbol, "attempt to construct token from asset with different symbol" );
}
/**
......@@ -65,7 +65,7 @@ namespace eosio {
* @return this token after subtraction
*/
token& operator-=( const token& a ) {
assert( quantity >= a.quantity, "integer underflow subtracting token balance" );
eos_assert( quantity >= a.quantity, "integer underflow subtracting token balance" );
quantity -= a.quantity;
return *this;
}
......@@ -78,7 +78,7 @@ namespace eosio {
* @return this token after addition
*/
token& operator+=( const token& a ) {
assert( quantity + a.quantity >= a.quantity, "integer overflow adding token balance" );
eos_assert( quantity + a.quantity >= a.quantity, "integer overflow adding token balance" );
quantity += a.quantity;
return *this;
}
......@@ -258,8 +258,8 @@ namespace eosio {
* @param quote - quote token
*/
price( BaseToken base, QuoteToken quote ) {
assert( base >= BaseToken(1ul), "invalid price" );
assert( quote >= QuoteToken(1ul), "invalid price" );
eos_assert( base >= BaseToken(1ul), "invalid price" );
eos_assert( quote >= QuoteToken(1ul), "invalid price" );
base_per_quote = base.quantity;
base_per_quote *= precision;
......
......@@ -4,6 +4,9 @@
*/
#pragma once
#include <stdint.h>
#include <wchar.h>
extern "C" {
/**
......@@ -14,24 +17,10 @@ extern "C" {
* @{
*/
typedef unsigned __int128 uint128_t;
typedef unsigned long long uint64_t;
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
typedef __int128 int128_t;
typedef long long int64_t;
typedef long int32_t;
typedef short int16_t;
typedef char int8_t;
struct uint256 {
uint64_t words[4];
};
typedef unsigned int size_t;
typedef uint64_t account_name;
typedef uint64_t permission_name;
typedef uint64_t token_name;
......
......@@ -126,4 +126,4 @@ struct signed_int {
}
};
/// @}
\ No newline at end of file
/// @}
file(GLOB ABI_FILES "*.abi")
add_wast_target(exchange "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET exchange
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_dependencies( exchange currency )
......@@ -75,7 +75,7 @@ void apply_currency_transfer( const currency::transfer& transfer ) {
mod_account.currency_balance -= transfer.quantity;
});
} else {
assert( false, "notified on transfer that is not relevant to this exchange" );
eos_assert( false, "notified on transfer that is not relevant to this exchange" );
}
}
......@@ -95,7 +95,7 @@ void apply_eos_transfer( const eosio::transfer& transfer ) {
mod_account.eos_balance -= transfer.quantity;
});
} else {
assert( false, "notified on transfer that is not relevant to this exchange" );
eos_assert( false, "notified on transfer that is not relevant to this exchange" );
}
}
......@@ -132,13 +132,13 @@ void apply_exchange_buy( buy_order order ) {
bid& exchange_bid = order;
require_auth( exchange_bid.buyer.name );
assert( exchange_bid.quantity > eosio::tokens(0), "invalid quantity" );
assert( exchange_bid.expiration > now(), "order expired" );
eos_assert( exchange_bid.quantity > eosio::tokens(0), "invalid quantity" );
eos_assert( exchange_bid.expiration > now(), "order expired" );
print( name(exchange_bid.buyer.name), " created bid for ", order.quantity, " currency at price: ", order.at_price, "\n" );
bid existing_bid;
assert( !bids_by_id::get( exchange_bid.buyer, existing_bid ), "order with this id already exists" );
eos_assert( !bids_by_id::get( exchange_bid.buyer, existing_bid ), "order with this id already exists" );
print( __FILE__, __LINE__, "\n" );
auto buyer_account = get_account( exchange_bid.buyer.name );
......@@ -147,7 +147,7 @@ void apply_exchange_buy( buy_order order ) {
ask lowest_ask;
if( !asks_by_price::front( lowest_ask ) ) {
print( "\n No asks found, saving buyer account and storing bid\n" );
assert( !order.fill_or_kill, "order not completely filled" );
eos_assert( !order.fill_or_kill, "order not completely filled" );
bids::store( exchange_bid );
buyer_account.open_orders++;
save( buyer_account );
......@@ -183,7 +183,7 @@ void apply_exchange_buy( buy_order order ) {
print( "saving buyer's account\n" );
if( exchange_bid.quantity ) {
print( exchange_bid.quantity, " eos left over" );
assert( !order.fill_or_kill, "order not completely filled" );
eos_assert( !order.fill_or_kill, "order not completely filled" );
bids::store( exchange_bid );
return;
}
......@@ -195,14 +195,14 @@ void apply_exchange_sell( sell_order order ) {
ask& exchange_ask = order;
require_auth( exchange_ask.seller.name );
assert( exchange_ask.quantity > currency_tokens(0), "invalid quantity" );
assert( exchange_ask.expiration > now(), "order expired" );
eos_assert( exchange_ask.quantity > currency_tokens(0), "invalid quantity" );
eos_assert( exchange_ask.expiration > now(), "order expired" );
print( "\n\n", name(exchange_ask.seller.name), " created sell for ", order.quantity,
" currency at price: ", order.at_price, "\n");
ask existing_ask;
assert( !asks_by_id::get( exchange_ask.seller, existing_ask ), "order with this id already exists" );
eos_assert( !asks_by_id::get( exchange_ask.seller, existing_ask ), "order with this id already exists" );
auto seller_account = get_account( exchange_ask.seller.name );
seller_account.currency_balance -= exchange_ask.quantity;
......@@ -210,7 +210,7 @@ void apply_exchange_sell( sell_order order ) {
bid highest_bid;
if( !bids_by_price::back( highest_bid ) ) {
assert( !order.fill_or_kill, "order not completely filled" );
eos_assert( !order.fill_or_kill, "order not completely filled" );
print( "\n No bids found, saving seller account and storing ask\n" );
asks::store( exchange_ask );
seller_account.open_orders++;
......@@ -241,7 +241,7 @@ void apply_exchange_sell( sell_order order ) {
if( exchange_ask.quantity && !order.fill_or_kill ) seller_account.open_orders++;
save( seller_account );
if( exchange_ask.quantity ) {
assert( !order.fill_or_kill, "order not completely filled" );
eos_assert( !order.fill_or_kill, "order not completely filled" );
print( "saving ask\n" );
asks::store( exchange_ask );
return;
......@@ -254,7 +254,7 @@ void apply_exchange_cancel_buy( order_id order ) {
require_auth( order.name );
bid bid_to_cancel;
assert( bids_by_id::get( order, bid_to_cancel ), "bid with this id does not exists" );
eos_assert( bids_by_id::get( order, bid_to_cancel ), "bid with this id does not exists" );
auto buyer_account = get_account( order.name );
buyer_account.eos_balance += bid_to_cancel.quantity;
......@@ -270,7 +270,7 @@ void apply_exchange_cancel_sell( order_id order ) {
require_auth( order.name );
ask ask_to_cancel;
assert( asks_by_id::get( order, ask_to_cancel ), "ask with this id does not exists" );
eos_assert( asks_by_id::get( order, ask_to_cancel ), "ask with this id does not exists" );
auto seller_account = get_account( order.name );
seller_account.currency_balance += ask_to_cancel.quantity;
......@@ -307,7 +307,7 @@ extern "C" {
apply_exchange_cancel_sell( current_action<exchange::order_id>() );
break;
default:
assert( false, "unknown action" );
eos_assert( false, "unknown action" );
}
}
else if( code == N(currency) ) {
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(identity "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET identity
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
add_subdirectory(test)
......@@ -308,8 +308,8 @@ namespace identity {
static void on( const create& c ) {
require_auth( c.creator );
assert( !idents_table::exists( c.identity ), "identity already exists" );
assert( c.identity != 0, "identity=0 is not allowed" );
eos_assert( !idents_table::exists( c.identity ), "identity already exists" );
eos_assert( c.identity != 0, "identity=0 is not allowed" );
idents_table::set( identrow{ .identity = c.identity,
.creator = c.creator } );
}
......@@ -319,7 +319,7 @@ namespace identity {
if( cert.bill_storage_to != cert.certifier )
require_auth( cert.bill_storage_to );
assert( idents_table::exists( cert.identity ), "identity does not exist" );
eos_assert( idents_table::exists( cert.identity ), "identity does not exist" );
/// the table exists in the scope of the identity
certs_table certs( cert.identity );
......@@ -331,7 +331,7 @@ namespace identity {
row.trusted = is_trusted( cert.certifier );
row.certifier = cert.certifier;
row.confidence = value.confidence;
assert(value.type.get_size() <= 32, "certrow::type should be not longer than 32 bytes");
eos_assert(value.type.get_size() <= 32, "certrow::type should be not longer than 32 bytes");
row.type = value.type;
row.data = value.data;
......@@ -341,7 +341,7 @@ namespace identity {
//special handling for owner
if (value.property == N(owner)) {
assert(sizeof(account_name) == value.data.size(), "data size doesn't match account_name size");
eos_assert(sizeof(account_name) == value.data.size(), "data size doesn't match account_name size");
account_name acnt = *reinterpret_cast<const account_name*>(value.data.data());
if (cert.certifier == acnt) { //only self-certitication affects accounts_table
accounts_table::set( cert.identity, acnt );
......@@ -353,7 +353,7 @@ namespace identity {
certs.remove(value.property, 1, cert.certifier);
//special handling for owner
if (value.property == N(owner)) {
assert(sizeof(account_name) == value.data.size(), "data size doesn't match account_name size");
eos_assert(sizeof(account_name) == value.data.size(), "data size doesn't match account_name size");
account_name acnt = *reinterpret_cast<const account_name*>(value.data.data());
if (cert.certifier == acnt) { //only self-certitication affects accounts_table
accounts_table::remove( acnt );
......
set(ABI_FILES "identity_test.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(identity_test "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET identity_test
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
add_wast_target(infinite "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET infinite
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
if (NOT LIBCXX_INSTALL_SUPPORT_HEADERS)
set(LIBCXX_SUPPORT_HEADER_PATTERN PATTERN "support" EXCLUDE)
endif()
set(LIBCXX_HEADER_PATTERN
PATTERN "*"
PATTERN "CMakeLists.txt" EXCLUDE
PATTERN ".svn" EXCLUDE
PATTERN "__config_site.in" EXCLUDE
${LIBCXX_SUPPORT_HEADER_PATTERN}
)
if(NOT LIBCXX_USING_INSTALLED_LLVM AND LLVM_BINARY_DIR)
file(COPY .
DESTINATION "${LLVM_BINARY_DIR}/include/c++/v1"
FILES_MATCHING
${LIBCXX_HEADER_PATTERN}
)
endif()
if (LIBCXX_INSTALL_HEADERS)
install(DIRECTORY .
DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1
COMPONENT cxx-headers
FILES_MATCHING
${LIBCXX_HEADER_PATTERN}
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
if (LIBCXX_NEEDS_SITE_CONFIG)
# Generate and install a custom __config header. The new header is created
# by prepending __config_site to the current __config header.
add_custom_command(OUTPUT ${LIBCXX_BINARY_DIR}/__generated_config
COMMAND ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/cat_files.py
${LIBCXX_BINARY_DIR}/__config_site
${LIBCXX_SOURCE_DIR}/include/__config
-o ${LIBCXX_BINARY_DIR}/__generated_config
DEPENDS ${LIBCXX_SOURCE_DIR}/include/__config
${LIBCXX_BINARY_DIR}/__config_site
)
# Add a target that executes the generation commands.
add_custom_target(generate_config_header ALL
DEPENDS ${LIBCXX_BINARY_DIR}/__generated_config)
set(generated_config_deps generate_config_header)
# Install the generated header as __config.
install(FILES ${LIBCXX_BINARY_DIR}/__generated_config
DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
RENAME __config
COMPONENT cxx-headers)
endif()
if (NOT CMAKE_CONFIGURATION_TYPES)
# this target is just needed as a placeholder for the distribution target
add_custom_target(cxx-headers)
add_custom_target(install-cxx-headers
DEPENDS cxx-headers ${generated_config_deps}
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=cxx-headers
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
add_custom_target(libcxx-headers)
add_custom_target(install-libcxx-headers DEPENDS install-cxx-headers)
endif()
endif()
此差异已折叠。
// -*- C++ -*-
//===---------------------- __bsd_locale_defaults.h -----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// The BSDs have lots of *_l functions. We don't want to define those symbols
// on other platforms though, for fear of conflicts with user code. So here,
// we will define the mapping from an internal macro to the real BSD symbol.
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_BSD_LOCALE_DEFAULTS_H
#define _LIBCPP_BSD_LOCALE_DEFAULTS_H
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
#define __libcpp_mb_cur_max_l(loc) MB_CUR_MAX_L(loc)
#define __libcpp_btowc_l(ch, loc) btowc_l(ch, loc)
#define __libcpp_wctob_l(wch, loc) wctob_l(wch, loc)
#define __libcpp_wcsnrtombs_l(dst, src, nwc, len, ps, loc) wcsnrtombs_l(dst, src, nwc, len, ps, loc)
#define __libcpp_wcrtomb_l(src, wc, ps, loc) wcrtomb_l(src, wc, ps, loc)
#define __libcpp_mbsnrtowcs_l(dst, src, nms, len, ps, loc) mbsnrtowcs_l(dst, src, nms, len, ps, loc)
#define __libcpp_mbrtowc_l(pwc, s, n, ps, l) mbrtowc_l(pwc, s, n, ps, l)
#define __libcpp_mbtowc_l(pwc, pmb, max, l) mbtowc_l(pwc, pmb, max, l)
#define __libcpp_mbrlen_l(s, n, ps, l) mbrlen_l(s, n, ps, l)
#define __libcpp_localeconv_l(l) localeconv_l(l)
#define __libcpp_mbsrtowcs_l(dest, src, len, ps, l) mbsrtowcs_l(dest, src, len, ps, l)
#define __libcpp_snprintf_l(...) snprintf_l(__VA_ARGS__)
#define __libcpp_asprintf_l(...) asprintf_l(__VA_ARGS__)
#define __libcpp_sscanf_l(...) sscanf_l(__VA_ARGS__)
#endif // _LIBCPP_BSD_LOCALE_DEFAULTS_H
// -*- C++ -*-
//===---------------------- __bsd_locale_fallbacks.h ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// The BSDs have lots of *_l functions. This file provides reimplementations
// of those functions for non-BSD platforms.
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H
#define _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H
#include <stdlib.h>
#include <stdarg.h>
#include <memory>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
inline _LIBCPP_ALWAYS_INLINE
decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l)
{
__libcpp_locale_guard __current(__l);
return MB_CUR_MAX;
}
inline _LIBCPP_ALWAYS_INLINE
wint_t __libcpp_btowc_l(int __c, locale_t __l)
{
__libcpp_locale_guard __current(__l);
return btowc(__c);
}
inline _LIBCPP_ALWAYS_INLINE
int __libcpp_wctob_l(wint_t __c, locale_t __l)
{
__libcpp_locale_guard __current(__l);
return wctob(__c);
}
inline _LIBCPP_ALWAYS_INLINE
size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
size_t __len, mbstate_t *__ps, locale_t __l)
{
__libcpp_locale_guard __current(__l);
return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
}
inline _LIBCPP_ALWAYS_INLINE
size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
{
__libcpp_locale_guard __current(__l);
return wcrtomb(__s, __wc, __ps);
}
inline _LIBCPP_ALWAYS_INLINE
size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
size_t __len, mbstate_t *__ps, locale_t __l)
{
__libcpp_locale_guard __current(__l);
return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
}
inline _LIBCPP_ALWAYS_INLINE
size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
mbstate_t *__ps, locale_t __l)
{
__libcpp_locale_guard __current(__l);
return mbrtowc(__pwc, __s, __n, __ps);
}
inline _LIBCPP_ALWAYS_INLINE
int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
{
__libcpp_locale_guard __current(__l);
return mbtowc(__pwc, __pmb, __max);
}
inline _LIBCPP_ALWAYS_INLINE
size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
{
__libcpp_locale_guard __current(__l);
return mbrlen(__s, __n, __ps);
}
inline _LIBCPP_ALWAYS_INLINE
lconv *__libcpp_localeconv_l(locale_t __l)
{
__libcpp_locale_guard __current(__l);
return localeconv();
}
inline _LIBCPP_ALWAYS_INLINE
size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
mbstate_t *__ps, locale_t __l)
{
__libcpp_locale_guard __current(__l);
return mbsrtowcs(__dest, __src, __len, __ps);
}
inline
int __libcpp_snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
va_list __va;
va_start(__va, __format);
__libcpp_locale_guard __current(__l);
int __res = vsnprintf(__s, __n, __format, __va);
va_end(__va);
return __res;
}
inline
int __libcpp_asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
va_list __va;
va_start(__va, __format);
__libcpp_locale_guard __current(__l);
int __res = vasprintf(__s, __format, __va);
va_end(__va);
return __res;
}
inline
int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
va_list __va;
va_start(__va, __format);
__libcpp_locale_guard __current(__l);
int __res = vsscanf(__s, __format, __va);
va_end(__va);
return __res;
}
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H
此差异已折叠。
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_CONFIG_SITE
#define _LIBCPP_CONFIG_SITE
#cmakedefine _LIBCPP_ABI_VERSION @_LIBCPP_ABI_VERSION@
#cmakedefine _LIBCPP_ABI_UNSTABLE
#cmakedefine _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
#cmakedefine _LIBCPP_HAS_NO_STDIN
#cmakedefine _LIBCPP_HAS_NO_STDOUT
#cmakedefine _LIBCPP_HAS_NO_THREADS
#cmakedefine _LIBCPP_HAS_NO_MONOTONIC_CLOCK
#cmakedefine _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
#cmakedefine _LIBCPP_HAS_MUSL_LIBC
#cmakedefine _LIBCPP_HAS_THREAD_API_PTHREAD
#cmakedefine _LIBCPP_HAS_THREAD_API_EXTERNAL
#cmakedefine _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL
#cmakedefine _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS
#endif // _LIBCPP_CONFIG_SITE
此差异已折叠。
此差异已折叠。
此差异已折叠。
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_FUNCTIONAL_BASE_03
#define _LIBCPP_FUNCTIONAL_BASE_03
// manual variadic expansion for <functional>
// __invoke
template <class _Ret, class _T1, bool _IsFunc, bool _IsBase>
struct __enable_invoke_imp;
template <class _Ret, class _T1>
struct __enable_invoke_imp<_Ret, _T1, true, true> {
typedef _Ret _Bullet1;
typedef _Bullet1 type;
};
template <class _Ret, class _T1>
struct __enable_invoke_imp<_Ret, _T1, true, false> {
typedef _Ret _Bullet2;
typedef _Bullet2 type;
};
template <class _Ret, class _T1>
struct __enable_invoke_imp<_Ret, _T1, false, true> {
typedef typename add_lvalue_reference<
typename __apply_cv<_T1, _Ret>::type
>::type _Bullet3;
typedef _Bullet3 type;
};
template <class _Ret, class _T1>
struct __enable_invoke_imp<_Ret, _T1, false, false> {
typedef typename add_lvalue_reference<
typename __apply_cv<decltype(*_VSTD::declval<_T1>()), _Ret>::type
>::type _Bullet4;
typedef _Bullet4 type;
};
template <class _Ret, class _T1>
struct __enable_invoke_imp<_Ret, _T1*, false, false> {
typedef typename add_lvalue_reference<
typename __apply_cv<_T1, _Ret>::type
>::type _Bullet4;
typedef _Bullet4 type;
};
template <class _Fn, class _T1,
class _Traits = __member_pointer_traits<_Fn>,
class _Ret = typename _Traits::_ReturnType,
class _Class = typename _Traits::_ClassType>
struct __enable_invoke : __enable_invoke_imp<
_Ret, _T1,
is_member_function_pointer<_Fn>::value,
is_base_of<_Class, typename remove_reference<_T1>::type>::value>
{
};
__nat __invoke(__any, ...);
// first bullet
template <class _Fn, class _T1>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet1
__invoke(_Fn __f, _T1& __t1) {
return (__t1.*__f)();
}
template <class _Fn, class _T1, class _A0>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet1
__invoke(_Fn __f, _T1& __t1, _A0& __a0) {
return (__t1.*__f)(__a0);
}
template <class _Fn, class _T1, class _A0, class _A1>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet1
__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
return (__t1.*__f)(__a0, __a1);
}
template <class _Fn, class _T1, class _A0, class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet1
__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
return (__t1.*__f)(__a0, __a1, __a2);
}
template <class _Fn, class _T1>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet2
__invoke(_Fn __f, _T1& __t1) {
return ((*__t1).*__f)();
}
template <class _Fn, class _T1, class _A0>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet2
__invoke(_Fn __f, _T1& __t1, _A0& __a0) {
return ((*__t1).*__f)(__a0);
}
template <class _Fn, class _T1, class _A0, class _A1>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet2
__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
return ((*__t1).*__f)(__a0, __a1);
}
template <class _Fn, class _T1, class _A0, class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet2
__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
return ((*__t1).*__f)(__a0, __a1, __a2);
}
template <class _Fn, class _T1>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet3
__invoke(_Fn __f, _T1& __t1) {
return __t1.*__f;
}
template <class _Fn, class _T1>
inline _LIBCPP_INLINE_VISIBILITY
typename __enable_invoke<_Fn, _T1>::_Bullet4
__invoke(_Fn __f, _T1& __t1) {
return (*__t1).*__f;
}
// fifth bullet
template <class _Fp>
inline _LIBCPP_INLINE_VISIBILITY
decltype(_VSTD::declval<_Fp&>()())
__invoke(_Fp& __f)
{
return __f();
}
template <class _Fp, class _A0>
inline _LIBCPP_INLINE_VISIBILITY
decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>()))
__invoke(_Fp& __f, _A0& __a0)
{
return __f(__a0);
}
template <class _Fp, class _A0, class _A1>
inline _LIBCPP_INLINE_VISIBILITY
decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>()))
__invoke(_Fp& __f, _A0& __a0, _A1& __a1)
{
return __f(__a0, __a1);
}
template <class _Fp, class _A0, class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>(), _VSTD::declval<_A2&>()))
__invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2)
{
return __f(__a0, __a1, __a2);
}
template <class _Fp, bool = __has_result_type<__weak_result_type<_Fp> >::value>
struct __invoke_return
{
typedef typename __weak_result_type<_Fp>::result_type type;
};
template <class _Fp>
struct __invoke_return<_Fp, false>
{
typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type;
};
template <class _Tp, class _A0>
struct __invoke_return0
{
typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>())) type;
};
template <class _Rp, class _Tp, class _A0>
struct __invoke_return0<_Rp _Tp::*, _A0>
{
typedef typename __enable_invoke<_Rp _Tp::*, _A0>::type type;
};
template <class _Tp, class _A0, class _A1>
struct __invoke_return1
{
typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
_VSTD::declval<_A1&>())) type;
};
template <class _Rp, class _Class, class _A0, class _A1>
struct __invoke_return1<_Rp _Class::*, _A0, _A1> {
typedef typename __enable_invoke<_Rp _Class::*, _A0>::type type;
};
template <class _Tp, class _A0, class _A1, class _A2>
struct __invoke_return2
{
typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(),
_VSTD::declval<_A1&>(),
_VSTD::declval<_A2&>())) type;
};
template <class _Ret, class _Class, class _A0, class _A1, class _A2>
struct __invoke_return2<_Ret _Class::*, _A0, _A1, _A2> {
typedef typename __enable_invoke<_Ret _Class::*, _A0>::type type;
};
#endif // _LIBCPP_FUNCTIONAL_BASE_03
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
// -*- C++ -*-
//===------------------------ __undef_macros ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifdef min
#if !defined(_LIBCPP_DISABLE_MACRO_CONFLICT_WARNINGS)
#if defined(_LIBCPP_WARNING)
_LIBCPP_WARNING("macro min is incompatible with C++. Try #define NOMINMAX "
"before any Windows header. #undefing min")
#else
#warning: macro min is incompatible with C++. #undefing min
#endif
#endif
#undef min
#endif
#ifdef max
#if !defined(_LIBCPP_DISABLE_MACRO_CONFLICT_WARNINGS)
#if defined(_LIBCPP_WARNING)
_LIBCPP_WARNING("macro max is incompatible with C++. Try #define NOMINMAX "
"before any Windows header. #undefing max")
#else
#warning: macro max is incompatible with C++. #undefing max
#endif
#endif
#undef max
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
// -*- C++ -*-
//===-------------------------- cassert -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/*
cassert synopsis
Macros:
assert
*/
#include <__config>
#include <assert.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册