提交 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)
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,11 +10,11 @@ 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
......
......@@ -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;
}
};
......
......@@ -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
*
* @{
*/
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)
{
}
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)
{
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;
}
}
void* malloc(size_t size);
current = current_buffer.next_ptr();
}
void* calloc(size_t count, size_t size);
// failed to find any free memory
return nullptr;
}
void* realloc(void* ptr, size_t size);
char* realloc_in_place(char* const ptr, uint32_t size, uint32_t* orig_ptr_size)
{
const char* const end_of_buffer = _heap + _heap_size;
void free(void* ptr);
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;
......
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++ -*-
//===--------------------------- __debug ----------------------------------===//
//
// 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_DEBUG_H
#define _LIBCPP_DEBUG_H
#include <__config>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
#if defined(_LIBCPP_HAS_NO_NULLPTR)
# include <cstddef>
#endif
#if _LIBCPP_DEBUG_LEVEL >= 1 || defined(_LIBCPP_BUILDING_LIBRARY)
# include <cstdlib>
# include <cstdio>
# include <cstddef>
# include <exception>
#endif
#if _LIBCPP_DEBUG_LEVEL >= 1 && !defined(_LIBCPP_ASSERT)
# define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : \
_VSTD::__libcpp_debug_function(_VSTD::__libcpp_debug_info(__FILE__, __LINE__, #x, m)))
#endif
#if _LIBCPP_DEBUG_LEVEL >= 2
#ifndef _LIBCPP_DEBUG_ASSERT
#define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(x, m)
#endif
#define _LIBCPP_DEBUG_MODE(...) __VA_ARGS__
#endif
#ifndef _LIBCPP_ASSERT
# define _LIBCPP_ASSERT(x, m) ((void)0)
#endif
#ifndef _LIBCPP_DEBUG_ASSERT
# define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0)
#endif
#ifndef _LIBCPP_DEBUG_MODE
#define _LIBCPP_DEBUG_MODE(...) ((void)0)
#endif
#if _LIBCPP_DEBUG_LEVEL < 1
class _LIBCPP_EXCEPTION_ABI __libcpp_debug_exception;
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
struct _LIBCPP_TEMPLATE_VIS __libcpp_debug_info {
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
__libcpp_debug_info()
: __file_(nullptr), __line_(-1), __pred_(nullptr), __msg_(nullptr) {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
__libcpp_debug_info(const char* __f, int __l, const char* __p, const char* __m)
: __file_(__f), __line_(__l), __pred_(__p), __msg_(__m) {}
const char* __file_;
int __line_;
const char* __pred_;
const char* __msg_;
};
/// __libcpp_debug_function_type - The type of the assertion failure handler.
typedef void(*__libcpp_debug_function_type)(__libcpp_debug_info const&);
/// __libcpp_debug_function - The handler function called when a _LIBCPP_ASSERT
/// fails.
extern _LIBCPP_EXTERN_VIS __libcpp_debug_function_type __libcpp_debug_function;
/// __libcpp_abort_debug_function - A debug handler that aborts when called.
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS
void __libcpp_abort_debug_function(__libcpp_debug_info const&);
/// __libcpp_throw_debug_function - A debug handler that throws
/// an instance of __libcpp_debug_exception when called.
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS
void __libcpp_throw_debug_function(__libcpp_debug_info const&);
/// __libcpp_set_debug_function - Set the debug handler to the specified
/// function.
_LIBCPP_FUNC_VIS
bool __libcpp_set_debug_function(__libcpp_debug_function_type __func);
// Setup the throwing debug handler during dynamic initialization.
#if _LIBCPP_DEBUG_LEVEL >= 1 && defined(_LIBCPP_DEBUG_USE_EXCEPTIONS)
# if defined(_LIBCPP_NO_EXCEPTIONS)
# error _LIBCPP_DEBUG_USE_EXCEPTIONS cannot be used when exceptions are disabled.
# endif
static bool __init_dummy = __libcpp_set_debug_function(__libcpp_throw_debug_function);
#endif
#if _LIBCPP_DEBUG_LEVEL >= 1 || defined(_LIBCPP_BUILDING_LIBRARY)
class _LIBCPP_EXCEPTION_ABI __libcpp_debug_exception : public exception {
public:
__libcpp_debug_exception() _NOEXCEPT;
explicit __libcpp_debug_exception(__libcpp_debug_info const& __i);
__libcpp_debug_exception(__libcpp_debug_exception const&);
~__libcpp_debug_exception() _NOEXCEPT;
const char* what() const _NOEXCEPT;
private:
struct __libcpp_debug_exception_imp;
__libcpp_debug_exception_imp *__imp_;
};
#endif
#if _LIBCPP_DEBUG_LEVEL >= 2 || defined(_LIBCPP_BUILDING_LIBRARY)
struct _LIBCPP_TYPE_VIS __c_node;
struct _LIBCPP_TYPE_VIS __i_node
{
void* __i_;
__i_node* __next_;
__c_node* __c_;
#ifndef _LIBCPP_CXX03_LANG
__i_node(const __i_node&) = delete;
__i_node& operator=(const __i_node&) = delete;
#else
private:
__i_node(const __i_node&);
__i_node& operator=(const __i_node&);
public:
#endif
_LIBCPP_INLINE_VISIBILITY
__i_node(void* __i, __i_node* __next, __c_node* __c)
: __i_(__i), __next_(__next), __c_(__c) {}
~__i_node();
};
struct _LIBCPP_TYPE_VIS __c_node
{
void* __c_;
__c_node* __next_;
__i_node** beg_;
__i_node** end_;
__i_node** cap_;
#ifndef _LIBCPP_CXX03_LANG
__c_node(const __c_node&) = delete;
__c_node& operator=(const __c_node&) = delete;
#else
private:
__c_node(const __c_node&);
__c_node& operator=(const __c_node&);
public:
#endif
_LIBCPP_INLINE_VISIBILITY
__c_node(void* __c, __c_node* __next)
: __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {}
virtual ~__c_node();
virtual bool __dereferenceable(const void*) const = 0;
virtual bool __decrementable(const void*) const = 0;
virtual bool __addable(const void*, ptrdiff_t) const = 0;
virtual bool __subscriptable(const void*, ptrdiff_t) const = 0;
void __add(__i_node* __i);
_LIBCPP_HIDDEN void __remove(__i_node* __i);
};
template <class _Cont>
struct _C_node
: public __c_node
{
_C_node(void* __c, __c_node* __n)
: __c_node(__c, __n) {}
virtual bool __dereferenceable(const void*) const;
virtual bool __decrementable(const void*) const;
virtual bool __addable(const void*, ptrdiff_t) const;
virtual bool __subscriptable(const void*, ptrdiff_t) const;
};
template <class _Cont>
inline bool
_C_node<_Cont>::__dereferenceable(const void* __i) const
{
typedef typename _Cont::const_iterator iterator;
const iterator* __j = static_cast<const iterator*>(__i);
_Cont* _Cp = static_cast<_Cont*>(__c_);
return _Cp->__dereferenceable(__j);
}
template <class _Cont>
inline bool
_C_node<_Cont>::__decrementable(const void* __i) const
{
typedef typename _Cont::const_iterator iterator;
const iterator* __j = static_cast<const iterator*>(__i);
_Cont* _Cp = static_cast<_Cont*>(__c_);
return _Cp->__decrementable(__j);
}
template <class _Cont>
inline bool
_C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const
{
typedef typename _Cont::const_iterator iterator;
const iterator* __j = static_cast<const iterator*>(__i);
_Cont* _Cp = static_cast<_Cont*>(__c_);
return _Cp->__addable(__j, __n);
}
template <class _Cont>
inline bool
_C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const
{
typedef typename _Cont::const_iterator iterator;
const iterator* __j = static_cast<const iterator*>(__i);
_Cont* _Cp = static_cast<_Cont*>(__c_);
return _Cp->__subscriptable(__j, __n);
}
class _LIBCPP_TYPE_VIS __libcpp_db
{
__c_node** __cbeg_;
__c_node** __cend_;
size_t __csz_;
__i_node** __ibeg_;
__i_node** __iend_;
size_t __isz_;
__libcpp_db();
public:
#ifndef _LIBCPP_CXX03_LANG
__libcpp_db(const __libcpp_db&) = delete;
__libcpp_db& operator=(const __libcpp_db&) = delete;
#else
private:
__libcpp_db(const __libcpp_db&);
__libcpp_db& operator=(const __libcpp_db&);
public:
#endif
~__libcpp_db();
class __db_c_iterator;
class __db_c_const_iterator;
class __db_i_iterator;
class __db_i_const_iterator;
__db_c_const_iterator __c_end() const;
__db_i_const_iterator __i_end() const;
template <class _Cont>
_LIBCPP_INLINE_VISIBILITY
void __insert_c(_Cont* __c)
{
__c_node* __n = __insert_c(static_cast<void*>(__c));
::new(__n) _C_node<_Cont>(__n->__c_, __n->__next_);
}
void __insert_i(void* __i);
__c_node* __insert_c(void* __c);
void __erase_c(void* __c);
void __insert_ic(void* __i, const void* __c);
void __iterator_copy(void* __i, const void* __i0);
void __erase_i(void* __i);
void* __find_c_from_i(void* __i) const;
void __invalidate_all(void* __c);
__c_node* __find_c_and_lock(void* __c) const;
__c_node* __find_c(void* __c) const;
void unlock() const;
void swap(void* __c1, void* __c2);
bool __dereferenceable(const void* __i) const;
bool __decrementable(const void* __i) const;
bool __addable(const void* __i, ptrdiff_t __n) const;
bool __subscriptable(const void* __i, ptrdiff_t __n) const;
bool __less_than_comparable(const void* __i, const void* __j) const;
private:
_LIBCPP_HIDDEN
__i_node* __insert_iterator(void* __i);
_LIBCPP_HIDDEN
__i_node* __find_iterator(const void* __i) const;
friend _LIBCPP_FUNC_VIS __libcpp_db* __get_db();
};
_LIBCPP_FUNC_VIS __libcpp_db* __get_db();
_LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db();
#endif // _LIBCPP_DEBUG_LEVEL >= 2 || defined(_LIBCPP_BUILDING_LIBRARY)
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_DEBUG_H
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册