diff --git a/libraries/table/include/eos/table/dynamic_object.hpp b/libraries/table/include/eos/table/dynamic_object.hpp index 8301c8a..d25220d 100644 --- a/libraries/table/include/eos/table/dynamic_object.hpp +++ b/libraries/table/include/eos/table/dynamic_object.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include namespace eos { namespace table { diff --git a/libraries/table/include/eos/table/dynamic_table.hpp b/libraries/table/include/eos/table/dynamic_table.hpp index 54211ae..572629e 100644 --- a/libraries/table/include/eos/table/dynamic_table.hpp +++ b/libraries/table/include/eos/table/dynamic_table.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include diff --git a/libraries/types/CMakeLists.txt b/libraries/types/CMakeLists.txt index 702b852..8a8b247 100644 --- a/libraries/types/CMakeLists.txt +++ b/libraries/types/CMakeLists.txt @@ -1,7 +1,7 @@ -file(GLOB HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/eos/types/*.hpp") +file(GLOB HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/eos/types/*.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/eos/eoslib/*.hpp") -add_definitions(-DBOOST_PP_VARIADICS) +add_definitions(-DBOOST_PP_VARIADICS -DEOS_TYPES_FULL_CAPABILITY) add_library( eos_types reflect.cpp diff --git a/libraries/types/field_metadata.cpp b/libraries/types/field_metadata.cpp index 35931b7..1f31e0e 100644 --- a/libraries/types/field_metadata.cpp +++ b/libraries/types/field_metadata.cpp @@ -1,9 +1,11 @@ -#include +#include +#include +#ifdef EOS_TYPES_FULL_CAPABILITY #include #include -#include #include +#endif namespace eos { namespace types { @@ -28,12 +30,12 @@ namespace eos { namespace types { if( is_offset_in_bits() ) { if( offset_window::get(_extra) >= offset_limit_in_bits ) - throw std::invalid_argument("Offset (specified in bits) is too large."); + EOS_ERROR(std::invalid_argument, "Offset (specified in bits) is too large."); } else { if( offset_window::get(_extra) >= offset_limit ) - throw std::invalid_argument("Offset is too large."); + EOS_ERROR(std::invalid_argument, "Offset is too large."); } } @@ -46,7 +48,7 @@ namespace eos { namespace types { : _tid(tid), _extra(0) { if( offset >= offset_limit ) - throw std::domain_error("Offset is too large"); + EOS_ERROR(std::domain_error, "Offset is too large"); offset_window::set(_extra, offset); @@ -60,7 +62,7 @@ namespace eos { namespace types { void field_metadata::set_offset(uint32_t offset) { if( offset >= offset_limit ) - throw std::domain_error("Offset is too large."); + EOS_ERROR(std::domain_error, "Offset is too large."); if( is_offset_in_bits() ) offset <<= 3; @@ -71,7 +73,7 @@ namespace eos { namespace types { void field_metadata::set_offset_in_bits(uint32_t offset) { if( offset >= offset_limit_in_bits ) - throw std::domain_error("Offset is too large."); + EOS_ERROR(std::domain_error, "Offset is too large."); if( !is_offset_in_bits() ) offset >>= 3; @@ -79,6 +81,7 @@ namespace eos { namespace types { offset_window::set(_extra, offset); } +#ifdef EOS_TYPES_FULL_CAPABILITY std::ostream& operator<<(std::ostream& os, const field_metadata& f) { boost::io::ios_flags_saver ifs( os ); @@ -104,6 +107,7 @@ namespace eos { namespace types { return os; } +#endif } } diff --git a/libraries/types/full_types_manager.cpp b/libraries/types/full_types_manager.cpp index b4b4b9c..de87021 100644 --- a/libraries/types/full_types_manager.cpp +++ b/libraries/types/full_types_manager.cpp @@ -1,10 +1,13 @@ -#include +#include +#include +#ifdef EOS_TYPES_FULL_CAPABILITY #include #include #include #include #include +#endif namespace eos { namespace types { @@ -25,7 +28,7 @@ namespace eos { namespace types { uint16_t total_num_members; std::tie(member_data_offset, num_sorted_members, total_num_members) = get_members_common(struct_index); if( member_index >= total_num_members ) - throw std::out_of_range("Trying to get a member which does not exist."); + EOS_ERROR(std::out_of_range, "Trying to get a member which does not exist."); return members[(member_data_offset + num_sorted_members) + member_index]; } @@ -34,11 +37,11 @@ namespace eos { namespace types { { auto itr = lookup_by_name.find(name); if( itr == lookup_by_name.end() ) - throw std::invalid_argument("Cannot find table with the given name."); + EOS_ERROR(std::invalid_argument, "Cannot find table with the given name."); auto storage = valid_indices[itr->second]; if( static_cast(index_type_window::get(storage)) != index_type::table_index ) - throw std::invalid_argument("Name does not refer to a table."); + EOS_ERROR(std::invalid_argument, "Name does not refer to a table."); return index_window::get(storage); } @@ -47,7 +50,7 @@ namespace eos { namespace types { { auto itr = lookup_by_name.find(name); if( itr == lookup_by_name.end() ) - throw std::invalid_argument("Cannot find struct with the given name."); + EOS_ERROR(std::invalid_argument, "Cannot find struct with the given name."); auto storage = valid_indices[itr->second]; auto t = static_cast(index_type_window::get(storage)); @@ -63,11 +66,11 @@ namespace eos { namespace types { { auto itr = find_index(index); if( itr == valid_indices.end() ) - throw std::invalid_argument("Not a valid struct index."); + EOS_ERROR(std::invalid_argument, "Not a valid struct index."); auto t = static_cast(index_type_window::get(*itr)); if( t != index_type::simple_struct_index && t != index_type::derived_struct_index ) - throw std::invalid_argument("Index is not to a struct type."); + EOS_ERROR(std::invalid_argument, "Index is not to a struct type."); ++itr; @@ -123,11 +126,126 @@ namespace eos { namespace types { type_id::size_align full_types_manager::get_size_align(type_id tid)const { if( !is_type_valid(tid) ) - throw std::invalid_argument("Type is not valid."); + EOS_ERROR(std::invalid_argument, "Type is not valid."); return types_manager_common::get_size_align(tid); } + pair + full_types_manager::get_struct_info(vector::const_iterator itr)const + { + if( itr == valid_indices.end() || continuation_window::get(*itr) ) + EOS_ERROR(std::invalid_argument, "Iterator does not point to the start of an entry within valid_indices."); + + auto t = static_cast(index_type_window::get(*itr)); + if( t != index_type::simple_struct_index && t != index_type::derived_struct_index ) + EOS_ERROR(std::invalid_argument, "Iterator points to an entry that is not for a struct."); + + ++itr; + const string& name = (lookup_by_name.begin() + index_window::get(*itr))->first; + ++itr; + ++itr; + + return {name, base_sort_window::get(*itr)}; + } + + range::const_iterator> + full_types_manager::get_struct_fields_info(vector::const_iterator itr)const + { + if( itr == valid_indices.end() || continuation_window::get(*itr) ) + EOS_ERROR(std::invalid_argument, "Iterator does not point to the start of an entry within valid_indices."); + + auto t = static_cast(index_type_window::get(*itr)); + if( t != index_type::simple_struct_index && t != index_type::derived_struct_index ) + EOS_ERROR(std::invalid_argument, "Iterator points to an entry that is not for a struct."); + + uint64_t fields_info_index = 0; + uint16_t num_fields = 0; + + fields_info_index |= (static_cast(three_bits_window::get(*itr)) << 37); + + ++itr; + fields_info_index |= (static_cast(seven_bits_window::get(*itr)) << 30); + + ++itr; + fields_info_index |= (static_cast(fifteen_bits_window::get(*itr)) << 15); + num_fields = field_size_window::get(*itr); + + ++itr; + fields_info_index |= static_cast(fifteen_bits_window::get(*itr)); + + return make_range(fields_info, fields_info_index, fields_info_index + num_fields); + } + + std::ptrdiff_t full_types_manager::adjust_iterator(vector::const_iterator& itr)const + { + std::ptrdiff_t seq = 0; + + if( itr == valid_indices.end() ) + return seq; + + while( continuation_window::get(*itr) ) + { + if( itr == valid_indices.begin() ) + EOS_ERROR(std::runtime_error, "Invariant failure: valid_indices was not constructed properly."); + --itr; + --seq; + } + + return seq; + } + + std::ptrdiff_t full_types_manager::advance_iterator(vector::const_iterator& itr)const + { + std::ptrdiff_t step = 1; + switch( static_cast(index_type_window::get(*itr)) ) + { + case index_type::table_index: + step = 2; + break; + case index_type::simple_struct_index: + case index_type::derived_struct_index: + step = 4; + break; + default: + break; + } + std::advance(itr, step); + return step; + } + + vector::const_iterator full_types_manager::find_index(type_id::index_t index)const + { + auto first = valid_indices.begin(); + auto itr = valid_indices.end(); + size_t step = 0; + size_t count = std::distance(first, itr); + + while( count > 0 ) + { + itr = first; + step = count / 2; + + std::advance(itr, step); + step += adjust_iterator(itr); + + if( index_window::get(*itr) < index ) + { + count -= step + advance_iterator(itr); + first = itr; + } + else + count = step; + } + + if( index_window::get(*itr) == index ) + return itr; + else + return valid_indices.end(); + } + +#ifdef EOS_TYPES_FULL_CAPABILITY + struct print_type_visitor { const full_types_manager& tm; @@ -310,7 +428,7 @@ namespace eos { namespace types { for( auto itr = begin; itr != end; ++info_itr, ++itr ) { if( info_itr == r2.end() ) - throw std::runtime_error("Invariant failure: get_struct_fields_info return range of unexpected size."); + EOS_ERROR(std::runtime_error, "Invariant failure: get_struct_fields_info return range of unexpected size."); auto field_length = field_names[fields_index_window::get(*info_itr)].size(); max_fieldname_length = std::max(max_fieldname_length, field_length); @@ -346,128 +464,17 @@ namespace eos { namespace types { case index_type::tuple_index: break; // Tuple needs to be handled by the same code that handles other non-struct types. default: - throw std::invalid_argument("Struct or tuple does not exist with index specified in the given type."); + EOS_ERROR(std::invalid_argument, "Struct or tuple does not exist with index specified in the given type."); } } else if( !tid.is_void() && !is_type_valid(tid) ) - throw std::logic_error("Type is not valid."); + EOS_ERROR(std::logic_error, "Type is not valid."); // Otherwise, print the non-struct type (includes tuples): traverse_type(tid, v); } - pair - full_types_manager::get_struct_info(vector::const_iterator itr)const - { - if( itr == valid_indices.end() || continuation_window::get(*itr) ) - throw std::invalid_argument("Iterator does not point to the start of an entry within valid_indices."); - - auto t = static_cast(index_type_window::get(*itr)); - if( t != index_type::simple_struct_index && t != index_type::derived_struct_index ) - throw std::invalid_argument("Iterator points to an entry that is not for a struct."); - - ++itr; - const string& name = (lookup_by_name.begin() + index_window::get(*itr))->first; - ++itr; - ++itr; - - return {name, base_sort_window::get(*itr)}; - } - - range::const_iterator> - full_types_manager::get_struct_fields_info(vector::const_iterator itr)const - { - if( itr == valid_indices.end() || continuation_window::get(*itr) ) - throw std::invalid_argument("Iterator does not point to the start of an entry within valid_indices."); - - auto t = static_cast(index_type_window::get(*itr)); - if( t != index_type::simple_struct_index && t != index_type::derived_struct_index ) - throw std::invalid_argument("Iterator points to an entry that is not for a struct."); - - uint64_t fields_info_index = 0; - uint16_t num_fields = 0; - - fields_info_index |= (static_cast(three_bits_window::get(*itr)) << 37); - - ++itr; - fields_info_index |= (static_cast(seven_bits_window::get(*itr)) << 30); - - ++itr; - fields_info_index |= (static_cast(fifteen_bits_window::get(*itr)) << 15); - num_fields = field_size_window::get(*itr); - - ++itr; - fields_info_index |= static_cast(fifteen_bits_window::get(*itr)); - - return make_range(fields_info, fields_info_index, fields_info_index + num_fields); - } - - std::ptrdiff_t full_types_manager::adjust_iterator(vector::const_iterator& itr)const - { - std::ptrdiff_t seq = 0; - - if( itr == valid_indices.end() ) - return seq; - - while( continuation_window::get(*itr) ) - { - if( itr == valid_indices.begin() ) - throw std::runtime_error("Invariant failure: valid_indices was not constructed properly."); - --itr; - --seq; - } - - return seq; - } - - std::ptrdiff_t full_types_manager::advance_iterator(vector::const_iterator& itr)const - { - std::ptrdiff_t step = 1; - switch( static_cast(index_type_window::get(*itr)) ) - { - case index_type::table_index: - step = 2; - break; - case index_type::simple_struct_index: - case index_type::derived_struct_index: - step = 4; - break; - default: - break; - } - std::advance(itr, step); - return step; - } - - vector::const_iterator full_types_manager::find_index(type_id::index_t index)const - { - auto first = valid_indices.begin(); - auto itr = valid_indices.end(); - size_t step = 0; - size_t count = std::distance(first, itr); - - while( count > 0 ) - { - itr = first; - step = count / 2; - - std::advance(itr, step); - step += adjust_iterator(itr); - - if( index_window::get(*itr) < index ) - { - count -= step + advance_iterator(itr); - first = itr; - } - else - count = step; - } - - if( index_window::get(*itr) == index ) - return itr; - else - return valid_indices.end(); - } +#endif } } diff --git a/libraries/types/include/eos/types/bit_view.hpp b/libraries/types/include/eos/eoslib/bit_view.hpp similarity index 67% rename from libraries/types/include/eos/types/bit_view.hpp rename to libraries/types/include/eos/eoslib/bit_view.hpp index 3924419..4b8da5c 100644 --- a/libraries/types/include/eos/types/bit_view.hpp +++ b/libraries/types/include/eos/eoslib/bit_view.hpp @@ -1,19 +1,24 @@ #pragma once -#include -#include +#include +#include namespace eos { namespace types { + using eoslib::is_integral; + using eoslib::is_signed; + using eoslib::is_same; + using eoslib::enable_if; + template struct bit_view { - static_assert( std::is_integral::value, "T must be an integral type" ); - static_assert( std::is_integral::value && !std::is_signed::value, "S must be an unsigned integral type" ); + static_assert( is_integral::value, "T must be an integral type" ); + static_assert( is_integral::value && !is_signed::value, "S must be an unsigned integral type" ); static_assert( sizeof(T) <= sizeof(S), "size of T cannot be larger than size of S" ); static_assert( 0 <= start && start < sizeof(S)*8, "start must be within the internal [0, N) where N = number of bits in S" ); static_assert( size > 0, "size cannot be 0" ); - static_assert( size != 1 || !std::is_signed::value, "T cannot be signed if size == 1" ); + static_assert( size != 1 || !is_signed::value, "T cannot be signed if size == 1" ); static_assert( size <= sizeof(S)*8, "size is too large" ); static_assert( start >= sizeof(S)*8 || start + size <= sizeof(S)*8, "size is too large for window to fit into S given the start" ); static_assert( sizeof(T)*8 >= size, "size is too large to fit into specified type T" ); @@ -28,20 +33,20 @@ namespace eos { namespace types { template static inline - typename std::enable_if::value, U>::type + typename enable_if::value, U>::type get( S s ) // Expects T to be unsigned { - static_assert( std::is_same::value, "Do not override default template argument for get method" ); + static_assert( is_same::value, "Do not override default template argument for get method" ); return static_cast((s & mask) >> start); } template static inline - typename std::enable_if::value && size == sizeof(U)*8, U>::type + typename enable_if::value && size == sizeof(U)*8, U>::type get( S s ) // Handles special case of signed T (faster implementation than general case) { - static_assert( std::is_same::value, "Do not override default template argument for get method" ); + static_assert( is_same::value, "Do not override default template argument for get method" ); return static_cast((s & mask) >> start); } @@ -49,10 +54,10 @@ namespace eos { namespace types { template static inline - typename std::enable_if::value && size != sizeof(U)*8, U>::type + typename enable_if::value && size != sizeof(U)*8, U>::type get( S s ) // Handles general case of signed T { - static_assert( std::is_same::value, "Do not override default template argument for get method" ); + static_assert( is_same::value, "Do not override default template argument for get method" ); bool negative = ((sign_check_mask & s) != 0); diff --git a/libraries/types/include/eos/types/deserialize_visitor.hpp b/libraries/types/include/eos/eoslib/deserialize_visitor.hpp similarity index 78% rename from libraries/types/include/eos/types/deserialize_visitor.hpp rename to libraries/types/include/eos/eoslib/deserialize_visitor.hpp index 79a40e6..3a162df 100644 --- a/libraries/types/include/eos/types/deserialize_visitor.hpp +++ b/libraries/types/include/eos/eoslib/deserialize_visitor.hpp @@ -1,14 +1,17 @@ #pragma once -#include -#include -#include - -#include -#include +#include +#include +#include +#include +#include namespace eos { namespace types { + using eoslib::is_integral; + using eoslib::is_same; + using eoslib::enable_if; + struct deserialize_visitor { const full_types_manager& tm; @@ -21,21 +24,21 @@ namespace eos { namespace types { {} template - typename std::enable_if::value && !std::is_same::value>::type + typename enable_if::value && !is_same::value>::type operator()(B& b)const { if( tid.get_builtin_type() != eos::types::reflector::builtin_type ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); b = r.get(offset); } template - typename std::enable_if::value>::type + typename enable_if::value>::type operator()(B& b)const { if( tid.get_builtin_type() != eos::types::reflector::builtin_type ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); b = r.get(offset); } @@ -46,12 +49,12 @@ namespace eos { namespace types { #define EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( builtin_name ) \ template \ - typename std::enable_if::is_builtin::value && !std::is_integral::value \ + typename enable_if::is_builtin::value && !is_integral::value \ && eos::types::reflector::builtin_type == type_id::builtin_ ## builtin_name >::type \ - operator()(B& b)const \ + operator()(B& b)const \ { \ if( tid.get_builtin_type() != eos::types::reflector::builtin_type ) \ - throw std::runtime_error("Type mismatch"); \ + EOS_ERROR(std::runtime_error, "Type mismatch"); \ #define EOS_TYPES_CUSTOM_BUILTIN_MATCH_END \ } @@ -77,7 +80,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( bytes ) read_vector(b); -// throw std::logic_error("Bytes should be represented in C++ by a vector of uint8_t."); +// EOS_ERROR(std::logic_error, "Bytes should be represented in C++ by a vector of uint8_t."); EOS_TYPES_CUSTOM_BUILTIN_MATCH_END EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( rational ) @@ -86,11 +89,11 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( rational ) EOS_TYPES_CUSTOM_BUILTIN_MATCH_END EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( any ) - throw std::runtime_error("Not implemented"); + EOS_ERROR(std::runtime_error, "Not implemented"); EOS_TYPES_CUSTOM_BUILTIN_MATCH_END template - typename std::enable_if::is_struct::value && eos::types::reflector::is_struct::value>::type + typename enable_if::is_struct::value && eos::types::reflector::is_struct::value>::type operator()(Base& b)const { auto base_tid = tm.get_member(tid.get_type_index(), 0).get_type_id(); @@ -117,7 +120,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END } template - typename std::enable_if::is_struct::value>::type + typename enable_if::is_struct::value>::type operator()(Class& c, const char* name, uint32_t member_index)const { auto vis = make_visitor_for_product_type_member(member_index); @@ -125,7 +128,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END } template // Meant for tuples/pairs - typename std::enable_if::is_tuple::value>::type + typename enable_if::is_tuple::value>::type operator()(Class& c)const { auto vis = make_visitor_for_product_type_member(static_cast(Index)); @@ -133,16 +136,16 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END } template - typename std::enable_if::is_array::value>::type + typename enable_if::is_array::value>::type operator()(Container& c)const { type_id element_tid; uint32_t num_elements; std::tie(element_tid, num_elements) = tm.get_container_element_type(tid); if( num_elements < 2 ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); if( num_elements != c.size() ) - throw std::runtime_error("Mismatch in number of elements of array"); + EOS_ERROR(std::runtime_error, "Mismatch in number of elements of array"); auto stride = tm.get_size_align(element_tid).get_stride(); @@ -158,13 +161,13 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END void read_vector(Container& c, bool extra_zero_at_end = false)const { if( c.size() != 0 ) - throw std::runtime_error("Expected vector to construct to be initially empty."); + EOS_ERROR(std::runtime_error, "Expected vector to construct to be initially empty."); type_id element_tid; uint32_t num_elements; std::tie(element_tid, num_elements) = tm.get_container_element_type(tid); if( num_elements != 0 ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); num_elements = r.get(offset); if( num_elements == 0 || (extra_zero_at_end && num_elements == 1) ) @@ -176,9 +179,9 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END uint32_t vector_data_offset = r.get(offset+4); if( vector_data_offset != type_id::round_up_to_alignment(vector_data_offset, align) ) - throw std::logic_error("Vector data located at offset that does not satisfy alignment requirements for element type."); + EOS_ERROR(std::logic_error, "Vector data located at offset that does not satisfy alignment requirements for element type."); if( (vector_data_offset + (num_elements * stride)) > r.offset_end() ) - throw std::logic_error("Raw region is too small to contain this type."); + EOS_ERROR(std::logic_error, "Raw region is too small to contain this type."); deserialize_visitor vis(tm, r, element_tid, vector_data_offset); auto itr = std::inserter(c, c.end()); @@ -194,21 +197,21 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END } template - typename std::enable_if::is_vector::value>::type + typename enable_if::is_vector::value>::type operator()(Container& c)const { read_vector(c); } template - typename std::enable_if::is_optional::value>::type + typename enable_if::is_optional::value>::type operator()(Container& c)const { type_id element_tid; uint32_t num_elements; std::tie(element_tid, num_elements) = tm.get_container_element_type(tid); if( num_elements != 1 ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); if( !static_cast(c) ) return; // Since region is zero initialized, it would be redundant to set optional tag to false. diff --git a/libraries/types/include/eos/eoslib/exceptions.hpp b/libraries/types/include/eos/eoslib/exceptions.hpp new file mode 100644 index 0000000..1e86560 --- /dev/null +++ b/libraries/types/include/eos/eoslib/exceptions.hpp @@ -0,0 +1,19 @@ +#pragma once + +#ifdef EOS_TYPES_FULL_CAPABILITY + +#include + +#define EOS_ERROR(type, message) do { throw type(message); } while(0) + +#else + +//void assert( unsigned int test, const char* cstr ); + +//#define EOS_ERROR(type, message) do { assert(0, message); } while(0) + +#include + +#define EOS_ERROR(type, message) do { assert(0); } while(0) + +#endif diff --git a/libraries/types/include/eos/types/field_metadata.hpp b/libraries/types/include/eos/eoslib/field_metadata.hpp similarity index 95% rename from libraries/types/include/eos/types/field_metadata.hpp rename to libraries/types/include/eos/eoslib/field_metadata.hpp index 8019ccf..3cae4c5 100644 --- a/libraries/types/include/eos/types/field_metadata.hpp +++ b/libraries/types/include/eos/eoslib/field_metadata.hpp @@ -1,9 +1,11 @@ #pragma once -#include -#include +#include +#include +#ifdef EOS_TYPES_FULL_CAPABILITY #include +#endif namespace eos { namespace types { @@ -103,7 +105,9 @@ namespace eos { namespace types { friend inline bool operator==(field_metadata lhs, field_metadata rhs) { return (lhs._tid == rhs._tid) && (lhs._extra == rhs._extra); } friend inline bool operator!=(field_metadata lhs, field_metadata rhs) { return (lhs._tid != rhs._tid) || (lhs._extra != rhs._extra); } +#ifdef EOS_TYPES_FULL_CAPABILITY friend std::ostream& operator<<(std::ostream& os, const field_metadata&); +#endif }; diff --git a/libraries/types/include/eos/types/full_types_manager.hpp b/libraries/types/include/eos/eoslib/full_types_manager.hpp similarity index 94% rename from libraries/types/include/eos/types/full_types_manager.hpp rename to libraries/types/include/eos/eoslib/full_types_manager.hpp index d84a08c..c7f286c 100644 --- a/libraries/types/include/eos/types/full_types_manager.hpp +++ b/libraries/types/include/eos/eoslib/full_types_manager.hpp @@ -1,12 +1,13 @@ #pragma once -#include -#include -#include +#include +#include -#include #include #include +#ifdef EOS_TYPES_FULL_CAPABILITY +#include +#endif namespace eos { namespace types { @@ -65,21 +66,16 @@ namespace eos { namespace types { type_id::index_t get_struct_index(const string& name)const; string get_struct_name(type_id::index_t index)const; - template - inline - typename std::enable_if::is_struct::value, type_id::index_t>::type - get_struct_index()const - { - return get_struct_index(eos::types::reflector::name()); - } - bool is_type_valid(type_id tid)const; type_id::size_align get_size_align(type_id tid)const; - void print_type(std::ostream& os, type_id tid)const; friend class types_constructor; + +#ifdef EOS_TYPES_FULL_CAPABILITY + void print_type(std::ostream& os, type_id tid)const; friend struct print_type_visitor; +#endif private: diff --git a/libraries/types/include/eos/eoslib/immutable_region.hpp b/libraries/types/include/eos/eoslib/immutable_region.hpp new file mode 100644 index 0000000..a219c3b --- /dev/null +++ b/libraries/types/include/eos/eoslib/immutable_region.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace eos { namespace types { + + using eoslib::enable_if; + using eoslib::remove_cv; + + class immutable_region + { + public: + + immutable_region(const full_types_manager& tm, const raw_region& raw_data) + : tm(tm), raw_data(raw_data) + { + } + + immutable_region(const full_types_manager& tm, raw_region&& raw_data) + : tm(tm), raw_data(std::move(raw_data)) + { + } + + //TODO: Complete implementation + + template + typename enable_if::type>::is_struct::value>::type + read_struct(T& type, type_id tid, uint32_t offset = 0) + { + using PlainT = typename remove_cv::type; + auto sa = tm.get_size_align(tid); + if( offset != type_id::round_up_to_alignment(offset, sa.get_align()) ) + EOS_ERROR(std::logic_error, "Offset not at appropriate alignment required by the struct."); + if( raw_data.offset_end() < offset + sa.get_size() ) + EOS_ERROR(std::logic_error, "Raw data is too small to possibly contain the struct at the specified offset."); + deserialize_visitor vis(tm, raw_data, tid, offset); + eos::types::reflector::visit(type, vis); + } + + inline const vector& get_raw_data()const { return raw_data.get_raw_data(); } + + private: + const full_types_manager& tm; + raw_region raw_data; + }; + +} } + diff --git a/libraries/types/include/eos/eoslib/mutable_region.hpp b/libraries/types/include/eos/eoslib/mutable_region.hpp new file mode 100644 index 0000000..b281375 --- /dev/null +++ b/libraries/types/include/eos/eoslib/mutable_region.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace eos { namespace types { + + using eoslib::enable_if; + using eoslib::remove_cv; + + class mutable_region + { + public: + + mutable_region(const full_types_manager& tm, const raw_region& raw_data) + : tm(tm), raw_data(raw_data) + { + } + + mutable_region(const full_types_manager& tm, raw_region&& raw_data) + : tm(tm), raw_data(std::move(raw_data)) + { + } + + //TODO: Complete implementation + + template + typename enable_if::type>::is_struct::value>::type + read_struct(T& type, type_id tid, uint32_t offset = 0) + { + using PlainT = typename remove_cv::type; + auto sa = tm.get_size_align(tid); + if( offset != type_id::round_up_to_alignment(offset, sa.get_align()) ) + EOS_ERROR(std::logic_error, "Offset not at appropriate alignment required by the struct."); + if( raw_data.offset_end() < offset + sa.get_size() ) + EOS_ERROR(std::logic_error, "Raw data is too small to possibly contain the struct at the specified offset."); + deserialize_visitor vis(tm, raw_data, tid, offset); + eos::types::reflector::visit(type, vis); + } + + inline const vector& get_raw_data()const { return raw_data.get_raw_data(); } + + private: + const full_types_manager& tm; + raw_region raw_data; + }; + +} } + diff --git a/libraries/types/include/eos/types/raw_region.hpp b/libraries/types/include/eos/eoslib/raw_region.hpp similarity index 70% rename from libraries/types/include/eos/types/raw_region.hpp rename to libraries/types/include/eos/eoslib/raw_region.hpp index bebee88..d0635c4 100644 --- a/libraries/types/include/eos/types/raw_region.hpp +++ b/libraries/types/include/eos/eoslib/raw_region.hpp @@ -1,8 +1,13 @@ #pragma once -#include -#include +#include +#include +#include + #include +#ifdef EOS_TYPES_FULL_CAPABILITY +#include +#endif namespace eos { namespace types { @@ -10,11 +15,16 @@ namespace eos { namespace types { using std::vector; + using eoslib::is_integral; + using eoslib::is_same; + using eoslib::enable_if; + class raw_region { static const byte byte_masks[16]; public: + raw_region() {}; raw_region(const raw_region& other) = default; @@ -44,45 +54,45 @@ namespace eos { namespace types { template inline - typename std::enable_if::value && !std::is_same::value, T>::type + typename enable_if::value && !is_same::value, T>::type get( uint32_t offset )const { if( offset + sizeof(T) > offset_end() ) - throw std::out_of_range("Offset puts type outside of current range."); + EOS_ERROR(std::out_of_range, "Offset puts type outside of current range."); return *reinterpret_cast(raw_data.data() + offset); } template inline - typename std::enable_if::value && !std::is_same::value, T&>::type + typename enable_if::value && !is_same::value, T&>::type get( uint32_t offset ) { if( offset + sizeof(T) > offset_end() ) - throw std::out_of_range("Offset puts type outside of current range."); + EOS_ERROR(std::out_of_range, "Offset puts type outside of current range."); return *reinterpret_cast(raw_data.data() + offset); } template inline - typename std::enable_if::value && !std::is_same::value>::type + typename enable_if::value && !is_same::value>::type set( uint32_t offset, T value ) { if( offset + sizeof(T) > offset_end() ) - throw std::out_of_range("Offset puts type outside of current range."); + EOS_ERROR(std::out_of_range, "Offset puts type outside of current range."); *reinterpret_cast(raw_data.data() + offset) = value; } template inline - typename std::enable_if::value, bool>::type + typename enable_if::value, bool>::type get( uint32_t offset_in_bits )const { uint32_t offset = (offset_in_bits >> 3); if( offset >= offset_end() ) - throw std::out_of_range("Offset puts type outside of current range."); + EOS_ERROR(std::out_of_range, "Offset puts type outside of current range."); byte b = *reinterpret_cast(raw_data.data() + offset); auto index = ((offset_in_bits & 7) << 1); @@ -91,12 +101,12 @@ namespace eos { namespace types { template inline - typename std::enable_if::value>::type + typename enable_if::value>::type set( uint32_t offset_in_bits, bool value ) { uint32_t offset = (offset_in_bits >> 3); if( offset >= offset_end() ) - throw std::out_of_range("Offset puts type outside of current range."); + EOS_ERROR(std::out_of_range, "Offset puts type outside of current range."); byte& b = *reinterpret_cast(raw_data.data() + offset); auto index = ((offset_in_bits & 7) << 1); @@ -106,9 +116,11 @@ namespace eos { namespace types { b &= byte_masks[index+1]; } +#ifdef EOS_TYPES_FULL_CAPABILITY void print_raw_data(std::ostream& os, uint32_t offset = 0, uint32_t size = 4096 )const; friend std::ostream& operator<<(std::ostream& os, const raw_region& r); +#endif private: vector raw_data; diff --git a/libraries/types/include/eos/eoslib/reflect_basic.hpp b/libraries/types/include/eos/eoslib/reflect_basic.hpp new file mode 100644 index 0000000..15a7be9 --- /dev/null +++ b/libraries/types/include/eos/eoslib/reflect_basic.hpp @@ -0,0 +1,335 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +using eoslib::true_type; +using eoslib::false_type; + +namespace eos { namespace types { + template + struct reflector + { + using is_defined = false_type; + }; + + template + struct table_reflector + { + using is_defined = false_type; + }; + + template + struct types_initializer + { + }; + + struct rational + { + rational() + : numerator(0), denominator(1) + {} + + rational(int64_t n, uint64_t d) + : numerator(n), denominator(d) + {} + + int64_t numerator; + uint64_t denominator; + }; + +} } + +#ifndef _MSC_VER + #define TEMPLATE template +#else + // Disable warning C4482: nonstandard extention used: enum 'enum_type::enum_value' used in qualified name + #pragma warning( disable: 4482 ) + #define TEMPLATE +#endif + +#define EOS_TYPES_REFLECT_SIMPLE_VISIT \ + template \ + static void visit(Visitor& _v) \ + { \ + _v.TEMPLATE operator()(); \ + } \ + template \ + static void visit(const type& _x, const Visitor& _v) \ + { \ + _v.TEMPLATE operator()(_x); \ + } \ + template \ + static void visit(type& _x, const Visitor& _v) \ + { \ + _v.TEMPLATE operator()(_x); \ + } \ + +#define EOS_TYPES_REFLECT_BUILTIN(T, B) \ +namespace eos { namespace types { \ + template <> \ + struct reflector \ + { \ + using is_defined = true_type; \ + using is_struct = false_type; \ + using is_builtin = true_type; \ + using type = T; \ + static const type_id::builtin builtin_type = type_id::B; \ + EOS_TYPES_REFLECT_SIMPLE_VISIT \ + }; \ +} } + +#define EOS_TYPES_REFLECT_ARRAY(C) \ +namespace eos { namespace types { \ + template \ + struct reflector> \ + { \ + using is_defined = true_type; \ + using is_struct = false_type; \ + using is_array = true_type; \ + using type = C; \ + enum num_elements_enum { \ + num_elements = N \ + }; \ + EOS_TYPES_REFLECT_SIMPLE_VISIT \ + }; \ +} } + +#define EOS_TYPES_REFLECT_VECTOR(C) \ +namespace eos { namespace types { \ + template \ + struct reflector> \ + { \ + using is_defined = true_type; \ + using is_struct = false_type; \ + using is_vector = true_type; \ + using type = C; \ + EOS_TYPES_REFLECT_SIMPLE_VISIT \ + }; \ +} } + +#define EOS_TYPES_REFLECT_OPTIONAL(C) \ +namespace eos { namespace types { \ + template \ + struct reflector> \ + { \ + using is_defined = true_type; \ + using is_struct = false_type; \ + using is_optional = true_type; \ + using type = C; \ + EOS_TYPES_REFLECT_SIMPLE_VISIT \ + }; \ +} } + +// Alternative to requiring Boost Preprocesser headers just to implement EOS_TYPES_REFLECT_TUPLE +// Adapted from: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms + +#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) +#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ + +#define IIF(c) PRIMITIVE_CAT(IIF_, c) +#define IIF_0(t, ...) __VA_ARGS__ +#define IIF_1(t, ...) t + +#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) +#define COMPL_0 1 +#define COMPL_1 0 + +#define BITAND(x) PRIMITIVE_CAT(BITAND_, x) +#define BITAND_0(y) 0 +#define BITAND_1(y) y + +#define INC(x) PRIMITIVE_CAT(INC_, x) +#define INC_0 1 +#define INC_1 2 +#define INC_2 3 +#define INC_3 4 +#define INC_4 5 +#define INC_5 6 +#define INC_6 7 +#define INC_7 8 +#define INC_8 9 +#define INC_9 9 + +#define DEC(x) PRIMITIVE_CAT(DEC_, x) +#define DEC_0 0 +#define DEC_1 0 +#define DEC_2 1 +#define DEC_3 2 +#define DEC_4 3 +#define DEC_5 4 +#define DEC_6 5 +#define DEC_7 6 +#define DEC_8 7 +#define DEC_9 8 + +#define CHECK_N(x, n, ...) n +#define CHECK(...) CHECK_N(__VA_ARGS__, 0,) +#define PROBE(x) x, 1, + +#define IS_PAREN(x) CHECK(IS_PAREN_PROBE x) +#define IS_PAREN_PROBE(...) PROBE(~) + +#define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x)) +#define NOT_0 PROBE(~) + +#define BOOL(x) COMPL(NOT(x)) +#define IF(c) IIF(BOOL(c)) + +#define EAT(...) +#define EXPAND(...) __VA_ARGS__ +#define WHEN(c) IF(c)(EXPAND, EAT) + +#define EMPTY() +#define DEFER(id) id EMPTY() +#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() +#define EXPAND(...) __VA_ARGS__ + +#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) +#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) +#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) +#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) +#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__))) +#define EVAL5(...) __VA_ARGS__ + +#define REPEAT(count, macro, ...) \ + WHEN(count) \ + ( \ + OBSTRUCT(REPEAT_INDIRECT) () \ + ( \ + DEC(count), macro, __VA_ARGS__ \ + ) \ + OBSTRUCT(macro) \ + ( \ + DEC(count), __VA_ARGS__ \ + ) \ + ) +#define REPEAT_INDIRECT() REPEAT + +#define PRIMITIVE_COMPARE(x, y) IS_PAREN \ +( \ +COMPARE_ ## x ( COMPARE_ ## y) (()) \ +) + +#define IS_COMPARABLE(x) IS_PAREN( CAT(COMPARE_, x) (()) ) + +#define NOT_EQUAL(x, y) \ +IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y)) ) \ +( \ + PRIMITIVE_COMPARE, \ + 1 EAT \ +)(x, y) + +#define EQUAL(x, y) COMPL(NOT_EQUAL(x, y)) + +#define COMPARE_0(x) x +#define COMPARE_1(x) x +#define COMPARE_2(x) x +#define COMPARE_3(x) x +#define COMPARE_4(x) x +#define COMPARE_5(x) x +#define COMPARE_6(x) x +#define COMPARE_7(x) x +#define COMPARE_8(x) x +#define COMPARE_9(x) x + +#define REPEAT_FROM_TO(from, to, macro, ...) \ + WHEN(BITAND(NOT_EQUAL(from, to))(to)) \ + ( \ + OBSTRUCT(REPEAT_FROM_TO_INDIRECT) () \ + ( \ + from, DEC(to), macro, __VA_ARGS__ \ + ) \ + OBSTRUCT(macro) \ + ( \ + DEC(to), __VA_ARGS__ \ + ) \ + ) +#define REPEAT_FROM_TO_INDIRECT() REPEAT_FROM_TO + +#define EOS_TYPES_REFLECT_TEMPLATE_ARG( index, data ) , data T##index + +#define EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT( index, data ) \ + _v.TEMPLATE operator()( _s ); + +#define EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT_TYPE( index, data ) \ + _v.TEMPLATE operator()(); + +#define EOS_TYPES_REFLECT_TUPLE(C, num_template_args) \ +namespace eos { namespace types { \ + template \ + struct reflector> \ + { \ + using is_defined = std::true_type; \ + using is_product_type = std::true_type; \ + using is_struct = std::false_type; \ + using is_tuple = std::true_type; \ + using type = C; \ + enum field_count_enum { \ + field_count = num_template_args \ + }; \ + enum sorted_member_count_enum { \ + sorted_member_count = num_template_args \ + }; \ + template \ + static void visit(Visitor& _v) \ + { \ + EVAL(REPEAT(num_template_args, EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT_TYPE, T)) \ + _v.TEMPLATE operator()(); \ + } \ + template \ + static void visit(const type& _s, const Visitor& _v) \ + { \ + EVAL(REPEAT(num_template_args, EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT, T)) \ + } \ + template \ + static void visit(type& _s, const Visitor& _v) \ + { \ + EVAL(REPEAT(num_template_args, EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT, T)) \ + } \ + }; \ +} } + +EOS_TYPES_REFLECT_BUILTIN(bool, builtin_bool) +EOS_TYPES_REFLECT_BUILTIN(char, builtin_uint8) +EOS_TYPES_REFLECT_BUILTIN(int8_t, builtin_int8) +EOS_TYPES_REFLECT_BUILTIN(uint8_t, builtin_uint8) +EOS_TYPES_REFLECT_BUILTIN(int16_t, builtin_int16) +EOS_TYPES_REFLECT_BUILTIN(uint16_t, builtin_uint16) +EOS_TYPES_REFLECT_BUILTIN(int32_t, builtin_int32) +EOS_TYPES_REFLECT_BUILTIN(uint32_t, builtin_uint32) +EOS_TYPES_REFLECT_BUILTIN(int64_t, builtin_int64) +EOS_TYPES_REFLECT_BUILTIN(uint64_t, builtin_uint64) +EOS_TYPES_REFLECT_BUILTIN(std::string, builtin_string) +EOS_TYPES_REFLECT_BUILTIN(std::vector, builtin_bytes) +EOS_TYPES_REFLECT_BUILTIN(eos::types::rational, builtin_rational) +EOS_TYPES_REFLECT_BUILTIN(eos::types::type_id, builtin_uint32) + +EOS_TYPES_REFLECT_ARRAY(std::array) +EOS_TYPES_REFLECT_VECTOR(std::vector) +//EOS_TYPES_REFLECT_OPTIONAL(boost::optional) + +EOS_TYPES_REFLECT_TUPLE(std::pair, 2) +EOS_TYPES_REFLECT_TUPLE(std::tuple, 2) +EOS_TYPES_REFLECT_TUPLE(std::tuple, 3) +EOS_TYPES_REFLECT_TUPLE(std::tuple, 4) +EOS_TYPES_REFLECT_TUPLE(std::tuple, 5) +EOS_TYPES_REFLECT_TUPLE(std::tuple, 6) +EOS_TYPES_REFLECT_TUPLE(std::tuple, 7) + + +#define EOS_TYPES_REFLECT_STRUCT(...) +#define EOS_TYPES_REFLECT_STRUCT_DERIVED(...) +#define EOS_TYPES_CREATE_TABLE(...) +#define EOS_TYPES_REGISTER_TYPES(...) + + diff --git a/libraries/types/include/eos/types/serialization_region.hpp b/libraries/types/include/eos/eoslib/serialization_region.hpp similarity index 79% rename from libraries/types/include/eos/types/serialization_region.hpp rename to libraries/types/include/eos/eoslib/serialization_region.hpp index 89d0fbe..02a6608 100644 --- a/libraries/types/include/eos/types/serialization_region.hpp +++ b/libraries/types/include/eos/eoslib/serialization_region.hpp @@ -1,15 +1,19 @@ #pragma once -#include -#include -#include -#include - -#include -#include +#include +#include +#include +#include +#include +#include namespace eos { namespace types { + using eoslib::is_integral; + using eoslib::is_same; + using eoslib::enable_if; + using eoslib::remove_cv; + class serialization_region { public: @@ -33,21 +37,21 @@ namespace eos { namespace types { {} template - typename std::enable_if::value && !std::is_same::value>::type + typename enable_if::value && !is_same::value>::type operator()(const B& b)const { if( tid.get_builtin_type() != eos::types::reflector::builtin_type ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); r.set(offset, b); } template - typename std::enable_if::value>::type + typename enable_if::value>::type operator()(const B& b)const { if( tid.get_builtin_type() != eos::types::reflector::builtin_type ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); r.set(offset, b); // In this case, offset is in bits. } @@ -58,12 +62,12 @@ namespace eos { namespace types { #define EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( builtin_name ) \ template \ - typename std::enable_if::is_builtin::value && !std::is_integral::value \ + typename enable_if::is_builtin::value && !is_integral::value \ && eos::types::reflector::builtin_type == type_id::builtin_ ## builtin_name >::type \ operator()(const B& b)const \ { \ if( tid.get_builtin_type() != eos::types::reflector::builtin_type ) \ - throw std::runtime_error("Type mismatch"); \ + EOS_ERROR(std::runtime_error, "Type mismatch"); \ #define EOS_TYPES_CUSTOM_BUILTIN_MATCH_END \ } @@ -89,7 +93,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( bytes ) write_vector(b); -// throw std::logic_error("Bytes should be represented in C++ by a vector of uint8_t."); +// EOS_ERROR(std::logic_error, "Bytes should be represented in C++ by a vector of uint8_t."); EOS_TYPES_CUSTOM_BUILTIN_MATCH_END EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( rational ) @@ -98,11 +102,11 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( rational ) EOS_TYPES_CUSTOM_BUILTIN_MATCH_END EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( any ) - throw std::runtime_error("Not implemented"); + EOS_ERROR(std::runtime_error, "Not implemented"); EOS_TYPES_CUSTOM_BUILTIN_MATCH_END template - typename std::enable_if::is_struct::value && eos::types::reflector::is_struct::value>::type + typename enable_if::is_struct::value && eos::types::reflector::is_struct::value>::type operator()(const Base& b)const { auto base_tid = tm.get_member(tid.get_type_index(), 0).get_type_id(); @@ -129,7 +133,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END } template - typename std::enable_if::is_struct::value>::type + typename enable_if::is_struct::value>::type operator()(const Class& c, const char* name, uint32_t member_index)const { auto vis = make_visitor_for_product_type_member(member_index); @@ -137,7 +141,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END } template // Meant for tuples/pairs - typename std::enable_if::is_tuple::value>::type + typename enable_if::is_tuple::value>::type operator()(const Class& c)const { auto vis = make_visitor_for_product_type_member(static_cast(Index)); @@ -145,16 +149,16 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END } template - typename std::enable_if::is_array::value>::type + typename enable_if::is_array::value>::type operator()(const Container& c)const { type_id element_tid; uint32_t num_elements; std::tie(element_tid, num_elements) = tm.get_container_element_type(tid); if( num_elements < 2 ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); if( num_elements != c.size() ) - throw std::runtime_error("Mismatch in number of elements of array"); + EOS_ERROR(std::runtime_error, "Mismatch in number of elements of array"); auto stride = tm.get_size_align(element_tid).get_stride(); @@ -173,7 +177,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END uint32_t num_elements; std::tie(element_tid, num_elements) = tm.get_container_element_type(tid); if( num_elements != 0 ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); num_elements = c.size(); if( num_elements == 0 ) return; @@ -192,7 +196,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END for( uint32_t i = 0; i < num_elements; ++i, ++itr ) { if( itr == c.end() ) - throw std::runtime_error("Unexpected end of vector."); + EOS_ERROR(std::runtime_error, "Unexpected end of vector."); eos::types::reflector::visit(*itr, vis); vis.offset += stride; @@ -200,21 +204,21 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END } template - typename std::enable_if::is_vector::value>::type + typename enable_if::is_vector::value>::type operator()(const Container& c)const { write_vector(c); } template - typename std::enable_if::is_optional::value>::type + typename enable_if::is_optional::value>::type operator()(const Container& c)const { type_id element_tid; uint32_t num_elements; std::tie(element_tid, num_elements) = tm.get_container_element_type(tid); if( num_elements != 1 ) - throw std::runtime_error("Type mismatch"); + EOS_ERROR(std::runtime_error, "Type mismatch"); if( !static_cast(c) ) return; // Since region is zero initialized, it would be redundant to set optional tag to false. @@ -229,10 +233,10 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END }; template - typename std::enable_if::type>::is_defined::value, uint32_t>::type + typename enable_if::type>::is_defined::value, uint32_t>::type write_type(const T& type, type_id tid) { - using PlainT = typename std::remove_cv::type; + using PlainT = typename remove_cv::type; auto sa = tm.get_size_align(tid); auto starting_offset = type_id::round_up_to_alignment(raw_data.offset_end(), sa.get_align()); raw_data.extend(starting_offset + sa.get_size()); @@ -242,15 +246,15 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END } template - typename std::enable_if::type>::is_defined::value>::type + typename enable_if::type>::is_defined::value>::type read_type(T& type, type_id tid, uint32_t offset = 0) { - using PlainT = typename std::remove_cv::type; + using PlainT = typename remove_cv::type; auto sa = tm.get_size_align(tid); if( offset != type_id::round_up_to_alignment(offset, sa.get_align()) ) - throw std::logic_error("Offset not at appropriate alignment required by the struct."); + EOS_ERROR(std::logic_error, "Offset not at appropriate alignment required by the struct."); if( raw_data.offset_end() < offset + sa.get_size() ) - throw std::logic_error("Raw data is too small to possibly contain the struct at the specified offset."); + EOS_ERROR(std::logic_error, "Raw data is too small to possibly contain the struct at the specified offset."); deserialize_visitor vis(tm, raw_data, tid, offset); eos::types::reflector::visit(type, vis); } diff --git a/libraries/types/include/eos/types/type_id.hpp b/libraries/types/include/eos/eoslib/type_id.hpp similarity index 98% rename from libraries/types/include/eos/types/type_id.hpp rename to libraries/types/include/eos/eoslib/type_id.hpp index b3ba5e1..914783a 100644 --- a/libraries/types/include/eos/types/type_id.hpp +++ b/libraries/types/include/eos/eoslib/type_id.hpp @@ -1,8 +1,10 @@ #pragma once -#include +#include +#ifdef EOS_TYPES_FULL_CAPABILITY #include +#endif namespace eos { namespace types { @@ -170,7 +172,9 @@ namespace eos { namespace types { friend inline bool operator==(type_id lhs, type_id rhs) { return lhs.get_storage() == rhs.get_storage(); } friend inline bool operator!=(type_id lhs, type_id rhs) { return lhs.get_storage() != rhs.get_storage(); } +#ifdef EOS_TYPES_FULL_CAPABILITY friend std::ostream& operator<<(std::ostream& os, const type_id&); +#endif }; diff --git a/libraries/types/include/eos/eoslib/type_traits.hpp b/libraries/types/include/eos/eoslib/type_traits.hpp new file mode 100644 index 0000000..b31e91a --- /dev/null +++ b/libraries/types/include/eos/eoslib/type_traits.hpp @@ -0,0 +1,89 @@ +#pragma once + +// Derived from: https://github.com/llvm-mirror/libcxx/blob/master/include/type_traits +// Using MIT License. See: https://github.com/llvm-mirror/libcxx/blob/master/LICENSE.TXT + +namespace eoslib { + + // integral_constant + + template + struct integral_constant + { + static constexpr const _Tp value = __v; + typedef _Tp value_type; + typedef integral_constant type; + }; + + template + constexpr const _Tp integral_constant<_Tp, __v>::value; + + // bool_constant and true_type and false_type + + template + using bool_constant = integral_constant; + + typedef bool_constant true_type; + typedef bool_constant false_type; + + // remove_const + + template struct remove_const {typedef _Tp type;}; + template struct remove_const {typedef _Tp type;}; + + // remove_volatile + + template struct remove_volatile {typedef _Tp type;}; + template struct remove_volatile {typedef _Tp type;}; + + // remove_cv + + template struct remove_cv {typedef typename remove_volatile::type>::type type;}; + + // remove_reference + + template struct remove_reference {typedef _Tp type;}; + template struct remove_reference<_Tp&> {typedef _Tp type;}; + template struct remove_reference<_Tp&&> {typedef _Tp type;}; + + // enable_if + + template struct enable_if {}; + template struct enable_if {typedef _Tp type;}; + + // is_integral + + template struct __libcpp_is_integral : public false_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral : public true_type {}; + template <> struct __libcpp_is_integral<__int128_t> : public true_type {}; + template <> struct __libcpp_is_integral<__uint128_t> : public true_type {}; + + template struct is_integral + : public __libcpp_is_integral::type> {}; + + // is_signed (easier implementation since float types are not supported) + + template struct is_signed : public bool_constant<_Tp(-1) < _Tp(0)> { typedef typename enable_if::value>::type enable_if_t; }; + + // is_unsigned (easier implementation since float types are not supported) + + template struct is_unsigned : public bool_constant<_Tp(0) < _Tp(-1)> { typedef typename enable_if::value>::type enable_if_t; }; + + // is_same + + template struct is_same : public false_type {}; + template struct is_same<_Tp, _Tp> : public true_type {}; + +} + diff --git a/libraries/types/include/eos/eoslib/types.h b/libraries/types/include/eos/eoslib/types.h new file mode 100644 index 0000000..fbb05c8 --- /dev/null +++ b/libraries/types/include/eos/eoslib/types.h @@ -0,0 +1,16 @@ +#pragma once + +extern "C" { + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int int16_t; +typedef unsigned short int uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef long int int64_t; +typedef unsigned long int uint64_t; +typedef __int128 int128_t; +typedef unsigned __int128 uint128_t; + +} /// extern "C" diff --git a/libraries/types/include/eos/types/types_manager_common.hpp b/libraries/types/include/eos/eoslib/types_manager_common.hpp similarity index 99% rename from libraries/types/include/eos/types/types_manager_common.hpp rename to libraries/types/include/eos/eoslib/types_manager_common.hpp index f715d3b..ca78b62 100644 --- a/libraries/types/include/eos/types/types_manager_common.hpp +++ b/libraries/types/include/eos/eoslib/types_manager_common.hpp @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include +#include #include #include diff --git a/libraries/types/include/eos/types/abi_definition.hpp b/libraries/types/include/eos/types/abi_definition.hpp index e7b68fc..052d5d4 100644 --- a/libraries/types/include/eos/types/abi_definition.hpp +++ b/libraries/types/include/eos/types/abi_definition.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/libraries/types/include/eos/types/immutable_region.hpp b/libraries/types/include/eos/types/immutable_region.hpp deleted file mode 100644 index 26e4fe0..0000000 --- a/libraries/types/include/eos/types/immutable_region.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include - -namespace eos { namespace types { - - class immutable_region - { - public: - - immutable_region(const types_manager& tm, const raw_region& raw_data) - : tm(tm), raw_data(raw_data) - { - } - - immutable_region(const types_manager& tm, raw_region&& raw_data) - : tm(tm), raw_data(std::move(raw_data)) - { - } - - - //TODO: Complete implementation - - template - typename std::enable_if::type>::is_struct::value>::type - read_struct(T& type, type_id tid, uint32_t offset = 0) - { - using PlainT = typename std::remove_cv::type; - auto sa = tm.get_size_align(tid); - if( offset != type_id::round_up_to_alignment(offset, sa.get_align()) ) - throw std::logic_error("Offset not at appropriate alignment required by the struct."); - if( raw_data.offset_end() < offset + sa.get_size() ) - throw std::logic_error("Raw data is too small to possibly contain the struct at the specified offset."); - deserialize_visitor vis(tm, raw_data, tid, offset); - eos::types::reflector::visit(type, vis); - } - - inline const vector& get_raw_data()const { return raw_data.get_raw_data(); } - - private: - const types_manager& tm; - raw_region raw_data; - }; - -} } - diff --git a/libraries/types/include/eos/types/mutable_region.hpp b/libraries/types/include/eos/types/mutable_region.hpp deleted file mode 100644 index fd3d51b..0000000 --- a/libraries/types/include/eos/types/mutable_region.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include - -namespace eos { namespace types { - - class mutable_region - { - public: - - mutable_region(const types_manager& tm, const raw_region& raw_data) - : tm(tm), raw_data(raw_data) - { - } - - mutable_region(const types_manager& tm, raw_region&& raw_data) - : tm(tm), raw_data(std::move(raw_data)) - { - } - - //TODO: Complete implementation - - template - typename std::enable_if::type>::is_struct::value>::type - read_struct(T& type, type_id tid, uint32_t offset = 0) - { - using PlainT = typename std::remove_cv::type; - auto sa = tm.get_size_align(tid); - if( offset != type_id::round_up_to_alignment(offset, sa.get_align()) ) - throw std::logic_error("Offset not at appropriate alignment required by the struct."); - if( raw_data.offset_end() < offset + sa.get_size() ) - throw std::logic_error("Raw data is too small to possibly contain the struct at the specified offset."); - deserialize_visitor vis(tm, raw_data, tid, offset); - eos::types::reflector::visit(type, vis); - } - - inline const vector& get_raw_data()const { return raw_data.get_raw_data(); } - - private: - const types_manager& tm; - raw_region raw_data; - }; - -} } - diff --git a/libraries/types/include/eos/types/reflect.hpp b/libraries/types/include/eos/types/reflect.hpp index f1a8883..6a453f2 100644 --- a/libraries/types/include/eos/types/reflect.hpp +++ b/libraries/types/include/eos/types/reflect.hpp @@ -1,18 +1,14 @@ #pragma once -#include +#include +#include +#include #include -#include #include -#include -#include #include #include #include -#include -#include -#include #include #include #include @@ -24,16 +20,13 @@ #include #include #include -#include -#include - -#ifndef _MSC_VER - #define TEMPLATE template -#else - // Disable warning C4482: nonstandard extention used: enum 'enum_type::enum_value' used in qualified name - #pragma warning( disable: 4482 ) - #define TEMPLATE -#endif +//#include +//#include + +#undef EOS_TYPES_REFLECT_STRUCT +#undef EOS_TYPES_REFLECT_STRUCT_DERIVED +#undef EOS_TYPES_CREATE_TABLE +#undef EOS_TYPES_REGISTER_TYPES #define EOS_TYPES_REFLECT_GET_MEMBER_TYPE(structure, member) decltype((static_cast(nullptr))->member) @@ -267,125 +260,6 @@ EOS_TYPES_REFLECT_STRUCT_DERIVED_END(T, B, fields) BOOST_PP_CAT(BOOST_PP_OVERLOAD(EOS_TYPES_REFLECT_STRUCT_DERIVED_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY()) #endif -#define EOS_TYPES_REFLECT_TEMPLATE_ARG(r, index, data) , data T##index - -#define EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT( r, index, data ) \ - _v.TEMPLATE operator()( _s ); - -#define EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT_TYPE( r, index, data ) \ - _v.TEMPLATE operator()(); - -#define EOS_TYPES_REFLECT_TUPLE(C, num_template_args) \ -namespace eos { namespace types { \ - template \ - struct reflector> \ - { \ - using is_defined = std::true_type; \ - using is_product_type = std::true_type; \ - using is_struct = std::false_type; \ - using is_tuple = std::true_type; \ - using type = C; \ - enum field_count_enum { \ - field_count = num_template_args \ - }; \ - enum sorted_member_count_enum { \ - sorted_member_count = num_template_args \ - }; \ - template \ - static void visit(Visitor& _v) \ - { \ - BOOST_PP_REPEAT(num_template_args, EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT_TYPE, T) \ - _v.TEMPLATE operator()(); \ - } \ - template \ - static void visit(const type& _s, const Visitor& _v) \ - { \ - BOOST_PP_REPEAT(num_template_args, EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT, T) \ - } \ - template \ - static void visit(type& _s, const Visitor& _v) \ - { \ - BOOST_PP_REPEAT(num_template_args, EOS_TYPES_REFLECT_VISIT_TUPLE_ELEMENT, T) \ - } \ - }; \ -} } - -#define EOS_TYPES_REFLECT_SIMPLE_VISIT \ - template \ - static void visit(Visitor& _v) \ - { \ - _v.TEMPLATE operator()(); \ - } \ - template \ - static void visit(const type& _x, const Visitor& _v) \ - { \ - _v.TEMPLATE operator()(_x); \ - } \ - template \ - static void visit(type& _x, const Visitor& _v) \ - { \ - _v.TEMPLATE operator()(_x); \ - } \ - -#define EOS_TYPES_REFLECT_BUILTIN(T, B) \ -namespace eos { namespace types { \ - template <> \ - struct reflector \ - { \ - using is_defined = std::true_type; \ - using is_struct = std::false_type; \ - using is_builtin = std::true_type; \ - using type = T; \ - static const type_id::builtin builtin_type = type_id::B; \ - EOS_TYPES_REFLECT_SIMPLE_VISIT \ - }; \ -} } - -#define EOS_TYPES_REFLECT_ARRAY(C) \ -namespace eos { namespace types { \ - template \ - struct reflector> \ - { \ - using is_defined = std::true_type; \ - using is_struct = std::false_type; \ - using is_array = std::true_type; \ - using type = C; \ - enum num_elements_enum { \ - num_elements = N \ - }; \ - EOS_TYPES_REFLECT_SIMPLE_VISIT \ - }; \ -} } - -#define EOS_TYPES_REFLECT_VECTOR(C) \ -namespace eos { namespace types { \ - template \ - struct reflector> \ - { \ - using is_defined = std::true_type; \ - using is_struct = std::false_type; \ - using is_vector = std::true_type; \ - using type = C; \ - EOS_TYPES_REFLECT_SIMPLE_VISIT \ - }; \ -} } - -#define EOS_TYPES_REFLECT_OPTIONAL(C) \ -namespace eos { namespace types { \ - template \ - struct reflector> \ - { \ - using is_defined = std::true_type; \ - using is_struct = std::false_type; \ - using is_optional = std::true_type; \ - using type = C; \ - EOS_TYPES_REFLECT_SIMPLE_VISIT \ - }; \ -} } - #define EOS_TYPES_REFLECT_INDEX_TYPE_u_asc true, true #define EOS_TYPES_REFLECT_INDEX_TYPE_u_desc true, false #define EOS_TYPES_REFLECT_INDEX_TYPE_nu_asc false, true @@ -456,74 +330,12 @@ namespace eos { namespace types { namespace eos { namespace types { - template - struct reflector - { - using is_defined = std::false_type; - }; - - template - struct table_reflector - { - using is_defined = std::false_type; - }; - - template - struct types_initializer - { - }; - - struct rational - { - rational() - : numerator(0), denominator(1) - {} - - rational(int64_t n, uint64_t d) - : numerator(n), denominator(d) - {} - - int64_t numerator; - uint64_t denominator; - }; uint32_t register_struct(abi_constructor& ac, const std::vector& field_types, const char* struct_name, const char* const field_names[], uint32_t field_names_length, const char* const sorted_member_names[], bool const sorted_member_dir[], uint32_t sorted_member_count, const char* base_name = nullptr); -} } - - -EOS_TYPES_REFLECT_BUILTIN(bool, builtin_bool) -EOS_TYPES_REFLECT_BUILTIN(char, builtin_uint8) -EOS_TYPES_REFLECT_BUILTIN(int8_t, builtin_int8) -EOS_TYPES_REFLECT_BUILTIN(uint8_t, builtin_uint8) -EOS_TYPES_REFLECT_BUILTIN(int16_t, builtin_int16) -EOS_TYPES_REFLECT_BUILTIN(uint16_t, builtin_uint16) -EOS_TYPES_REFLECT_BUILTIN(int32_t, builtin_int32) -EOS_TYPES_REFLECT_BUILTIN(uint32_t, builtin_uint32) -EOS_TYPES_REFLECT_BUILTIN(int64_t, builtin_int64) -EOS_TYPES_REFLECT_BUILTIN(uint64_t, builtin_uint64) -EOS_TYPES_REFLECT_BUILTIN(std::string, builtin_string) -EOS_TYPES_REFLECT_BUILTIN(std::vector, builtin_bytes) -EOS_TYPES_REFLECT_BUILTIN(eos::types::rational, builtin_rational) -EOS_TYPES_REFLECT_BUILTIN(eos::types::type_id, builtin_uint32) - -EOS_TYPES_REFLECT_ARRAY(std::array) -EOS_TYPES_REFLECT_VECTOR(std::vector) -EOS_TYPES_REFLECT_OPTIONAL(boost::optional) - -EOS_TYPES_REFLECT_TUPLE(std::pair, 2) -EOS_TYPES_REFLECT_TUPLE(std::tuple, 2) -EOS_TYPES_REFLECT_TUPLE(std::tuple, 3) -EOS_TYPES_REFLECT_TUPLE(std::tuple, 4) -EOS_TYPES_REFLECT_TUPLE(std::tuple, 5) -EOS_TYPES_REFLECT_TUPLE(std::tuple, 6) -EOS_TYPES_REFLECT_TUPLE(std::tuple, 7) - -namespace eos { namespace types { - using std::vector; using std::pair; diff --git a/libraries/types/include/eos/types/type_traversal.hpp b/libraries/types/include/eos/types/type_traversal.hpp deleted file mode 100644 index c990114..0000000 --- a/libraries/types/include/eos/types/type_traversal.hpp +++ /dev/null @@ -1,251 +0,0 @@ -#pragma once - -#include - -namespace eos { namespace types { - -namespace type_traversal { - - enum traversal_shortcut - { - no_shortcut, - no_deeper, - return_now - }; - - struct struct_type { type_id::index_t index; }; - struct array_type { type_id element_type; uint32_t num_elements; }; - struct vector_type { type_id element_type; }; - struct optional_type { type_id element_type; type_id optional_tid; }; - struct variant_type { type_id::index_t index; }; - - // Type traversal: (Caller needs to ensure types vector is in a coherent state, or else things will go horribly wrong) - template - traversal_shortcut traverse_type(type_id tid, Visitor& v, const vector& types) - { - if( tid.is_void() ) - { - traversal_shortcut s = v(); - return (s == no_deeper ? no_shortcut : s); - } - - switch( tid.get_type_class() ) - { - case type_id::builtin_type: - { - traversal_shortcut s = v(tid.get_builtin_type()); - return (s == no_deeper ? no_shortcut : s); - } - case type_id::struct_type: - { - traversal_shortcut s = v(struct_type{tid.get_type_index()}); - return (s == no_deeper ? no_shortcut : s); - } - case type_id::vector_type: - { - //type_id element_type(types[tid.get_type_index()], true); - type_id element_type(types[tid.get_type_index()]); - traversal_shortcut traverse_element = v(vector_type{element_type}); - switch( traverse_element ) - { - case return_now: - return return_now; - case no_deeper: - return no_shortcut; - case no_shortcut: - break; - } - traversal_shortcut s = traverse_type(element_type, v, types); - return (s == no_deeper ? no_shortcut : s); - } - case type_id::vector_of_something_type: - { - auto element_type = tid.get_element_type(); - traversal_shortcut traverse_element = v(vector_type{element_type}); - switch( traverse_element ) - { - case return_now: - return return_now; - case no_deeper: - return no_shortcut; - case no_shortcut: - break; - } - traversal_shortcut s = traverse_type(element_type, v, types); - return (s == no_deeper ? no_shortcut : s); - } - case type_id::optional_struct_type: - { - auto element_type = tid.get_element_type(); - - traversal_shortcut traverse_element = v(optional_type{element_type, tid}); - switch( traverse_element ) - { - case return_now: - return return_now; - case no_deeper: - return no_shortcut; - case no_shortcut: - break; - } - traversal_shortcut s = traverse_type(element_type, v, types); - return (s == no_deeper ? no_shortcut : s); - } - case type_id::variant_or_optional_type: - { - auto index = tid.get_type_index(); - if( types[index+1] >= type_id::variant_case_limit ) // If actually an optional - { - //type_id element_type(types[index+1], true); - type_id element_type(types[index+1]); - traversal_shortcut traverse_element = v(optional_type{element_type, tid}); - switch( traverse_element ) - { - case return_now: - return return_now; - case no_deeper: - return no_shortcut; - case no_shortcut: - break; - } - traversal_shortcut s = traverse_type(element_type, v, types); - return (s == no_deeper ? no_shortcut : s); - } - - // Otherwise, it is a variant: - auto var = variant_type{index}; - traversal_shortcut traverse_variant = v(var); - bool visit_cases = true; - switch( traverse_variant ) - { - case return_now: - return return_now; - case no_deeper: - visit_cases = false; - break; - case no_shortcut: - break; - } - - auto itr = types.begin() + index + 1; - auto n = *itr; - ++itr; - if( visit_cases ) - { - for( uint32_t i = 0; i < n; ++i, ++itr ) - { - //type_id t(*itr, true); - type_id t(*itr); - traversal_shortcut s = v(var, i); - switch( s ) - { - case return_now: - return return_now; - case no_deeper: - visit_cases = false; - case no_shortcut: - break; - } - if( !visit_cases ) - break; - s = traverse_type(t, v, types); - switch( s ) - { - case return_now: - return return_now; - case no_deeper: - case no_shortcut: - break; - } - } - } - traversal_shortcut s = v(var, visit_cases); - switch( s ) - { - case return_now: - return return_now; - case no_deeper: - case no_shortcut: - break; - } - return no_shortcut; - } - case type_id::small_array_of_builtins_type: - case type_id::small_array_type: - { - auto num_elems = tid.get_small_array_size(); - auto element_type = tid.get_element_type(); - traversal_shortcut traverse_element = v(array_type{element_type, num_elems}); - switch( traverse_element ) - { - case return_now: - return return_now; - case no_deeper: - return no_shortcut; - case no_shortcut: - break; - } - traversal_shortcut s = traverse_type(element_type, v, types); - return (s == no_deeper ? no_shortcut : s); - } - case type_id::array_type: - { - auto itr = types.begin() + tid.get_type_index() + 1; - auto num_elems = *itr; - ++itr; - //type_id element_type(*itr, true); - type_id element_type(*itr); - traversal_shortcut traverse_element = v(array_type{element_type, num_elems}); - switch( traverse_element ) - { - case return_now: - return return_now; - case no_deeper: - return no_shortcut; - case no_shortcut: - break; - } - traversal_shortcut s = traverse_type(element_type, v, types); - return (s == no_deeper ? no_shortcut : s); - } - } - return no_shortcut; // Should never reach here. But apparently the compiler isn't smart enough to realize this. - } - - /* - // Below is an example of what a Visitor should look like: - struct Visitor - { - const types_manager& tm; - state_t state; - - Visitor(const types_manager& tm, const state_t& state) : tm(tm), state(state) {} - - using traversal_shortcut = type_traversal::traversal_shortcut; - using array_type = type_traversal::array_type; - using struct_type = type_traversal::struct_type; - using vector_type = type_traversal::vector_type; - using optional_type = type_traversal::optional_type; - using variant_type = type_traversal::variant_type; - - template - traversal_shortcut operator()(const T&) { return type_traversal::no_shortcut; } // Default implementation - template - traversal_shortcut operator()(const T&, U) { return type_traversal::no_shortcut; } // Default implementation - - traversal_shortcut operator()(type_id::builtin b); // Builtin - traversal_shortcut operator()(struct_type t); // Struct. It is the responsibility of this function if it wishes to traverse over any of its field types. - traversal_shortcut operator()(variant_type t); // Variant, but its individual cases will be traversed afterwards unless this function returns no_deeper or return_now. - traversal_shortcut operator()(variant_type t, uint32_t case_index); // Called just before each variant case is processed. - traversal_shortcut operator()(variant_type t, bool visited_all_cases); // Called after all cases of a particular variant have been processed. - traversal_shortcut operator()(array_type t); // Array (small or general), but its element type will be traversed afterwards unless this function returns no_deeper or return_now. - traversal_shortcut operator()(vector_type t); // Vector, but its element type will be traversed afterwards unless this function returns no_deeper or return_now. - traversal_shortcut operator()(optional_type t); // Optional, but its element type will be traversed afterwards unless this function returns no_deeper or return_now. - traversal_shortcut operator()(); // Void - }; - */ - -} - -} } - diff --git a/libraries/types/include/eos/types/types_constructor.hpp b/libraries/types/include/eos/types/types_constructor.hpp index b2c4f1c..c9ee0c8 100644 --- a/libraries/types/include/eos/types/types_constructor.hpp +++ b/libraries/types/include/eos/types/types_constructor.hpp @@ -1,11 +1,10 @@ #pragma once -#include -#include -#include -#include +#include +#include +#include #include -#include +#include #include #include diff --git a/libraries/types/include/eos/types/types_manager.hpp b/libraries/types/include/eos/types/types_manager.hpp index ec62c78..e2c9d17 100644 --- a/libraries/types/include/eos/types/types_manager.hpp +++ b/libraries/types/include/eos/types/types_manager.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -28,7 +28,7 @@ namespace eos { namespace types { { } - type_id::index_t get_table(const string& name)const; + type_id::index_t get_table(const string& name)const; friend class types_constructor; diff --git a/libraries/types/raw_region.cpp b/libraries/types/raw_region.cpp index 625da82..33bfda5 100644 --- a/libraries/types/raw_region.cpp +++ b/libraries/types/raw_region.cpp @@ -1,10 +1,11 @@ -#include -#include +#include +#include +#ifdef EOS_TYPES_FULL_CAPABILITY #include #include -#include #include +#endif namespace eos { namespace types { @@ -27,7 +28,7 @@ namespace eos { namespace types { void raw_region::extend(uint32_t new_offset_end) { if( new_offset_end >= field_metadata::offset_limit ) - throw std::invalid_argument("Cannot enlarge raw region to that large of a size."); + EOS_ERROR(std::invalid_argument, "Cannot enlarge raw region to that large of a size."); if( new_offset_end <= raw_data.size() ) return; raw_data.resize(new_offset_end); @@ -38,6 +39,7 @@ namespace eos { namespace types { raw_data.clear(); } +#ifdef EOS_TYPES_FULL_CAPABILITY void raw_region::print_raw_data(std::ostream& os, uint32_t offset, uint32_t size)const { using std::endl; @@ -45,10 +47,10 @@ namespace eos { namespace types { boost::io::ios_flags_saver ifs( os ); if( offset >= offset_end() ) - throw std::invalid_argument("Raw region subset is empty."); + EOS_ERROR(std::invalid_argument, "Raw region subset is empty."); if( size > 4096 ) - throw std::invalid_argument("Raw region subset is too large to print."); + EOS_ERROR(std::invalid_argument, "Raw region subset is too large to print."); auto col = 0; auto row = 0; @@ -85,6 +87,7 @@ namespace eos { namespace types { r.print_raw_data(os); return os; } +#endif } } diff --git a/libraries/types/type_id.cpp b/libraries/types/type_id.cpp index c366110..896685d 100644 --- a/libraries/types/type_id.cpp +++ b/libraries/types/type_id.cpp @@ -1,9 +1,11 @@ -#include +#include +#include +#ifdef EOS_TYPES_FULL_CAPABILITY #include #include -#include #include +#endif namespace eos { namespace types { @@ -54,7 +56,7 @@ namespace eos { namespace types { : _storage(0) { if( num_elements == 0 ) - throw std::domain_error("Number of elements cannot be 0."); + EOS_ERROR(std::domain_error, "Number of elements cannot be 0."); //if( num_elements >= small_builtin_array_limit ) // Redundant since the limit is the natural limit of the uint8_t // throw std::domain_error("The maximum number of elements for a small array of builtins is 255. For larger arrays, use the make_array function."); @@ -66,7 +68,7 @@ namespace eos { namespace types { inline void check_index_limit(type_id::index_t index) { if( index >= type_id::type_index_limit ) - throw std::domain_error("Index is too large."); + EOS_ERROR(std::domain_error, "Index is too large."); } inline void check_arguments(type_id::index_t index, uint8_t num_elements) @@ -74,10 +76,10 @@ namespace eos { namespace types { check_index_limit(index); if( num_elements == 0 ) - throw std::domain_error("Number of elements cannot be 0."); + EOS_ERROR(std::domain_error, "Number of elements cannot be 0."); if( num_elements >= type_id::small_array_limit ) - throw std::domain_error("The maximum number of elements for a small array is 31. For larger arrays, use the make_array function."); + EOS_ERROR(std::domain_error, "The maximum number of elements for a small array is 31. For larger arrays, use the make_array function."); } type_id type_id::make_struct(index_t index, uint8_t num_elements) @@ -160,7 +162,7 @@ namespace eos { namespace types { type_id::size_align type_id::get_builtin_type_size_align(builtin bt) { if( static_cast(bt) >= static_cast(builtin_types_size) ) - throw std::invalid_argument("Not a valid builtin type"); + EOS_ERROR(std::invalid_argument, "Not a valid builtin type"); uint8_t size_and_align = 8; // Default word size switch(bt) @@ -198,7 +200,7 @@ namespace eos { namespace types { const char* type_id::get_builtin_type_name(builtin bt) { if( static_cast(bt) >= static_cast(builtin_types_size) ) - throw std::invalid_argument("Not a valid builtin type"); + EOS_ERROR(std::invalid_argument, "Not a valid builtin type"); switch(bt) { @@ -236,7 +238,7 @@ namespace eos { namespace types { type_id::type_class type_id::get_type_class()const { if( is_void() ) - throw std::invalid_argument("Cannot call get_type_class on a Void type"); + EOS_ERROR(std::invalid_argument, "Cannot call get_type_class on a Void type"); uint32_t size = small_array_size_window::get(_storage); if( size > 1 ) @@ -273,13 +275,14 @@ namespace eos { namespace types { else if( size == 1 ) return builtin_type; - throw std::runtime_error("Invariant failure: somehow a type_id with reserved representation was created."); + EOS_ERROR(std::runtime_error, "Invariant failure: somehow a type_id with reserved representation was created."); + return builtin_type; // Should never be reached. Just here to silence compiler warning. } type_id::builtin type_id::get_builtin_type()const { if( is_void() || small_array_size_window::get(_storage) > 0 || extra_metadata_window::get(_storage) >= 2 ) - throw std::logic_error("This type does not contain a builtin."); + EOS_ERROR(std::logic_error, "This type does not contain a builtin."); return static_cast(builtin_type_window::get(_storage)); } @@ -287,7 +290,7 @@ namespace eos { namespace types { type_id::index_t type_id::get_type_index()const { if( small_array_size_window::get(_storage) == 0 && extra_metadata_window::get(_storage) < 2 ) - throw std::logic_error("This type does not contain an index."); + EOS_ERROR(std::logic_error, "This type does not contain an index."); return index_window::get(_storage); } @@ -295,7 +298,7 @@ namespace eos { namespace types { void type_id::set_type_index(index_t index) { if( small_array_size_window::get(_storage) == 0 && extra_metadata_window::get(_storage) < 2 ) - throw std::logic_error("This type does not contain an index."); + EOS_ERROR(std::logic_error, "This type does not contain an index."); check_index_limit(index); @@ -317,9 +320,10 @@ namespace eos { namespace types { return 1; if( is_void() ) - throw std::logic_error("Type is void."); + EOS_ERROR(std::logic_error, "Type is void."); - throw std::runtime_error("Invariant failure: somehow a type_id with reserved representation was created."); + EOS_ERROR(std::runtime_error, "Invariant failure: somehow a type_id with reserved representation was created."); + return 0; // Should never be reached. Just here to silence compiler warning. } type_id type_id::get_element_type()const // Return Void if it is not possible to find the element type @@ -354,6 +358,28 @@ namespace eos { namespace types { return {storage, true}; } + // Sorts in order of descending alignment and descending size (in that order of priority). + // However, alignments of 0 or 1 are treated the same. + bool operator<(type_id::size_align lhs, type_id::size_align rhs) + { + using size_align = type_id::size_align; + + auto lhs_align = size_align::align_window::get(lhs._storage); + auto rhs_align = size_align::align_window::get(rhs._storage); + if( (lhs_align == 0 || lhs_align == 1) && rhs_align > 1 ) + return false; + else if( lhs_align > 1 && (rhs_align == 0 || rhs_align == 1) ) + return true; + else if( !(lhs_align > 1 && rhs_align > 1) ) + { + lhs_align = 1; + rhs_align = 1; + } + // TODO: Handle bool arrays properly. + return (lhs_align > rhs_align) || ( (lhs_align == rhs_align) && (size_align::size_window::get(lhs._storage) > size_align::size_window::get(rhs._storage)) ); + } + +#ifdef EOS_TYPES_FULL_CAPABILITY void print_builtin(std::ostream& os, type_id tid) { auto tc = tid.get_type_class(); @@ -377,7 +403,7 @@ namespace eos { namespace types { return; } - throw std::invalid_argument("This function only prints builtins and small arrays of builtins"); + EOS_ERROR(std::invalid_argument, "This function only prints builtins and small arrays of builtins"); } std::ostream& operator<<(std::ostream& os, const type_id& tid) @@ -421,7 +447,7 @@ namespace eos { namespace types { tc = type_id::struct_type; break; default: - throw std::runtime_error("Unexpected result: should not have encountered this type class while writing type to output."); + EOS_ERROR(std::runtime_error, "Unexpected result: should not have encountered this type class while writing type to output."); } break; } @@ -453,33 +479,12 @@ namespace eos { namespace types { os << "sum_type"; break; default: - throw std::runtime_error("Unexpected result: should not have encountered this type class while writing type to output."); + EOS_ERROR(std::runtime_error, "Unexpected result: should not have encountered this type class while writing type to output."); } os << "(" << tid.get_type_index() << ")]"; return os; } - - // Sorts in order of descending alignment and descending size (in that order of priority). - // However, alignments of 0 or 1 are treated the same. - bool operator<(type_id::size_align lhs, type_id::size_align rhs) - { - using size_align = type_id::size_align; - - auto lhs_align = size_align::align_window::get(lhs._storage); - auto rhs_align = size_align::align_window::get(rhs._storage); - if( (lhs_align == 0 || lhs_align == 1) && rhs_align > 1 ) - return false; - else if( lhs_align > 1 && (rhs_align == 0 || rhs_align == 1) ) - return true; - else if( !(lhs_align > 1 && rhs_align > 1) ) - { - lhs_align = 1; - rhs_align = 1; - } - // TODO: Handle bool arrays properly. - return std::make_tuple(lhs_align, size_align::size_window::get(lhs._storage)) > std::make_tuple(rhs_align, size_align::size_window::get(rhs._storage)); - } - +#endif } } diff --git a/libraries/types/types_constructor.cpp b/libraries/types/types_constructor.cpp index b6bafa9..6b6998a 100644 --- a/libraries/types/types_constructor.cpp +++ b/libraries/types/types_constructor.cpp @@ -1,6 +1,6 @@ #include -#include -#include +#include +#include #include #include diff --git a/libraries/types/types_manager_common.cpp b/libraries/types/types_manager_common.cpp index 9368c1a..4f102c1 100644 --- a/libraries/types/types_manager_common.cpp +++ b/libraries/types/types_manager_common.cpp @@ -1,4 +1,5 @@ -#include +#include +#include namespace eos { namespace types { @@ -156,7 +157,7 @@ namespace eos { namespace types { types_manager_common::get_members_common(type_id::index_t struct_index)const { if( struct_index + 3 >= types.size() ) - throw std::out_of_range("Struct index is not valid."); + EOS_ERROR(std::out_of_range, "Struct index is not valid."); auto itr = types.begin() + struct_index + 1; auto member_data_offset = *itr; @@ -165,7 +166,7 @@ namespace eos { namespace types { uint16_t num_sorted_members = (*itr & 0xFFFF); if( (member_data_offset + num_sorted_members + total_num_members) > members.size() ) - throw std::runtime_error("Invariant failure: range would be out of the bounds, most likely because struct_index was not valid."); + EOS_ERROR(std::runtime_error, "Invariant failure: range would be out of the bounds, most likely because struct_index was not valid."); return std::make_tuple(member_data_offset, num_sorted_members, total_num_members); } @@ -182,15 +183,15 @@ namespace eos { namespace types { type_id types_manager_common::get_variant_case_type(type_id tid, uint16_t which)const { if( tid.get_type_class() != type_id::variant_or_optional_type ) - throw std::invalid_argument("Must provide a variant type to this function."); + EOS_ERROR(std::invalid_argument, "Must provide a variant type to this function."); auto itr = types.begin() + tid.get_type_index() + 1; if( *itr >= type_id::variant_case_limit ) - throw std::invalid_argument("Provided type points to an optional, not a variant."); + EOS_ERROR(std::invalid_argument, "Provided type points to an optional, not a variant."); if( which >= *itr ) - throw std::out_of_range("Case index specified by which is not valid"); + EOS_ERROR(std::out_of_range, "Case index specified by which is not valid"); itr += 1 + which; @@ -200,14 +201,14 @@ namespace eos { namespace types { uint32_t types_manager_common::get_variant_tag_offset(type_id tid)const { if( tid.get_type_class() != type_id::variant_or_optional_type ) - throw std::invalid_argument("Must provide a variant type to this function."); + EOS_ERROR(std::invalid_argument, "Must provide a variant type to this function."); auto itr = types.begin() + tid.get_type_index(); type_id::size_align sa(*itr); ++itr; if( *itr >= type_id::variant_case_limit ) - throw std::invalid_argument("Provided type points to an optional, not a variant."); + EOS_ERROR(std::invalid_argument, "Provided type points to an optional, not a variant."); return (sa.get_size() - 2); } @@ -222,14 +223,14 @@ namespace eos { namespace types { } if( tc != type_id::variant_or_optional_type ) - throw std::invalid_argument("Must provide a variant type to this function."); + EOS_ERROR(std::invalid_argument, "Must provide a variant type to this function."); auto itr = types.begin() + tid.get_type_index(); type_id::size_align sa(*itr); ++itr; if( *itr < type_id::variant_case_limit ) - throw std::invalid_argument("Provided type points to a variant, not an optional."); + EOS_ERROR(std::invalid_argument, "Provided type points to a variant, not an optional."); return (sa.get_size() - 1); } @@ -238,7 +239,7 @@ namespace eos { namespace types { types_manager_common::get_base_info(type_id::index_t struct_index)const { if( struct_index + 3 >= types.size() ) - throw std::out_of_range("Struct index is not valid."); + EOS_ERROR(std::out_of_range, "Struct index is not valid."); auto itr = types.begin() + struct_index + 3; field_metadata::sort_order base_sort_order = ( !sorted_window::get(*itr) ? field_metadata::unsorted @@ -280,17 +281,17 @@ namespace eos { namespace types { type_id element_tid(*itr); return {element_tid, 1}; } - throw std::invalid_argument("Given type is not a container."); + EOS_ERROR(std::invalid_argument, "Given type is not a container."); } case type_id::builtin_type: { auto b = tid.get_builtin_type(); if( b == type_id::builtin_string || b == type_id::builtin_bytes ) return {type_id(type_id::builtin_uint8), 0}; - throw std::invalid_argument("Given type is not a container."); + EOS_ERROR(std::invalid_argument, "Given type is not a container."); } case type_id::struct_type: - throw std::invalid_argument("Given type is not a container."); + EOS_ERROR(std::invalid_argument, "Given type is not a container."); } return {tid.get_element_type(), num_elements}; @@ -299,7 +300,7 @@ namespace eos { namespace types { uint8_t types_manager_common::get_num_indices_in_table(type_id::index_t index)const { if( index + 3 > types.size() ) - throw std::invalid_argument("Table index is not valid."); + EOS_ERROR(std::invalid_argument, "Table index is not valid."); auto itr = types.begin() + index; return index_seq_window::get(*itr); @@ -308,7 +309,7 @@ namespace eos { namespace types { type_id::index_t types_manager_common::get_struct_index_of_table_object(type_id::index_t index)const { if( index + 3 > types.size() ) - throw std::invalid_argument("Table index is not valid."); + EOS_ERROR(std::invalid_argument, "Table index is not valid."); auto itr = types.begin() + index; return index_window::get(*itr); @@ -323,11 +324,11 @@ namespace eos { namespace types { : tm(tm) { if( index + 1 + 2*(index_seq_num+1) > tm.types.size() ) - throw std::invalid_argument("Table index is not valid."); + EOS_ERROR(std::invalid_argument, "Table index is not valid."); auto itr = tm.types.begin() + index; if( index_seq_window::get(*itr) <= index_seq_num ) - throw std::out_of_range("Index sequence number if outside the range of valid sequence numbers for this table."); + EOS_ERROR(std::out_of_range, "Index sequence number if outside the range of valid sequence numbers for this table."); itr = tm.types.begin() + index + 1 + 2*index_seq_num; @@ -640,7 +641,8 @@ namespace eos { namespace types { traversal_shortcut operator()() { - throw std::runtime_error("Invariant failure: Void type should not be allowed in structs or table keys."); + EOS_ERROR(std::runtime_error, "Invariant failure: Void type should not be allowed in structs or table keys."); + return types_manager_common::no_shortcut; // Should never be reached. Just here to silence compiler warning. } }; @@ -654,19 +656,19 @@ namespace eos { namespace types { auto f = *(object_range.begin()); if( f.get_type_id() != key_type ) - throw std::runtime_error("Invariant failure: key type of index does not match the type of the view into the object."); + EOS_ERROR(std::runtime_error, "Invariant failure: key type of index does not match the type of the view into the object."); compare_visitor v(*this, object_data, f.get_offset(), key_data, 0, f.get_sort_order() == field_metadata::ascending); traverse_type( key_type, v); return (ti.is_ascending() ? v.comparison_result : -v.comparison_result); } else if(tc != type_id::struct_type ) - throw std::runtime_error("Invariant failure: key type of index is not builtin type or struct."); + EOS_ERROR(std::runtime_error, "Invariant failure: key type of index is not builtin type or struct."); auto key_range = ti.get_types_manager().get_sorted_members(key_type.get_type_index()); auto num_sorted_members = key_range.end() - key_range.begin(); if( num_sorted_members != (object_range.end() - object_range.begin()) ) - throw std::runtime_error("Invariant failure: Number of sorted members of key and key-shaped view into the object are not the same."); + EOS_ERROR(std::runtime_error, "Invariant failure: Number of sorted members of key and key-shaped view into the object are not the same."); for( auto i = 0; i < num_sorted_members; ++i ) { @@ -680,7 +682,7 @@ namespace eos { namespace types { f_key.set_offset(0); if( f != f_key ) - throw std::runtime_error("Invariant failure: key and key-shaped view into the object are structs with different member metadata."); + EOS_ERROR(std::runtime_error, "Invariant failure: key and key-shaped view into the object are structs with different member metadata."); compare_visitor v(*this, object_data, f_offset, key_data, f_key_offset, f.get_sort_order() == field_metadata::ascending); traverse_type(f.get_type_id(), v); diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt index fbd3c72..2c293e9 100644 --- a/programs/CMakeLists.txt +++ b/programs/CMakeLists.txt @@ -1,3 +1,5 @@ +add_definitions(-DEOS_TYPES_FULL_CAPABILITY) + add_executable( reflection_test1 reflection_test1.cpp ) target_link_libraries( reflection_test1 eos_types ) diff --git a/programs/reflection_test1.cpp b/programs/reflection_test1.cpp index 061aa6f..b3088ee 100644 --- a/programs/reflection_test1.cpp +++ b/programs/reflection_test1.cpp @@ -1,7 +1,11 @@ -#include +#include #include +#include #include +#include +#include #include +#include #include #include @@ -11,6 +15,16 @@ using std::vector; using std::array; using std::string; +using eoslib::enable_if; + +template +inline +typename enable_if::is_struct::value, eos::types::type_id::index_t>::type +get_struct_index(const eos::types::full_types_manager& ftm) +{ + return ftm.get_struct_index(eos::types::reflector::name()); +} + struct type1 { uint32_t a; @@ -70,14 +84,14 @@ int main() types_constructor abi_tc(abi_ac.get_abi()); auto abi_types_managers = abi_tc.destructively_extract_types_managers(); const auto& abi_tm = abi_types_managers.second; - auto abi_tid = type_id::make_struct(abi_tm.get_struct_index()); + auto abi_tid = type_id::make_struct(get_struct_index(abi_tm)); serialization_region abi_serializer(abi_tm); vector abi_structs = { abi_tid.get_type_index(), - abi_tm.get_struct_index(), - abi_tm.get_struct_index(), - abi_tm.get_struct_index(), - abi_tm.get_struct_index() + get_struct_index(abi_tm), + get_struct_index(abi_tm), + get_struct_index(abi_tm), + get_struct_index(abi_tm) }; for( auto indx : abi_structs ) { @@ -118,15 +132,15 @@ int main() cout << f << endl; }; - auto type1_tid = type_id::make_struct(ftm.get_struct_index()); + auto type1_tid = type_id::make_struct(get_struct_index(ftm)); print_type_info(type1_tid); cout << endl; - auto type2_tid = type_id::make_struct(ftm.get_struct_index()); + auto type2_tid = type_id::make_struct(get_struct_index(ftm)); print_type_info(type2_tid); cout << endl; - auto type3_tid = type_id::make_struct(ftm.get_struct_index()); + auto type3_tid = type_id::make_struct(get_struct_index(ftm)); print_type_info(type3_tid); cout << endl; diff --git a/programs/reflection_test2.cpp b/programs/reflection_test2.cpp index 60bbc76..40aad3a 100644 --- a/programs/reflection_test2.cpp +++ b/programs/reflection_test2.cpp @@ -1,9 +1,11 @@ -#include +#include #include #include +#include +#include #include +#include -#include #include #include #include @@ -12,6 +14,18 @@ using std::vector; using std::array; using std::string; +using eoslib::enable_if; +using eoslib::is_integral; +using eoslib::is_same; + +template +inline +typename enable_if::is_struct::value, eos::types::type_id::index_t>::type +get_struct_index(const eos::types::full_types_manager& ftm) +{ + return ftm.get_struct_index(eos::types::reflector::name()); +} + struct eos_symbol; struct currency_symbol; @@ -20,7 +34,7 @@ class token { private: - using enable_if_t = typename std::enable_if< std::is_integral::value && !std::is_same::value >::type; + using enable_if_t = typename enable_if< is_integral::value && !is_same::value >::type; NumberType quantity; @@ -211,15 +225,15 @@ int main() cout << f << endl; }; - auto order_id_tid = type_id::make_struct(ftm.get_struct_index()); + auto order_id_tid = type_id::make_struct(get_struct_index(ftm)); print_type_info(order_id_tid); cout << endl; - auto bid_tid = type_id::make_struct(ftm.get_struct_index()); + auto bid_tid = type_id::make_struct(get_struct_index(ftm)); print_type_info(bid_tid); cout << endl; - auto ask_tid = type_id::make_struct(ftm.get_struct_index()); + auto ask_tid = type_id::make_struct(get_struct_index(ftm)); print_type_info(ask_tid); cout << endl; diff --git a/programs/table_test1.cpp b/programs/table_test1.cpp index 776490a..dde35d8 100644 --- a/programs/table_test1.cpp +++ b/programs/table_test1.cpp @@ -1,8 +1,11 @@ -#include +#include #include #include +#include +#include #include #include +#include #include #include @@ -12,6 +15,16 @@ using std::vector; using std::array; using std::string; +using eoslib::enable_if; + +template +inline +typename enable_if::is_struct::value, eos::types::type_id::index_t>::type +get_struct_index(const eos::types::full_types_manager& ftm) +{ + return ftm.get_struct_index(eos::types::reflector::name()); +} + struct type1 { uint32_t a; @@ -75,11 +88,11 @@ int main() cout << r << endl; }; - auto type1_tid = type_id::make_struct(ftm.get_struct_index()); + auto type1_tid = type_id::make_struct(get_struct_index(ftm)); print_type_info(type1_tid); cout << endl; - auto type2_tid = type_id::make_struct(ftm.get_struct_index()); + auto type2_tid = type_id::make_struct(get_struct_index(ftm)); print_type_info(type2_tid); cout << endl;