diff --git a/libraries/types/include/eos/types/abi.hpp b/libraries/types/include/eos/types/abi.hpp index 9365421..ca9e33a 100644 --- a/libraries/types/include/eos/types/abi.hpp +++ b/libraries/types/include/eos/types/abi.hpp @@ -1,68 +1,11 @@ #pragma once -#include -#include -#include -#include - -namespace eos { namespace types { - - using std::string; - using std::vector; - using std::pair; - - struct ABI - { - enum type_specification : uint8_t - { - struct_type, - array_type, - vector_type, - optional_type, - variant_type - }; - - struct type_definition - { - uint32_t first; - int32_t second; - type_specification ts; - }; - - struct struct_t - { - string name; - vector> fields; - vector sort_order; - }; - - struct table_index - { - type_id key_type; - bool unique; - bool ascending; - vector mapping; - }; - - struct table - { - type_id::index_t object_index; - vector indices; - }; - - - vector types; - vector structs; - vector variant_cases; - vector tables; - }; - -} } - -/* -EOS_TYPES_REFLECT_STRUCT( type_definition, (first)(second)(ts) ); -EOS_TYPES_REFLECT_STRUCT( struct_t, (name)(fields)(sort_order) ); -EOS_TYPES_REFLECT_STRUCT( table_index, (key_type)(unique)(ascending)(mapping) ); -EOS_TYPES_REFLECT_STRUCT( table, (name)(object_index)(indices) ); -EOS_TYPES_REFLECT_STRUCT( ABI, (types)(structs)(variant_cases)(tables) ); -*/ +#include +#include + +EOS_TYPES_REFLECT_BUILTIN( eos::types::ABI::type_specification, builtin_uint8 ) +EOS_TYPES_REFLECT_STRUCT( eos::types::ABI::type_definition, (first)(second)(ts) ) +EOS_TYPES_REFLECT_STRUCT( eos::types::ABI::struct_t, (name)(fields)(sort_order) ) +EOS_TYPES_REFLECT_STRUCT( eos::types::ABI::table_index, (key_type)(unique)(ascending)(mapping) ) +EOS_TYPES_REFLECT_STRUCT( eos::types::ABI::table, (object_index)(indices) ) +EOS_TYPES_REFLECT_STRUCT( eos::types::ABI, (types)(structs)(variant_cases)(tables) ) diff --git a/libraries/types/include/eos/types/abi_constructor.hpp b/libraries/types/include/eos/types/abi_constructor.hpp index b10867a..3814756 100644 --- a/libraries/types/include/eos/types/abi_constructor.hpp +++ b/libraries/types/include/eos/types/abi_constructor.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/libraries/types/include/eos/types/abi_definition.hpp b/libraries/types/include/eos/types/abi_definition.hpp new file mode 100644 index 0000000..1fc4edc --- /dev/null +++ b/libraries/types/include/eos/types/abi_definition.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include +#include +#include + +namespace eos { namespace types { + + using std::string; + using std::vector; + using std::pair; + + struct ABI + { + enum type_specification : uint8_t + { + struct_type, + array_type, + vector_type, + optional_type, + variant_type + }; + + struct type_definition + { + uint32_t first; + int32_t second; + type_specification ts; + }; + + struct struct_t + { + string name; + vector> fields; + vector sort_order; + }; + + struct table_index + { + type_id key_type; + bool unique; + bool ascending; + vector mapping; + }; + + struct table + { + type_id::index_t object_index; + vector indices; + }; + + + vector types; + vector structs; + vector variant_cases; + vector
tables; + }; + +} } + + diff --git a/libraries/types/include/eos/types/deserialize_visitor.hpp b/libraries/types/include/eos/types/deserialize_visitor.hpp index f51de8a..a61950b 100644 --- a/libraries/types/include/eos/types/deserialize_visitor.hpp +++ b/libraries/types/include/eos/types/deserialize_visitor.hpp @@ -58,7 +58,7 @@ namespace eos { namespace types { #define EOS_TYPES_CUSTOM_BUILTIN_PRIMITIVE( builtin_name, primitive_type ) \ EOS_TYPES_CUSTOM_BUILTIN_MATCH_START( builtin_name ) \ - b = r.get(offset); \ + b = static_cast(r.get(offset)); \ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END EOS_TYPES_CUSTOM_BUILTIN_PRIMITIVE( int8, int8_t ) @@ -98,9 +98,7 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END eos::types::reflector::visit(b, vis); } - template - typename std::enable_if::is_struct::value>::type - operator()(Class& c, const char* name, uint32_t member_index)const + deserialize_visitor make_visitor_for_product_type_member( uint32_t member_index )const { auto f = tm.get_member(tid.get_type_index(), member_index); auto member_tid = f.get_type_id(); @@ -114,11 +112,26 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END { member_offset += f.get_offset(); } - - deserialize_visitor vis(tm, r, member_tid, member_offset); + + return {tm, r, member_tid, member_offset}; + } + + template + typename std::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); eos::types::reflector::visit(c.*member, vis); } + template // Meant for tuples/pairs + typename std::enable_if::is_struct::value>::type + operator()(Class& c)const + { + auto vis = make_visitor_for_product_type_member(static_cast(Index)); + eos::types::reflector::visit(std::get(c), vis); + } + template typename std::enable_if::is_array::value>::type operator()(Container& c)const diff --git a/libraries/types/include/eos/types/reflect.hpp b/libraries/types/include/eos/types/reflect.hpp index 9740677..437af95 100644 --- a/libraries/types/include/eos/types/reflect.hpp +++ b/libraries/types/include/eos/types/reflect.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,8 @@ #include #include #include +#include +#include #ifndef _MSC_VER #define TEMPLATE template @@ -85,6 +88,39 @@ bool const eos::types::reflector::sorted_member_dir[BOOST_PP_SEQ_SIZE(member_ sorted_member_count = 0 BOOST_PP_SEQ_FOR_EACH(EOS_TYPES_REFLECT_INCREMENTER, +, member_sort ) \ }; +#define EOS_TYPES_REFLECT_GET_MEMBER_INFO_START \ + static inline void get_member_info( const char* * * field_names, \ + const char* * * sorted_member_names, \ + bool * * sorted_member_dir ) \ + { + +#define EOS_TYPES_REFLECT_GET_MEMBER_INFO_NOOP \ + EOS_TYPES_REFLECT_GET_MEMBER_INFO_START \ + } + +#define EOS_TYPES_REFLECT_GET_MEMBER_INFO_COMMON(fields) \ + EOS_TYPES_REFLECT_GET_MEMBER_INFO_START \ + static const char* _field_names[BOOST_PP_SEQ_SIZE(fields)] = { \ + BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(EOS_TYPES_REFLECT_STRINGIZE, _, fields)) \ + }; \ + *field_names = _field_names; + +#define EOS_TYPES_REFLECT_GET_MEMBER_INFO_FIELDS_ONLY(fields) \ + EOS_TYPES_REFLECT_GET_MEMBER_INFO_COMMON(fields) \ + } + +#define EOS_TYPES_REFLECT_GET_MEMBER_INFO(fields, member_sort) \ + EOS_TYPES_REFLECT_GET_MEMBER_INFO_COMMON(fields) \ + static const char* _sorted_member_names[BOOST_PP_SEQ_SIZE(member_sort)] = { \ + BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(EOS_TYPES_REFLECT_MEMBER_NAME, _, member_sort)) \ + }; \ + *sorted_member_names = _sorted_member_names; \ + bool _sorted_member_dir[BOOST_PP_SEQ_SIZE(member_sort)] = { \ + BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(EOS_TYPES_REFLECT_SORT_ORDER, _, member_sort)) \ + }; \ + *sorted_member_dir = _sorted_member_dir; \ + } + #define EOS_TYPES_REFLECT_STRUCT_START(T) \ namespace eos { namespace types { \ template <> \ @@ -92,9 +128,27 @@ namespace eos { namespace types { { \ using is_defined = std::true_type; \ using is_struct = std::true_type; \ - using type = T; \ - static const char* const name; - + using type = T; + +#define EOS_TYPES_REFLECT_STRUCT_END_HELPER(NAME) \ + static inline uint32_t register_struct(eos::types::abi_constructor& ac, const std::vector& ft)\ + { \ + const char* * field_names = nullptr; \ + const char* * sorted_member_names = nullptr; \ + bool * sorted_member_dir = nullptr; \ + get_member_info(&field_names, &sorted_member_names, &sorted_member_dir); \ + return eos::types::register_struct(ac, ft, NAME, \ + field_names, static_cast(field_count), \ + sorted_member_names, sorted_member_dir, \ + static_cast(sorted_member_count)); \ + } \ + static inline const char* name() \ + { \ + return NAME; \ + } \ + }; \ +} } + #define EOS_TYPES_REFLECT_STRUCT_END(T, fields) \ template \ static void visit(Visitor& _v) \ @@ -113,39 +167,21 @@ namespace eos { namespace types { { \ BOOST_PP_SEQ_FOR_EACH_I(EOS_TYPES_REFLECT_VISIT_MEMBER, 0, fields) \ } \ - static inline uint32_t register_struct(eos::types::abi_constructor& ac, const std::vector& ft)\ - { \ - return eos::types::register_struct(ac, ft, BOOST_PP_STRINGIZE(T), \ - field_names, static_cast(field_count), \ - sorted_member_names, sorted_member_dir, \ - static_cast(sorted_member_count)); \ - } \ - }; \ -} } \ -const char* const eos::types::reflector::name = BOOST_PP_STRINGIZE(T); + EOS_TYPES_REFLECT_STRUCT_END_HELPER(BOOST_PP_STRINGIZE(T)) #define EOS_TYPES_REFLECT_STRUCT_1 #define EOS_TYPES_REFLECT_STRUCT_2(T, fields) \ EOS_TYPES_REFLECT_STRUCT_START(T) \ - static const char* const field_names[BOOST_PP_SEQ_SIZE(fields)]; \ - static const char* const sorted_member_names[1]; \ - static bool const sorted_member_dir[1]; \ EOS_TYPES_REFLECT_MEMBER_COUNT(fields, BOOST_PP_SEQ_NIL) \ -EOS_TYPES_REFLECT_STRUCT_END(T, fields) \ -EOS_TYPES_REFLECT_FIELD_NAMES(T, fields) \ -const char* const eos::types::reflector::sorted_member_names[1] = {""}; \ -bool const eos::types::reflector::sorted_member_dir[1] = {false}; +EOS_TYPES_REFLECT_GET_MEMBER_INFO_FIELDS_ONLY(fields) \ +EOS_TYPES_REFLECT_STRUCT_END(T, fields) #define EOS_TYPES_REFLECT_STRUCT_3(T, fields, member_sort) \ EOS_TYPES_REFLECT_STRUCT_START(T) \ - static const char* const field_names[BOOST_PP_SEQ_SIZE(fields)]; \ - static const char* const sorted_member_names[BOOST_PP_SEQ_SIZE(member_sort)]; \ - static bool const sorted_member_dir[BOOST_PP_SEQ_SIZE(member_sort)]; \ EOS_TYPES_REFLECT_MEMBER_COUNT(fields, member_sort) \ -EOS_TYPES_REFLECT_STRUCT_END(T, fields) \ -EOS_TYPES_REFLECT_FIELD_NAMES(T, fields) \ -EOS_TYPES_REFLECT_SORT_MEMBER(T, member_sort) +EOS_TYPES_REFLECT_GET_MEMBER_INFO(fields, member_sort) \ +EOS_TYPES_REFLECT_STRUCT_END(T, fields) #if !BOOST_PP_VARIADICS_MSVC #define EOS_TYPES_REFLECT_STRUCT(...) \ @@ -162,8 +198,7 @@ namespace eos { namespace types { { \ using is_defined = std::true_type; \ using is_struct = std::true_type; \ - using type = T; \ - static const char* const name; + using type = T; #define EOS_TYPES_REFLECT_STRUCT_DERIVED_END(T, B, fields) \ template \ @@ -188,49 +223,42 @@ namespace eos { namespace types { } \ static inline uint32_t register_struct(eos::types::abi_constructor& ac, const std::vector& ft)\ { \ + const char* * field_names = nullptr; \ + const char* * sorted_member_names = nullptr; \ + bool * sorted_member_dir = nullptr; \ + get_member_info(&field_names, &sorted_member_names, &sorted_member_dir); \ return eos::types::register_struct(ac, ft, BOOST_PP_STRINGIZE(T), \ field_names, static_cast(field_count), \ sorted_member_names, sorted_member_dir, \ static_cast(sorted_member_count), \ BOOST_PP_STRINGIZE(B)); \ } \ - }; \ -} } \ -const char* const eos::types::reflector::name = BOOST_PP_STRINGIZE(T); + static inline const char* name() \ + { \ + return BOOST_PP_STRINGIZE(T); \ + } \ + }; \ +} } #define EOS_TYPES_REFLECT_STRUCT_DERIVED_1 #define EOS_TYPES_REFLECT_STRUCT_DERIVED_2(T, B) \ EOS_TYPES_REFLECT_STRUCT_DERIVED_START(T, B) \ - static const char* const field_names[1]; \ - static const char* const sorted_member_names[1]; \ - static bool const sorted_member_dir[1]; \ EOS_TYPES_REFLECT_MEMBER_COUNT(BOOST_PP_SEQ_NIL, BOOST_PP_SEQ_NIL) \ +EOS_TYPES_REFLECT_GET_MEMBER_INFO_NOOP() \ EOS_TYPES_REFLECT_STRUCT_DERIVED_END(T, B, BOOST_PP_SEQ_NIL) \ -const char* const eos::types::relector::field_names[1] = {""}; \ -const char* const eos::types::relector::sorted_member_names[1] = {""}; \ -bool const eos::types::reflector::sorted_member_dir[1] = {false}; #define EOS_TYPES_REFLECT_STRUCT_DERIVED_3(T, B, fields) \ EOS_TYPES_REFLECT_STRUCT_DERIVED_START(T, B) \ - static const char* const field_names[BOOST_PP_SEQ_SIZE(fields)]; \ - static const char* const sorted_member_names[1]; \ - static bool const sorted_member_dir[1]; \ EOS_TYPES_REFLECT_MEMBER_COUNT(fields, BOOST_PP_SEQ_NIL) \ +EOS_TYPES_REFLECT_GET_MEMBER_INFO_FIELDS_ONLY(fields) \ EOS_TYPES_REFLECT_STRUCT_DERIVED_END(T, B, fields) \ -EOS_TYPES_REFLECT_FIELD_NAMES(T, fields) \ -const char* const eos::types::relector::sorted_member_names[1] = {""}; \ -bool const eos::types::reflector::sorted_member_dir[1] = {false}; #define EOS_TYPES_REFLECT_STRUCT_DERIVED_4(T, B, fields, member_sort) \ EOS_TYPES_REFLECT_STRUCT_DERIVED_START(T, B) \ - static const char* const field_names[BOOST_PP_SEQ_SIZE(fields)]; \ - static const char* const sorted_member_names[BOOST_PP_SEQ_SIZE(member_sort)]; \ - static bool const sorted_member_dir[BOOST_PP_SEQ_SIZE(member_sort)]; \ EOS_TYPES_REFLECT_MEMBER_COUNT(fields, member_sort) \ +EOS_TYPES_REFLECT_GET_MEMBER_INFO(fields, member_sort) \ EOS_TYPES_REFLECT_STRUCT_DERIVED_END(T, B, fields) \ -EOS_TYPES_REFLECT_FIELD_NAMES(T, fields) \ -EOS_TYPES_REFLECT_SORT_MEMBER(T, member_sort) #if !BOOST_PP_VARIADICS_MSVC #define EOS_TYPES_REFLECT_STRUCT_DERIVED(...) \ @@ -240,6 +268,75 @@ EOS_TYPES_REFLECT_SORT_MEMBER(T, member_sort) BOOST_PP_CAT(BOOST_PP_OVERLOAD(EOS_TYPES_REFLECT_STRUCT_DERIVED_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY()) #endif +//#define EOS_TYPES_REFLECT_GET_TYPENAME(T) BOOST_PP_STRINGIZE(T) + +#define EOS_TYPES_REFLECT_GET_TYPENAME(T) typeid(T).name() + +#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_PRODUCT_TYPE_HELPER(C, num_template_args, NAME, fields, member_sort) \ +namespace eos { namespace types { \ + template \ + struct reflector> \ + { \ + using is_defined = std::true_type; \ + using is_struct = std::true_type; \ + using type = C; \ +EOS_TYPES_REFLECT_MEMBER_COUNT(fields, member_sort) \ +EOS_TYPES_REFLECT_GET_MEMBER_INFO(fields, member_sort) \ + template \ + static void visit(Visitor& _v) \ + { \ + if( !_v.TEMPLATE operator()( NAME ) ) { return; } \ + 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) \ + } \ +EOS_TYPES_REFLECT_STRUCT_END_HELPER(NAME) + +#define EOS_TYPES_REFLECT_ANONYMOUS_FIELD(r, index, data) (data##index) + +#define EOS_TYPES_REFLECT_ANONYMOUS_FIELD_ASCENDING(r, index, data) ((data##index, asc)) + +#if 0 + +#define EOS_TYPES_STRINGIZE_ALL_HELPER(...) #__VA_ARGS__ + +#define EOS_TYPES_STRINGIZE_ALL(...) EOS_TYPES_STRINGIZE_ALL_HELPER(__VA_ARGS__) + +#define EOS_TYPES_REFLECT_PRODUCT_TYPE(C, Ts) \ +EOS_TYPES_REFLECT_PRODUCT_TYPE_HELPER(C, BOOST_PP_SEQ_SIZE(Ts), \ + EOS_TYPES_STRINGIZE_ALL(C), \ + BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(Ts), EOS_TYPES_REFLECT_ANONYMOUS_FIELD, f), \ + BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(Ts), EOS_TYPES_REFLECT_ANONYMOUS_FIELD_ASCENDING, f) ) + +#endif + +#define EOS_TYPES_REFLECT_TUPLE(C, num_template_args) \ +EOS_TYPES_REFLECT_PRODUCT_TYPE_HELPER(C, num_template_args, \ + EOS_TYPES_REFLECT_GET_TYPENAME(type), \ + BOOST_PP_REPEAT(num_template_args, EOS_TYPES_REFLECT_ANONYMOUS_FIELD, f), \ + BOOST_PP_REPEAT(num_template_args, EOS_TYPES_REFLECT_ANONYMOUS_FIELD_ASCENDING, f) ) + + #define EOS_TYPES_REFLECT_SIMPLE_VISIT \ template \ static void visit(Visitor& _v) \ @@ -353,18 +450,24 @@ namespace eos { namespace types { #define EOS_TYPES_REFLECT_REGISTER_STRUCT(r, v, s) eos::types::reflector::visit(v); -#define EOS_TYPES_REGISTER_TYPES_1(tables) EOS_TYPES_REGISTER_TYPES_2(tables, BOOST_PP_SEQ_NIL) +#define EOS_TYPES_REGISTER_TYPES_1 -#define EOS_TYPES_REGISTER_TYPES_2(tables, structs) \ +#define EOS_TYPES_REGISTER_TYPES_2(name, tables) EOS_TYPES_REGISTER_TYPES_3(name, tables, BOOST_PP_SEQ_NIL) + +#define EOS_TYPES_REGISTER_TYPES_3(name, tables, structs) \ namespace eos { namespace types { \ - static abi_constructor initialize_types() \ + template <> \ + struct types_initializer \ { \ - abi_constructor ac; \ - type_discovery_visitor vis(ac); \ - BOOST_PP_SEQ_FOR_EACH(EOS_TYPES_REFLECT_REGISTER_TABLE, vis, tables) \ - BOOST_PP_SEQ_FOR_EACH(EOS_TYPES_REFLECT_REGISTER_STRUCT, vis, structs) \ - return ac; \ - } \ + static abi_constructor init() \ + { \ + abi_constructor ac; \ + type_discovery_visitor vis(ac); \ + BOOST_PP_SEQ_FOR_EACH(EOS_TYPES_REFLECT_REGISTER_TABLE, vis, tables) \ + BOOST_PP_SEQ_FOR_EACH(EOS_TYPES_REFLECT_REGISTER_STRUCT, vis, structs) \ + return ac; \ + } \ + }; \ } } #if !BOOST_PP_VARIADICS_MSVC @@ -389,6 +492,11 @@ namespace eos { namespace types { using is_defined = std::false_type; }; + template + struct types_initializer + { + }; + struct rational { rational() @@ -402,25 +510,41 @@ namespace eos { namespace types { 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_ARRAY(std::array); -EOS_TYPES_REFLECT_VECTOR(std::vector); -EOS_TYPES_REFLECT_OPTIONAL(boost::optional); +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 { @@ -457,7 +581,7 @@ namespace eos { namespace types { typename std::enable_if::is_struct::value>::type operator()(bool unique, bool ascending, const vector& mapping) // Table index of struct key type { - auto cur_struct_index = ac.get_struct_index(eos::types::reflector::name); + auto cur_struct_index = ac.get_struct_index(eos::types::reflector::name()); if( cur_struct_index >= 0 ) { tid = type_id::make_struct(static_cast(cur_struct_index)); @@ -475,7 +599,7 @@ namespace eos { namespace types { typename std::enable_if::is_struct::value>::type operator()(bool) // Called after processing the indices of the table. { - auto cur_struct_index = ac.get_struct_index(eos::types::reflector::name); + auto cur_struct_index = ac.get_struct_index(eos::types::reflector::name()); if( cur_struct_index < 0 ) { type_discovery_visitor vis(ac); @@ -487,15 +611,15 @@ namespace eos { namespace types { template typename std::enable_if::is_struct::value, bool>::type - operator()(const char* name) // Called before processing the fields of the struct or its base. + operator()(const char* name) // Called before processing the fields of a product type such as a struct or its base or a tuple/pair. { - auto cur_struct_index = ac.get_struct_index(eos::types::reflector::name); + auto cur_struct_index = ac.get_struct_index(eos::types::reflector::name()); if( cur_struct_index >= 0 ) { tid = type_id::make_struct(static_cast(cur_struct_index)); return false; // Do not bother processing this struct because it has already been processed or is in the middle of being processed.. } - ac.declare_struct(eos::types::reflector::name); + ac.declare_struct(eos::types::reflector::name()); return true; } @@ -503,7 +627,7 @@ namespace eos { namespace types { typename std::enable_if::is_struct::value && eos::types::reflector::is_struct::value>::type operator()()const { - if( ac.get_struct_index(eos::types::reflector::name) >= 0 ) + if( ac.get_struct_index(eos::types::reflector::name()) >= 0 ) return; type_discovery_visitor vis(ac); @@ -512,7 +636,7 @@ namespace eos { namespace types { template typename std::enable_if::is_struct::value>::type - operator()() // Called after processing the fields of the struct. + operator()() // Called after processing the fields of the product type { tid = type_id::make_struct(eos::types::reflector::register_struct(ac, field_types)); field_types.clear(); @@ -522,7 +646,7 @@ namespace eos { namespace types { typename std::enable_if::is_struct::value && eos::types::reflector::is_struct::value>::type operator()(const char* name, uint32_t member_index) { - auto index = ac.get_struct_index(eos::types::reflector::name); + auto index = ac.get_struct_index(eos::types::reflector::name()); if( index >= 0 ) { @@ -544,6 +668,33 @@ namespace eos { namespace types { field_types.push_back(vis.tid); } + template // Meant for tuples/pairs + typename std::enable_if::is_struct::value && eos::types::reflector::is_struct::value>::type + operator()() + { + auto index = ac.get_struct_index(eos::types::reflector::name()); + + if( index >= 0 ) + { + field_types.push_back(type_id::make_struct(index)); + return; + } + + type_discovery_visitor vis(ac); + eos::types::reflector::visit(vis); + field_types.push_back(vis.tid); + } + + template // Meant for tuples/pairs + typename std::enable_if::is_struct::value && !eos::types::reflector::is_struct::value>::type + operator()() + { + type_discovery_visitor vis(ac); + eos::types::reflector::visit(vis); + field_types.push_back(vis.tid); + } + + template typename std::enable_if::is_array::value>::type operator()() @@ -669,9 +820,5 @@ namespace eos { namespace types { }; - 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); } } diff --git a/libraries/types/include/eos/types/serialization_region.hpp b/libraries/types/include/eos/types/serialization_region.hpp index 3812da6..981818b 100644 --- a/libraries/types/include/eos/types/serialization_region.hpp +++ b/libraries/types/include/eos/types/serialization_region.hpp @@ -110,10 +110,9 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END eos::types::reflector::visit(b, vis); } - template - typename std::enable_if::is_struct::value>::type - operator()(const Class& c, const char* name, uint32_t member_index)const - { + + write_visitor make_visitor_for_product_type_member( uint32_t member_index )const + { auto f = tm.get_member(tid.get_type_index(), member_index); auto member_tid = f.get_type_id(); auto member_offset = offset; @@ -127,10 +126,25 @@ EOS_TYPES_CUSTOM_BUILTIN_MATCH_END member_offset += f.get_offset(); } - write_visitor vis(tm, r, member_tid, member_offset); + return {tm, r, member_tid, member_offset}; + } + + template + typename std::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); eos::types::reflector::visit(c.*member, vis); } - + + template // Meant for tuples/pairs + typename std::enable_if::is_struct::value>::type + operator()(const Class& c)const + { + auto vis = make_visitor_for_product_type_member(static_cast(Index)); + eos::types::reflector::visit(std::get(c), vis); + } + template typename std::enable_if::is_array::value>::type operator()(const Container& c)const diff --git a/libraries/types/include/eos/types/type_id.hpp b/libraries/types/include/eos/types/type_id.hpp index 554c39c..f7d4d43 100644 --- a/libraries/types/include/eos/types/type_id.hpp +++ b/libraries/types/include/eos/types/type_id.hpp @@ -123,7 +123,7 @@ namespace eos { namespace types { static const uint8_t small_array_limit = 64; type_id(); - type_id(uint32_t storage); + explicit type_id(uint32_t storage); // Also makes it possible to deserialize type_id from a builtin UInt32 type_id(builtin b, uint8_t num_elements = 1); static type_id make_struct(index_t index, uint8_t num_elements = 1); @@ -135,6 +135,9 @@ namespace eos { namespace types { static type_id make_vector_of_structs(index_t index); static type_id make_vector_of_builtins(builtin b, uint8_t num_elements = 1); + // The method is needed to serialize type_id as a builtin UInt32 + inline explicit operator uint32_t()const { return _storage; } + static size_align get_builtin_type_size_align(builtin bt); static const char* get_builtin_type_name(builtin bt); diff --git a/libraries/types/include/eos/types/types_constructor.hpp b/libraries/types/include/eos/types/types_constructor.hpp index f06ce42..9750691 100644 --- a/libraries/types/include/eos/types/types_constructor.hpp +++ b/libraries/types/include/eos/types/types_constructor.hpp @@ -49,7 +49,7 @@ namespace eos { namespace types { typename std::enable_if::is_struct::value, type_id::index_t>::type get_struct_index()const { - return get_struct_index(eos::types::reflector::name); + return get_struct_index(eos::types::reflector::name()); } diff --git a/libraries/types/type_id.cpp b/libraries/types/type_id.cpp index e972384..e4deaf2 100644 --- a/libraries/types/type_id.cpp +++ b/libraries/types/type_id.cpp @@ -328,7 +328,7 @@ namespace eos { namespace types { { uint32_t storage = _storage; small_array_size_window::set(storage, 1); - return {storage}; + return {storage, true}; } else if (size == 1) { @@ -350,7 +350,7 @@ namespace eos { namespace types { uint32_t storage = _storage; extra_metadata_window::set(storage, 0); - return {storage}; + return {storage, true}; } void print_builtin(std::ostream& os, type_id tid) diff --git a/libraries/types/types_constructor.cpp b/libraries/types/types_constructor.cpp index 3eacce1..d4c140c 100644 --- a/libraries/types/types_constructor.cpp +++ b/libraries/types/types_constructor.cpp @@ -38,17 +38,38 @@ namespace eos { namespace types { return false; bool first = true; + bool expectingColon = false; + bool disallowColon = false; for( auto c : name ) { if( first ) { first = false; - if( !std::isalpha(c) && c != '_' ) + if( !std::isalpha(c) && c != '_' && (c != ':' || disallowColon) ) return false; } - else if( !std::isalnum(c) && c != '_' ) + else if( !std::isalnum(c) && c != '_' && (c != ':' || disallowColon) ) return false; + + if( c == ':' ) + { + if( expectingColon ) // Continuation of :: seperator + { + expectingColon = false; + disallowColon = true; // Make sure more than two consecutive colons are not allowed + } + else // Start of :: seperator + expectingColon = true; + } + else if( expectingColon ) + return false; // Cannot have a single : as separator + else + disallowColon = false; // Reset consecutive colon counter } + + if( expectingColon || disallowColon ) // Do not allow any trailing colons + return false; + return true; } diff --git a/programs/reflection_test1.cpp b/programs/reflection_test1.cpp index 33e5e64..2d9ea1a 100644 --- a/programs/reflection_test1.cpp +++ b/programs/reflection_test1.cpp @@ -49,21 +49,58 @@ EOS_TYPES_CREATE_TABLE( type1, ((uint32_t, nu_asc, ({0}) ))((type3, u_desc, // nu_desc // non-unique index sorted according to key_type in descending order // } -EOS_TYPES_REGISTER_TYPES( (type1), (type2) ) -// tables, other structs + +struct reflection_test1_types; +EOS_TYPES_REGISTER_TYPES( reflection_test1_types, (type1), (type2) ) +// name, tables, other structs // By registering the table for type1, it automatically registers type1 (since it is the object type of the table) and type3 (since it is the key type of one of the indices of the table). // However, type2 is not discovered from the table of type1, so it needs to be explicitly registered through specifying it within the other structs arguments to the macro. + +struct abi_reflection; +EOS_TYPES_REGISTER_TYPES( abi_reflection, BOOST_PP_SEQ_NIL, (eos::types::ABI) ) + int main() { using namespace eos::types; using std::cout; using std::endl; + auto abi_ac = types_initializer::init(); + types_constructor abi_tc(abi_ac.get_abi()); + auto abi_tid = type_id::make_struct(abi_tc.get_struct_index()); + + vector abi_structs = { abi_tid.get_type_index(), + abi_tc.get_struct_index(), + abi_tc.get_struct_index(), + 12, // Hacky solution to print the anonymous pair used in ABI::struct_t + abi_tc.get_struct_index(), + abi_tc.get_struct_index() + }; + for( auto indx : abi_structs ) + { + abi_tc.print_type(cout, type_id::make_struct(indx)); + cout << "Members:" << endl; + for( auto f : abi_tc.get_all_members(indx) ) + cout << f << endl; + cout << endl; + } + + auto abi_tm = abi_tc.destructively_extract_types_manager(); + serialization_region abi_serializer(abi_tm); + + auto ac = types_initializer::init(); + abi_serializer.write_type(ac.get_abi(), abi_tid); + + cout << "Raw data of serialization of abi:" << std::hex << endl; + for( auto b : abi_serializer.get_raw_data() ) + cout << (int) b << " "; + cout << std::dec << endl << endl; + + ABI abi; + abi_serializer.read_type(abi, abi_tid); - auto ac = initialize_types(); - - types_constructor tc(ac.get_abi()); + types_constructor tc(abi); auto print_type_info = [&](type_id tid) { diff --git a/programs/reflection_test2.cpp b/programs/reflection_test2.cpp index 531dec5..61d06d5 100644 --- a/programs/reflection_test2.cpp +++ b/programs/reflection_test2.cpp @@ -30,13 +30,13 @@ class token : quantity() {} + // This constructor taking NumberType and the conversion method to NumberType below it allow this custom class to be used + // as if it is the primitive integer type NumberType by the serialization/deserialization system. + explicit token( NumberType v ) : quantity(v) {} - // This assignment operator and the conversion to NumberType below it allow this custom class to be used - // as if it is the primitive integer type NumberType by the serialization/deserialization system. - token& operator=( NumberType v ) { quantity = v; return *this; } explicit operator NumberType()const { return quantity; } token& operator-=( const token& a ) { @@ -111,8 +111,10 @@ class time_point_sec private: uint32_t utc_seconds; - // The assignment operator from and conversion to the integer type can also be private if desired as long as the appropriate classes are added as friends (see above). - time_point_sec& operator=(uint32_t seconds) { utc_seconds = seconds; return *this; } + // The conversion method to the integer type (and the constructor taking the integer type) can also be private if desired + // as long as the appropriate classes are added as friends (see above). + // In this case the constructor was kept public because it was useful for other purposes. + // But the conversion was kept private since users of this class are expected to use the more meaningful `sec_since_epoch` method. explicit operator uint32_t()const { return utc_seconds; } }; @@ -176,7 +178,8 @@ EOS_TYPES_CREATE_TABLE( ask, (( expiration_key, u_asc, ({3, 0}) )) ) -EOS_TYPES_REGISTER_TYPES( (bid)(ask) ) +struct reflection_test2_types; +EOS_TYPES_REGISTER_TYPES( reflection_test2_types, (bid)(ask) ) int main() { @@ -185,7 +188,7 @@ int main() using std::endl; - auto ac = initialize_types(); + auto ac = types_initializer::init(); types_constructor tc(ac.get_abi()); diff --git a/programs/table_test1.cpp b/programs/table_test1.cpp index da0fe52..8ef4659 100644 --- a/programs/table_test1.cpp +++ b/programs/table_test1.cpp @@ -35,7 +35,8 @@ EOS_TYPES_CREATE_TABLE( type1, (( vector, nu_asc, ({2}) )) ) -EOS_TYPES_REGISTER_TYPES( (type1) ) +struct table_test1_types; +EOS_TYPES_REGISTER_TYPES( table_test1_types, (type1) ) int main() { @@ -45,7 +46,7 @@ int main() using std::endl; - auto ac = initialize_types(); + auto ac = types_initializer::init(); types_constructor tc(ac.get_abi());