From eaf71e9399925d14833b2d9ee8db972aaa5071ca Mon Sep 17 00:00:00 2001 From: softprofe <65825209+softprofe@users.noreply.github.com> Date: Wed, 8 Sep 2021 14:14:44 -0700 Subject: [PATCH 1/2] Merge pull request #1196 from EOSIO/keke_epe948 Support std::array by adding abi symbol T[N] --- .../toolchain/abigen-pass/using_std_array.abi | 51 +++++ .../toolchain/abigen-pass/using_std_array.cpp | 24 +++ .../abigen-pass/using_std_array.json | 9 + tests/unit/test_contracts/CMakeLists.txt | 1 + tests/unit/test_contracts/array_tests.cpp | 192 ++++++++++++++++++ tools/include/eosio/abigen.hpp | 4 +- tools/include/eosio/gen.hpp | 14 ++ 7 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 tests/toolchain/abigen-pass/using_std_array.abi create mode 100644 tests/toolchain/abigen-pass/using_std_array.cpp create mode 100644 tests/toolchain/abigen-pass/using_std_array.json create mode 100644 tests/unit/test_contracts/array_tests.cpp diff --git a/tests/toolchain/abigen-pass/using_std_array.abi b/tests/toolchain/abigen-pass/using_std_array.abi new file mode 100644 index 00000000..6c75d02d --- /dev/null +++ b/tests/toolchain/abigen-pass/using_std_array.abi @@ -0,0 +1,51 @@ +{ + "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ", + "version": "eosio::abi/1.2", + "types": [], + "structs": [ + { + "name": "greeting", + "base": "", + "fields": [ + { + "name": "id", + "type": "uint64" + }, + { + "name": "t", + "type": "int32[32]" + } + ] + }, + { + "name": "hi", + "base": "", + "fields": [ + { + "name": "user", + "type": "name" + } + ] + } + ], + "actions": [ + { + "name": "hi", + "type": "hi", + "ricardian_contract": "" + } + ], + "tables": [ + { + "name": "greeting", + "type": "greeting", + "index_type": "i64", + "key_names": [], + "key_types": [] + } + ], + "kv_tables": {}, + "ricardian_clauses": [], + "variants": [], + "action_results": [] +} \ No newline at end of file diff --git a/tests/toolchain/abigen-pass/using_std_array.cpp b/tests/toolchain/abigen-pass/using_std_array.cpp new file mode 100644 index 00000000..ad03b5cf --- /dev/null +++ b/tests/toolchain/abigen-pass/using_std_array.cpp @@ -0,0 +1,24 @@ +#include +#include +#include + +using std::array; +using namespace eosio; + +class[[eosio::contract("using_std_array")]] using_std_array : public contract +{ +public: + using contract::contract; + + [[eosio::action]] void hi(name user) { + require_auth(user); + print("Hello, ", user); + } + + struct [[eosio::table]] greeting { + uint64_t id; + array t; + uint64_t primary_key() const { return id; } + }; + typedef multi_index<"greeting"_n, greeting> greeting_index; +}; diff --git a/tests/toolchain/abigen-pass/using_std_array.json b/tests/toolchain/abigen-pass/using_std_array.json new file mode 100644 index 00000000..29c09f89 --- /dev/null +++ b/tests/toolchain/abigen-pass/using_std_array.json @@ -0,0 +1,9 @@ +{ + "tests" : [ + { + "expected" : { + "abi-file" : "using_std_array.abi" + } + } + ] +} diff --git a/tests/unit/test_contracts/CMakeLists.txt b/tests/unit/test_contracts/CMakeLists.txt index 292f9081..91222bb5 100644 --- a/tests/unit/test_contracts/CMakeLists.txt +++ b/tests/unit/test_contracts/CMakeLists.txt @@ -2,6 +2,7 @@ add_contract(action_results_test action_results_test action_results_test.cpp) add_contract(malloc_tests malloc_tests malloc_tests.cpp) add_contract(malloc_tests old_malloc_tests malloc_tests.cpp) add_contract(simple_tests simple_tests simple_tests.cpp) +add_contract(array_tests array_tests array_tests.cpp) add_contract(transfer_contract transfer_contract transfer.cpp) add_contract(minimal_tests minimal_tests minimal_tests.cpp) add_contract(crypto_primitives_tests crypto_primitives_tests crypto_primitives_tests.cpp) diff --git a/tests/unit/test_contracts/array_tests.cpp b/tests/unit/test_contracts/array_tests.cpp new file mode 100644 index 00000000..a5e85e69 --- /dev/null +++ b/tests/unit/test_contracts/array_tests.cpp @@ -0,0 +1,192 @@ +#include +#include +#include + +using namespace eosio; + +class [[eosio::contract]] array_tests : public contract { + public: + using contract::contract; + + TABLE tests { + uint64_t id; + std::array str; + uint64_t primary_key() const { return id; } + }; + + struct info { + int age; + std::string name; + }; + + typedef multi_index tests_table; + typedef std::array array_string_4; + struct my_struct { + uint32_t id; + std::array aastr; + + bool operator==(const my_struct& b) const { + return id == b.id && + aastr == b.aastr; + } + }; + + struct [[eosio::table]] my_table_array : eosio::kv::table { + KV_NAMED_INDEX("id"_n, id) + + my_table_array(eosio::name contract_name) { + init(contract_name, id); + } + }; + my_struct s1; + my_struct s2; + // test nested std::array used in kv talbe + [[eosio::action]] + void testkv() { + my_table_array tarr{get_self()}; + + s1.id = 1; + s1.aastr[0] = {"abc","bcd","cde", "def"}; + s1.aastr[1] = {"hij","ijk","jkl", "klm"}; + s2.id = 2, + s2.aastr[0] = {"opq","pqr","qrs", "rst"}; + s2.aastr[1] = {"uvw","vwx","wxy", "xyz"}; + + tarr.put(s1, get_self()); + tarr.put(s2, get_self()); + auto itarr = tarr.id.begin(); + auto itarr_e = tarr.id.end(); + eosio::cout << "print table:: \n"; + while(itarr != itarr_e){ + auto row = itarr.value(); + eosio::cout << "id=" << row.id << "\n"; + for(int i = 0; i < row.aastr.size(); ++i) { + for(int j = 0; j < row.aastr[i].size(); ++j){ + eosio::cout << row.aastr[i][j] << " "; + } + eosio::cout << "\n"; + } + ++itarr; + } + } + + // test inside using std::array + [[eosio::action]] + void testin(std::string message) { + tests_table _tests(get_self(), get_self().value); + + std::array str = {'a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a' }; + int len = message.length() < 32 ? message.length() : 32; + for(int i = 0; i < len ; ++i){ + str[i] = (uint8_t)message[i]; + } + + std::array str2 = str; + eosio::cout << "size of std::array str is : " << str.size() << "\n"; + for(int i = 0; i < 32; ++i){ + eosio::cout << str[i] << " "; + } + eosio::cout << "\n"; + for(int i = 0; i < 32; ++i){ + eosio::cout << str2[i] << " "; + } + eosio::cout << "\n"; + std::array info_arr; + info_arr[0].age = 20; + info_arr[0].name = "abc"; + info_arr[1].age = 21; + info_arr[1].name = "cde"; + for(int i = 0; i < 2; ++i){ + eosio::cout << info_arr[i].age << " " << info_arr[i].name << "\n"; + } + } + + // test parameter using std::array + // not supported so far + [[eosio::action]] + void testpa(std::array input){ + std::array arr = input; + for(int i = 0; i < 4; ++i){ + eosio::cout << arr[i] << " "; + } + eosio::cout << "\n"; + } + + // test return using std::array, not supported so far + [[eosio::action]] + // cleos -v push action eosio testre '[[1,2,3,4]]' -p eosio@active + std::array testre(std::array input){ + std::array arr = input; + for(auto & v : arr) v += 1; + return arr; + } + + // test return using std::vector + [[eosio::action]] + // cleos -v push action eosio testrev '[[1,2,3,4]]' -p eosio@active + std::vector testrev(std::vector input){ + std::vector vec = input; + for(auto & v : vec) v += 1; + return vec; + } + + // test nested array + [[eosio::action]] + void testne() { + std::array nest; + std::array str = {'a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a' }; + + nest[0].id = 1; + nest[0].str = str; + nest[1].id = 2; + nest[1].str = str; + for(int i = 0; i < nest.size(); ++i){ + eosio::cout << nest[i].id << " " ; + for(int j = 0; j < nest[i].str.size(); ++j) { + eosio::cout << nest[i].str[j] + i << " "; + } + eosio::cout << "\n"; + } + std::array, 3> nest2; + for(int i = 0; i < nest2.size(); ++i){ + for(int j = 0; j < nest2[i].size(); ++j) { + nest2[i][j] = "test nested "; + eosio::cout << nest2[i][j] << " "; + } + eosio::cout << "\n"; + } + } + + // test complex data + [[eosio::action]] + void testcom(name user) { + require_auth(user); + tests_table _tests(get_self(), get_self().value); + + std::array str = {'a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a' }; + _tests.emplace(user, [&](auto& t) { + t.id = user.value + std::time(0); // primary key can't be same + t.str = str; + }); + auto it = _tests.begin(); + auto ite = _tests.end(); + while(it != ite){ + eosio::cout << "id = " << it->id << "\n"; + for(int i = 0; i < it->str.size(); ++i) { + eosio::cout << it->str[i] << " "; + } + eosio::cout << "\n"; + ++it; + } + } + +}; diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 4000ed0c..206c8170 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -27,7 +27,7 @@ #include #include #include - +#include #include using namespace llvm; @@ -269,6 +269,8 @@ namespace eosio { namespace cdt { add_pair(type); else if (is_template_specialization(type, {"tuple"})) add_tuple(type); + else if (is_template_specialization(type, {"array"}) ) + add_type(std::get(get_template_argument(type, 0))); else if (is_template_specialization(type, {"variant"})) add_variant(type); else if (is_template_specialization(type, {})) { diff --git a/tools/include/eosio/gen.hpp b/tools/include/eosio/gen.hpp index ab53762c..3a4b83fe 100644 --- a/tools/include/eosio/gen.hpp +++ b/tools/include/eosio/gen.hpp @@ -541,6 +541,20 @@ struct generation_utils { } return replace_in_name(ret); } + else if ( is_template_specialization( type, {"array"} )) { + std::string orig = type.getAsString(); + std:: string ret = ""; + ret += get_template_argument_as_string( type, 0 ); + ret = replace_in_name(ret); + ret += '['; + auto pos1 = orig.find_last_of(','); + auto pos2 = orig.find_last_of('>'); + std::string digits = orig.substr(pos1 + 1, pos2 - pos1 - 1); + digits.erase(std::remove(digits.begin(), digits.end(), ' '), digits.end()); + ret += digits; + ret += ']'; + return ret; + } else if ( is_template_specialization( type, {} )) { auto pt = llvm::dyn_cast(type.getTypePtr()); auto tst = llvm::dyn_cast(pt ? pt->desugar().getTypePtr() : type.getTypePtr() ); From 49e05b111dfa58a1e7c88368ef8a20e06afe40ae Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Fri, 15 Jul 2022 13:58:53 -0500 Subject: [PATCH 2/2] Remove KV related changes as not currently supported in mandel. --- .../toolchain/abigen-pass/using_std_array.abi | 1 - tests/unit/test_contracts/array_tests.cpp | 41 +------------------ 2 files changed, 1 insertion(+), 41 deletions(-) diff --git a/tests/toolchain/abigen-pass/using_std_array.abi b/tests/toolchain/abigen-pass/using_std_array.abi index 6c75d02d..4019ff00 100644 --- a/tests/toolchain/abigen-pass/using_std_array.abi +++ b/tests/toolchain/abigen-pass/using_std_array.abi @@ -44,7 +44,6 @@ "key_types": [] } ], - "kv_tables": {}, "ricardian_clauses": [], "variants": [], "action_results": [] diff --git a/tests/unit/test_contracts/array_tests.cpp b/tests/unit/test_contracts/array_tests.cpp index a5e85e69..bbd72050 100644 --- a/tests/unit/test_contracts/array_tests.cpp +++ b/tests/unit/test_contracts/array_tests.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include using namespace eosio; @@ -31,45 +31,6 @@ class [[eosio::contract]] array_tests : public contract { } }; - struct [[eosio::table]] my_table_array : eosio::kv::table { - KV_NAMED_INDEX("id"_n, id) - - my_table_array(eosio::name contract_name) { - init(contract_name, id); - } - }; - my_struct s1; - my_struct s2; - // test nested std::array used in kv talbe - [[eosio::action]] - void testkv() { - my_table_array tarr{get_self()}; - - s1.id = 1; - s1.aastr[0] = {"abc","bcd","cde", "def"}; - s1.aastr[1] = {"hij","ijk","jkl", "klm"}; - s2.id = 2, - s2.aastr[0] = {"opq","pqr","qrs", "rst"}; - s2.aastr[1] = {"uvw","vwx","wxy", "xyz"}; - - tarr.put(s1, get_self()); - tarr.put(s2, get_self()); - auto itarr = tarr.id.begin(); - auto itarr_e = tarr.id.end(); - eosio::cout << "print table:: \n"; - while(itarr != itarr_e){ - auto row = itarr.value(); - eosio::cout << "id=" << row.id << "\n"; - for(int i = 0; i < row.aastr.size(); ++i) { - for(int j = 0; j < row.aastr[i].size(); ++j){ - eosio::cout << row.aastr[i][j] << " "; - } - eosio::cout << "\n"; - } - ++itarr; - } - } - // test inside using std::array [[eosio::action]] void testin(std::string message) {