From 7b180f0291638fa558ea95942f9ac82caf3eb52d Mon Sep 17 00:00:00 2001 From: Bucky Kittinger Date: Thu, 7 Jul 2022 17:26:57 -0400 Subject: [PATCH 01/12] update readme --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dd368fe096..00ee5bfa10 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,9 @@ CDT is a toolchain for WebAssembly (WASM) and a set of tools to facilitate smart CDT currently supports Linux x86_64 Debian packages. ### Debian Package Install ```sh -wget https://github.com/eosnetworkfoundation/mandel.cdt/releases/download/v3.0.0/cdt_3.0.0_amd64.deb -sudo apt install ./cdt_3.0.0_amd64.deb +wget https://github.com/eosnetworkfoundation/mandel.cdt/releases/download/v3.0.0-rc1/cdt_3.0.0-rc1_amd64.deb +sudo apt install ./cdt_3.0.0-rc1_amd64.deb ``` - ### Debian Package Uninstall ```sh sudo apt remove cdt 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 02/12] 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 0000000000..6c75d02d66 --- /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 0000000000..ad03b5cf61 --- /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 0000000000..29c09f89cf --- /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 292f9081b5..91222bb594 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 0000000000..a5e85e6916 --- /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 4000ed0cce..206c817082 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 ab53762cf4..3a4b83fe96 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 03/12] 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 6c75d02d66..4019ff00a2 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 a5e85e6916..bbd72050be 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) { From 8d43cc62fdc74ec2b98959a80a3be00ce5ee66de Mon Sep 17 00:00:00 2001 From: Clayton Calabrese Date: Fri, 22 Jul 2022 15:36:03 -0500 Subject: [PATCH 04/12] update head of llvm for fixing wasm bloat --- cdt-llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdt-llvm b/cdt-llvm index 45b675763a..52f194ad6a 160000 --- a/cdt-llvm +++ b/cdt-llvm @@ -1 +1 @@ -Subproject commit 45b675763a73d6fac0b297dc3b4c0e2f2181b1ba +Subproject commit 52f194ad6ac0206edce2b4e43779d778d6a4c073 From 3bf9a9338338fd277364a404ead71d7998e3a1e6 Mon Sep 17 00:00:00 2001 From: softprofe <65825209+softprofe@users.noreply.github.com> Date: Thu, 21 Oct 2021 15:11:59 -0700 Subject: [PATCH 05/12] GH-722 Merge pull request #1213 from EOSIO/keke_epe559 Support explicit nested using of template commonly used --- .../abigen-pass/nested_container.abi | 111 ++++++++ tests/unit/test_contracts/CMakeLists.txt | 1 + .../test_contracts/explicit_nested_tests.cpp | 239 ++++++++++++++++++ tools/include/eosio/abigen.hpp | 203 +++++++++++++++ tools/include/eosio/gen.hpp | 167 +++++++++++- 5 files changed, 720 insertions(+), 1 deletion(-) create mode 100644 tests/toolchain/abigen-pass/nested_container.abi create mode 100644 tests/unit/test_contracts/explicit_nested_tests.cpp diff --git a/tests/toolchain/abigen-pass/nested_container.abi b/tests/toolchain/abigen-pass/nested_container.abi new file mode 100644 index 0000000000..cdc39aeeb5 --- /dev/null +++ b/tests/toolchain/abigen-pass/nested_container.abi @@ -0,0 +1,111 @@ +{ + "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ", + "version": "eosio::abi/1.2", + "types": [ + { + "new_type_name": "B_map_string_string_E", + "type": "pair_string_string[]" + }, + { + "new_type_name": "B_vector_int32_E", + "type": "int32[]" + } + ], + "structs": [ + { + "name": "map2map", + "base": "", + "fields": [ + { + "name": "m", + "type": "pair_string_string[]" + }, + { + "name": "m2m", + "type": "pair_string_B_map_string_string_E[]" + } + ] + }, + { + "name": "pair_string_B_map_string_string_E", + "base": "", + "fields": [ + { + "name": "key", + "type": "string" + }, + { + "name": "value", + "type": "B_map_string_string_E" + } + ] + }, + { + "name": "pair_string_string", + "base": "", + "fields": [ + { + "name": "key", + "type": "string" + }, + { + "name": "value", + "type": "string" + } + ] + }, + { + "name": "settuple2", + "base": "", + "fields": [ + { + "name": "user", + "type": "name" + }, + { + "name": "tp2", + "type": "tuple_int32_float64_string_B_vector_int32_E" + } + ] + }, + { + "name": "tuple_int32_float64_string_B_vector_int32_E", + "base": "", + "fields": [ + { + "name": "field_0", + "type": "int32" + }, + { + "name": "field_1", + "type": "float64" + }, + { + "name": "field_2", + "type": "string" + }, + { + "name": "field_3", + "type": "B_vector_int32_E" + } + ] + } + ], + "actions": [ + { + "name": "map2map", + "type": "map2map", + "ricardian_contract": "" + }, + { + "name": "settuple2", + "type": "settuple2", + "ricardian_contract": "" + } + ], + "tables": [], + "kv_tables": {}, + "ricardian_clauses": [], + "variants": [], + "action_results": [] +} \ No newline at end of file diff --git a/tests/unit/test_contracts/CMakeLists.txt b/tests/unit/test_contracts/CMakeLists.txt index 91222bb594..1e418f38b0 100644 --- a/tests/unit/test_contracts/CMakeLists.txt +++ b/tests/unit/test_contracts/CMakeLists.txt @@ -3,6 +3,7 @@ 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(explicit_nested_tests explicit_nested_tests explicit_nested_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/explicit_nested_tests.cpp b/tests/unit/test_contracts/explicit_nested_tests.cpp new file mode 100644 index 0000000000..7febcab6aa --- /dev/null +++ b/tests/unit/test_contracts/explicit_nested_tests.cpp @@ -0,0 +1,239 @@ +#include + + +using namespace std; +using namespace eosio; + +CONTRACT explicit_nested_tests : public contract { + public: + using contract::contract; + + explicit_nested_tests(name receiver, name code, datastream ds): + contract(receiver, code, ds),test_table(receiver, receiver.value){} + + ACTION nothing() { + std::array>, 4> arrv4; + std::vector, 4>> varr4; + }; + typedef std::optional opt_float; + typedef std::vector vec_opt_float; + typedef struct _mystruct{ + int field0; + float field1; + std::vector> field2; + }mystruct; + + TABLE testdata { + uint64_t id; + std::map > data; + std::vector>> data_vec; + std::vector> data_vec2; + vec_opt_float data_vec3; + std::tuple, std::vector> tup1; + std::variant>, std::vector> var1; + std::vector> vvmys; + auto primary_key() const { return id; } + + EOSLIB_SERIALIZE(testdata, (id)(data)(data_vec)(data_vec2)(data_vec3)(tup1)(var1)(vvmys)); + }; + using test_data_idx = multi_index<"testdata"_n, testdata>; + + [[eosio::action]] + //usage: cleos -v push action eosio vvstr '[[["abc", "cde"],["def","fgh"]]]' -p eosio@active + std::vector> vvstr(std::vector> input) { + std::vector> output = input; + for(auto & row : output) { + for(auto & word : row) { + eosio::cout << " " << word; + } + eosio::cout << "\n"; + } + return output; + } + [[eosio::action]] + // usage : cleos -v push action eosio vvvstr '[[[["abc", "cde"],["def","fgh"]]]]' -p eosio@active + std::vector>> vvvstr(std::vector>> input) { + std::vector>> output = input; + for(auto & vecvec : output){ + for(auto & row : vecvec) { + for(auto & word : row) { + eosio::cout << " " << word; + } + eosio::cout << "\n"; + } + } + return output; + } + + [[eosio::action]] + //usage : cleos -v push action eosio mapo '[[{"key":1,"value":2.0},{"key":2,"value":3.9}]]' -p eosio@active + std::map > mapo(std::map> input){ + std::map> output = input; + return output; + } + + [[eosio::action]] + // usage : cleos -v push action eosio vecop '[[{"first":1,"second":2.0},{"first":2,"second":3.9}]]' -p eosio@active + std::vector>> vecop(std::vector>> input){ + std::vector>> output = input; + return output; + } + + [[eosio::action]] + // usage : cleos -v push action eosio vecpo '[[{"first":1,"second":2.0},{"first":2,"second":3.9}]]' -p eosio@active + std::vector> vecpo(std::vector> input){ + std::vector> output = input; + return output; + } + + [[eosio::action]] + // usage : cleos -v push action eosio vecpoe '[[{"first":1,"second":2.0},{"first":2,"second":3.9}]]' -p eosio@active + std::vector >> vecpoe(std::vector >> input){ + std::vector >> output = input; + return output; + } + + [[eosio::action]] + // usage : cleos -v push action eosio tup '[{"field_0":1,"field_1":2.0,"field_2":[4,5,6,7]}]' -p eosio@active + std::tuple, std::vector> tup(std::tuple, std::vector> input){ + std::tuple, std::vector> output = input; + return output; + } + + [[eosio::action]] + // usage : cleos -v push action eosio var '[["uint64",8]]' -p eosio@active + // usage : cleos -v push action eosio var '[["B_optional_B_pair_int32_float32_E_E", {"first":1,"second":2.0}]]' -p eosio@active + // usage : cleos -v push action eosio var '[["B_vector_int32_E", [2,3,4]]]' -p eosio@active + std::variant>, std::vector> var(std::variant>, std::vector> input){ + std::variant>, std::vector> output = input; + return output; + } + + [[eosio::action]] // sdl means set deque list , as we support them should test them as well. + // usage : cleos -v push action eosio sdlstr '[[[["abc", "cde"],["def","fgh"]]]]' -p eosio@active + std::set>> sdlstr(std::set>> input) { + std::set>> output = input; + for(auto & deqlist : output){ + for(auto & row : deqlist) { + for(auto & word : row) { + eosio::cout << " " << word; + } + eosio::cout << "\n"; + } + } + return output; + } + + typedef std::vector> vecvecstr; + [[eosio::action]] // this test is for the whole type is not explicit nested by the inside type is a alias of explicit nested. + // usage : cleos -v push action eosio vivvstr '[[[["abc", "cde"],["def","fgh"]]]]' -p eosio@active + std::vector vivvstr(std::vector input) { + std::vector output = input; + for(auto & vecvec : output){ + for(auto & row : vecvec) { + for(auto & word : row) { + eosio::cout << " " << word; + } + eosio::cout << "\n"; + } + } + return output; + } + + typedef vector > > myvec3; + typedef set myset; + + [[eosio::action]] // this test is for the whole type is not explicit nested by the inside type is a alias of explicit nested. + // usage : cleos -v push action eosio sivvvi '[[[[[1, 2],[3,4]]]]]' -p eosio@active + myset sivvvi(myset input) { + myset output = input; + for(auto & vvvi : output){ + for(auto & vecvec : vvvi){ + for(auto & row : vecvec) { + for(auto & num : row) { + eosio::cout << " " << num; + } + eosio::cout << "\n"; + } + } + } + return output; + } + + [[eosio::action]] + std::vector> vvmystr(){ + std::vector> output = {{{56,5.6, {{"test"}} }, {78,7.8, {{"passed"}} }}}; + return output; + } + + [[eosio::action]] // this test is for the put simple data to table, so as to check the the data read from table is the same + // usage : cleos -v push action eosio putd '[eosio]' -p eosio@active + // cleos -v get table eosio eosio testdata + void putd(name user) { + require_auth(user); + test_data_idx _tests(get_self(), get_self().value); + + std::map > data; + data[12] = 34; + std::vector>> data_vec = {{{12,1.2}}, {{34, 3.4}}}; + std::vector> data_vec2 = {{56, {5.6}},{78,{7.8}}}; + vec_opt_float data_vec3 = {{1.1}, {2.2}, {3.3}}; + std::tuple, std::vector> tup1 = {12, {3.4}, {5,6,7}}; + std::vector tempvec = {8,9,10}; + std::variant>, std::vector> var1 = tempvec; + std::vector> vvmys = {{{12,1.2, {{"test"}}}, {34,3.4,{{"passed"}} }}}; + _tests.emplace(user, [&](auto& t) { + t.id = user.value + std::time(0); // primary key can't be same + t.data = data; + t.data_vec = data_vec; + t.data_vec2 = data_vec2; + t.data_vec3 = data_vec3; + t.tup1 = tup1; + t.var1 = var1; + t.vvmys = vvmys; + }); + auto it = _tests.begin(); + auto ite = _tests.end(); + while(it != ite){ + eosio::cout << "id = " << it->id << "\n"; + eosio::cout << "data : " << "\n"; + for(auto & p : it->data){ + eosio::cout << p.first << ":" << p.second.value() << "\n"; + } + eosio::cout << "data_vec : \n"; + for(auto & opt : it->data_vec){ + if(opt.has_value()) eosio::cout << opt.value().first << ":" << opt.value().second << "\n"; + else eosio::cout << "no value in optional \n"; + } + eosio::cout << "data_vec2 : \n"; + for(auto & p : it->data_vec2){ + eosio::cout << p.first << ":" << p.second.value() << "\n"; + } + eosio::cout << "data_vec3 : \n"; + for(auto & opt : it->data_vec3){ + if(opt.has_value()) eosio::cout << opt.value() << "\n"; + else eosio::cout << "no value in optional \n"; + } + eosio::cout << "tup1 : \n"; + auto [a, b, c] = it->tup1; + eosio:cout << a << ", " << b.value() << ", " ; + for(auto & v : c){ eosio::cout << v << " ";} + eosio::cout << "\n"; + + eosio::cout << "var1 : \n"; + for(auto & v : std::get<2>(it->var1)) { eosio::cout << v << " "; }; + eosio::cout << "\n"; + + eosio::cout << "vvmys: \n"; + for(auto & vmys : it->vvmys){ + for(auto & mys : vmys){ + eosio::cout << mys.field0 << "," << mys.field1 << mys.field2[0][0] << "\n"; + } + } + eosio::cout << "\n\n"; + ++it; + } + } + + test_data_idx test_table; +}; diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 206c817082..f515c0ca01 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -253,11 +253,214 @@ namespace eosio { namespace cdt { _abi.variants.insert(var); } + inline void adding_explicit_nested_dispatcher(const clang::QualType& inside_type, int depth, std::string & inside_type_name){ + if(is_explicit_nested(inside_type)){ // inside type is still explict nested <<>> + inside_type_name = add_explicit_nested_type(inside_type, depth + 1); + } else if(is_explicit_container(inside_type)) { // inside type is single container, only one <> + inside_type_name = add_explicit_nested_type(inside_type, depth + 1); + }else if (is_builtin_type(translate_type(inside_type))){ // inside type is builtin + inside_type_name = translate_type(inside_type); + } else if (is_aliasing(inside_type)) { // inside type is an alias + add_typedef(inside_type); + inside_type_name = get_base_type_name( inside_type ); + } else if (is_template_specialization(inside_type, {})) { + add_struct(inside_type.getTypePtr()->getAsCXXRecordDecl(), get_template_name(inside_type)); + inside_type_name = get_template_name(inside_type); + }else if (inside_type.getTypePtr()->isRecordType()) { + add_struct(inside_type.getTypePtr()->getAsCXXRecordDecl()); + inside_type_name = inside_type.getTypePtr()->getAsCXXRecordDecl()->getNameAsString(); + } else { + std::string errstring = "adding_explicit_nested_dispatcher: this inside type "; + errstring += inside_type.getAsString(); + errstring += " is unexpected, maybe not supported so far. \n"; + CDT_INTERNAL_ERROR(errstring); + } + } + + void add_explicit_nested_linear(const clang::QualType& type, int depth, abi_typedef & abidef, std::string & ret, const std::string & tname, bool & gottype){ + ret += tname + "_"; + auto inside_type = std::get(get_template_argument(type)); + std::string inside_type_name; + adding_explicit_nested_dispatcher(inside_type, depth, inside_type_name); + if(inside_type_name != ""){ + ret += inside_type_name; + abidef.type = inside_type_name + ( (tname == "optional") ? "?" : "[]" ); + gottype = true; + } + } + + void add_explicit_nested_map(const clang::QualType& type, int depth, abi_typedef & abidef, std::string & ret, const std::string & tname, bool & gottype){ + ret += tname + "_"; + clang::QualType inside_type[2]; + std::string inside_type_name[2]; + for(int i = 0; i < 2; ++i){ + inside_type[i] = std::get(get_template_argument(type, i)); + adding_explicit_nested_dispatcher(inside_type[i], depth, inside_type_name[i]); + } + + if(inside_type_name[0] != "" && inside_type_name[1] != ""){ + ret += inside_type_name[0] + "_" + inside_type_name[1]; + abidef.type = "pair_" + inside_type_name[0] + "_" + inside_type_name[1] + "[]"; + + abi_struct kv; + kv.name = "pair_" + inside_type_name[0] + "_" + inside_type_name[1]; + kv.fields.push_back( {"key", inside_type_name[0]} ); + kv.fields.push_back( {"value", inside_type_name[1]} ); + _abi.structs.insert(kv); + + gottype = true; + } + } + + void add_explicit_nested_pair(const clang::QualType& type, int depth, abi_typedef & abidef, std::string & ret, const std::string & tname, bool & gottype){ + ret += tname + "_"; + clang::QualType inside_type[2]; + std::string inside_type_name[2]; + for(int i = 0; i < 2; ++i){ + inside_type[i] = std::get(get_template_argument(type, i)); + adding_explicit_nested_dispatcher(inside_type[i], depth, inside_type_name[i]); + } + + if(inside_type_name[0] != "" && inside_type_name[1] != ""){ + ret += inside_type_name[0] + "_" + inside_type_name[1]; + abidef.type = "pair_" + inside_type_name[0] + "_" + inside_type_name[1]; + + abi_struct pair; + pair.name = "pair_" + inside_type_name[0] + "_" + inside_type_name[1]; + pair.fields.push_back( {"first", inside_type_name[0]} ); + pair.fields.push_back( {"second", inside_type_name[1]} ); + _abi.structs.insert(pair); + + gottype = true; + } + } + + void add_explicit_nested_tuple(const clang::QualType& type, int argcnt, int depth, abi_typedef & abidef, std::string & ret, const std::string & tname, bool & gottype){ + ret += tname + "_"; + std::vector inside_type(argcnt); + std::vector inside_type_name(argcnt); + for(int i = 0; i < argcnt; ++i){ + inside_type[i] = std::get(get_template_argument(type, i)); + adding_explicit_nested_dispatcher(inside_type[i], depth, inside_type_name[i]); + } + bool allgot = true; + for(auto & inside_tn : inside_type_name) { + if(inside_tn == "") allgot = false; + } + if(allgot){ + abi_struct tup; + tup.name = "tuple_"; + abidef.type = "tuple_"; + for (int i = 0; i < argcnt; ++i) { + ret += inside_type_name[i] + (i < (argcnt - 1) ? "_" : ""); + abidef.type += inside_type_name[i] + (i < (argcnt - 1) ? "_" : ""); + tup.name += inside_type_name[i] + (i < (argcnt - 1) ? "_" : ""); + tup.fields.push_back( {"field_"+std::to_string(i), inside_type_name[i]} ); + } + _abi.structs.insert(tup); + + gottype = true; + } + } + + void add_explicit_nested_array(const clang::QualType& type, int depth, abi_typedef & abidef, std::string & ret, const std::string & tname, bool & gottype){ + ret += tname + "_"; + auto inside_type = std::get(get_template_argument(type)); + std::string inside_type_name; + adding_explicit_nested_dispatcher(inside_type, depth, inside_type_name); + + if(inside_type_name != ""){ + ret += inside_type_name + "_"; + std::string orig = type.getAsString(); + 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; + abidef.type = inside_type_name + "[" + digits + "]" ; + gottype = true; + } + } + + void add_explicit_nested_variant(const clang::QualType& type, int argcnt, int depth, abi_typedef & abidef, std::string & ret, const std::string & tname, bool & gottype){ + ret += tname + "_"; + std::vector inside_type(argcnt); + std::vector inside_type_name(argcnt); + for(int i = 0; i < argcnt; ++i){ + inside_type[i] = std::get(get_template_argument(type, i)); + adding_explicit_nested_dispatcher(inside_type[i], depth, inside_type_name[i]); + } + bool allgot = true; + for(auto & inside_tn : inside_type_name) { + if(inside_tn == "") allgot = false; + } + + if(allgot){ + abi_variant var; + var.name = "variant_"; + abidef.type = "variant_"; + for (int i = 0; i < argcnt; ++i) { + ret += inside_type_name[i] + (i < (argcnt - 1) ? "_" : ""); + abidef.type += inside_type_name[i] + (i < (argcnt - 1) ? "_" : ""); + var.name += inside_type_name[i] + (i < (argcnt - 1) ? "_" : ""); + var.types.push_back( inside_type_name[i]); + } + _abi.variants.insert(var); + + gottype = true; + } + } + + // return combined typename, and mid-type will be add automatically, only be used on explicit nested type has <<>> or more + std::string add_explicit_nested_type(const clang::QualType& type, int depth = 0){ + abi_typedef abidef; + std::string ret = "B_"; + bool gottype = false; + auto pt = llvm::dyn_cast(type.getTypePtr()); + if(auto tst = llvm::dyn_cast(pt ? pt->desugar().getTypePtr() : type.getTypePtr())){ + if(auto rt = llvm::dyn_cast(tst->desugar())){ + if(auto * decl = rt->getDecl()){ + std::string tname = decl->getName().str(); + if(tname == "vector" || tname == "set" || tname == "deque" || tname == "list" || tname == "optional") { + add_explicit_nested_linear(type, depth, abidef, ret, tname, gottype); + } else if (tname == "map" ) { + add_explicit_nested_map(type, depth, abidef, ret, tname, gottype); + } else if (tname == "pair" ) { + add_explicit_nested_pair(type, depth, abidef, ret, tname, gottype); + } else if (tname == "tuple") { + int argcnt = tst->getNumArgs(); + add_explicit_nested_tuple(type, argcnt, depth, abidef, ret, tname, gottype); + } else if (tname == "array") { + add_explicit_nested_array(type, depth, abidef, ret, tname, gottype); + } else if (tname == "variant") { + int argcnt = tst->getNumArgs(); + add_explicit_nested_variant(type, argcnt, depth, abidef, ret, tname, gottype); + } + } + } + } + + if(!gottype) { + std::string errstring = "add_explicit_nested_type failed to fetch type from "; + errstring += type.getAsString(); + CDT_INTERNAL_ERROR(errstring); + return ""; + } + ret +="_E"; + abidef.new_type_name = ret; // the name is combined from container name and low layer type + if(depth > 0) _abi.typedefs.insert(abidef); + return ret; + } + void add_type( const clang::QualType& t ) { if (evaluated.count(t.getTypePtr())) return; evaluated.insert(t.getTypePtr()); auto type = get_ignored_type(t); + if(is_explicit_nested(t)){ + add_explicit_nested_type(t.getNonReferenceType()); + return; + } if (!is_builtin_type(translate_type(type))) { if (is_aliasing(type)) { add_typedef(type); diff --git a/tools/include/eosio/gen.hpp b/tools/include/eosio/gen.hpp index 3a4b83fe96..99a92db65e 100644 --- a/tools/include/eosio/gen.hpp +++ b/tools/include/eosio/gen.hpp @@ -500,8 +500,161 @@ struct generation_utils { return _translate_type(replace_in_name(ret)); } + inline void translating_explicit_nested_dispatcher(const clang::QualType& inside_type, int depth, std::string & inside_type_name){ + if(is_explicit_nested(inside_type)){ // inside type is still explict nested <<>> + inside_type_name = translate_explicit_nested_type(inside_type, depth + 1); + } else if(is_explicit_container(inside_type)) { // inside type is single container, only one <> + inside_type_name = translate_explicit_nested_type(inside_type, depth + 1); + }else if (is_builtin_type(translate_type(inside_type))){ // inside type is builtin + inside_type_name = translate_type(inside_type); + } else if (is_aliasing(inside_type)) { // inside type is a alias + inside_type_name = get_base_type_name( inside_type ); + } else if (is_template_specialization(inside_type, {})) { + inside_type_name = get_template_name(inside_type); + }else if (inside_type.getTypePtr()->isRecordType()) { + inside_type_name = inside_type.getTypePtr()->getAsCXXRecordDecl()->getNameAsString(); + } else { + std::string errstring = "translating_explicit_nested_dispatcher: this inside type "; + errstring += inside_type.getAsString(); + errstring += " is unexpected, maybe not supported so far. \n"; + CDT_INTERNAL_ERROR(errstring); + } + } + + void translate_explicit_nested_linear_or_optional(const clang::QualType& type, int depth, std::string & ret, const std::string & tname, bool & gottype){ + ret += depth > 0 ? tname + "_" : ""; + auto inside_type = std::get(get_template_argument(type)); + std::string inside_type_name; + translating_explicit_nested_dispatcher(inside_type, depth, inside_type_name); + if(inside_type_name != ""){ + ret += inside_type_name; + ret += depth > 0 ? "_E" : ( (tname == "optional") ? "?" : "[]" ); + gottype = true; + } + } + + void translate_explicit_nested_map_or_pair(const clang::QualType& type, int depth, std::string & ret, const std::string & tname, bool & gottype){ + ret += depth > 0 ? tname + "_" : "pair_"; + clang::QualType inside_type[2]; + std::string inside_type_name[2]; + for(int i = 0; i < 2; ++i){ + inside_type[i] = std::get(get_template_argument(type, i)); + translating_explicit_nested_dispatcher(inside_type[i], depth, inside_type_name[i]); + } + + if(inside_type_name[0] != "" && inside_type_name[1] != ""){ + ret += inside_type_name[0] + "_" + inside_type_name[1]; + ret += depth > 0 ? "_E" : ( tname == "map" ? "[]" : ""); + gottype = true; + } + } + + void translate_explicit_nested_tuple(const clang::QualType& type, int depth, int argcnt, std::string & ret, const std::string & tname, bool & gottype){ + ret += tname + "_"; + std::vector inside_type(argcnt); + std::vector inside_type_name(argcnt); + for(int i = 0; i < argcnt; ++i){ + inside_type[i] = std::get(get_template_argument(type, i)); + translating_explicit_nested_dispatcher(inside_type[i], depth, inside_type_name[i]); + } + bool allgot = true; + for(auto & inside_tn : inside_type_name) { + if(inside_tn == "") allgot = false; + } + if(allgot){ + for (int i = 0; i < argcnt; ++i) { + ret += inside_type_name[i] + (i < (argcnt - 1) ? "_" : ""); + } + ret += depth > 0 ? "_E" : ""; + gottype = true; + } + } + + void translate_explicit_nested_array(const clang::QualType& type, int depth, std::string & ret, const std::string & tname, bool & gottype){ + ret += depth > 0 ? tname + "_" : ""; + auto inside_type = std::get(get_template_argument(type, 0)); + std::string inside_type_name; + translating_explicit_nested_dispatcher(inside_type, depth, inside_type_name); + + if(inside_type_name != ""){ + ret += inside_type_name; + std::string orig = type.getAsString(); + 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()); + if(depth == 0){ + ret += "[" + digits + "]"; + } else { + ret += "_" + digits + "_E"; + } + + gottype = true; + } + } + + void translate_explicit_nested_variant(const clang::QualType& type, int depth, int argcnt, std::string & ret, const std::string & tname, bool & gottype){ + ret += tname + "_"; + std::vector inside_type(argcnt); + std::vector inside_type_name(argcnt); + for(int i = 0; i < argcnt; ++i){ + inside_type[i] = std::get(get_template_argument(type, i)); + translating_explicit_nested_dispatcher(inside_type[i], depth, inside_type_name[i]); + } + bool allgot = true; + for(auto & inside_tn : inside_type_name) { + if(inside_tn == "") allgot = false; + } + + if(allgot){ + for (int i = 0; i < argcnt; ++i) { + ret += inside_type_name[i] + (i < (argcnt - 1) ? "_" : ""); + } + ret += depth > 0 ? "_E" : ""; + gottype = true; + } + } + + // return combined typename, only be used only explicit nested type which has <<>> or more + std::string translate_explicit_nested_type(const clang::QualType& type, int depth = 0){ + std::string ret = depth > 0 ? "B_" : ""; + // one layer cdt string can be made from this layer container name and low layer type names, no need low layer ctd type string + bool gottype = false; + auto pt = llvm::dyn_cast(type.getTypePtr()); + if(auto tst = llvm::dyn_cast(pt ? pt->desugar().getTypePtr() : type.getTypePtr())){ + if(auto rt = llvm::dyn_cast(tst->desugar())){ + if(auto * decl = rt->getDecl()){ + std::string tname = decl->getName().str(); + if(tname == "vector" || tname == "set" || tname == "deque" || tname == "list" || tname == "optional") { + translate_explicit_nested_linear_or_optional(type, depth, ret, tname, gottype); + } else if (tname == "map" || tname == "pair") { + translate_explicit_nested_map_or_pair(type, depth, ret, tname, gottype); + } else if (tname == "tuple") { + int argcnt = tst->getNumArgs(); + translate_explicit_nested_tuple(type, depth, argcnt, ret, tname, gottype); + } else if (tname == "array") { + translate_explicit_nested_array(type, depth, ret, tname, gottype); + } else if (tname == "variant") { + int argcnt = tst->getNumArgs(); + translate_explicit_nested_variant(type, depth, argcnt, ret, tname, gottype); + } + } + } + } + if(!gottype) { + std::string errstring = "add_explicit_nested_type failed to fetch type from "; + errstring += type.getAsString(); + CDT_INTERNAL_ERROR(errstring); + return ""; + } + return ret; + } + inline std::string translate_type( const clang::QualType& type ) { - if ( is_template_specialization( type, {"ignore"} ) ) + if(is_explicit_nested(type)){ + return translate_explicit_nested_type(type.getNonReferenceType()); + } + else if ( is_template_specialization( type, {"ignore"} ) ) return get_template_argument_as_string( type ); else if ( is_template_specialization( type, {"binary_extension"} ) ) { auto t = get_template_argument_as_string( type ); @@ -650,6 +803,18 @@ struct generation_utils { return get_base_type_name(t).compare(get_type_alias_string(t)) != 0; } + inline bool is_explicit_nested(const clang::QualType& t ){ + std::string tstr = t.getAsString(); + if(tstr.find("decay_t") != std::string::npos || tstr.find("decltype") != std::string::npos || tstr.find("ignore") != std::string::npos || + tstr.find("invoke") != std::string::npos || tstr.find("index") != std::string::npos || tstr.find("declval") != std::string::npos ) return false; + return std::count (tstr.begin(), tstr.end(), '<') >= 2; + } + + inline bool is_explicit_container(const clang::QualType& t ){ + std::string tstr = t.getAsString(); + return std::count (tstr.begin(), tstr.end(), '<') == 1; + } + inline bool is_tuple(const clang::QualType& t) { constexpr std::string_view test_str = "tuple<"; return t.getAsString().substr(0, test_str.size()) == test_str; From 460058f49a26c740dfb4484e83e46f6ed5b20af8 Mon Sep 17 00:00:00 2001 From: Chris Gundlach Date: Wed, 27 Jul 2022 09:47:00 -0500 Subject: [PATCH 06/12] GH-730 added map support --- tools/include/eosio/abigen.hpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index f515c0ca01..b950c59232 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -163,6 +163,28 @@ namespace eosio { namespace cdt { _abi.structs.insert(pair); } + void add_map(const clang::QualType& type) { + for (int i = 0; i < 2; ++i) { + add_type(std::get(get_template_argument(type, i))); + } + abi_struct kv; + std::string name = get_type(type); + kv.name = name.substr(0, name.length() - 2); + auto remove_ending_brackets = [&]( std::string name ) { + int i = name.length()-1; + for (; i >= 0; i--) + if ( name[i] != '[' && name[i] != ']' ) + break; + return name.substr(0,i+1); + }; + kv.name = remove_ending_brackets(name); + kv.fields.push_back( {"key", get_template_argument_as_string(type)} ); + kv.fields.push_back( {"value", get_template_argument_as_string(type, 1)} ); + add_type(std::get(get_template_argument(type))); + add_type(std::get(get_template_argument(type, 1))); + _abi.structs.insert(kv); + } + void add_struct( const clang::CXXRecordDecl* decl, const std::string& rname="" ) { abi_struct ret; if ( decl->getNumBases() == 1 ) { @@ -468,6 +490,8 @@ namespace eosio { namespace cdt { else if (is_template_specialization(type, {"vector", "set", "deque", "list", "optional", "binary_extension", "ignore"})) { add_type(std::get(get_template_argument(type))); } + else if (is_template_specialization(type, {"map"})) + add_map(type); else if (is_template_specialization(type, {"pair"})) add_pair(type); else if (is_template_specialization(type, {"tuple"})) From 2a5e91cf8ffe1cb9097e0d1edfbbd6b5dd4a42e8 Mon Sep 17 00:00:00 2001 From: Chris Gundlach Date: Wed, 27 Jul 2022 09:47:34 -0500 Subject: [PATCH 07/12] GH-730 added tests for map support --- tests/toolchain/abigen-pass/nested_container.cpp | 13 +++++++++++++ tests/toolchain/abigen-pass/nested_container.json | 9 +++++++++ 2 files changed, 22 insertions(+) create mode 100644 tests/toolchain/abigen-pass/nested_container.cpp create mode 100644 tests/toolchain/abigen-pass/nested_container.json diff --git a/tests/toolchain/abigen-pass/nested_container.cpp b/tests/toolchain/abigen-pass/nested_container.cpp new file mode 100644 index 0000000000..4c0a16c75a --- /dev/null +++ b/tests/toolchain/abigen-pass/nested_container.cpp @@ -0,0 +1,13 @@ +#include + +using namespace eosio; +using std::map; +using std::string; + +class [[eosio::contract]] nested_container : public contract { +public: + using contract::contract; + + [[eosio::action]] + void map2map(map m, map> m2m) {} +}; diff --git a/tests/toolchain/abigen-pass/nested_container.json b/tests/toolchain/abigen-pass/nested_container.json new file mode 100644 index 0000000000..4f2c8aae7f --- /dev/null +++ b/tests/toolchain/abigen-pass/nested_container.json @@ -0,0 +1,9 @@ +{ + "tests" : [ + { + "expected" : { + "abi-file" : "nested_container.abi" + } + } + ] +} From 398aaff4925010e458266b933f778dd7a1cadc3b Mon Sep 17 00:00:00 2001 From: bogniq Date: Thu, 26 Aug 2021 07:04:26 -0400 Subject: [PATCH 08/12] GH-731 Merge pull request #1193 from EOSIO/plCDTtuplesupport Add support for std::tuple in eosio.cdt --- .../abigen-pass/nested_container.abi | 41 +- .../abigen-pass/nested_container.cpp | 7 + tests/toolchain/build-pass/nestcontn2a.cpp | 1182 ++++++++++++++ tests/toolchain/build-pass/nestcontn2a.json | 10 + tests/toolchain/build-pass/nestcontn2kv.cpp | 1426 +++++++++++++++++ tests/toolchain/build-pass/nestcontn2kv.json | 10 + tests/toolchain/build-pass/tupletest.cpp | 518 ++++++ tests/toolchain/build-pass/tupletest.json | 10 + tests/toolchain/build-pass/tupletestkv.cpp | 530 ++++++ tests/toolchain/build-pass/tupletestkv.json | 10 + tools/include/eosio/gen.hpp | 10 +- 11 files changed, 3715 insertions(+), 39 deletions(-) create mode 100644 tests/toolchain/build-pass/nestcontn2a.cpp create mode 100644 tests/toolchain/build-pass/nestcontn2a.json create mode 100644 tests/toolchain/build-pass/nestcontn2kv.cpp create mode 100644 tests/toolchain/build-pass/nestcontn2kv.json create mode 100644 tests/toolchain/build-pass/tupletest.cpp create mode 100644 tests/toolchain/build-pass/tupletest.json create mode 100644 tests/toolchain/build-pass/tupletestkv.cpp create mode 100644 tests/toolchain/build-pass/tupletestkv.json diff --git a/tests/toolchain/abigen-pass/nested_container.abi b/tests/toolchain/abigen-pass/nested_container.abi index cdc39aeeb5..912d31d704 100644 --- a/tests/toolchain/abigen-pass/nested_container.abi +++ b/tests/toolchain/abigen-pass/nested_container.abi @@ -1,16 +1,7 @@ { "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ", "version": "eosio::abi/1.2", - "types": [ - { - "new_type_name": "B_map_string_string_E", - "type": "pair_string_string[]" - }, - { - "new_type_name": "B_vector_int32_E", - "type": "int32[]" - } - ], + "types": [], "structs": [ { "name": "map2map", @@ -22,12 +13,12 @@ }, { "name": "m2m", - "type": "pair_string_B_map_string_string_E[]" + "type": "pair_string_pair_string_string[][]" } ] }, { - "name": "pair_string_B_map_string_string_E", + "name": "pair_string_pair_string_string", "base": "", "fields": [ { @@ -36,7 +27,7 @@ }, { "name": "value", - "type": "B_map_string_string_E" + "type": "pair_string_string[]" } ] }, @@ -64,29 +55,7 @@ }, { "name": "tp2", - "type": "tuple_int32_float64_string_B_vector_int32_E" - } - ] - }, - { - "name": "tuple_int32_float64_string_B_vector_int32_E", - "base": "", - "fields": [ - { - "name": "field_0", - "type": "int32" - }, - { - "name": "field_1", - "type": "float64" - }, - { - "name": "field_2", - "type": "string" - }, - { - "name": "field_3", - "type": "B_vector_int32_E" + "type": "tuple_int32_float64_string_int32[]" } ] } diff --git a/tests/toolchain/abigen-pass/nested_container.cpp b/tests/toolchain/abigen-pass/nested_container.cpp index 4c0a16c75a..e89c8a39db 100644 --- a/tests/toolchain/abigen-pass/nested_container.cpp +++ b/tests/toolchain/abigen-pass/nested_container.cpp @@ -1,8 +1,12 @@ #include +#include +#include using namespace eosio; using std::map; using std::string; +using std::tuple; +using std::vector; class [[eosio::contract]] nested_container : public contract { public: @@ -10,4 +14,7 @@ class [[eosio::contract]] nested_container : public contract { [[eosio::action]] void map2map(map m, map> m2m) {} + + [[eosio::action]] + void settuple2(name user, const tuple >& tp2) {} }; diff --git a/tests/toolchain/build-pass/nestcontn2a.cpp b/tests/toolchain/build-pass/nestcontn2a.cpp new file mode 100644 index 0000000000..e2ccc18405 --- /dev/null +++ b/tests/toolchain/build-pass/nestcontn2a.cpp @@ -0,0 +1,1182 @@ +/* Verify the support of nested containers in eosio multi-index table + * For each action, an example regarding how to use the action with the cleos command line is given. + * + * std:pair is a struct with 2 fields first and second, + * std::map is handled as an array/vector of pairs/structs by EOSIO with implicit fields key, value, + * the cases of combined use of key/value and first/second involving map,pair in the cleos are documented here. + * so handling of std::pair is NOT the same as the handling of a general struct such as struct mystruct! + * + * When assigning data input with cleos: + * [] represents an empty vector/set or empty map where T, T1, T2 can be any composite types + * null represents an uninitialized std::optional where T can be any composite type + * BUT [] or null can NOT be used to represent an empty struct or empty std::pair + * + * Expected printout: + * For each setx action, the printed result on the cleos console is given in its corresponding prntx action. + */ + +#include + +#include +#include +#include +#include +#include + +using namespace eosio; +using namespace std; + +#define SETCONTAINERVAL(x) do { \ + require_auth(user); \ + psninfoindex2 tblIndex(get_self(), get_first_receiver().value); \ + auto iter = tblIndex.find(user.value); \ + if (iter == tblIndex.end()) \ + { \ + tblIndex.emplace(user, [&](auto &row) { \ + row.key = user; \ + row.x = x; \ + }); \ + } \ + else \ + { \ + tblIndex.modify(iter, user, [&]( auto& row ) { \ + row.x = x; \ + }); \ + } \ + }while(0) + +#define PRNTCHECK() require_auth(user); \ + psninfoindex2 tblIndex(get_self(), get_first_receiver().value); \ + auto iter = tblIndex.find(user.value); \ + check(iter != tblIndex.end(), "Record does not exist"); + +struct mystruct +{ + uint64_t _count; + string _strID; +}; + +//mystruct2 has embeded mystruct +struct mystruct2 +{ + mystruct _structfld; + string _strID2; +}; + +// use typedefs to make multi-layer nested containers work! +typedef vector vec_uint16; +typedef set set_uint16; +typedef optional op_uint16; +typedef map mp_uint16; +typedef pair pr_unit16; + +typedef vector vec_uint32; +typedef vector vecvec_uint32; + + +class [[eosio::contract("nestcontn2a")]] nestcontn2a : public eosio::contract { + private: + struct [[eosio::table]] person2 { + name key; + + // Each container/object is represented by one letter: v-vector, m-map, s-mystruct,o-optional, p-pair, + // with exceptions: s2 - mystruct2, st - set + + vector v; + map m; + mystruct s; + mystruct2 s2; + set st; + optional o; + pair p; + vector vs; + + //The following are 2-layer nested containers involving vector/optional/map + vector vv; + optional oo; + map mm; + set stst; + + vector vst; + set stv; + + vector vo; + optional ov; + set sto; + optional ost; + + vector vm; + map mv; + + set stm; + map mst; + + optional om; + map mo; + + //The following are composite types involving pair and containers + vector > vp; + pair pv; + + set > stp; + pair pst; + + optional op; + pair po; + + map mp; + pair pm; + + pair pp; + + //The following is a 3-layer nested containers for motivation + optional ovv; + + uint64_t primary_key() const { return key.value; } + }; + using psninfoindex2 = eosio::multi_index<"people2"_n, person2>; + + + public: + using contract::contract; + + nestcontn2a(name receiver, name code, datastream ds): contract(receiver, code, ds) {} + + + //[[eosio::action]] void settuple(name user, const tuple& tp) {} + // eosio-cpp compile error for std::tuple: Tried to get a nested template type of a template not containing one + + /*Examples: + * cleos --verbose push action nestcontn2a setv '["alice", [100,200,300,600]]' -p alice@active + * cleos --verbose push action nestcontn2a setv '["bob", []]' -p bob@active + */ + [[eosio::action]] + void setv(name user, const vector& v) + { + SETCONTAINERVAL(v); + eosio::print("vector stored successfully"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a prntv '["alice"]' -p alice@active + * output: >> size of stored v:4 vals of v:100,200,300,600, + * + * cleos --verbose push action nestcontn2a prntv '["bob"]' -p bob@active + * output: >> size of stored v:0 vals of v: + */ + [[eosio::action]] + void prntv(name user) + { + PRNTCHECK(); + eosio::print("size of stored v:", iter->v.size()," vals of v:"); + for (const auto & ele : iter->v) + eosio::print(ele, ","); + + } + + /*Examples: + * cleos --verbose push action nestcontn2a setst '["alice", [101,201,301]]' -p alice@active + * cleos --verbose push action nestcontn2a setst '["bob", []]' -p bob@active + */ + [[eosio::action]] + void setst(name user, const set & st) + { + SETCONTAINERVAL(st); + eosio::print("set stored successfully"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a prntst '["alice"]' -p alice@active + * output: >> size of stored st:3 vals:101,201,301, + * + * cleos --verbose push action nestcontn2a prntst '["bob"]' -p bob@active + * output: >> size of stored st:0 vals: + */ + [[eosio::action]] + void prntst(name user) + { + PRNTCHECK(); + eosio::print("size of stored st:", iter->st.size()," vals:"); + for (const auto & ele : iter->st) + eosio::print(ele, ","); + + } + + /*Examples: + * To use shortcut notation: + * cleos --verbose push action nestcontn2a setm '["alice", [{"key":"str1","value":"str1val"}, {"key":"str3","value":"str3val"}]]' -p alice@active + * + * To use full JSON notation: + * cleos --verbose push action nestcontn2a setm '{"user":"jane", "m":[{"key":"str4", "value":"str4val"}, {"key":"str6", "value":"str6val"}]}' -p jane@active + * + * To pass an empty map: + * cleos --verbose push action nestcontn2a setm '["bob", []]' -p bob@active + */ + [[eosio::action]] + void setm(name user, const map & m) + { + SETCONTAINERVAL(m); + eosio::print("map stored successfully"); + } + + /* Examples: + * cleos --verbose push action nestcontn2a prntm '["alice"]' -p alice@active + * output: >> size of stored m:2 vals of m:str1:str1val str3:str3val + * + * cleos --verbose push action nestcontn2a prntm '["jane"]' -p jane@active + * output: >> size of stored m:2 vals of m:str4:str4val str6:str6val + * + * cleos --verbose push action nestcontn2a prntm '["bob"]' -p bob@active + * output: >> size of stored m:0 vals of m: + */ + [[eosio::action]] + void prntm(name user) + { + PRNTCHECK(); + eosio::print("size of stored m:", iter->m.size()," vals of m:"); + for (auto it2 = iter->m.begin(); it2 != iter->m.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + + } + + //Example: cleos --verbose push action nestcontn2a sets '["alice", {"_count":18, "_strID":"dumstr"}]' -p alice@active + [[eosio::action]] + void sets(name user, const mystruct& s) + { + SETCONTAINERVAL(s); + eosio::print("mystruct stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prnts '["alice"]' -p alice@active + * output: >> stored mystruct val:18,dumstr + */ + [[eosio::action]] + void prnts(name user) + { + PRNTCHECK(); + eosio::print("stored mystruct val:", iter->s._count,",", iter->s._strID); + } + + //Example: cleos --verbose push action nestcontn2a sets2 '["alice", {"_structfld":{"_count":18, "_strID":"dumstr"}, "_strID2":"dumstr2"}]' -p alice@active + [[eosio::action]] + void sets2(name user, const mystruct2& s2) + { + SETCONTAINERVAL(s2); + eosio::print("complex mystruct2 stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prnts2 '["alice"]' -p alice@active + * output: >> stored mystruct2 val:18,dumstr,dumstr2 + */ + [[eosio::action]] + void prnts2(name user) + { + PRNTCHECK(); + eosio::print("stored mystruct2 val:", iter->s2._structfld._count,",", iter->s2._structfld._strID, ",", iter->s2._strID2); + } + + /*Example: + * cleos --verbose push action nestcontn2a setvs '["alice", [{"_count":18, "_strID":"dumstr"},{"_count":19, "_strID":"dumstr2"}]]' -p alice@active + */ + [[eosio::action]] + void setvs(name user, const vector& vs) + { + SETCONTAINERVAL(vs); + eosio::print("vector stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntvs '["alice"]' -p alice@active + * output: >> stored vector size=2: + * >> 18,dumstr + * >> 19,dumstr2 + */ + [[eosio::action]] + void prntvs(name user) + { + PRNTCHECK(); + eosio::print("stored vector size=",iter->vs.size(), ":\n"); + for (const auto& ele: iter->vs) + { + eosio::print(ele._count,",", ele._strID,"\n"); + } + } + + /*Examples + * To pass a null value: + * cleos --verbose push action nestcontn2a seto '["bob", null]' -p bob@active + * + * To pass a non-null value: + * cleos --verbose push action nestcontn2a seto '["alice","hello strval22"]' -p alice@active + * + */ + [[eosio::action]] + void seto(name user, const optional& o) + { + SETCONTAINERVAL(o); + eosio::print("optional stored successfully"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a prnto '["bob"]' -p bob@active + * output: >> stored optional has null value! + * + * cleos --verbose push action nestcontn2a prnto '["alice"]' -p alice@active + * output: >> stored optional =hello strval22 + */ + [[eosio::action]] + void prnto(name user) + { + PRNTCHECK(); + if (iter->o) + eosio::print("stored optional =", iter->o.value()); + else + eosio::print("stored optional has null value!"); + } + + //Example: cleos --verbose push action nestcontn2a setp '["alice", {"first":183, "second":269}]' -p alice@active + [[eosio::action]] + void setp(name user, const pair& p) + { + SETCONTAINERVAL(p); + eosio::print("pair stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntp '["alice"]' -p alice@active + * output: tored pair val:183,269 + */ + [[eosio::action]] + void prntp(name user) + { + PRNTCHECK(); + eosio::print("stored pair val:", iter->p.first,",", iter->p.second); + } + + //============Two-layer nest containers start here=========== + //=== 1. Try vector - set,vector,optional,map,pair + + //Example: cleos --verbose push action nestcontn2a setvst '["alice", [[10,20],[3], [400,500,600]]]' -p alice@active + [[eosio::action]] + void setvst(name user, const vector& vst) + { + SETCONTAINERVAL(vst); + eosio::print("type defined vector stored successfully!"); + + } + + /*Example: + * cleos --verbose push action nestcontn2a prntvst '["alice"]' -p alice@active + * output: >> stored vector>:size=3 vals: + * >> 10 20 + * >> 3 + * >> 400 500 600 + */ + [[eosio::action]] + void prntvst(name user) + { + + PRNTCHECK(); + eosio::print("stored vector>:size=", iter->vst.size(), " vals:\n"); + for (auto it1=iter->vst.begin(); it1!= iter->vst.end(); it1++) + { + for (auto it2=it1->begin(); it2!= it1->end(); it2++) + eosio::print(*it2, " "); + eosio::print("\n"); + } + } + + + //Example: cleos --verbose push action nestcontn2a setvv '["alice", [[1,2],[30], [40,50,60]]]' -p alice@active + [[eosio::action]] + void setvv(name user, const vector& vv) + { + SETCONTAINERVAL(vv); + eosio::print("type defined vector stored successfully!"); + + } + + /*Example: + * cleos --verbose push action nestcontn2a prntvv '["alice"]' -p alice@active + * output: >> stored vector> vals: + * >> 1 2 + * >> 30 + * >> 40 50 60 + */ + [[eosio::action]] + void prntvv(name user) + { + + PRNTCHECK(); + eosio::print("stored vector> vals:\n"); + for (int i=0 ; i < iter->vv.size(); i++) + { + for (int j=0; j < iter->vv[i].size(); j++) + eosio::print(iter->vv[i][j], " "); + eosio::print("\n"); //--- use cleos --verbose to show new lines !!! + } + } + + /*Example: + * cleos --verbose push action nestcontn2a setvo '["alice", [100, null, 200, null, 300]]' -p alice@active + * ******user data can NOT be pushed into the chain, cleos get table will not work if using setvo + * vector > is NOT supported currently! + */ + [[eosio::action]] + void setvo(name user, const vector& vo) + { + SETCONTAINERVAL(vo); + eosio::print("type defined vector > stored successfully!"); + } + + //Example: cleos --verbose push action nestcontn2a prntvo '["alice"]' -p alice@active + // NOT supported + [[eosio::action]] + void prntvo(name user) + { + PRNTCHECK(); + eosio::print("stored vector vals:\n"); + for (const auto& ele : iter->vo) + { + if (ele) + eosio::print(ele.value(), " "); + else + eosio::print("NULL", " "); + } + } + + + /*Example: + * cleos --verbose push action nestcontn2a setvm '["alice", [ [{"first":10,"second":100},{"first":11,"second":101}], [{"first":80,"second":800},{"first":81,"second":9009}] ]]' -p alice@active + */ + [[eosio::action]] + void setvm(name user, const vector& vm) + { + SETCONTAINERVAL(vm); + eosio::print("type defined vector > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntvm '["alice"]' -p alice@active + * output: >> stored vector: size=2 content: + * >> + * >> Element 0---> + * >> 10:100 11:101 + * >> Element 1---> + * >> 80:800 81:9009 + */ + [[eosio::action]] + void prntvm(name user) + { + PRNTCHECK(); + eosio::print("stored vector: size=", iter->vm.size()," content:\n"); + int count=0; + for (const auto& mpval : iter->vm) + { + eosio::print("\nElement ", count++, "--->\n\t"); + for (auto it2 = mpval.begin(); it2 != mpval.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + } + + } + + + /*Example: + * cleos --verbose push action nestcontn2a setvp '["alice", [{"first":18, "second":28}, {"first":19, "second":29}]]' -p alice@active + */ + [[eosio::action]] + void setvp(name user, const vector >& vp) + { + SETCONTAINERVAL(vp); + eosio::print("vector > stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntvp '["alice"]' -p alice@active + * output: >> stored vector > size=2: + * >> 18,28 + * >> 19,29 + */ + [[eosio::action]] + void prntvp(name user) + { + PRNTCHECK(); + eosio::print("stored vector > size=",iter->vp.size(), ":\n"); + for (const auto& ele: iter->vp) + { + eosio::print(ele.first,",", ele.second,"\n"); + } + } + + //=== 2. Try set - set,vector,optional,map,pair + + //Example: cleos --verbose push action nestcontn2a setstst '["alice", [[10,20],[3], [400,500,600]]]' -p alice@active + [[eosio::action]] + void setstst(name user, const set& stst) + { + SETCONTAINERVAL(stst); + eosio::print("type defined set stored successfully!"); + + } + + /*Example: + * cleos --verbose push action nestcontn2a prntstst '["alice"]' -p alice@active + * output: >> stored set>:size=3 vals: + * >> 3 + * >> 10 20 + * >> 400 500 600 + */ + [[eosio::action]] + void prntstst(name user) + { + + PRNTCHECK(); + eosio::print("stored set>:size=", iter->stst.size(), " vals:\n"); + for (auto it1=iter->stst.begin(); it1!= iter->stst.end(); it1++) + { + for (auto it2=it1->begin(); it2!= it1->end(); it2++) + eosio::print(*it2, " "); + eosio::print("\n"); + } + } + + //Example: cleos --verbose push action nestcontn2a setstv '["alice", [[16,26],[36], [46,506,606]]]' -p alice@active + [[eosio::action]] + void setstv(name user, const set& stv) + { + SETCONTAINERVAL(stv); + eosio::print("type defined set stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntstv '["alice"]' -p alice@active + * output: >> stored set>:size=3 vals: + * >> 16 26 + * >> 36 + * >> 46 506 606 + */ + [[eosio::action]] + void prntstv(name user) + { + + PRNTCHECK(); + eosio::print("stored set>:size=", iter->stv.size(), " vals:\n"); + for (auto it1=iter->stv.begin(); it1!= iter->stv.end(); it1++) + { + for (auto it2=it1->begin(); it2!= it1->end(); it2++) + eosio::print(*it2, " "); + eosio::print("\n"); + } + } + + /*Example: + * cleos --verbose push action nestcontn2a setsto '["alice", [101, null, 201, 301]]' -p alice@active + * ***user data can NOT be pushed into the chain, cleos get table will not work if using setsto + * set > is NOT supported currently! + */ + [[eosio::action]] + void setsto(name user, const set& sto) + { + SETCONTAINERVAL(sto); + eosio::print("type defined set > stored successfully!"); + } + + //Example: cleos --verbose push action nestcontn2a prntsto '["alice"]' -p alice@active + // NOT supported + [[eosio::action]] + void prntsto(name user) + { + PRNTCHECK(); + eosio::print("stored vector vals:\n"); + for (const auto& ele : iter->sto) + { + if (ele) + eosio::print(ele.value(), " "); + else + eosio::print("NULL", " "); + } + } + + /*Example: + * cleos --verbose push action nestcontn2a setstm '["alice", [ [{"first":30,"second":300},{"first":31,"second":301}], [{"first":60,"second":600},{"first":61,"second":601}] ]]' -p alice@active + */ + [[eosio::action]] + void setstm(name user, const set& stm) + { + SETCONTAINERVAL(stm); + eosio::print("type defined set > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntstm '["alice"]' -p alice@active + * output: >> stored set: size=2 content: + * >> + * >> Element 0---> + * >> 30:300 31:301 + * >> Element 1---> + * >> 60:600 61:601 + */ + [[eosio::action]] + void prntstm(name user) + { + PRNTCHECK(); + eosio::print("stored set: size=", iter->stm.size()," content:\n"); + int count=0; + for (const auto& mpval : iter->stm) + { + eosio::print("\nElement ", count++, "--->\n\t"); + for (auto it2 = mpval.begin(); it2 != mpval.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + } + } + + + /*Example: + * cleos --verbose push action nestcontn2a setstp '["alice", [{"first":68, "second":128}, {"first":69, "second":129}]]' -p alice@active + */ + [[eosio::action]] + void setstp(name user, const set >& stp) + { + SETCONTAINERVAL(stp); + eosio::print("set> stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntstp '["alice"]' -p alice@active + * output: >> stored set > size=2: + * >> 68,128 + * >> 69,129 + */ + [[eosio::action]] + void prntstp(name user) + { + PRNTCHECK(); + eosio::print("stored set > size=",iter->stp.size(), ":\n"); + for (const auto& ele: iter->stp) + { + eosio::print(ele.first,",", ele.second,"\n"); + } + } + + //=== 3. Try optional - set,vector,optional,map,pair + + + /*Examples: + * cleos --verbose push action nestcontn2a setost '["bob", null]' -p bob@active + * cleos --verbose push action nestcontn2a setost '["alice", [1006,2006, 3006]]' -p alice@active + */ + [[eosio::action]] + void setost(name user, const optional& ost) + { + SETCONTAINERVAL(ost); + eosio::print("type defined optional > stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a prntost '["bob"]' -p bob@active + * output: >> stored optional vals: + * >> NULL or no value + * + * cleos --verbose push action nestcontn2a prntost '["alice"]' -p alice@active + * output: >> stored optional vals: + * >> 1006 2006 3006 + */ + [[eosio::action]] + void prntost(name user) + { + PRNTCHECK(); + eosio::print("stored optional vals:\n"); + if (iter->ost) + { + for (const auto& ele : iter->ost.value()) + eosio::print(ele, " "); + } + else + eosio::print("NULL or no value"); + } + + + + /*Examples: + * cleos --verbose push action nestcontn2a setov '["bob", null]' -p bob@active + * + * cleos --verbose push action nestcontn2a setov '["alice", [1001,2001, 3001]]' -p alice@active + */ + [[eosio::action]] + void setov(name user, const optional& ov) + { + SETCONTAINERVAL(ov); + eosio::print("type defined optional > stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a prntov '["bob"]' -p bob@active + * output: >> stored optional vals: + * >> NULL or no value + * + * cleos --verbose push action nestcontn2a prntov '["alice"]' -p alice@active + * output: >> stored optional vals: + * >> 1001 2001 3001 + */ + [[eosio::action]] + void prntov(name user) + { + PRNTCHECK(); + eosio::print("stored optional vals:\n"); + if (iter->ov) + { + for (const auto& ele : iter->ov.value()) + eosio::print(ele, " "); + } + else + eosio::print("NULL or no value"); + } + + + + /*Examples: + * cleos --verbose push action nestcontn2a setoo '["bob", null]' -p bob@active + * + * cleos --verbose push action nestcontn2a setoo '["alice",123]' -p alice@active + */ + [[eosio::action]] + void setoo(name user, const optional& oo) + { + SETCONTAINERVAL(oo); + eosio::print("type defined optional stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a prntoo '["bob"]' -p bob@active + * ouput: >> stored optional> val:null or no real value stored + * + * cleos --verbose push action nestcontn2a prntoo '["alice"]' -p alice@active + * output: >> stored optional> val:123 + */ + [[eosio::action]] + void prntoo(name user) + { + PRNTCHECK(); + eosio::print("stored optional> val:"); + if (iter->oo && iter->oo.value()) + eosio::print(iter->oo.value().value(),"\n"); + else + eosio::print("null or no real value stored"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a setom '["alice",[{"first":10,"second":1000},{"first":11,"second":1001}] ]' -p alice@active + * + * cleos --verbose push action nestcontn2a setom '["bob", null ]' -p bob@active + */ + [[eosio::action]] + void setom(name user, const optional& om) + { + SETCONTAINERVAL(om); + eosio::print("type defined optional > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntom '["alice"]' -p alice@active + * output: >> size of stored om:2 vals:10:1000 11:1001 + * + * cleos --verbose push action nestcontn2a prntom '["bob"]' -p bob@active + * output: >> optional has NULL value + */ + [[eosio::action]] + void prntom(name user) + { + PRNTCHECK(); + if (iter->om) + { + auto mpval = iter->om.value(); + eosio::print("size of stored om:", mpval.size()," vals:"); + for (auto it2 = mpval.begin(); it2 != mpval.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + + } + else + eosio::print("optional has NULL value\n"); + } + + + /*Examples: + * cleos --verbose push action nestcontn2a setop '["alice", {"first":60, "second":61}]' -p alice@active + * + * cleos --verbose push action nestcontn2a setop '["bob", null]' -p bob@active + */ + [[eosio::action]] + void setop(name user, const optional & op) + { + SETCONTAINERVAL(op); + eosio::print("type-defined optional-pair optional stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a prntop '["alice"]' -p alice@active + * output: >> stored optional data:60 61 + * + * cleos --verbose push action nestcontn2a prntop '["bob"]' -p bob@active + * output: >> optional has NULL value + */ + [[eosio::action]] + void prntop(name user) + { + PRNTCHECK(); + if (iter->op) + eosio::print("stored optional data:", iter->op.value().first, " ", iter->op.value().second); + else + eosio::print("optional has NULL value\n"); + } + + + //=== 4. Try map - set,vector,optional,map,pair + + /*Example: + * cleos --verbose push action nestcontn2a setmst '["alice", [{"key":1,"value":[10,11,12,16]}, {"key":2,"value":[200,300]} ]]' -p alice@active + */ + [[eosio::action]] + void setmst(name user, const map & mst) + { + SETCONTAINERVAL(mst); + eosio::print("type-defined map > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntmst '["alice"]' -p alice@active + * output: >> stored map: size=2 content: + * >> 1:vals 10 11 12 16 + * >> 2:vals 200 300 + */ + [[eosio::action]] + void prntmst(name user) + { + PRNTCHECK(); + eosio::print("stored map: size=", iter->mst.size()," content:\n"); + for (auto it2 = iter->mst.begin(); it2 != iter->mst.end(); ++it2) + { + eosio::print(it2->first, ":", "vals "); + for (const auto& ele: it2->second) + { + eosio::print(ele," "); + } + eosio::print("\n"); + } + } + + + + /*Example: + * cleos --verbose push action nestcontn2a setmv '["alice", [{"key":1,"value":[10,11,12,16]}, {"key":2,"value":[200,300]} ]]' -p alice@active + */ + [[eosio::action]] + void setmv(name user, const map& mv) + { + SETCONTAINERVAL(mv); + eosio::print("type defined map > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntmv '["alice"]' -p alice@active + * output: >> stored map: size=2 content: + * >> 1:vals 10 11 12 16 + * >> 2:vals 200 300 + */ + [[eosio::action]] + void prntmv(name user) + { + PRNTCHECK(); + eosio::print("stored map: size=", iter->mv.size()," content:\n"); + for (auto it2 = iter->mv.begin(); it2 != iter->mv.end(); ++it2) + { + eosio::print(it2->first, ":", "vals "); + for (const auto& ele: it2->second) + { + eosio::print(ele," "); + } + eosio::print("\n"); + } + } + + + /*Example: + * cleos --verbose push action nestcontn2a setmo '["alice", [{"key":10,"value":1000},{"key":11,"value":null}]]' -p alice@active + */ + [[eosio::action]] + void setmo(name user, const map& mo) + { + SETCONTAINERVAL(mo); + eosio::print("type defined map > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntmo '["alice"]' -p alice@active + * output: >> size of stored mo:2 vals + * >> 10:1000 11:NULL + */ + [[eosio::action]] + void prntmo(name user) + { + PRNTCHECK(); + eosio::print("size of stored mo:", iter->mo.size()," vals\n"); + for (auto it2 = iter->mo.begin(); it2 != iter->mo.end(); ++it2) + { + eosio::print(it2->first, ":"); + if (it2->second) + eosio::print(it2->second.value()," "); + else + eosio::print("NULL "); + } + } + + /*Example: + * cleos push action nestcontn2a setmm '["alice", [{"key":10,"value":[{"first":200,"second":2000}, {"first":201,"second":2001}] }, {"key":11,"value":[{"first":300,"second":3000}, {"first":301,"second":3001}] } ]]' -p alice@active + * Attention: please note the cleos input of mm or map > is a combination of strings key/value and first/second ! + * i.e the "value" part of mm is an array of pairs! + */ + [[eosio::action]] + void setmm(name user, const map& mm) + { + SETCONTAINERVAL(mm); + eosio::print("type defined map > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntmm '["alice"]' -p alice@active + * output: >> stored map val:size=2 vals are the following: + * >> 10---> + * >> 200:2000 + * >> 201:2001 + * >> 11---> + * >> 300:3000 + * >> 301:3001 + */ + [[eosio::action]] + void prntmm(name user) + { + PRNTCHECK(); + eosio::print("stored map val:"); + eosio::print("size=", iter->mm.size()," vals are the following:\n"); + for (auto it2 = iter->mm.begin(); it2 != iter->mm.end(); ++it2) + { + eosio::print(it2->first,"--->\n"); + const auto& temp = it2->second; + for (auto it3 = temp.begin(); it3 != temp.end(); ++it3) + eosio::print("\t",it3->first, ":", it3->second, "\n"); + } + } + + /*Example: + * cleos --verbose push action nestcontn2a setmp '["alice", [{"key":36,"value":{"first":300, "second":301}}, {"key":37,"value":{"first":600, "second":601}} ]]' -p alice@active + */ + [[eosio::action]] + void setmp(name user, const map & mp) + { + SETCONTAINERVAL(mp); + eosio::print("type-defined map-pair map stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntmp '["alice"]' -p alice@active + * output: >> size of stored mp:2 vals: + * >> 36:300 301 + * >> 37:600 601 + */ + [[eosio::action]] + void prntmp(name user) + { + PRNTCHECK(); + eosio::print("size of stored mp:", iter->mp.size()," vals:\n"); + for (auto it2 = iter->mp.begin(); it2 != iter->mp.end(); ++it2) + eosio::print(it2->first, ":", it2->second.first, " ", it2->second.second, "\n"); + } + + //=== 5. Try pair - set,vector,optional,map,pair + + /*Example: + * cleos --verbose push action nestcontn2a setpst '["alice", {"first":20, "second":[200,201,202]}]' -p alice@active + */ + [[eosio::action]] + void setpst(name user, const pair& pst) + { + SETCONTAINERVAL(pst); + eosio::print("type-defined pair-set pair stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntpst '["alice"]' -p alice@active + * output: >> content of stored pair: first=20 + * >> second=200 201 202 + */ + [[eosio::action]] + void prntpst(name user) + { + PRNTCHECK(); + eosio::print("content of stored pair: first=", iter->pst.first, "\nsecond="); + for (const auto& ele: iter->pst.second) + eosio::print(ele, " "); + } + + /*Example: + * cleos --verbose push action nestcontn2a setpv '["alice", {"first":10, "second":[100,101,102]}]' -p alice@active + */ + [[eosio::action]] + void setpv(name user, const pair& pv) + { + SETCONTAINERVAL(pv); + eosio::print("type-defined pair-vector pair stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntpv '["alice"]' -p alice@active + * output: >> content of stored pair: first=10 + * >> second=100 101 102 + */ + [[eosio::action]] + void prntpv(name user) + { + PRNTCHECK(); + eosio::print("content of stored pair: first=", iter->pv.first, "\nsecond="); + for (const auto& ele: iter->pv.second) + eosio::print(ele, " "); + } + + /*Examples: + * cleos --verbose push action nestcontn2a setpo '["alice", {"first":70, "second":71}]' -p alice@active + * + * cleos --verbose push action nestcontn2a setpo '["bob", {"first":70, "second":null}]' -p bob@active + */ + [[eosio::action]] + void setpo(name user, const pair & po) + { + SETCONTAINERVAL(po); + eosio::print("type-defined pair-optional pair stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a prntpo '["alice"]' -p alice@active + * output: >> content of stored pair: first=70 + * >> second=71 + * + * cleos --verbose push action nestcontn2a prntpo '["bob"]' -p bob@active + * output: >> content of stored pair: first=70 + * >> second=NULL + */ + [[eosio::action]] + void prntpo(name user) + { + PRNTCHECK(); + eosio::print("content of stored pair: first=", iter->po.first, "\nsecond="); + if (iter->po.second) + eosio::print(iter->po.second.value(), " "); + else + eosio::print("NULL "); + } + + /*Example: + * cleos --verbose push action nestcontn2a setpm '["alice", {"key":6, "value":[{"first":20,"second":300}, {"first":21,"second":301}] }]' -p alice@active + * Remark: the data input for pm uses a combination of key/vale and first/second + */ + [[eosio::action]] + void setpm(name user, const pair & pm) + { + SETCONTAINERVAL(pm); + eosio::print("type-defined pair-map pair stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2a prntpm '["alice"]' -p alice@active + * output: >> content of stored pair: first=6 + * >> second=20:300 21:301 + */ + [[eosio::action]] + void prntpm(name user) + { + PRNTCHECK(); + eosio::print("content of stored pair: first=", iter->pm.first, "\nsecond="); + for (auto it2 = iter->pm.second.begin(); it2 != iter->pm.second.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + } + + + /*Example: + * cleos --verbose push action nestcontn2a setpp '["alice", {"key":30, "value":{"first":301, "second":302} }]' -p alice@active + * Remark: input data for pp or pair-pair is a combination of key/value and first/second + */ + [[eosio::action]] + void setpp(name user, const pair & pp) + { + SETCONTAINERVAL(pp); + eosio::print("type-defined pair-pair pair stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2a prntpp '["alice"]' -p alice@active + * output: >> content of stored pair: first=30 + * >> second=301 302 + */ + [[eosio::action]] + void prntpp(name user) + { + PRNTCHECK(); + eosio::print("content of stored pair: first=", iter->pp.first, "\nsecond="); + eosio::print(iter->pp.second.first, " ", iter->pp.second.second); + } + + + //Try an example of 3-layer nested container + + /*Example: + * cleos --verbose push action nestcontn2a setovv '["alice", [[21,22],[230], [240,250,260,280]]]' -p alice@active + */ + [[eosio::action]] + void setovv(name user, const optional& ovv) + { + // try type-defined 3-layer nested container optional > > here + SETCONTAINERVAL(ovv); + eosio::print("type-defined optional stored successfully!"); + + } + + /*Example: + * cleos --verbose push action nestcontn2a prntovv '["alice"]' -p alice@active + * output: >> stored optional > > vals: + * >> 21 22 + * >> 230 + * >> 240 250 260 280 + */ + [[eosio::action]] + void prntovv(name user) + { + PRNTCHECK(); + eosio::print("stored optional > > vals:\n"); + if (iter->ovv) + { + auto v2 = iter->ovv.value(); + for (int i=0 ; i < v2.size(); i++) + { + for (int j=0; j < v2[i].size(); j++) + eosio::print(v2[i][j], " "); + eosio::print("\n"); + } + } + else + eosio::print("stored optional > > has null value!"); + } + + //Example: cleos --verbose push action nestcontn2a erase '["alice"]' -p alice@active + [[eosio::action]] + void erase(name user) + { + require_auth(user); + psninfoindex2 tblIndex( get_self(), get_first_receiver().value); + + auto iter = tblIndex.find(user.value); + check(iter != tblIndex.end(), "Record does not exist"); + tblIndex.erase(iter); + eosio::print("record erased successfully"); + } + +}; \ No newline at end of file diff --git a/tests/toolchain/build-pass/nestcontn2a.json b/tests/toolchain/build-pass/nestcontn2a.json new file mode 100644 index 0000000000..b3598b0cf4 --- /dev/null +++ b/tests/toolchain/build-pass/nestcontn2a.json @@ -0,0 +1,10 @@ +{ + "tests": [ + { + "expected": { + "exit-code": 0 + } + } + ] +} + diff --git a/tests/toolchain/build-pass/nestcontn2kv.cpp b/tests/toolchain/build-pass/nestcontn2kv.cpp new file mode 100644 index 0000000000..eb62000703 --- /dev/null +++ b/tests/toolchain/build-pass/nestcontn2kv.cpp @@ -0,0 +1,1426 @@ +/* Verify the support of nested containers for the new Key-value table eosio::kv::map + * For each action, an example regarding how to use the action with the cleos command line is given. + * + * std:pair is a struct with 2 fields first and second, + * std::map is handled as an array/vector of pairs/structs by EOSIO with implicit fields key, value, + * the cases of combined use of key/value and first/second involving map,pair in the cleos are documented here, + * so handling of std::pair is NOT the same as the handling of a general struct such as struct mystruct! + * + * When assigning data input with cleos: + * [] represents an empty vector/set or empty map where T, T1, T2 can be any composite types + * null represents an uninitialized std::optional where T can be any composite type + * BUT [] or null can NOT be used to represent an empty struct or empty std::pair + * + * Attention: + * 1) Please follow https://github.com/EOSIO/eos/tree/develop/contracts/enable-kv to enable key-value support of nodeos first + * 2) To get to the point right away, here authentication/permission checking is skipped for each action in this contract, + * however in practice, suitable permission checking such as require_auth(user) has to be used! + * + * Expected printout: + * For each setx action, the printed result on the cleos console is given in its corresponding prntx action. + */ + +#include +#include + +#include +#include +#include +#include +#include + +using namespace eosio; +using namespace std; + + +#define SETCONTAINERVAL(x) do { \ + person2kv obj = mymap[id]; \ + obj.x = x; \ + mymap[id] = obj; \ + }while(0) + +//when the keys of kv::map are of different types, the following sets values of mymap2, mymap3, mymap4 +#define SETCONTAINERVALN(num, x) do { \ + person2kv obj = mymap ## num[id]; \ + obj.x = x; \ + mymap ## num[id] = obj; \ + }while(0) + + +struct mystruct +{ + uint64_t _count; + string _strID; +}; + +//mystruct2 has embeded mystruct +struct mystruct2 +{ + mystruct _structfld; + string _strID2; +}; + +//mystructrefl has CDT_REFLECT wrapper over above mystruct, it is the key of following my_map_t4, +//if the key of an kv::map is a self-defined struct, the struct has to be self-reflective +struct mystructrefl +{ + uint64_t _count; + string _strID; + CDT_REFLECT(_count, _strID); +}; + +// use typedefs to make multi-layer nested containers work! +typedef vector vec_uint16; +typedef set set_uint16; +typedef optional op_uint16; +typedef map mp_uint16; +typedef pair pr_unit16; + +typedef vector vec_uint32; +typedef vector vecvec_uint32; + +//using dummy_kvmap = eosio::kv::map<"dumkv"_n, int, int>; + +struct person2kv { + // Each container/object is represented by one letter: v-vector, m-map, s-mystruct,o-optional, p-pair, + // with exceptions: s2 - mystruct2, st - set + + vector v; + map m; + mystruct s; + mystruct2 s2; + set st; + optional o; + pair p; + vector vs; + + //The following are 2-layer nested containers involving vector/optional/map + vector vv; + optional oo; + map mm; + set stst; + + vector vst; + set stv; + + vector vo; + optional ov; + set sto; + optional ost; + + vector vm; + map mv; + + set stm; + map mst; + + optional om; + map mo; + + //The following are composite types involving pair and containers + vector > vp; + pair pv; + + set > stp; + pair pst; + + optional op; + pair po; + + map mp; + pair pm; + + pair pp; + + //The following is a 3-layer nested containers for motivation + optional ovv; +}; + + +class [[eosio::contract("nestcontn2kv")]] nestcontn2kv : public eosio::contract { + using my_map_t = eosio::kv::map<"people2kv"_n, int, person2kv>; + + //The following kv::map have different key types: std::string, eosio::name, mystructrefl + using my_map_t2 = eosio::kv::map<"people2kv2"_n, string, person2kv>; + using my_map_t3 = eosio::kv::map<"people2kv3"_n, name, person2kv>; + using my_map_t4 = eosio::kv::map<"people2kv4"_n, mystructrefl, person2kv>; + + private: + my_map_t mymap{}; + my_map_t2 mymap2{}; + my_map_t3 mymap3{}; + my_map_t4 mymap4{}; + + public: + using contract::contract; + + nestcontn2kv(name receiver, name code, datastream ds): contract(receiver, code, ds) {} + + //[[eosio::action]] void settuple(name user, const tuple& tp) {} + //[[eosio::action]] void settuple(name user, const tuple& tp) {} + // eosio-cpp compile error for std::tuple: Tried to get a nested template type of a template not containing one + + //[[eosio::action]] void setdumkv(name user, const dummy_kvmap& tp) {} + // eosio-cpp compile error for above dummy_kvmap: Tried to get a non-existent template argument + + //Example: cleos --verbose push action nestcontn2kv get '[1]' -p alice@active + [[eosio::action]] + person2kv get(int id) + { + //This action will be used by all prntx actions to retrieve item_found for given id + auto iter = mymap.find(id); + check(iter != mymap.end(), "Record does not exist"); + const auto& item_found = iter->second(); + return item_found; + } + + /*Examples: + * cleos --verbose push action nestcontn2kv setv '[1,[100,200,300,600]]' -p alice@active + * cleos --verbose push action nestcontn2kv setv '[2, []]' -p bob@active + */ + [[eosio::action]] + void setv(int id, const vector& v) + { + SETCONTAINERVAL(v); + eosio::print("vector stored successfully"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntv '[1]' -p alice@active + * output: >> size of stored v:4 vals:100,200,300,600, + * + * cleos --verbose push action nestcontn2kv prntv '[2]' -p bob@active + * output: >> size of stored v:0 vals: + */ + [[eosio::action]] + void prntv(int id) + { + const auto& psn = get(id); + eosio::print("size of stored v:", psn.v.size()," vals:"); + for (const auto & ele : psn.v) + eosio::print(ele, ","); + } + + + /*Examples: + * cleos --verbose push action nestcontn2kv setst '[1, [101,201,301]]' -p alice@active + * cleos --verbose push action nestcontn2kv setst '[2, []]' -p bob@active + */ + [[eosio::action]] + void setst(int id, const set & st) + { + SETCONTAINERVAL(st); + eosio::print("set stored successfully"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntst '[1]' -p alice@active + * output: >> size of stored st:3 vals:101,201,301, + * + * cleos --verbose push action nestcontn2kv prntst '[2]' -p bob@active + * output: >> size of stored st:0 vals: + */ + [[eosio::action]] + void prntst(int id) + { + const auto& psn = get(id); + eosio::print("size of stored st:", psn.st.size()," vals:"); + for (const auto & ele : psn.st) + eosio::print(ele, ","); + + } + + /*Examples: + * To use shortcut notation: + * cleos --verbose push action nestcontn2kv setm '[1, [{"key":"str1","value":"str1val"}, {"key":"str3","value":"str3val"}]]' -p alice@active + * + * To use full JSON notation: + * cleos --verbose push action nestcontn2kv setm '{"id":2, "m":[{"key":"str4", "value":"str4val"}, {"key":"str6", "value":"str6val"}]}' -p jane@active + * + * To pass an empty map: + * cleos --verbose push action nestcontn2kv setm '[3, []]' -p bob@active + */ + [[eosio::action]] + void setm(int id, const map & m) + { + SETCONTAINERVAL(m); + eosio::print("map stored successfully"); + } + + /* Examples: + * cleos --verbose push action nestcontn2kv prntm '[1]' -p alice@active + * output: >> size of stored m:2 vals of m:str1:str1val str3:str3val + * + * cleos --verbose push action nestcontn2kv prntm '[2]' -p jane@active + * output: >> size of stored m:2 vals of m:str4:str4val str6:str6val + * + * cleos --verbose push action nestcontn2kv prntm '[3]' -p bob@active + * output: >> size of stored m:0 vals of m: + */ + [[eosio::action]] + void prntm(int id) + { + const auto& psn = get(id); + eosio::print("size of stored m:", psn.m.size()," vals of m:"); + for (auto it2 = psn.m.begin(); it2 != psn.m.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + + } + + //Example: cleos --verbose push action nestcontn2kv sets '[1, {"_count":18, "_strID":"dumstr"}]' -p alice@active + [[eosio::action]] + void sets(int id, const mystruct& s) + { + SETCONTAINERVAL(s); + eosio::print("mystruct stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prnts '[1]' -p alice@active + * output: >> stored mystruct val:18,dumstr + */ + [[eosio::action]] + void prnts(int id) + { + const auto& psn = get(id); + eosio::print("stored mystruct val:", psn.s._count,",", psn.s._strID); + } + + //Example: cleos --verbose push action nestcontn2kv sets2 '[1, {"_structfld":{"_count":18, "_strID":"dumstr"}, "_strID2":"dumstr2"}]' -p alice@active + [[eosio::action]] + void sets2(int id, const mystruct2& s2) + { + SETCONTAINERVAL(s2); + eosio::print("complex mystruct2 stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prnts2 '[1]' -p alice@active + * output: >> stored mystruct2 val:18,dumstr,dumstr2 + */ + [[eosio::action]] + void prnts2(int id) + { + const auto& psn = get(id); + eosio::print("stored mystruct2 val:", psn.s2._structfld._count,",", psn.s2._structfld._strID, ",", psn.s2._strID2); + } + + /*Example: + * cleos --verbose push action nestcontn2kv setvs '[1, [{"_count":18, "_strID":"dumstr"},{"_count":19, "_strID":"dumstr2"}]]' -p alice@active + */ + [[eosio::action]] + void setvs(int id, const vector& vs) + { + SETCONTAINERVAL(vs); + eosio::print("vector stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntvs '[1]' -p alice@active + * output: >> stored vector size=2: + * >> 18,dumstr + * >> 19,dumstr2 + */ + [[eosio::action]] + void prntvs(int id) + { + const auto& psn = get(id); + eosio::print("stored vector size=",psn.vs.size(), ":\n"); + for (const auto& ele: psn.vs) + { + eosio::print(ele._count,",", ele._strID,"\n"); + } + } + + /*Examples + * To pass a null value: + * cleos --verbose push action nestcontn2kv seto '[1, null]' -p bob@active + * + * To pass a non-null value: + * cleos --verbose push action nestcontn2kv seto '[2,"hello strval22"]' -p alice@active + * + */ + [[eosio::action]] + void seto(int id, const optional& o) + { + SETCONTAINERVAL(o); + eosio::print("optional stored successfully"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prnto '[1]' -p bob@active + * output: >> stored optional has null value! + * + * cleos --verbose push action nestcontn2kv prnto '[2]' -p alice@active + * output: >> stored optional =hello strval22 + */ + [[eosio::action]] + void prnto(int id) + { + const auto& psn = get(id); + if (psn.o) + eosio::print("stored optional =", psn.o.value()); + else + eosio::print("stored optional has null value!"); + } + + //Example: cleos --verbose push action nestcontn2kv setp '[1, {"first":183, "second":269}]' -p alice@active + [[eosio::action]] + void setp(int id, const pair& p) + { + SETCONTAINERVAL(p); + eosio::print("pair stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntp '[1]' -p alice@active + * output: tored pair val:183,269 + */ + [[eosio::action]] + void prntp(int id) + { + const auto& psn = get(id); + eosio::print("stored pair val:", psn.p.first,",", psn.p.second); + } + + //============Two-layer nest containers start here=========== + //=== 1. Try set - set,vector,optional,map,pair + + //Example: cleos --verbose push action nestcontn2kv setstst '[1, [[10,20],[3], [400,500,600]]]' -p alice@active + [[eosio::action]] + void setstst(int id, const set& stst) + { + SETCONTAINERVAL(stst); + eosio::print("type defined set stored successfully!"); + + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntstst '[1]' -p alice@active + * output: >> stored set>:size=3 vals: + * >> 3 + * >> 10 20 + * >> 400 500 600 + */ + [[eosio::action]] + void prntstst(int id) + { + const auto& psn = get(id); + eosio::print("stored set>:size=", psn.stst.size(), " vals:\n"); + for (auto it1=psn.stst.begin(); it1!= psn.stst.end(); it1++) + { + for (auto it2=it1->begin(); it2!= it1->end(); it2++) + eosio::print(*it2, " "); + eosio::print("\n"); + } + } + + //Example: cleos --verbose push action nestcontn2kv setstv '[1, [[16,26],[36], [46,506,606]]]' -p alice@active + [[eosio::action]] + void setstv(int id, const set& stv) + { + SETCONTAINERVAL(stv); + eosio::print("type defined set stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntstv '[1]' -p alice@active + * output: >> stored set>:size=3 vals: + * >> 16 26 + * >> 36 + * >> 46 506 606 + */ + [[eosio::action]] + void prntstv(int id) + { + const auto& psn = get(id); + eosio::print("stored set>:size=", psn.stv.size(), " vals:\n"); + for (auto it1=psn.stv.begin(); it1!= psn.stv.end(); it1++) + { + for (auto it2=it1->begin(); it2!= it1->end(); it2++) + eosio::print(*it2, " "); + eosio::print("\n"); + } + } + + /*Example: + * cleos --verbose push action nestcontn2kv setsto '[1, [101, null, 201, 301]]' -p alice@active + * *****user data can NOT be pushed into the chain, cleos get kv_table will not work if using setsto + * set > is NOT supported currently! + */ + [[eosio::action]] + void setsto(int id, const set& sto) + { + SETCONTAINERVAL(sto); + eosio::print("type defined set > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntsto '[1]' -p alice@active + * NOT supported + */ + [[eosio::action]] + void prntsto(int id) + { + const auto& psn = get(id); + eosio::print("stored vector vals:\n"); + for (const auto& ele : psn.sto) + { + if (ele) + eosio::print(ele.value(), " "); + else + eosio::print("NULL", " "); + } + } + + /*Example: + * cleos --verbose push action nestcontn2kv setstm '[1, [ [{"first":30,"second":300},{"first":31,"second":301}], [{"first":60,"second":600},{"first":61,"second":601}] ]]' -p alice@active + */ + [[eosio::action]] + void setstm(int id, const set& stm) + { + SETCONTAINERVAL(stm); + eosio::print("type defined set > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntstm '[1]' -p alice@active + * output: >> stored set: size=2 content: + * >> + * >> Element 0---> + * >> 30:300 31:301 + * >> Element 1---> + * >> 60:600 61:601 + */ + [[eosio::action]] + void prntstm(int id) + { + const auto& psn = get(id); + eosio::print("stored set: size=", psn.stm.size()," content:\n"); + int count=0; + for (const auto& mpval : psn.stm) + { + eosio::print("\nElement ", count++, "--->\n\t"); + for (auto it2 = mpval.begin(); it2 != mpval.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + } + } + + + /*Example: + * cleos --verbose push action nestcontn2kv setstp '[1, [{"first":68, "second":128}, {"first":69, "second":129}]]' -p alice@active + */ + [[eosio::action]] + void setstp(int id, const set >& stp) + { + SETCONTAINERVAL(stp); + eosio::print("set> stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntstp '[1]' -p alice@active + * output: >> stored set > size=2: + * >> 68,128 + * >> 69,129 + */ + [[eosio::action]] + void prntstp(int id) + { + const auto& psn = get(id); + eosio::print("stored set > size=", psn.stp.size(), ":\n"); + for (const auto& ele: psn.stp) + { + eosio::print(ele.first,",", ele.second,"\n"); + } + } + + //=== 2. Try vector - set,vector,optional,map,pair + + //Example: cleos --verbose push action nestcontn2kv setvst '[1, [[10,20],[3], [400,500,600]]]' -p alice@active + [[eosio::action]] + void setvst(int id, const vector& vst) + { + SETCONTAINERVAL(vst); + eosio::print("type defined vector stored successfully!"); + + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntvst '[1]' -p alice@active + * output: >> stored vector>:size=3 vals: + * >> 10 20 + * >> 3 + * >> 400 500 600 + */ + [[eosio::action]] + void prntvst(int id) + { + + const auto& psn = get(id); + eosio::print("stored vector>:size=", psn.vst.size(), " vals:\n"); + for (auto it1=psn.vst.begin(); it1!= psn.vst.end(); it1++) + { + for (auto it2=it1->begin(); it2!= it1->end(); it2++) + eosio::print(*it2, " "); + eosio::print("\n"); + } + } + + + //Example: cleos --verbose push action nestcontn2kv setvv '[1, [[1,2],[30], [40,50,60]]]' -p alice@active + [[eosio::action]] + void setvv(int id, const vector& vv) + { + SETCONTAINERVAL(vv); + eosio::print("type defined vector stored successfully!"); + + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntvv '[1]' -p alice@active + * output: >> stored vector> vals: + * >> 1 2 + * >> 30 + * >> 40 50 60 + */ + [[eosio::action]] + void prntvv(int id) + { + const auto& psn = get(id); + eosio::print("stored vector> vals:\n"); + for (int i=0 ; i < psn.vv.size(); i++) + { + for (int j=0; j < psn.vv[i].size(); j++) + eosio::print(psn.vv[i][j], " "); + eosio::print("\n"); //--- use cleos --verbose to show new lines !!! + } + } + + /*Example: + * cleos --verbose push action nestcontn2kv setvo '[1, [100, null, 200, null, 300]]' -p alice@active + * *****user data can NOT be pushed into the chain, cleos get kv_table will not work if using setvo + * vector > is NOT supported currently! + */ + [[eosio::action]] + void setvo(int id, const vector& vo) + { + SETCONTAINERVAL(vo); + eosio::print("type defined vector > stored successfully!"); + } + + //Example: cleos --verbose push action nestcontn2kv prntvo '[1]' -p alice@active + // NOT supported + [[eosio::action]] + void prntvo(int id) + { + const auto& psn = get(id); + eosio::print("stored vector vals:\n"); + for (const auto& ele : psn.vo) + { + if (ele) + eosio::print(ele.value(), " "); + else + eosio::print("NULL", " "); + } + } + + + /*Example: + * cleos --verbose push action nestcontn2kv setvm '[1, [ [{"first":10,"second":100},{"first":11,"second":101}], [{"first":80,"second":800},{"first":81,"second":9009}] ]]' -p alice@active + */ + [[eosio::action]] + void setvm(int id, const vector& vm) + { + SETCONTAINERVAL(vm); + eosio::print("type defined vector > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntvm '[1]' -p alice@active + * output: >> stored vector: size=2 content: + * >> + * >> Element 0---> + * >> 10:100 11:101 + * >> Element 1---> + * >> 80:800 81:9009 + */ + [[eosio::action]] + void prntvm(int id) + { + const auto& psn = get(id); + eosio::print("stored vector: size=", psn.vm.size()," content:\n"); + int count=0; + for (const auto& mpval : psn.vm) + { + eosio::print("\nElement ", count++, "--->\n\t"); + for (auto it2 = mpval.begin(); it2 != mpval.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + } + + } + + + /*Example: + * cleos --verbose push action nestcontn2kv setvp '[1, [{"first":18, "second":28}, {"first":19, "second":29}]]' -p alice@active + */ + [[eosio::action]] + void setvp(int id, const vector >& vp) + { + SETCONTAINERVAL(vp); + eosio::print("vector > stored successfully"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntvp '[1]' -p alice@active + * output: >> stored vector > size=2: + * >> 18,28 + * >> 19,29 + */ + [[eosio::action]] + void prntvp(int id) + { + const auto& psn = get(id); + eosio::print("stored vector > size=", psn.vp.size(), ":\n"); + for (const auto& ele: psn.vp) + { + eosio::print(ele.first,",", ele.second,"\n"); + } + } + + //=== 3. Try optional - set,vector,optional,map,pair + + + /*Examples: + * cleos --verbose push action nestcontn2kv setost '[1, null]' -p bob@active + * cleos --verbose push action nestcontn2kv setost '[2, [1006,2006, 3006]]' -p alice@active + */ + [[eosio::action]] + void setost(int id, const optional& ost) + { + SETCONTAINERVAL(ost); + eosio::print("type defined optional > stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntost '[1]' -p bob@active + * output: >> stored optional vals: + * >> NULL or no value + * + * cleos --verbose push action nestcontn2kv prntost '[2]' -p alice@active + * output: >> stored optional vals: + * >> 1006 2006 3006 + */ + [[eosio::action]] + void prntost(int id) + { + const auto& psn = get(id); + eosio::print("stored optional vals:\n"); + if (psn.ost) + { + for (const auto& ele : psn.ost.value()) + eosio::print(ele, " "); + } + else + eosio::print("NULL or no value"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv setov '[1, null]' -p bob@active + * + * cleos --verbose push action nestcontn2kv setov '[2, [1001,2001, 3001]]' -p alice@active + */ + [[eosio::action]] + void setov(int id, const optional& ov) + { + SETCONTAINERVAL(ov); + eosio::print("type defined optional > stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntov '[1]' -p bob@active + * output: >> stored optional vals: + * >> NULL or no value + * + * cleos --verbose push action nestcontn2kv prntov '[2]' -p alice@active + * output: >> stored optional vals: + * >> 1001 2001 3001 + */ + [[eosio::action]] + void prntov(int id) + { + const auto& psn = get(id); + eosio::print("stored optional vals:\n"); + if (psn.ov) + { + for (const auto& ele : psn.ov.value()) + eosio::print(ele, " "); + } + else + eosio::print("NULL or no value"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv setoo '[1, null]' -p bob@active + * + * cleos --verbose push action nestcontn2kv setoo '[2,123]' -p alice@active + */ + [[eosio::action]] + void setoo(int id, const optional& oo) + { + SETCONTAINERVAL(oo); + eosio::print("type defined optional stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntoo '[1]' -p bob@active + * ouput: >> stored optional> val:null or no real value stored + * + * cleos --verbose push action nestcontn2a prntoo '[2]' -p alice@active + * output: >> stored optional> val:123 + */ + [[eosio::action]] + void prntoo(int id) + { + const auto& psn = get(id); + eosio::print("stored optional> val:"); + if (psn.oo && psn.oo.value()) + eosio::print(psn.oo.value().value(),"\n"); + else + eosio::print("null or no real value stored"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv setom '[1,[{"first":10,"second":1000},{"first":11,"second":1001}] ]' -p alice@active + * + * cleos --verbose push action nestcontn2kv setom '[2, null ]' -p bob@active + */ + [[eosio::action]] + void setom(int id, const optional& om) + { + SETCONTAINERVAL(om); + eosio::print("type defined optional > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntom '[1]' -p alice@active + * output: >> size of stored om:2 vals:10:1000 11:1001 + * + * cleos --verbose push action nestcontn2kv prntom '[2]' -p bob@active + * output: >> optional has NULL value + */ + [[eosio::action]] + void prntom(int id) + { + const auto& psn = get(id); + if (psn.om) + { + auto mpval = psn.om.value(); + eosio::print("size of stored om:", mpval.size()," vals:"); + for (auto it2 = mpval.begin(); it2 != mpval.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + + } + else + eosio::print("optional has NULL value\n"); + } + + + /*Examples: + * cleos --verbose push action nestcontn2kv setop '[1, {"first":60, "second":61}]' -p alice@active + * + * cleos --verbose push action nestcontn2kv setop '[2, null]' -p bob@active + */ + [[eosio::action]] + void setop(int id, const optional & op) + { + SETCONTAINERVAL(op); + eosio::print("type-defined optional-pair optional stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntop '[1]' -p alice@active + * output: >> stored optional data:60 61 + * + * cleos --verbose push action nestcontn2kv prntop '[2]' -p bob@active + * output: >> optional has NULL value + */ + [[eosio::action]] + void prntop(int id) + { + const auto& psn = get(id); + if (psn.op) + eosio::print("stored optional data:", psn.op.value().first, " ", psn.op.value().second); + else + eosio::print("optional has NULL value\n"); + } + + //=== 4. Try map - set,vector,optional,map,pair + + /*Example: + * cleos --verbose push action nestcontn2kv setmst '[1, [{"key":1,"value":[10,11,12,16]}, {"key":2,"value":[200,300]} ]]' -p alice@active + */ + [[eosio::action]] + void setmst(int id, const map & mst) + { + SETCONTAINERVAL(mst); + eosio::print("type-defined map > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntmst '[1]' -p alice@active + * output: >> stored map: size=2 content: + * >> 1:vals 10 11 12 16 + * >> 2:vals 200 300 + */ + [[eosio::action]] + void prntmst(int id) + { + const auto& psn = get(id); + eosio::print("stored map: size=", psn.mst.size()," content:\n"); + for (auto it2 = psn.mst.begin(); it2 != psn.mst.end(); ++it2) + { + eosio::print(it2->first, ":", "vals "); + for (const auto& ele: it2->second) + { + eosio::print(ele," "); + } + eosio::print("\n"); + } + } + + + + /*Example: + * cleos --verbose push action nestcontn2kv setmv '[1, [{"key":1,"value":[10,11,12,16]}, {"key":2,"value":[200,300]} ]]' -p alice@active + */ + [[eosio::action]] + void setmv(int id, const map& mv) + { + SETCONTAINERVAL(mv); + eosio::print("type defined map > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntmv '[1]' -p alice@active + * output: >> stored map: size=2 content: + * >> 1:vals 10 11 12 16 + * >> 2:vals 200 300 + */ + [[eosio::action]] + void prntmv(int id) + { + const auto& psn = get(id); + eosio::print("stored map: size=", psn.mv.size()," content:\n"); + for (auto it2 = psn.mv.begin(); it2 != psn.mv.end(); ++it2) + { + eosio::print(it2->first, ":", "vals "); + for (const auto& ele: it2->second) + { + eosio::print(ele," "); + } + eosio::print("\n"); + } + } + + + /*Example: + * cleos --verbose push action nestcontn2kv setmo '[1, [{"key":10,"value":1000},{"key":11,"value":null}]]' -p alice@active + */ + [[eosio::action]] + void setmo(int id, const map& mo) + { + SETCONTAINERVAL(mo); + eosio::print("type defined map > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntmo '[1]' -p alice@active + * output: >> size of stored mo:2 vals + * >> 10:1000 11:NULL + */ + [[eosio::action]] + void prntmo(int id) + { + const auto& psn = get(id); + eosio::print("size of stored mo:", psn.mo.size()," vals\n"); + for (auto it2 = psn.mo.begin(); it2 != psn.mo.end(); ++it2) + { + eosio::print(it2->first, ":"); + if (it2->second) + eosio::print(it2->second.value()," "); + else + eosio::print("NULL "); + } + } + + /*Example: + * cleos push action nestcontn2kv setmm '[1, [{"key":10,"value":[{"first":200,"second":2000}, {"first":201,"second":2001}] }, {"key":11,"value":[{"first":300,"second":3000}, {"first":301,"second":3001}] } ]]' -p alice@active + * Attention: please note the cleos input of mm or map > is a combination of strings key/value and first/second ! + * i.e the "value" part of mm is an array of pairs! + */ + [[eosio::action]] + void setmm(int id, const map& mm) + { + SETCONTAINERVAL(mm); + eosio::print("type defined map > stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntmm '[1]' -p alice@active + * output: >> stored map val:size=2 vals are the following: + * >> 10---> + * >> 200:2000 + * >> 201:2001 + * >> 11---> + * >> 300:3000 + * >> 301:3001 + */ + [[eosio::action]] + void prntmm(int id) + { + const auto& psn = get(id); + eosio::print("stored map val:"); + eosio::print("size=", psn.mm.size()," vals are the following:\n"); + for (auto it2 = psn.mm.begin(); it2 != psn.mm.end(); ++it2) + { + eosio::print(it2->first,"--->\n"); + const auto& temp = it2->second; + for (auto it3 = temp.begin(); it3 != temp.end(); ++it3) + eosio::print("\t",it3->first, ":", it3->second, "\n"); + } + } + + /*Example: + * cleos --verbose push action nestcontn2kv setmp '[1, [{"key":36,"value":{"first":300, "second":301}}, {"key":37,"value":{"first":600, "second":601}} ]]' -p alice@active + */ + [[eosio::action]] + void setmp(int id, const map & mp) + { + SETCONTAINERVAL(mp); + eosio::print("type-defined map-pair map stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntmp '[1]' -p alice@active + * output: >> size of stored mp:2 vals: + * >> 36:300 301 + * >> 37:600 601 + */ + [[eosio::action]] + void prntmp(int id) + { + const auto& psn = get(id); + eosio::print("size of stored mp:", psn.mp.size()," vals:\n"); + for (auto it2 = psn.mp.begin(); it2 != psn.mp.end(); ++it2) + eosio::print(it2->first, ":", it2->second.first, " ", it2->second.second, "\n"); + } + + + //=== 5. Try pair - set,vector,optional,map,pair + + /*Example: + * cleos --verbose push action nestcontn2kv setpst '[1, {"first":20, "second":[200,201,202]}]' -p alice@active + */ + [[eosio::action]] + void setpst(int id, const pair& pst) + { + SETCONTAINERVAL(pst); + eosio::print("type-defined pair-set pair stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntpst '[1]' -p alice@active + * output: >> content of stored pair: first=20 + * >> second=200 201 202 + */ + [[eosio::action]] + void prntpst(int id) + { + const auto& psn = get(id); + eosio::print("content of stored pair: first=", psn.pst.first, "\nsecond="); + for (const auto& ele: psn.pst.second) + eosio::print(ele, " "); + } + + /*Example: + * cleos --verbose push action nestcontn2kv setpv '[1, {"first":10, "second":[100,101,102]}]' -p alice@active + */ + [[eosio::action]] + void setpv(int id, const pair& pv) + { + SETCONTAINERVAL(pv); + eosio::print("type-defined pair-vector pair stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntpv '[1]' -p alice@active + * output: >> content of stored pair: first=10 + * >> second=100 101 102 + */ + [[eosio::action]] + void prntpv(int id) + { + const auto& psn = get(id); + eosio::print("content of stored pair: first=", psn.pv.first, "\nsecond="); + for (const auto& ele: psn.pv.second) + eosio::print(ele, " "); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv setpo '[1, {"first":70, "second":71}]' -p alice@active + * + * cleos --verbose push action nestcontn2kv setpo '[2, {"first":70, "second":null}]' -p bob@active + */ + [[eosio::action]] + void setpo(int id, const pair & po) + { + SETCONTAINERVAL(po); + eosio::print("type-defined pair-optional pair stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntpo '[1]' -p alice@active + * output: >> content of stored pair: first=70 + * >> second=71 + * + * cleos --verbose push action nestcontn2a prntpo '[2]' -p bob@active + * output: >> content of stored pair: first=70 + * >> second=NULL + */ + [[eosio::action]] + void prntpo(int id) + { + const auto& psn = get(id); + eosio::print("content of stored pair: first=", psn.po.first, "\nsecond="); + if (psn.po.second) + eosio::print(psn.po.second.value(), " "); + else + eosio::print("NULL "); + } + + /*Example: + * cleos --verbose push action nestcontn2kv setpm '[1, {"key":6, "value":[{"first":20,"second":300}, {"first":21,"second":301}] }]' -p alice@active + * Remark: the data input for pm uses a combination of key/vale and first/second + */ + [[eosio::action]] + void setpm(int id, const pair & pm) + { + SETCONTAINERVAL(pm); + eosio::print("type-defined pair-map pair stored successfully!"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntpm '[1]' -p alice@active + * output: >> content of stored pair: first=6 + * >> second=20:300 21:301 + */ + [[eosio::action]] + void prntpm(int id) + { + const auto& psn = get(id); + eosio::print("content of stored pair: first=", psn.pm.first, "\nsecond="); + for (auto it2 = psn.pm.second.begin(); it2 != psn.pm.second.end(); ++it2) + eosio::print(it2->first, ":", it2->second, " "); + } + + + /*Example: + * cleos --verbose push action nestcontn2kv setpp '[1, {"key":30, "value":{"first":301, "second":302} }]' -p alice@active + * Remark: input data for pp or pair-pair is a combination of key/value and first/second + */ + [[eosio::action]] + void setpp(int id, const pair & pp) + { + SETCONTAINERVAL(pp); + eosio::print("type-defined pair-pair pair stored successfully!"); + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntpp '[1]' -p alice@active + * output: >> content of stored pair: first=30 + * >> second=301 302 + */ + [[eosio::action]] + void prntpp(int id) + { + const auto& psn = get(id); + eosio::print("content of stored pair: first=", psn.pp.first, "\nsecond="); + eosio::print(psn.pp.second.first, " ", psn.pp.second.second); + } + + + //Try an example of 3-layer nested container + + /*Example: + * cleos --verbose push action nestcontn2kv setovv '[1, [[21,22],[230], [240,250,260,280]]]' -p alice@active + */ + [[eosio::action]] + void setovv(int id, const optional& ovv) + { + // try type-defined 3-layer nested container optional > > here + SETCONTAINERVAL(ovv); + eosio::print("type-defined optional stored successfully!"); + + } + + /*Example: + * cleos --verbose push action nestcontn2kv prntovv '[1]' -p alice@active + * output: >> stored optional > > vals: + * >> 21 22 + * >> 230 + * >> 240 250 260 280 + */ + [[eosio::action]] + void prntovv(int id) + { + const auto& psn = get(id); + eosio::print("stored optional > > vals:\n"); + if (psn.ovv) + { + auto v2 = psn.ovv.value(); + for (int i=0 ; i < v2.size(); i++) + { + for (int j=0; j < v2[i].size(); j++) + eosio::print(v2[i][j], " "); + eosio::print("\n"); + } + } + else + eosio::print("stored optional > > has null value!"); + } + + //Example: cleos --verbose push action nestcontn2kv erase '["bob", 2]' -p bob@active + [[eosio::action]] + void erase(name user, int id) + { + require_auth(user); + eosio::print (user, " is requesting to erase the record with key=", id, "\n"); + auto iter = mymap.find(id); + check(iter != mymap.end(), "cannot erase: Record with given id does not exist"); + mymap.erase(id); + eosio::print("record with id=", id, " is successfully erased!"); + } + + //Example: cleos --verbose push action nestcontn2kv prntallkeys '["bob"]' -p bob@active + [[eosio::action]] + void prntallkeys(name user) + { + //print all keys stored in this block chain for this contract + require_auth(user); + eosio::print (user, " is requesting prntallkeys\n"); + if (mymap.empty()) + eosio::print ("mymap is empty, no key in mymap!"); + + eosio::print("mymap keys include:\n"); + for ( const auto& item : mymap ) + { + eosio::print(item.first(), "\n"); + } + } + + //Example: cleos --verbose push action nestcontn2kv get2 '["str1"]' -p alice@active + [[eosio::action]] + person2kv get2(string id) + { + auto iter = mymap2.find(id); + check(iter != mymap2.end(), "Record does not exist"); + const auto& item_found = iter->second(); + return item_found; + } + + /*Examples: + * cleos --verbose push action nestcontn2kv setv2 '["str1",[102,202,302,602]]' -p alice@active + * cleos --verbose push action nestcontn2kv setv2 '["str2", []]' -p bob@active + */ + [[eosio::action]] + void setv2(string id, const vector& v) + { + SETCONTAINERVALN(2, v); + eosio::print("vector stored successfully"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntv2 '["str1"]' -p alice@active + * output: >> size of stored v:4 vals:102,202,302,602, + * + * cleos --verbose push action nestcontn2kv prntv2 '["str2"]' -p bob@active + * output: >> size of stored v:0 vals: + */ + [[eosio::action]] + void prntv2(string id) + { + const auto& psn = get2(id); + eosio::print("size of stored v:", psn.v.size()," vals:"); + for (const auto & ele : psn.v) + eosio::print(ele, ","); + } + + + //Example: cleos --verbose push action nestcontn2kv get3 '["name1"]' -p alice@active + [[eosio::action]] + person2kv get3(name id) + { + auto iter = mymap3.find(id); + check(iter != mymap3.end(), "Record does not exist"); + const auto& item_found = iter->second(); + return item_found; + } + + /*Examples: + * cleos --verbose push action nestcontn2kv setv3 '["name1",[103,203,303,603]]' -p alice@active + * cleos --verbose push action nestcontn2kv setv3 '["name2", []]' -p bob@active + */ + [[eosio::action]] + void setv3(name id, const vector& v) + { + SETCONTAINERVALN(3, v); + eosio::print("vector stored successfully"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntv3 '["name1"]' -p alice@active + * output: >> size of stored v:4 vals:103,203,303,603, + * + * cleos --verbose push action nestcontn2kv prntv3 '["name2"]' -p bob@active + * output: >> size of stored v:0 vals: + */ + [[eosio::action]] + void prntv3(name id) + { + const auto& psn = get3(id); + eosio::print("size of stored v:", psn.v.size()," vals:"); + for (const auto & ele : psn.v) + eosio::print(ele, ","); + } + + + //Example: cleos --verbose push action nestcontn2kv get4 '[{"_count":18, "_strID":"dumstr"}]' -p alice@active + [[eosio::action]] + person2kv get4(mystructrefl id) + { + auto iter = mymap4.find(id); + check(iter != mymap4.end(), "Record does not exist"); + const auto& item_found = iter->second(); + return item_found; + } + + /*Examples: + * cleos --verbose push action nestcontn2kv setv4 '[{"_count":18, "_strID":"dumstr"},[104,204,304,604]]' -p alice@active + * cleos --verbose push action nestcontn2kv setv4 '[{"_count":11, "_strID":"dumstr1"}, []]' -p bob@active + */ + [[eosio::action]] + void setv4(mystructrefl id, const vector& v) + { + SETCONTAINERVALN(4, v); + eosio::print("vector stored successfully"); + } + + /*Examples: + * cleos --verbose push action nestcontn2kv prntv4 '[{"_count":18, "_strID":"dumstr"}]' -p alice@active + * output: >> size of stored v:4 vals:104,204,304,604, + * + * cleos --verbose push action nestcontn2kv prntv4 '[{"_count":11, "_strID":"dumstr1"}]' -p bob@active + * output: >> size of stored v:0 vals: + */ + [[eosio::action]] + void prntv4(mystructrefl id) + { + const auto& psn = get4(id); + eosio::print("size of stored v:", psn.v.size()," vals:"); + for (const auto & ele : psn.v) + eosio::print(ele, ","); + } + + //The following are needed for eosio-cpp compiler to identify the actions in genearted .abi + using get_action = eosio::action_wrapper<"get"_n, &nestcontn2kv::get>; + using erase_action = eosio::action_wrapper<"erase"_n, &nestcontn2kv::erase>; + using prntallkeys_action = eosio::action_wrapper<"prntallkeys"_n, &nestcontn2kv::prntallkeys>; + + using setv_action = eosio::action_wrapper<"setv"_n, &nestcontn2kv::setv>; + using prntv_action = eosio::action_wrapper<"prntv"_n, &nestcontn2kv::prntv>; + using setst_action = eosio::action_wrapper<"setst"_n, &nestcontn2kv::setst>; + using prntst_action = eosio::action_wrapper<"prntst"_n, &nestcontn2kv::prntst>; + using setm_action = eosio::action_wrapper<"setm"_n, &nestcontn2kv::setm>; + using prntm_action = eosio::action_wrapper<"prntm"_n, &nestcontn2kv::prntm>; + using sets_action = eosio::action_wrapper<"sets"_n, &nestcontn2kv::sets>; + using prnts_action = eosio::action_wrapper<"prnts"_n, &nestcontn2kv::prnts>; + using sets2_action = eosio::action_wrapper<"sets2"_n, &nestcontn2kv::sets2>; + using prnts2_action = eosio::action_wrapper<"prnts2"_n, &nestcontn2kv::prnts2>; + using setvs_action = eosio::action_wrapper<"setvs"_n, &nestcontn2kv::setvs>; + using prntvs_action = eosio::action_wrapper<"prntvs"_n, &nestcontn2kv::prntvs>; + using seto_action = eosio::action_wrapper<"seto"_n, &nestcontn2kv::seto>; + using prnto_action = eosio::action_wrapper<"prnto"_n, &nestcontn2kv::prnto>; + using setp_action = eosio::action_wrapper<"setp"_n, &nestcontn2kv::setp>; + using prntp_action = eosio::action_wrapper<"prntp"_n, &nestcontn2kv::prntp>; + + using setstst_action = eosio::action_wrapper<"setstst"_n, &nestcontn2kv::setstst>; + using prntstst_action = eosio::action_wrapper<"prntstst"_n, &nestcontn2kv::prntstst>; + using setstv_action = eosio::action_wrapper<"setstv"_n, &nestcontn2kv::setstv>; + using prntstv_action = eosio::action_wrapper<"prntstv"_n, &nestcontn2kv::prntstv>; + using setsto_action = eosio::action_wrapper<"setsto"_n, &nestcontn2kv::setsto>; + using prntsto_action = eosio::action_wrapper<"prntsto"_n, &nestcontn2kv::prntsto>; + using setstm_action = eosio::action_wrapper<"setstm"_n, &nestcontn2kv::setstm>; + using prntstm_action = eosio::action_wrapper<"prntstm"_n, &nestcontn2kv::prntstm>; + using setstp_action = eosio::action_wrapper<"setstp"_n, &nestcontn2kv::setstp>; + using prntstp_action = eosio::action_wrapper<"prntstp"_n, &nestcontn2kv::prntstp>; + + using setvst_action = eosio::action_wrapper<"setvst"_n, &nestcontn2kv::setvst>; + using prntvst_action = eosio::action_wrapper<"prntvst"_n, &nestcontn2kv::prntvst>; + using setvv_action = eosio::action_wrapper<"setvv"_n, &nestcontn2kv::setvv>; + using prntvv_action = eosio::action_wrapper<"prntvv"_n, &nestcontn2kv::prntvv>; + using setvo_action = eosio::action_wrapper<"setvo"_n, &nestcontn2kv::setvo>; + using prntvo_action = eosio::action_wrapper<"prntvo"_n, &nestcontn2kv::prntvo>; + using setvm_action = eosio::action_wrapper<"setvm"_n, &nestcontn2kv::setvm>; + using prntvm_action = eosio::action_wrapper<"prntvm"_n, &nestcontn2kv::prntvm>; + using setvp_action = eosio::action_wrapper<"setvp"_n, &nestcontn2kv::setvp>; + using prntvp_action = eosio::action_wrapper<"prntvp"_n, &nestcontn2kv::prntvp>; + + using setost_action = eosio::action_wrapper<"setost"_n, &nestcontn2kv::setost>; + using prntost_action = eosio::action_wrapper<"prntost"_n, &nestcontn2kv::prntost>; + using setov_action = eosio::action_wrapper<"setov"_n, &nestcontn2kv::setov>; + using prntov_action = eosio::action_wrapper<"prntov"_n, &nestcontn2kv::prntov>; + using setoo_action = eosio::action_wrapper<"setoo"_n, &nestcontn2kv::setoo>; + using prntoo_action = eosio::action_wrapper<"prntoo"_n, &nestcontn2kv::prntoo>; + using setom_action = eosio::action_wrapper<"setom"_n, &nestcontn2kv::setom>; + using prntom_action = eosio::action_wrapper<"prntom"_n, &nestcontn2kv::prntom>; + using setop_action = eosio::action_wrapper<"setop"_n, &nestcontn2kv::setop>; + using prntop_action = eosio::action_wrapper<"prntop"_n, &nestcontn2kv::prntop>; + + using setmst_action = eosio::action_wrapper<"setmst"_n, &nestcontn2kv::setmst>; + using prntmst_action = eosio::action_wrapper<"prntmst"_n, &nestcontn2kv::prntmst>; + using setmv_action = eosio::action_wrapper<"setmv"_n, &nestcontn2kv::setmv>; + using prntmv_action = eosio::action_wrapper<"prntmv"_n, &nestcontn2kv::prntmv>; + using setmo_action = eosio::action_wrapper<"setmo"_n, &nestcontn2kv::setmo>; + using prntmo_action = eosio::action_wrapper<"prntmo"_n, &nestcontn2kv::prntmo>; + using setmm_action = eosio::action_wrapper<"setmm"_n, &nestcontn2kv::setmm>; + using prntmm_action = eosio::action_wrapper<"prntmm"_n, &nestcontn2kv::prntmm>; + using setmp_action = eosio::action_wrapper<"setmp"_n, &nestcontn2kv::setmp>; + using prntmp_action = eosio::action_wrapper<"prntmp"_n, &nestcontn2kv::prntmp>; + + using setpst_action = eosio::action_wrapper<"setpst"_n, &nestcontn2kv::setpst>; + using prntpst_action = eosio::action_wrapper<"prntpst"_n, &nestcontn2kv::prntpst>; + using setpv_action = eosio::action_wrapper<"setpv"_n, &nestcontn2kv::setpv>; + using prntpv_action = eosio::action_wrapper<"prntpv"_n, &nestcontn2kv::prntpv>; + using setpo_action = eosio::action_wrapper<"setpo"_n, &nestcontn2kv::setpo>; + using prntpo_action = eosio::action_wrapper<"prntpo"_n, &nestcontn2kv::prntpo>; + using setpm_action = eosio::action_wrapper<"setpm"_n, &nestcontn2kv::setpm>; + using prntpm_action = eosio::action_wrapper<"prntpm"_n, &nestcontn2kv::prntpm>; + using setpp_action = eosio::action_wrapper<"setpp"_n, &nestcontn2kv::setpp>; + using prntpp_action = eosio::action_wrapper<"prntpp"_n, &nestcontn2kv::prntpp>; + + using setovv_action = eosio::action_wrapper<"setovv"_n, &nestcontn2kv::setovv>; + using prntovv_action = eosio::action_wrapper<"prntovv"_n, &nestcontn2kv::prntovv>; + + using get2_action = eosio::action_wrapper<"get2"_n, &nestcontn2kv::get2>; + using setv2_action = eosio::action_wrapper<"setv2"_n, &nestcontn2kv::setv2>; + using prntv2_action = eosio::action_wrapper<"prntv2"_n, &nestcontn2kv::prntv2>; + + using get3_action = eosio::action_wrapper<"get3"_n, &nestcontn2kv::get3>; + using setv3_action = eosio::action_wrapper<"setv3"_n, &nestcontn2kv::setv3>; + using prntv3_action = eosio::action_wrapper<"prntv3"_n, &nestcontn2kv::prntv3>; + + using get4_action = eosio::action_wrapper<"get4"_n, &nestcontn2kv::get4>; + using setv4_action = eosio::action_wrapper<"setv4"_n, &nestcontn2kv::setv4>; + using prntv4_action = eosio::action_wrapper<"prntv4"_n, &nestcontn2kv::prntv4>; +}; + diff --git a/tests/toolchain/build-pass/nestcontn2kv.json b/tests/toolchain/build-pass/nestcontn2kv.json new file mode 100644 index 0000000000..b3598b0cf4 --- /dev/null +++ b/tests/toolchain/build-pass/nestcontn2kv.json @@ -0,0 +1,10 @@ +{ + "tests": [ + { + "expected": { + "exit-code": 0 + } + } + ] +} + diff --git a/tests/toolchain/build-pass/tupletest.cpp b/tests/toolchain/build-pass/tupletest.cpp new file mode 100644 index 0000000000..500e4e8354 --- /dev/null +++ b/tests/toolchain/build-pass/tupletest.cpp @@ -0,0 +1,518 @@ +/* Verify the support of nested containers involving std::tuple in eosio multi-index table + * This tupletest.cpp can be regarded as a continuation of ../nestcontn2a.cpp + * For each action, an example regarding how to use the action with the cleos command line is given. + * + * Important Remarks: + * 1) The input of a std::tuple via cleos uses [ele0, ele1, ele2], it is the same as the input of a vector/set + * 2) However the input formats of settm,settp are different from those of corresponding setvm, setvp in nestcontn2a.cpp + * 3) More importantly, vector > and set > are NOT yet supported as shown in nestcontn2a.cpp, + * BUT tuple of optional is supported as shown here in this tupletest.cpp + * + * Expected printout: + * For each setx action, the printed result on the cleos console is given in its corresponding prntx action. + */ + +#include + +#include +#include +#include +#include +#include + +using namespace eosio; +using namespace std; + +#define SETCONTAINERVAL(x) do { \ + require_auth(user); \ + psninfoindex2 tblIndex(get_self(), get_first_receiver().value); \ + auto iter = tblIndex.find(user.value); \ + if (iter == tblIndex.end()) \ + { \ + tblIndex.emplace(user, [&](auto &row) { \ + row.key = user; \ + row.x = x; \ + }); \ + } \ + else \ + { \ + tblIndex.modify(iter, user, [&]( auto& row ) { \ + row.x = x; \ + }); \ + } \ + }while(0) + +#define PRNTCHECK() require_auth(user); \ + psninfoindex2 tblIndex(get_self(), get_first_receiver().value); \ + auto iter = tblIndex.find(user.value); \ + check(iter != tblIndex.end(), "Record does not exist"); + + +// use typedefs to make multi-layer nested containers work! +typedef vector vec_uint16; +typedef set set_uint16; +typedef optional op_uint16; +typedef map mp_uint16; +typedef pair pr_uint16; + +typedef tuple tup_uint16; + +class [[eosio::contract("tupletest")]] tupletest : public eosio::contract { + private: + struct [[eosio::table]] person2 { + name key; + + // Each container/object is represented by one letter: v-vector, m-map, s-mystruct,o-optional, p-pair, t - tuple + // with exceptions: s2 - mystruct2, st - set + + tuple t; + + //Two-layer nested-container involving tuple + vector vt; + set stt; + optional ot; + map mt; + pair pt; + tuple tt; + + tuple tv; //tuple of vectors + tuple tst; + tuple to; + tuple tm; + tuple tp; //tuple of pairs + + tuple tmisc; //tuple of misc. types + + + + uint64_t primary_key() const { return key.value; } + }; + using psninfoindex2 = eosio::multi_index<"people2"_n, person2>; + + + public: + using contract::contract; + + tupletest(name receiver, name code, datastream ds): contract(receiver, code, ds) {} + + /*Examples: + * cleos --verbose push action tupletest sett '["alice", [100,"strA"]]' -p alice@active + * cleos --verbose push action tupletest sett '["bob", [200, "strB"]]' -p bob@active + */ + [[eosio::action]] + void sett(name user, const tuple& t) + { + SETCONTAINERVAL(t); + eosio::print("tuple stored successfully"); + } + + /*Examples: + * cleos --verbose push action tupletest prntt '["alice"]' -p alice@active + * output: >> elements of stored tuple t:100, strA + * + * cleos --verbose push action tupletest prntt '["bob"]' -p bob@active + * output: >> elements of stored tuple t:200, strB + */ + [[eosio::action]] + void prntt(name user) + { + PRNTCHECK(); + eosio::print("elements of stored tuple t:", std::get<0>(iter->t), ", ", std::get<1>(iter->t)); + } + + //=== 1. Try other containers (vector,set,optional,map,pair,tuple) of tuples + + //Example: cleos --verbose push action tupletest setvt '["alice", [[10,20],[30,60], [80,90]]]' -p alice@active + [[eosio::action]] + void setvt(name user, const vector& vt) + { + SETCONTAINERVAL(vt); + eosio::print("type defined vector or vector stored successfully!"); + + } + + /*Example: + * cleos --verbose push action tupletest prntvt '["alice"]' -p alice@active + * output: >> stored vector vals: + * >> 10 20 + * >> 30 60 + * >> 80 90 + */ + [[eosio::action]] + void prntvt(name user) + { + + PRNTCHECK(); + eosio::print("stored vector vals:\n"); + for (int i=0 ; i < iter->vt.size(); i++) + { + eosio::print(std::get<0>(iter->vt[i]), " ", std::get<1>(iter->vt[i])); + eosio::print("\n"); + } + } + + //Example: cleos --verbose push action tupletest setstt '["alice", [[1,2],[3,6], [8,9]]]' -p alice@active + [[eosio::action]] + void setstt(name user, const set & stt) + { + SETCONTAINERVAL(stt); + eosio::print("type defined set or set stored successfully!"); + + } + + /*Example: + * cleos --verbose push action tupletest prntstt '["alice"]' -p alice@active + * output: >> stored set vals: + * >> 1 2 + * >> 3 6 + * >> 8 9 + */ + [[eosio::action]] + void prntstt(name user) + { + + PRNTCHECK(); + eosio::print("stored set vals:\n"); + for (auto it1=iter->stt.begin(); it1!= iter->stt.end(); it1++) + { + eosio::print(std::get<0>(*it1), " ", std::get<1>(*it1)); + eosio::print("\n"); + } + } + + + /*Examples: + * cleos --verbose push action tupletest setot '["bob", null]' -p bob@active + * + * cleos --verbose push action tupletest setot '["alice", [1001,2001]]' -p alice@active + */ + [[eosio::action]] + void setot(name user, const optional & ot) + { + SETCONTAINERVAL(ot); + eosio::print("type defined optional > stored successfully!"); + } + + /*Examples: + * cleos --verbose push action tupletest prntot '["bob"]' -p bob@active + * output: >> stored optional vals: + * >> NULL or no value + * + * cleos --verbose push action tupletest prntot '["alice"]' -p alice@active + * output: >> stored optional vals: + * >> 1001 2001 + */ + [[eosio::action]] + void prntot(name user) + { + PRNTCHECK(); + eosio::print("stored optional vals:\n"); + if (iter->ot) + { + eosio::print(std::get<0>(iter->ot.value()), " ", std::get<1>(iter->ot.value())); + } + else + eosio::print("NULL or no value"); + } + + + + /*Example: + * cleos --verbose push action tupletest setmt '["alice", [{"key":1,"value":[10,11]}, {"key":2,"value":[200,300]} ]]' -p alice@active + */ + [[eosio::action]] + void setmt(name user, const map & mt) + { + SETCONTAINERVAL(mt); + eosio::print("type defined map > stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletest prntmt '["alice"]' -p alice@active + * output: >> stored map: size=2 content: + * >> 1:vals 10 11 + * >> 2:vals 200 300 + */ + [[eosio::action]] + void prntmt(name user) + { + PRNTCHECK(); + eosio::print("stored map: size=", iter->mt.size()," content:\n"); + for (auto it2 = iter->mt.begin(); it2 != iter->mt.end(); ++it2) + { + eosio::print(it2->first, ":", "vals "); + eosio::print(std::get<0>(it2->second), " ", std::get<1>(it2->second)); + eosio::print("\n"); + } + } + + /*Example: + * cleos --verbose push action tupletest setpt '["alice", {"first":10, "second":[100,101]}]' -p alice@active + */ + [[eosio::action]] + void setpt(name user, const pair& pt) + { + SETCONTAINERVAL(pt); + eosio::print("type-defined pair-tuple pair stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletest prntpt '["alice"]' -p alice@active + * output: >> content of stored pair: first=10 + * >> second=100 101 + */ + [[eosio::action]] + void prntpt(name user) + { + PRNTCHECK(); + eosio::print("content of stored pair: first=", iter->pt.first, "\nsecond="); + eosio::print(std::get<0>(iter->pt.second), " ", std::get<1>(iter->pt.second)); + } + + //Example: cleos --verbose push action tupletest settt '["alice", [[1,2],[30,40], [50,60]]]' -p alice@active + [[eosio::action]] + void settt(name user, const tuple& tt) + { + SETCONTAINERVAL(tt); + eosio::print("type defined tuple > stored successfully!"); + + } + + /*Example: + * cleos --verbose push action tupletest prnttt '["alice"]' -p alice@active + * output: >> stored tuple vals: + * >> 1 2 + * >> 30 40 + * >> 50 60 + */ + [[eosio::action]] + void prnttt(name user) + { + + PRNTCHECK(); + eosio::print("stored tuple vals:\n"); + const auto& ele0 = std::get<0>(iter->tt); + const auto& ele1 = std::get<1>(iter->tt); + const auto& ele2 = std::get<2>(iter->tt); + + eosio::print(std::get<0>(ele0), " ", std::get<1>(ele0), "\n"); + eosio::print(std::get<0>(ele1), " ", std::get<1>(ele1), "\n"); + eosio::print(std::get<0>(ele2), " ", std::get<1>(ele2), "\n"); + } + + //=== 2. Try tuple of other containers (vector,set,optional,map,pair) + + //Example: cleos --verbose push action tupletest settv '["alice", [16,[26,36], [46,506,606]]]' -p alice@active + [[eosio::action]] + void settv(name user, const tuple& tv) + { + SETCONTAINERVAL(tv); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletest prnttv '["alice"]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: 16 + * >> ele1: 26 36 + * >> ele2: 46 506 606 + */ + [[eosio::action]] + void prnttv(name user) + { + + PRNTCHECK(); + + eosio::print("stored tuple vals:\n"); + + auto printVec = [](vec_uint16 v) {//eosio-cpp compiler allows c++11 usage such as lambda + for (int i=0; i < v.size();i++) + eosio::print(v[i]," "); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(iter->tv),"\n"); + eosio::print("ele1: "); printVec(std::get<1>(iter->tv)); + eosio::print("ele2: "); printVec(std::get<2>(iter->tv)); + } + + //Example: cleos --verbose push action tupletest settst '["alice", [10,[21,31], [41,51,61]]]' -p alice@active + [[eosio::action]] + void settst(name user, const tuple& tst) + { + SETCONTAINERVAL(tst); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletest prnttst '["alice"]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: 10 + * >> ele1: 21 31 + * >> ele2: 41 51 61 + */ + [[eosio::action]] + void prnttst(name user) + { + + PRNTCHECK(); + + eosio::print("stored tuple vals:\n"); + + auto printSet = [](set_uint16 s) { + for (auto it = s.begin(); it !=s.end(); it++ ) + eosio::print(*it, " "); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(iter->tst),"\n"); + eosio::print("ele1: "); printSet(std::get<1>(iter->tst)); + eosio::print("ele2: "); printSet(std::get<2>(iter->tst)); + } + + /*Examples: + * cleos --verbose push action tupletest setto '["alice", [100, null, 200, null, 300]]' -p alice@active + * + * cleos --verbose push action tupletest setto '["bob", [null, null, 10, null, 20]]' -p bob@active + * Remark: Yes, tuple of optionals is supported here ! + */ + [[eosio::action]] + void setto(name user, const tuple & to) + { + SETCONTAINERVAL(to); + eosio::print("type defined tuple stored successfully!"); + } + + /*Examples: + * cleos --verbose push action tupletest prntto '["alice"]' -p alice@active + * output: >> stored tuple vals: + * >> 100 NULL 200 NULL 300 + * + * cleos --verbose push action tupletest prntto '["bob"]' -p bob@active + * output: >> stored tuple vals: + * >> NULL NULL 10 NULL 20 + */ + [[eosio::action]] + void prntto(name user) + { + PRNTCHECK(); + eosio::print("stored tuple vals:\n"); + auto printOptional = [](op_uint16 op) { + if (op) + eosio::print(op.value(), " "); + else + eosio::print("NULL", " "); + }; + + printOptional(std::get<0>(iter->to)); + printOptional(std::get<1>(iter->to)); + printOptional(std::get<2>(iter->to)); + printOptional(std::get<3>(iter->to)); + printOptional(std::get<4>(iter->to)); + eosio::print("\n"); + } + + + //Example: cleos --verbose push action tupletest settm '["alice", [126, [{"key":10,"value":100},{"key":11,"value":101}], [{"key":80,"value":800},{"key":81,"value":9009}] ]]' -p alice@active + // ******Note: The input format of settm is different from that of setvm in nestcontn2a.cpp! + [[eosio::action]] + void settm(name user, const tuple& tm) + { + SETCONTAINERVAL(tm); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletest prnttm '["alice"]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: 126 + * >> ele1: 10:100 11:101 + * >> ele2: 80:800 81:9009 + */ + [[eosio::action]] + void prnttm(name user) + { + + PRNTCHECK(); + + eosio::print("stored tuple vals:\n"); + + auto printMap = [](mp_uint16 m) { + for (auto it = m.begin(); it !=m.end(); it++ ) + eosio::print(it->first, ":", it->second, " "); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(iter->tm),"\n"); + eosio::print("ele1: "); printMap(std::get<1>(iter->tm)); + eosio::print("ele2: "); printMap(std::get<2>(iter->tm)); + } + + //Example: cleos --verbose push action tupletest settp '["alice", [127, {"key":18, "value":28}, {"key":19, "value":29}]]' -p alice@active + // ******Note: The input format of settp is different from that of setvp in nestcontn2a.cpp! + [[eosio::action]] + void settp(name user, const tuple& tp) + { + SETCONTAINERVAL(tp); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletest prnttp '["alice"]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: 127 + * >> ele1: 18:28 + * >> ele2: 19:29 + */ + [[eosio::action]] + void prnttp(name user) + { + + PRNTCHECK(); + + eosio::print("stored tuple vals:\n"); + + auto printPair = [](pr_uint16 p) { + eosio::print(p.first, ":", p.second); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(iter->tp),"\n"); + eosio::print("ele1: "); printPair(std::get<1>(iter->tp)); + eosio::print("ele2: "); printPair(std::get<2>(iter->tp)); + } + + //Example: cleos --verbose push action tupletest settmisc '["alice", ["strHere", [10,11,12,16], {"key":86,"value":96}] ]' -p alice@active + [[eosio::action]] + void settmisc(name user, const tuple & tmisc) + { + SETCONTAINERVAL(tmisc); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletest prnttmisc '["alice"]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: strHere + * >> ele1: 10 11 12 16 + * >> ele2: 86:96 + */ + [[eosio::action]] + void prnttmisc(name user) + { + + PRNTCHECK(); + + eosio::print("stored tuple vals:\n"); + + auto printVec = [](vec_uint16 v) { + for (int i=0; i < v.size();i++) + eosio::print(v[i]," "); + eosio::print("\n"); + }; + + auto printPair = [](pr_uint16 p) { + eosio::print(p.first, ":", p.second); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(iter->tmisc),"\n"); + eosio::print("ele1: "); printVec(std::get<1>(iter->tmisc)); + eosio::print("ele2: "); printPair(std::get<2>(iter->tmisc)); + } +}; \ No newline at end of file diff --git a/tests/toolchain/build-pass/tupletest.json b/tests/toolchain/build-pass/tupletest.json new file mode 100644 index 0000000000..b3598b0cf4 --- /dev/null +++ b/tests/toolchain/build-pass/tupletest.json @@ -0,0 +1,10 @@ +{ + "tests": [ + { + "expected": { + "exit-code": 0 + } + } + ] +} + diff --git a/tests/toolchain/build-pass/tupletestkv.cpp b/tests/toolchain/build-pass/tupletestkv.cpp new file mode 100644 index 0000000000..61ba22f451 --- /dev/null +++ b/tests/toolchain/build-pass/tupletestkv.cpp @@ -0,0 +1,530 @@ +/* Verify the support of nested containers involving std::tuple for the new Key-value table eosio::kv::map + * This tupletestkv.cpp can be regarded as a continuation of ../nestcontn2kv.cpp + * For each action, an example regarding how to use the action with the cleos command line is given. + * + * Important Remarks: + * 1) The input of a std::tuple via cleos uses [ele0, ele1, ele2], it is the same as the input of a vector/set + * 2) However the input formats of settm,settp are different from those of corresponding setvm, setvp in nestcontn2a.cpp + * 3) More importantly, vector > and set > are NOT yet supported as shown in nestcontn2a.cpp, + * BUT tuple of optional is supported as shown here in this tupletest.cpp + * + * Expected printout: + * For each setx action, the printed result on the cleos console is given in its corresponding prntx action. + */ + + +//--- You might need to verify some eosio-defined types such as eosio::asset can be the values of kv::map + +#include +#include + +#include +#include +#include +#include +#include + +using namespace eosio; +using namespace std; + + +#define SETCONTAINERVAL(x) do { \ + person2kv obj = mymap[id]; \ + obj.x = x; \ + mymap[id] = obj; \ + }while(0) + +// use typedefs to make multi-layer nested containers work! +typedef vector vec_uint16; +typedef set set_uint16; +typedef optional op_uint16; +typedef map mp_uint16; +typedef pair pr_uint16; + +typedef tuple tup_uint16; + + +struct person2kv { + // Each container/object is represented by one letter: v-vector, m-map, s-mystruct,o-optional, p-pair, t-tuple + // with exceptions: s2 - mystruct2, st - set + + tuple t; //---new code on verifying std::tuple + + //Two-layer nested-container involving tuple + vector vt; + set stt; + optional ot; + map mt; + pair pt; + tuple tt; + + tuple tv; //tuple of vectors + tuple tst; + tuple to; + tuple tm; + tuple tp; //tuple of pairs + + tuple tmisc; //tuple of misc. types +}; + + +class [[eosio::contract("tupletestkv")]] tupletestkv : public eosio::contract { + using my_map_t = eosio::kv::map<"people2kv"_n, int, person2kv>; + private: + my_map_t mymap{}; + + public: + using contract::contract; + + tupletestkv(name receiver, name code, datastream ds): contract(receiver, code, ds) {} + + + //Example: cleos --verbose push action nestcontn2kv get '[1]' -p alice@active + [[eosio::action]] + person2kv get(int id) + { + //This action will be used by all prntx actions to retrieve item_found for given id + auto iter = mymap.find(id); + check(iter != mymap.end(), "Record does not exist"); + const auto& item_found = iter->second(); + return item_found; + } + + /*Examples: + * cleos --verbose push action tupletestkv sett '[1,[100,"str1"]]' -p alice@active + */ + [[eosio::action]] + void sett(int id, const tuple& t) + { + SETCONTAINERVAL(t); + eosio::print("tuple stored successfully"); + } + + + /*Examples: + * cleos --verbose push action tupletestkv prntt '[1]' -p alice@active + * output: >> elements of stored tuple t:100, str1 + */ + [[eosio::action]] + void prntt(int id) + { + const auto& psn = get(id); + eosio::print("elements of stored tuple t:", std::get<0>(psn.t), ", ", std::get<1>(psn.t)); + } + + //=== 1. Try other containers (vector,set,optional,map,pair,tuple) of tuples + + //Example: cleos --verbose push action tupletestkv setvt '[1, [[10,20],[30,40], [50,60]]]' -p alice@active + [[eosio::action]] + void setvt(int id, const vector& vt) + { + SETCONTAINERVAL(vt); + eosio::print("type defined vector stored successfully!"); + + } + + /*Example: + * cleos --verbose push action tupletestkv prntvt '[1]' -p alice@active + * output: >> stored vector> vals: + * >> 10 20 + * >> 30 40 + * >> 50 60 + */ + [[eosio::action]] + void prntvt(int id) + { + const auto& psn = get(id); + eosio::print("stored vector> vals:\n"); + for (int i=0 ; i < psn.vt.size(); i++) + { + eosio::print(std::get<0>(psn.vt[i]), " ", std::get<1>(psn.vt[i])); + eosio::print("\n"); + } + } + + //Example: cleos --verbose push action tupletestkv setstt '[1, [[1,2],[36,46], [56,66]]]' -p alice@active + [[eosio::action]] + void setstt(int id, const set& stt) + { + SETCONTAINERVAL(stt); + eosio::print("type defined set stored successfully!"); + + } + + /*Example: + * cleos --verbose push action tupletestkv prntstt '[1]' -p alice@active + * output: >> stored set> vals: + * >> 1 2 + * >> 36 46 + * >> 56 66 + */ + [[eosio::action]] + void prntstt(int id) + { + const auto& psn = get(id); + eosio::print("stored set> vals:\n"); + for (auto it1=psn.stt.begin(); it1!= psn.stt.end(); it1++) + { + eosio::print(std::get<0>(*it1), " ", std::get<1>(*it1)); + eosio::print("\n"); + } + } + + /*Examples: + * cleos --verbose push action tupletestkv setot '[1, null]' -p bob@active + * + * cleos --verbose push action tupletestkv setot '[2, [1001,2001]]' -p alice@active + */ + [[eosio::action]] + void setot(int id, const optional& ot) + { + SETCONTAINERVAL(ot); + eosio::print("type defined optional stored successfully!"); + } + + /*Examples: + * cleos --verbose push action tupletestkv prntot '[1]' -p bob@active + * output: >> stored optional vals: + * >> NULL or no value + * + * cleos --verbose push action tupletestkv prntot '[2]' -p alice@active + * output: >> stored optional vals: + * >> 1001 2001 + */ + [[eosio::action]] + void prntot(int id) + { + const auto& psn = get(id); + eosio::print("stored optional vals:\n"); + if (psn.ot) + { + eosio::print(std::get<0>(psn.ot.value()), " ", std::get<1>(psn.ot.value())); + } + else + eosio::print("NULL or no value"); + } + + /*Example: + * cleos --verbose push action tupletestkv setmt '[1, [{"key":1,"value":[10,11]}, {"key":2,"value":[200,300]} ]]' -p alice@active + */ + [[eosio::action]] + void setmt(int id, const map& mt) + { + SETCONTAINERVAL(mt); + eosio::print("type defined map stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletestkv prntmt '[1]' -p alice@active + * output: >> stored map: size=2 content: + * >> 1:vals 10 11 + * >> 2:vals 200 300 + */ + [[eosio::action]] + void prntmt(int id) + { + const auto& psn = get(id); + eosio::print("stored map: size=", psn.mt.size()," content:\n"); + for (auto it2 = psn.mt.begin(); it2 != psn.mt.end(); ++it2) + { + eosio::print(it2->first, ":", "vals "); + eosio::print(std::get<0>(it2->second), " ", std::get<1>(it2->second)); + eosio::print("\n"); + } + } + + + + /*Example: + * cleos --verbose push action tupletestkv setpt '[1, {"first":10, "second":[100,101]}]' -p alice@active + */ + [[eosio::action]] + void setpt(int id, const pair& pt) + { + SETCONTAINERVAL(pt); + eosio::print("type defined pair stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletestkv prntpt '[1]' -p alice@active + * output: >> content of stored pair: first=10 + * >> second=100 101 + */ + [[eosio::action]] + void prntpt(int id) + { + const auto& psn = get(id); + + eosio::print("content of stored pair: first=", psn.pt.first, "\nsecond="); + eosio::print(std::get<0>(psn.pt.second), " ", std::get<1>(psn.pt.second)); + } + + //Example: cleos --verbose push action tupletestkv settt '[1, [[1,2],[30,40], [50,60]]]' -p alice@active + [[eosio::action]] + void settt(int id, const tuple& tt) + { + SETCONTAINERVAL(tt); + eosio::print("type defined tuple > stored successfully!"); + + } + + /*Example: + * cleos --verbose push action tupletestkv prnttt '[1]' -p alice@active + * output: >> stored tuple vals: + * >> 1 2 + * >> 30 40 + * >> 50 60 + */ + [[eosio::action]] + void prnttt(int id) + { + const auto& psn = get(id); + eosio::print("stored tuple vals:\n"); + const auto& ele0 = std::get<0>(psn.tt); + const auto& ele1 = std::get<1>(psn.tt); + const auto& ele2 = std::get<2>(psn.tt); + + eosio::print(std::get<0>(ele0), " ", std::get<1>(ele0), "\n"); + eosio::print(std::get<0>(ele1), " ", std::get<1>(ele1), "\n"); + eosio::print(std::get<0>(ele2), " ", std::get<1>(ele2), "\n"); + } + + //=== 2. Try tuple of other containers (vector,set,optional,map,pair) + + //Example: cleos --verbose push action tupletestkv settv '[1, [16,[26,36], [46,506,606]]]' -p alice@active + [[eosio::action]] + void settv(int id, const tuple& tv) + { + SETCONTAINERVAL(tv); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletestkv prnttv '[1]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: 16 + * >> ele1: 26 36 + * >> ele2: 46 506 606 + */ + [[eosio::action]] + void prnttv(int id) + { + const auto& psn = get(id); + eosio::print("stored tuple vals:\n"); + + auto printVec = [](vec_uint16 v) {//eosio-cpp compiler allows c++11 usage such as lambda + for (int i=0; i < v.size();i++) + eosio::print(v[i]," "); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(psn.tv),"\n"); + eosio::print("ele1: "); printVec(std::get<1>(psn.tv)); + eosio::print("ele2: "); printVec(std::get<2>(psn.tv)); + } + + //Example: cleos --verbose push action tupletestkv settst '[1, [10,[21,31], [41,51,61]]]' -p alice@active + [[eosio::action]] + void settst(int id, const tuple& tst) + { + SETCONTAINERVAL(tst); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletestkv prnttst '[1]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: 10 + * >> ele1: 21 31 + * >> ele2: 41 51 61 + */ + [[eosio::action]] + void prnttst(int id) + { + const auto& psn = get(id); + eosio::print("stored tuple vals:\n"); + + auto printSet = [](set_uint16 s) { + for (auto it = s.begin(); it !=s.end(); it++ ) + eosio::print(*it, " "); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(psn.tst),"\n"); + eosio::print("ele1: "); printSet(std::get<1>(psn.tst)); + eosio::print("ele2: "); printSet(std::get<2>(psn.tst)); + } + + /*Examples: + * cleos --verbose push action tupletestkv setto '[1, [100, null, 200, null, 300]]' -p alice@active + * + * cleos --verbose push action tupletestkv setto '[2, [null, null, 10, null, 20]]' -p bob@active + * Remark: Yes, tuple of optionals is supported here ! + */ + [[eosio::action]] + void setto(int id, const tuple & to) + { + SETCONTAINERVAL(to); + eosio::print("type defined tuple stored successfully!"); + } + + /*Examples: + * cleos --verbose push action tupletest prntto '[1]' -p alice@active + * output: >> stored tuple vals: + * >> 100 NULL 200 NULL 300 + * + * cleos --verbose push action tupletest prntto '[2]' -p bob@active + * output: >> stored tuple vals: + * >> NULL NULL 10 NULL 20 + */ + [[eosio::action]] + void prntto(int id) + { + const auto& psn = get(id); + eosio::print("stored tuple vals:\n"); + auto printOptional = [](op_uint16 op) { + if (op) + eosio::print(op.value(), " "); + else + eosio::print("NULL", " "); + }; + + printOptional(std::get<0>(psn.to)); + printOptional(std::get<1>(psn.to)); + printOptional(std::get<2>(psn.to)); + printOptional(std::get<3>(psn.to)); + printOptional(std::get<4>(psn.to)); + eosio::print("\n"); + } + + + //Example: cleos --verbose push action tupletestkv settm '[1, [126, [{"key":10,"value":100},{"key":11,"value":101}], [{"key":80,"value":800},{"key":81,"value":9009}] ]]' -p alice@active + // ******Note: The input format of settm is different from that of setvm in nestcontn2a.cpp! + [[eosio::action]] + void settm(int id, const tuple& tm) + { + SETCONTAINERVAL(tm); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletestkv prnttm '[1]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: 126 + * >> ele1: 10:100 11:101 + * >> ele2: 80:800 81:9009 + */ + [[eosio::action]] + void prnttm(int id) + { + const auto& psn = get(id); + eosio::print("stored tuple vals:\n"); + + auto printMap = [](mp_uint16 m) { + for (auto it = m.begin(); it !=m.end(); it++ ) + eosio::print(it->first, ":", it->second, " "); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(psn.tm),"\n"); + eosio::print("ele1: "); printMap(std::get<1>(psn.tm)); + eosio::print("ele2: "); printMap(std::get<2>(psn.tm)); + } + + //Example: cleos --verbose push action tupletestkv settp '[1, [127, {"key":18, "value":28}, {"key":19, "value":29}]]' -p alice@active + // ******Note: The input format of settp is different from that of setvp in nestcontn2a.cpp! + [[eosio::action]] + void settp(int id, const tuple& tp) + { + SETCONTAINERVAL(tp); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletestkv prnttp '[1]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: 127 + * >> ele1: 18:28 + * >> ele2: 19:29 + */ + [[eosio::action]] + void prnttp(int id) + { + const auto& psn = get(id); + eosio::print("stored tuple vals:\n"); + + auto printPair = [](pr_uint16 p) { + eosio::print(p.first, ":", p.second); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(psn.tp),"\n"); + eosio::print("ele1: "); printPair(std::get<1>(psn.tp)); + eosio::print("ele2: "); printPair(std::get<2>(psn.tp)); + } + + //Example: cleos --verbose push action tupletestkv settmisc '[1, ["strHere", [10,11,12,16], {"key":86,"value":96}] ]' -p alice@active + [[eosio::action]] + void settmisc(int id, const tuple & tmisc) + { + SETCONTAINERVAL(tmisc); + eosio::print("type defined tuple stored successfully!"); + } + + /*Example: + * cleos --verbose push action tupletestkv prnttmisc '[1]' -p alice@active + * output: >> stored tuple vals: + * >> ele0: strHere + * >> ele1: 10 11 12 16 + * >> ele2: 86:96 + */ + [[eosio::action]] + void prnttmisc(int id) + { + const auto& psn = get(id); + eosio::print("stored tuple vals:\n"); + + auto printVec = [](vec_uint16 v) { + for (int i=0; i < v.size();i++) + eosio::print(v[i]," "); + eosio::print("\n"); + }; + + auto printPair = [](pr_uint16 p) { + eosio::print(p.first, ":", p.second); + eosio::print("\n"); + }; + eosio::print("ele0: ", std::get<0>(psn.tmisc),"\n"); + eosio::print("ele1: "); printVec(std::get<1>(psn.tmisc)); + eosio::print("ele2: "); printPair(std::get<2>(psn.tmisc)); + } + + //The following are needed for eosio-cpp compiler to identify the actions in genearted .abi + using get_action = eosio::action_wrapper<"get"_n, &tupletestkv::get>; + + using sett_action = eosio::action_wrapper<"sett"_n, &tupletestkv::sett>; + using prntt_action = eosio::action_wrapper<"prntt"_n, &tupletestkv::prntt>; + using setvt_action = eosio::action_wrapper<"setvt"_n, &tupletestkv::setvt>; + using prntvt_action = eosio::action_wrapper<"prntvt"_n, &tupletestkv::prntvt>; + using setstt_action = eosio::action_wrapper<"setstt"_n, &tupletestkv::setstt>; + using prntstt_action = eosio::action_wrapper<"prntstt"_n, &tupletestkv::prntstt>; + using setot_action = eosio::action_wrapper<"setot"_n, &tupletestkv::setot>; + using prntot_action = eosio::action_wrapper<"prntot"_n, &tupletestkv::prntot>; + using setmt_action = eosio::action_wrapper<"setmt"_n, &tupletestkv::setmt>; + using prntmt_action = eosio::action_wrapper<"prntmt"_n, &tupletestkv::prntmt>; + using setpt_action = eosio::action_wrapper<"setpt"_n, &tupletestkv::setpt>; + using prntpt_action = eosio::action_wrapper<"prntpt"_n, &tupletestkv::prntpt>; + using settt_action = eosio::action_wrapper<"settt"_n, &tupletestkv::settt>; + using prnttt_action = eosio::action_wrapper<"prnttt"_n, &tupletestkv::prnttt>; + + using settv_action = eosio::action_wrapper<"settv"_n, &tupletestkv::settv>; + using prnttv_action = eosio::action_wrapper<"prnttv"_n, &tupletestkv::prnttv>; + using settst_action = eosio::action_wrapper<"settst"_n, &tupletestkv::settst>; + using prnttst_action = eosio::action_wrapper<"prnttst"_n, &tupletestkv::prnttst>; + using setto_action = eosio::action_wrapper<"setto"_n, &tupletestkv::setto>; + using prntto_action = eosio::action_wrapper<"prntto"_n, &tupletestkv::prntto>; + using settm_action = eosio::action_wrapper<"settm"_n, &tupletestkv::settm>; + using prnttm_action = eosio::action_wrapper<"prnttm"_n, &tupletestkv::prnttm>; + using settp_action = eosio::action_wrapper<"settp"_n, &tupletestkv::settp>; + using prnttp_action = eosio::action_wrapper<"prnttp"_n, &tupletestkv::prnttp>; + using settmisc_action = eosio::action_wrapper<"settmisc"_n, &tupletestkv::settmisc>; + using prnttmisc_action = eosio::action_wrapper<"prnttmisc"_n, &tupletestkv::prnttmisc>; +}; + + diff --git a/tests/toolchain/build-pass/tupletestkv.json b/tests/toolchain/build-pass/tupletestkv.json new file mode 100644 index 0000000000..b3598b0cf4 --- /dev/null +++ b/tests/toolchain/build-pass/tupletestkv.json @@ -0,0 +1,10 @@ +{ + "tests": [ + { + "expected": { + "exit-code": 0 + } + } + ] +} + diff --git a/tools/include/eosio/gen.hpp b/tools/include/eosio/gen.hpp index 99a92db65e..b82eee63dc 100644 --- a/tools/include/eosio/gen.hpp +++ b/tools/include/eosio/gen.hpp @@ -668,9 +668,13 @@ struct generation_utils { return t+"[]"; } } - else if (is_tuple(type)) { - return translate_type(get_nested_type(type)); - } + //The following else if (is_tuple(type)) block is removed, because it causes eosio-cpp compilation + //failure on any action that has std::tuple parameter, also the type eosio::non_unique this block + //was supposed to handle is obsolete now. + // + //else if (is_tuple(type)) { + // return translate_type(get_nested_type(type)); + //} else if ( is_template_specialization( type, {"optional"} ) ) return get_template_argument_as_string( type )+"?"; else if ( is_template_specialization( type, {"map"} )) { From a992a5bde87d35d4a9e4cea9c0de815d24789ff8 Mon Sep 17 00:00:00 2001 From: Chris Gundlach Date: Thu, 28 Jul 2022 11:26:28 -0500 Subject: [PATCH 09/12] GH-731 removed kv tests --- tests/toolchain/build-pass/nestcontn2kv.cpp | 1426 ------------------ tests/toolchain/build-pass/nestcontn2kv.json | 10 - 2 files changed, 1436 deletions(-) delete mode 100644 tests/toolchain/build-pass/nestcontn2kv.cpp delete mode 100644 tests/toolchain/build-pass/nestcontn2kv.json diff --git a/tests/toolchain/build-pass/nestcontn2kv.cpp b/tests/toolchain/build-pass/nestcontn2kv.cpp deleted file mode 100644 index eb62000703..0000000000 --- a/tests/toolchain/build-pass/nestcontn2kv.cpp +++ /dev/null @@ -1,1426 +0,0 @@ -/* Verify the support of nested containers for the new Key-value table eosio::kv::map - * For each action, an example regarding how to use the action with the cleos command line is given. - * - * std:pair is a struct with 2 fields first and second, - * std::map is handled as an array/vector of pairs/structs by EOSIO with implicit fields key, value, - * the cases of combined use of key/value and first/second involving map,pair in the cleos are documented here, - * so handling of std::pair is NOT the same as the handling of a general struct such as struct mystruct! - * - * When assigning data input with cleos: - * [] represents an empty vector/set or empty map where T, T1, T2 can be any composite types - * null represents an uninitialized std::optional where T can be any composite type - * BUT [] or null can NOT be used to represent an empty struct or empty std::pair - * - * Attention: - * 1) Please follow https://github.com/EOSIO/eos/tree/develop/contracts/enable-kv to enable key-value support of nodeos first - * 2) To get to the point right away, here authentication/permission checking is skipped for each action in this contract, - * however in practice, suitable permission checking such as require_auth(user) has to be used! - * - * Expected printout: - * For each setx action, the printed result on the cleos console is given in its corresponding prntx action. - */ - -#include -#include - -#include -#include -#include -#include -#include - -using namespace eosio; -using namespace std; - - -#define SETCONTAINERVAL(x) do { \ - person2kv obj = mymap[id]; \ - obj.x = x; \ - mymap[id] = obj; \ - }while(0) - -//when the keys of kv::map are of different types, the following sets values of mymap2, mymap3, mymap4 -#define SETCONTAINERVALN(num, x) do { \ - person2kv obj = mymap ## num[id]; \ - obj.x = x; \ - mymap ## num[id] = obj; \ - }while(0) - - -struct mystruct -{ - uint64_t _count; - string _strID; -}; - -//mystruct2 has embeded mystruct -struct mystruct2 -{ - mystruct _structfld; - string _strID2; -}; - -//mystructrefl has CDT_REFLECT wrapper over above mystruct, it is the key of following my_map_t4, -//if the key of an kv::map is a self-defined struct, the struct has to be self-reflective -struct mystructrefl -{ - uint64_t _count; - string _strID; - CDT_REFLECT(_count, _strID); -}; - -// use typedefs to make multi-layer nested containers work! -typedef vector vec_uint16; -typedef set set_uint16; -typedef optional op_uint16; -typedef map mp_uint16; -typedef pair pr_unit16; - -typedef vector vec_uint32; -typedef vector vecvec_uint32; - -//using dummy_kvmap = eosio::kv::map<"dumkv"_n, int, int>; - -struct person2kv { - // Each container/object is represented by one letter: v-vector, m-map, s-mystruct,o-optional, p-pair, - // with exceptions: s2 - mystruct2, st - set - - vector v; - map m; - mystruct s; - mystruct2 s2; - set st; - optional o; - pair p; - vector vs; - - //The following are 2-layer nested containers involving vector/optional/map - vector vv; - optional oo; - map mm; - set stst; - - vector vst; - set stv; - - vector vo; - optional ov; - set sto; - optional ost; - - vector vm; - map mv; - - set stm; - map mst; - - optional om; - map mo; - - //The following are composite types involving pair and containers - vector > vp; - pair pv; - - set > stp; - pair pst; - - optional op; - pair po; - - map mp; - pair pm; - - pair pp; - - //The following is a 3-layer nested containers for motivation - optional ovv; -}; - - -class [[eosio::contract("nestcontn2kv")]] nestcontn2kv : public eosio::contract { - using my_map_t = eosio::kv::map<"people2kv"_n, int, person2kv>; - - //The following kv::map have different key types: std::string, eosio::name, mystructrefl - using my_map_t2 = eosio::kv::map<"people2kv2"_n, string, person2kv>; - using my_map_t3 = eosio::kv::map<"people2kv3"_n, name, person2kv>; - using my_map_t4 = eosio::kv::map<"people2kv4"_n, mystructrefl, person2kv>; - - private: - my_map_t mymap{}; - my_map_t2 mymap2{}; - my_map_t3 mymap3{}; - my_map_t4 mymap4{}; - - public: - using contract::contract; - - nestcontn2kv(name receiver, name code, datastream ds): contract(receiver, code, ds) {} - - //[[eosio::action]] void settuple(name user, const tuple& tp) {} - //[[eosio::action]] void settuple(name user, const tuple& tp) {} - // eosio-cpp compile error for std::tuple: Tried to get a nested template type of a template not containing one - - //[[eosio::action]] void setdumkv(name user, const dummy_kvmap& tp) {} - // eosio-cpp compile error for above dummy_kvmap: Tried to get a non-existent template argument - - //Example: cleos --verbose push action nestcontn2kv get '[1]' -p alice@active - [[eosio::action]] - person2kv get(int id) - { - //This action will be used by all prntx actions to retrieve item_found for given id - auto iter = mymap.find(id); - check(iter != mymap.end(), "Record does not exist"); - const auto& item_found = iter->second(); - return item_found; - } - - /*Examples: - * cleos --verbose push action nestcontn2kv setv '[1,[100,200,300,600]]' -p alice@active - * cleos --verbose push action nestcontn2kv setv '[2, []]' -p bob@active - */ - [[eosio::action]] - void setv(int id, const vector& v) - { - SETCONTAINERVAL(v); - eosio::print("vector stored successfully"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntv '[1]' -p alice@active - * output: >> size of stored v:4 vals:100,200,300,600, - * - * cleos --verbose push action nestcontn2kv prntv '[2]' -p bob@active - * output: >> size of stored v:0 vals: - */ - [[eosio::action]] - void prntv(int id) - { - const auto& psn = get(id); - eosio::print("size of stored v:", psn.v.size()," vals:"); - for (const auto & ele : psn.v) - eosio::print(ele, ","); - } - - - /*Examples: - * cleos --verbose push action nestcontn2kv setst '[1, [101,201,301]]' -p alice@active - * cleos --verbose push action nestcontn2kv setst '[2, []]' -p bob@active - */ - [[eosio::action]] - void setst(int id, const set & st) - { - SETCONTAINERVAL(st); - eosio::print("set stored successfully"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntst '[1]' -p alice@active - * output: >> size of stored st:3 vals:101,201,301, - * - * cleos --verbose push action nestcontn2kv prntst '[2]' -p bob@active - * output: >> size of stored st:0 vals: - */ - [[eosio::action]] - void prntst(int id) - { - const auto& psn = get(id); - eosio::print("size of stored st:", psn.st.size()," vals:"); - for (const auto & ele : psn.st) - eosio::print(ele, ","); - - } - - /*Examples: - * To use shortcut notation: - * cleos --verbose push action nestcontn2kv setm '[1, [{"key":"str1","value":"str1val"}, {"key":"str3","value":"str3val"}]]' -p alice@active - * - * To use full JSON notation: - * cleos --verbose push action nestcontn2kv setm '{"id":2, "m":[{"key":"str4", "value":"str4val"}, {"key":"str6", "value":"str6val"}]}' -p jane@active - * - * To pass an empty map: - * cleos --verbose push action nestcontn2kv setm '[3, []]' -p bob@active - */ - [[eosio::action]] - void setm(int id, const map & m) - { - SETCONTAINERVAL(m); - eosio::print("map stored successfully"); - } - - /* Examples: - * cleos --verbose push action nestcontn2kv prntm '[1]' -p alice@active - * output: >> size of stored m:2 vals of m:str1:str1val str3:str3val - * - * cleos --verbose push action nestcontn2kv prntm '[2]' -p jane@active - * output: >> size of stored m:2 vals of m:str4:str4val str6:str6val - * - * cleos --verbose push action nestcontn2kv prntm '[3]' -p bob@active - * output: >> size of stored m:0 vals of m: - */ - [[eosio::action]] - void prntm(int id) - { - const auto& psn = get(id); - eosio::print("size of stored m:", psn.m.size()," vals of m:"); - for (auto it2 = psn.m.begin(); it2 != psn.m.end(); ++it2) - eosio::print(it2->first, ":", it2->second, " "); - - } - - //Example: cleos --verbose push action nestcontn2kv sets '[1, {"_count":18, "_strID":"dumstr"}]' -p alice@active - [[eosio::action]] - void sets(int id, const mystruct& s) - { - SETCONTAINERVAL(s); - eosio::print("mystruct stored successfully"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prnts '[1]' -p alice@active - * output: >> stored mystruct val:18,dumstr - */ - [[eosio::action]] - void prnts(int id) - { - const auto& psn = get(id); - eosio::print("stored mystruct val:", psn.s._count,",", psn.s._strID); - } - - //Example: cleos --verbose push action nestcontn2kv sets2 '[1, {"_structfld":{"_count":18, "_strID":"dumstr"}, "_strID2":"dumstr2"}]' -p alice@active - [[eosio::action]] - void sets2(int id, const mystruct2& s2) - { - SETCONTAINERVAL(s2); - eosio::print("complex mystruct2 stored successfully"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prnts2 '[1]' -p alice@active - * output: >> stored mystruct2 val:18,dumstr,dumstr2 - */ - [[eosio::action]] - void prnts2(int id) - { - const auto& psn = get(id); - eosio::print("stored mystruct2 val:", psn.s2._structfld._count,",", psn.s2._structfld._strID, ",", psn.s2._strID2); - } - - /*Example: - * cleos --verbose push action nestcontn2kv setvs '[1, [{"_count":18, "_strID":"dumstr"},{"_count":19, "_strID":"dumstr2"}]]' -p alice@active - */ - [[eosio::action]] - void setvs(int id, const vector& vs) - { - SETCONTAINERVAL(vs); - eosio::print("vector stored successfully"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntvs '[1]' -p alice@active - * output: >> stored vector size=2: - * >> 18,dumstr - * >> 19,dumstr2 - */ - [[eosio::action]] - void prntvs(int id) - { - const auto& psn = get(id); - eosio::print("stored vector size=",psn.vs.size(), ":\n"); - for (const auto& ele: psn.vs) - { - eosio::print(ele._count,",", ele._strID,"\n"); - } - } - - /*Examples - * To pass a null value: - * cleos --verbose push action nestcontn2kv seto '[1, null]' -p bob@active - * - * To pass a non-null value: - * cleos --verbose push action nestcontn2kv seto '[2,"hello strval22"]' -p alice@active - * - */ - [[eosio::action]] - void seto(int id, const optional& o) - { - SETCONTAINERVAL(o); - eosio::print("optional stored successfully"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prnto '[1]' -p bob@active - * output: >> stored optional has null value! - * - * cleos --verbose push action nestcontn2kv prnto '[2]' -p alice@active - * output: >> stored optional =hello strval22 - */ - [[eosio::action]] - void prnto(int id) - { - const auto& psn = get(id); - if (psn.o) - eosio::print("stored optional =", psn.o.value()); - else - eosio::print("stored optional has null value!"); - } - - //Example: cleos --verbose push action nestcontn2kv setp '[1, {"first":183, "second":269}]' -p alice@active - [[eosio::action]] - void setp(int id, const pair& p) - { - SETCONTAINERVAL(p); - eosio::print("pair stored successfully"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntp '[1]' -p alice@active - * output: tored pair val:183,269 - */ - [[eosio::action]] - void prntp(int id) - { - const auto& psn = get(id); - eosio::print("stored pair val:", psn.p.first,",", psn.p.second); - } - - //============Two-layer nest containers start here=========== - //=== 1. Try set - set,vector,optional,map,pair - - //Example: cleos --verbose push action nestcontn2kv setstst '[1, [[10,20],[3], [400,500,600]]]' -p alice@active - [[eosio::action]] - void setstst(int id, const set& stst) - { - SETCONTAINERVAL(stst); - eosio::print("type defined set stored successfully!"); - - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntstst '[1]' -p alice@active - * output: >> stored set>:size=3 vals: - * >> 3 - * >> 10 20 - * >> 400 500 600 - */ - [[eosio::action]] - void prntstst(int id) - { - const auto& psn = get(id); - eosio::print("stored set>:size=", psn.stst.size(), " vals:\n"); - for (auto it1=psn.stst.begin(); it1!= psn.stst.end(); it1++) - { - for (auto it2=it1->begin(); it2!= it1->end(); it2++) - eosio::print(*it2, " "); - eosio::print("\n"); - } - } - - //Example: cleos --verbose push action nestcontn2kv setstv '[1, [[16,26],[36], [46,506,606]]]' -p alice@active - [[eosio::action]] - void setstv(int id, const set& stv) - { - SETCONTAINERVAL(stv); - eosio::print("type defined set stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntstv '[1]' -p alice@active - * output: >> stored set>:size=3 vals: - * >> 16 26 - * >> 36 - * >> 46 506 606 - */ - [[eosio::action]] - void prntstv(int id) - { - const auto& psn = get(id); - eosio::print("stored set>:size=", psn.stv.size(), " vals:\n"); - for (auto it1=psn.stv.begin(); it1!= psn.stv.end(); it1++) - { - for (auto it2=it1->begin(); it2!= it1->end(); it2++) - eosio::print(*it2, " "); - eosio::print("\n"); - } - } - - /*Example: - * cleos --verbose push action nestcontn2kv setsto '[1, [101, null, 201, 301]]' -p alice@active - * *****user data can NOT be pushed into the chain, cleos get kv_table will not work if using setsto - * set > is NOT supported currently! - */ - [[eosio::action]] - void setsto(int id, const set& sto) - { - SETCONTAINERVAL(sto); - eosio::print("type defined set > stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntsto '[1]' -p alice@active - * NOT supported - */ - [[eosio::action]] - void prntsto(int id) - { - const auto& psn = get(id); - eosio::print("stored vector vals:\n"); - for (const auto& ele : psn.sto) - { - if (ele) - eosio::print(ele.value(), " "); - else - eosio::print("NULL", " "); - } - } - - /*Example: - * cleos --verbose push action nestcontn2kv setstm '[1, [ [{"first":30,"second":300},{"first":31,"second":301}], [{"first":60,"second":600},{"first":61,"second":601}] ]]' -p alice@active - */ - [[eosio::action]] - void setstm(int id, const set& stm) - { - SETCONTAINERVAL(stm); - eosio::print("type defined set > stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntstm '[1]' -p alice@active - * output: >> stored set: size=2 content: - * >> - * >> Element 0---> - * >> 30:300 31:301 - * >> Element 1---> - * >> 60:600 61:601 - */ - [[eosio::action]] - void prntstm(int id) - { - const auto& psn = get(id); - eosio::print("stored set: size=", psn.stm.size()," content:\n"); - int count=0; - for (const auto& mpval : psn.stm) - { - eosio::print("\nElement ", count++, "--->\n\t"); - for (auto it2 = mpval.begin(); it2 != mpval.end(); ++it2) - eosio::print(it2->first, ":", it2->second, " "); - } - } - - - /*Example: - * cleos --verbose push action nestcontn2kv setstp '[1, [{"first":68, "second":128}, {"first":69, "second":129}]]' -p alice@active - */ - [[eosio::action]] - void setstp(int id, const set >& stp) - { - SETCONTAINERVAL(stp); - eosio::print("set> stored successfully"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntstp '[1]' -p alice@active - * output: >> stored set > size=2: - * >> 68,128 - * >> 69,129 - */ - [[eosio::action]] - void prntstp(int id) - { - const auto& psn = get(id); - eosio::print("stored set > size=", psn.stp.size(), ":\n"); - for (const auto& ele: psn.stp) - { - eosio::print(ele.first,",", ele.second,"\n"); - } - } - - //=== 2. Try vector - set,vector,optional,map,pair - - //Example: cleos --verbose push action nestcontn2kv setvst '[1, [[10,20],[3], [400,500,600]]]' -p alice@active - [[eosio::action]] - void setvst(int id, const vector& vst) - { - SETCONTAINERVAL(vst); - eosio::print("type defined vector stored successfully!"); - - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntvst '[1]' -p alice@active - * output: >> stored vector>:size=3 vals: - * >> 10 20 - * >> 3 - * >> 400 500 600 - */ - [[eosio::action]] - void prntvst(int id) - { - - const auto& psn = get(id); - eosio::print("stored vector>:size=", psn.vst.size(), " vals:\n"); - for (auto it1=psn.vst.begin(); it1!= psn.vst.end(); it1++) - { - for (auto it2=it1->begin(); it2!= it1->end(); it2++) - eosio::print(*it2, " "); - eosio::print("\n"); - } - } - - - //Example: cleos --verbose push action nestcontn2kv setvv '[1, [[1,2],[30], [40,50,60]]]' -p alice@active - [[eosio::action]] - void setvv(int id, const vector& vv) - { - SETCONTAINERVAL(vv); - eosio::print("type defined vector stored successfully!"); - - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntvv '[1]' -p alice@active - * output: >> stored vector> vals: - * >> 1 2 - * >> 30 - * >> 40 50 60 - */ - [[eosio::action]] - void prntvv(int id) - { - const auto& psn = get(id); - eosio::print("stored vector> vals:\n"); - for (int i=0 ; i < psn.vv.size(); i++) - { - for (int j=0; j < psn.vv[i].size(); j++) - eosio::print(psn.vv[i][j], " "); - eosio::print("\n"); //--- use cleos --verbose to show new lines !!! - } - } - - /*Example: - * cleos --verbose push action nestcontn2kv setvo '[1, [100, null, 200, null, 300]]' -p alice@active - * *****user data can NOT be pushed into the chain, cleos get kv_table will not work if using setvo - * vector > is NOT supported currently! - */ - [[eosio::action]] - void setvo(int id, const vector& vo) - { - SETCONTAINERVAL(vo); - eosio::print("type defined vector > stored successfully!"); - } - - //Example: cleos --verbose push action nestcontn2kv prntvo '[1]' -p alice@active - // NOT supported - [[eosio::action]] - void prntvo(int id) - { - const auto& psn = get(id); - eosio::print("stored vector vals:\n"); - for (const auto& ele : psn.vo) - { - if (ele) - eosio::print(ele.value(), " "); - else - eosio::print("NULL", " "); - } - } - - - /*Example: - * cleos --verbose push action nestcontn2kv setvm '[1, [ [{"first":10,"second":100},{"first":11,"second":101}], [{"first":80,"second":800},{"first":81,"second":9009}] ]]' -p alice@active - */ - [[eosio::action]] - void setvm(int id, const vector& vm) - { - SETCONTAINERVAL(vm); - eosio::print("type defined vector > stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntvm '[1]' -p alice@active - * output: >> stored vector: size=2 content: - * >> - * >> Element 0---> - * >> 10:100 11:101 - * >> Element 1---> - * >> 80:800 81:9009 - */ - [[eosio::action]] - void prntvm(int id) - { - const auto& psn = get(id); - eosio::print("stored vector: size=", psn.vm.size()," content:\n"); - int count=0; - for (const auto& mpval : psn.vm) - { - eosio::print("\nElement ", count++, "--->\n\t"); - for (auto it2 = mpval.begin(); it2 != mpval.end(); ++it2) - eosio::print(it2->first, ":", it2->second, " "); - } - - } - - - /*Example: - * cleos --verbose push action nestcontn2kv setvp '[1, [{"first":18, "second":28}, {"first":19, "second":29}]]' -p alice@active - */ - [[eosio::action]] - void setvp(int id, const vector >& vp) - { - SETCONTAINERVAL(vp); - eosio::print("vector > stored successfully"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntvp '[1]' -p alice@active - * output: >> stored vector > size=2: - * >> 18,28 - * >> 19,29 - */ - [[eosio::action]] - void prntvp(int id) - { - const auto& psn = get(id); - eosio::print("stored vector > size=", psn.vp.size(), ":\n"); - for (const auto& ele: psn.vp) - { - eosio::print(ele.first,",", ele.second,"\n"); - } - } - - //=== 3. Try optional - set,vector,optional,map,pair - - - /*Examples: - * cleos --verbose push action nestcontn2kv setost '[1, null]' -p bob@active - * cleos --verbose push action nestcontn2kv setost '[2, [1006,2006, 3006]]' -p alice@active - */ - [[eosio::action]] - void setost(int id, const optional& ost) - { - SETCONTAINERVAL(ost); - eosio::print("type defined optional > stored successfully!"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntost '[1]' -p bob@active - * output: >> stored optional vals: - * >> NULL or no value - * - * cleos --verbose push action nestcontn2kv prntost '[2]' -p alice@active - * output: >> stored optional vals: - * >> 1006 2006 3006 - */ - [[eosio::action]] - void prntost(int id) - { - const auto& psn = get(id); - eosio::print("stored optional vals:\n"); - if (psn.ost) - { - for (const auto& ele : psn.ost.value()) - eosio::print(ele, " "); - } - else - eosio::print("NULL or no value"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv setov '[1, null]' -p bob@active - * - * cleos --verbose push action nestcontn2kv setov '[2, [1001,2001, 3001]]' -p alice@active - */ - [[eosio::action]] - void setov(int id, const optional& ov) - { - SETCONTAINERVAL(ov); - eosio::print("type defined optional > stored successfully!"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntov '[1]' -p bob@active - * output: >> stored optional vals: - * >> NULL or no value - * - * cleos --verbose push action nestcontn2kv prntov '[2]' -p alice@active - * output: >> stored optional vals: - * >> 1001 2001 3001 - */ - [[eosio::action]] - void prntov(int id) - { - const auto& psn = get(id); - eosio::print("stored optional vals:\n"); - if (psn.ov) - { - for (const auto& ele : psn.ov.value()) - eosio::print(ele, " "); - } - else - eosio::print("NULL or no value"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv setoo '[1, null]' -p bob@active - * - * cleos --verbose push action nestcontn2kv setoo '[2,123]' -p alice@active - */ - [[eosio::action]] - void setoo(int id, const optional& oo) - { - SETCONTAINERVAL(oo); - eosio::print("type defined optional stored successfully!"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntoo '[1]' -p bob@active - * ouput: >> stored optional> val:null or no real value stored - * - * cleos --verbose push action nestcontn2a prntoo '[2]' -p alice@active - * output: >> stored optional> val:123 - */ - [[eosio::action]] - void prntoo(int id) - { - const auto& psn = get(id); - eosio::print("stored optional> val:"); - if (psn.oo && psn.oo.value()) - eosio::print(psn.oo.value().value(),"\n"); - else - eosio::print("null or no real value stored"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv setom '[1,[{"first":10,"second":1000},{"first":11,"second":1001}] ]' -p alice@active - * - * cleos --verbose push action nestcontn2kv setom '[2, null ]' -p bob@active - */ - [[eosio::action]] - void setom(int id, const optional& om) - { - SETCONTAINERVAL(om); - eosio::print("type defined optional > stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntom '[1]' -p alice@active - * output: >> size of stored om:2 vals:10:1000 11:1001 - * - * cleos --verbose push action nestcontn2kv prntom '[2]' -p bob@active - * output: >> optional has NULL value - */ - [[eosio::action]] - void prntom(int id) - { - const auto& psn = get(id); - if (psn.om) - { - auto mpval = psn.om.value(); - eosio::print("size of stored om:", mpval.size()," vals:"); - for (auto it2 = mpval.begin(); it2 != mpval.end(); ++it2) - eosio::print(it2->first, ":", it2->second, " "); - - } - else - eosio::print("optional has NULL value\n"); - } - - - /*Examples: - * cleos --verbose push action nestcontn2kv setop '[1, {"first":60, "second":61}]' -p alice@active - * - * cleos --verbose push action nestcontn2kv setop '[2, null]' -p bob@active - */ - [[eosio::action]] - void setop(int id, const optional & op) - { - SETCONTAINERVAL(op); - eosio::print("type-defined optional-pair optional stored successfully!"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntop '[1]' -p alice@active - * output: >> stored optional data:60 61 - * - * cleos --verbose push action nestcontn2kv prntop '[2]' -p bob@active - * output: >> optional has NULL value - */ - [[eosio::action]] - void prntop(int id) - { - const auto& psn = get(id); - if (psn.op) - eosio::print("stored optional data:", psn.op.value().first, " ", psn.op.value().second); - else - eosio::print("optional has NULL value\n"); - } - - //=== 4. Try map - set,vector,optional,map,pair - - /*Example: - * cleos --verbose push action nestcontn2kv setmst '[1, [{"key":1,"value":[10,11,12,16]}, {"key":2,"value":[200,300]} ]]' -p alice@active - */ - [[eosio::action]] - void setmst(int id, const map & mst) - { - SETCONTAINERVAL(mst); - eosio::print("type-defined map > stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntmst '[1]' -p alice@active - * output: >> stored map: size=2 content: - * >> 1:vals 10 11 12 16 - * >> 2:vals 200 300 - */ - [[eosio::action]] - void prntmst(int id) - { - const auto& psn = get(id); - eosio::print("stored map: size=", psn.mst.size()," content:\n"); - for (auto it2 = psn.mst.begin(); it2 != psn.mst.end(); ++it2) - { - eosio::print(it2->first, ":", "vals "); - for (const auto& ele: it2->second) - { - eosio::print(ele," "); - } - eosio::print("\n"); - } - } - - - - /*Example: - * cleos --verbose push action nestcontn2kv setmv '[1, [{"key":1,"value":[10,11,12,16]}, {"key":2,"value":[200,300]} ]]' -p alice@active - */ - [[eosio::action]] - void setmv(int id, const map& mv) - { - SETCONTAINERVAL(mv); - eosio::print("type defined map > stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntmv '[1]' -p alice@active - * output: >> stored map: size=2 content: - * >> 1:vals 10 11 12 16 - * >> 2:vals 200 300 - */ - [[eosio::action]] - void prntmv(int id) - { - const auto& psn = get(id); - eosio::print("stored map: size=", psn.mv.size()," content:\n"); - for (auto it2 = psn.mv.begin(); it2 != psn.mv.end(); ++it2) - { - eosio::print(it2->first, ":", "vals "); - for (const auto& ele: it2->second) - { - eosio::print(ele," "); - } - eosio::print("\n"); - } - } - - - /*Example: - * cleos --verbose push action nestcontn2kv setmo '[1, [{"key":10,"value":1000},{"key":11,"value":null}]]' -p alice@active - */ - [[eosio::action]] - void setmo(int id, const map& mo) - { - SETCONTAINERVAL(mo); - eosio::print("type defined map > stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntmo '[1]' -p alice@active - * output: >> size of stored mo:2 vals - * >> 10:1000 11:NULL - */ - [[eosio::action]] - void prntmo(int id) - { - const auto& psn = get(id); - eosio::print("size of stored mo:", psn.mo.size()," vals\n"); - for (auto it2 = psn.mo.begin(); it2 != psn.mo.end(); ++it2) - { - eosio::print(it2->first, ":"); - if (it2->second) - eosio::print(it2->second.value()," "); - else - eosio::print("NULL "); - } - } - - /*Example: - * cleos push action nestcontn2kv setmm '[1, [{"key":10,"value":[{"first":200,"second":2000}, {"first":201,"second":2001}] }, {"key":11,"value":[{"first":300,"second":3000}, {"first":301,"second":3001}] } ]]' -p alice@active - * Attention: please note the cleos input of mm or map > is a combination of strings key/value and first/second ! - * i.e the "value" part of mm is an array of pairs! - */ - [[eosio::action]] - void setmm(int id, const map& mm) - { - SETCONTAINERVAL(mm); - eosio::print("type defined map > stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntmm '[1]' -p alice@active - * output: >> stored map val:size=2 vals are the following: - * >> 10---> - * >> 200:2000 - * >> 201:2001 - * >> 11---> - * >> 300:3000 - * >> 301:3001 - */ - [[eosio::action]] - void prntmm(int id) - { - const auto& psn = get(id); - eosio::print("stored map val:"); - eosio::print("size=", psn.mm.size()," vals are the following:\n"); - for (auto it2 = psn.mm.begin(); it2 != psn.mm.end(); ++it2) - { - eosio::print(it2->first,"--->\n"); - const auto& temp = it2->second; - for (auto it3 = temp.begin(); it3 != temp.end(); ++it3) - eosio::print("\t",it3->first, ":", it3->second, "\n"); - } - } - - /*Example: - * cleos --verbose push action nestcontn2kv setmp '[1, [{"key":36,"value":{"first":300, "second":301}}, {"key":37,"value":{"first":600, "second":601}} ]]' -p alice@active - */ - [[eosio::action]] - void setmp(int id, const map & mp) - { - SETCONTAINERVAL(mp); - eosio::print("type-defined map-pair map stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntmp '[1]' -p alice@active - * output: >> size of stored mp:2 vals: - * >> 36:300 301 - * >> 37:600 601 - */ - [[eosio::action]] - void prntmp(int id) - { - const auto& psn = get(id); - eosio::print("size of stored mp:", psn.mp.size()," vals:\n"); - for (auto it2 = psn.mp.begin(); it2 != psn.mp.end(); ++it2) - eosio::print(it2->first, ":", it2->second.first, " ", it2->second.second, "\n"); - } - - - //=== 5. Try pair - set,vector,optional,map,pair - - /*Example: - * cleos --verbose push action nestcontn2kv setpst '[1, {"first":20, "second":[200,201,202]}]' -p alice@active - */ - [[eosio::action]] - void setpst(int id, const pair& pst) - { - SETCONTAINERVAL(pst); - eosio::print("type-defined pair-set pair stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntpst '[1]' -p alice@active - * output: >> content of stored pair: first=20 - * >> second=200 201 202 - */ - [[eosio::action]] - void prntpst(int id) - { - const auto& psn = get(id); - eosio::print("content of stored pair: first=", psn.pst.first, "\nsecond="); - for (const auto& ele: psn.pst.second) - eosio::print(ele, " "); - } - - /*Example: - * cleos --verbose push action nestcontn2kv setpv '[1, {"first":10, "second":[100,101,102]}]' -p alice@active - */ - [[eosio::action]] - void setpv(int id, const pair& pv) - { - SETCONTAINERVAL(pv); - eosio::print("type-defined pair-vector pair stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntpv '[1]' -p alice@active - * output: >> content of stored pair: first=10 - * >> second=100 101 102 - */ - [[eosio::action]] - void prntpv(int id) - { - const auto& psn = get(id); - eosio::print("content of stored pair: first=", psn.pv.first, "\nsecond="); - for (const auto& ele: psn.pv.second) - eosio::print(ele, " "); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv setpo '[1, {"first":70, "second":71}]' -p alice@active - * - * cleos --verbose push action nestcontn2kv setpo '[2, {"first":70, "second":null}]' -p bob@active - */ - [[eosio::action]] - void setpo(int id, const pair & po) - { - SETCONTAINERVAL(po); - eosio::print("type-defined pair-optional pair stored successfully!"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntpo '[1]' -p alice@active - * output: >> content of stored pair: first=70 - * >> second=71 - * - * cleos --verbose push action nestcontn2a prntpo '[2]' -p bob@active - * output: >> content of stored pair: first=70 - * >> second=NULL - */ - [[eosio::action]] - void prntpo(int id) - { - const auto& psn = get(id); - eosio::print("content of stored pair: first=", psn.po.first, "\nsecond="); - if (psn.po.second) - eosio::print(psn.po.second.value(), " "); - else - eosio::print("NULL "); - } - - /*Example: - * cleos --verbose push action nestcontn2kv setpm '[1, {"key":6, "value":[{"first":20,"second":300}, {"first":21,"second":301}] }]' -p alice@active - * Remark: the data input for pm uses a combination of key/vale and first/second - */ - [[eosio::action]] - void setpm(int id, const pair & pm) - { - SETCONTAINERVAL(pm); - eosio::print("type-defined pair-map pair stored successfully!"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntpm '[1]' -p alice@active - * output: >> content of stored pair: first=6 - * >> second=20:300 21:301 - */ - [[eosio::action]] - void prntpm(int id) - { - const auto& psn = get(id); - eosio::print("content of stored pair: first=", psn.pm.first, "\nsecond="); - for (auto it2 = psn.pm.second.begin(); it2 != psn.pm.second.end(); ++it2) - eosio::print(it2->first, ":", it2->second, " "); - } - - - /*Example: - * cleos --verbose push action nestcontn2kv setpp '[1, {"key":30, "value":{"first":301, "second":302} }]' -p alice@active - * Remark: input data for pp or pair-pair is a combination of key/value and first/second - */ - [[eosio::action]] - void setpp(int id, const pair & pp) - { - SETCONTAINERVAL(pp); - eosio::print("type-defined pair-pair pair stored successfully!"); - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntpp '[1]' -p alice@active - * output: >> content of stored pair: first=30 - * >> second=301 302 - */ - [[eosio::action]] - void prntpp(int id) - { - const auto& psn = get(id); - eosio::print("content of stored pair: first=", psn.pp.first, "\nsecond="); - eosio::print(psn.pp.second.first, " ", psn.pp.second.second); - } - - - //Try an example of 3-layer nested container - - /*Example: - * cleos --verbose push action nestcontn2kv setovv '[1, [[21,22],[230], [240,250,260,280]]]' -p alice@active - */ - [[eosio::action]] - void setovv(int id, const optional& ovv) - { - // try type-defined 3-layer nested container optional > > here - SETCONTAINERVAL(ovv); - eosio::print("type-defined optional stored successfully!"); - - } - - /*Example: - * cleos --verbose push action nestcontn2kv prntovv '[1]' -p alice@active - * output: >> stored optional > > vals: - * >> 21 22 - * >> 230 - * >> 240 250 260 280 - */ - [[eosio::action]] - void prntovv(int id) - { - const auto& psn = get(id); - eosio::print("stored optional > > vals:\n"); - if (psn.ovv) - { - auto v2 = psn.ovv.value(); - for (int i=0 ; i < v2.size(); i++) - { - for (int j=0; j < v2[i].size(); j++) - eosio::print(v2[i][j], " "); - eosio::print("\n"); - } - } - else - eosio::print("stored optional > > has null value!"); - } - - //Example: cleos --verbose push action nestcontn2kv erase '["bob", 2]' -p bob@active - [[eosio::action]] - void erase(name user, int id) - { - require_auth(user); - eosio::print (user, " is requesting to erase the record with key=", id, "\n"); - auto iter = mymap.find(id); - check(iter != mymap.end(), "cannot erase: Record with given id does not exist"); - mymap.erase(id); - eosio::print("record with id=", id, " is successfully erased!"); - } - - //Example: cleos --verbose push action nestcontn2kv prntallkeys '["bob"]' -p bob@active - [[eosio::action]] - void prntallkeys(name user) - { - //print all keys stored in this block chain for this contract - require_auth(user); - eosio::print (user, " is requesting prntallkeys\n"); - if (mymap.empty()) - eosio::print ("mymap is empty, no key in mymap!"); - - eosio::print("mymap keys include:\n"); - for ( const auto& item : mymap ) - { - eosio::print(item.first(), "\n"); - } - } - - //Example: cleos --verbose push action nestcontn2kv get2 '["str1"]' -p alice@active - [[eosio::action]] - person2kv get2(string id) - { - auto iter = mymap2.find(id); - check(iter != mymap2.end(), "Record does not exist"); - const auto& item_found = iter->second(); - return item_found; - } - - /*Examples: - * cleos --verbose push action nestcontn2kv setv2 '["str1",[102,202,302,602]]' -p alice@active - * cleos --verbose push action nestcontn2kv setv2 '["str2", []]' -p bob@active - */ - [[eosio::action]] - void setv2(string id, const vector& v) - { - SETCONTAINERVALN(2, v); - eosio::print("vector stored successfully"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntv2 '["str1"]' -p alice@active - * output: >> size of stored v:4 vals:102,202,302,602, - * - * cleos --verbose push action nestcontn2kv prntv2 '["str2"]' -p bob@active - * output: >> size of stored v:0 vals: - */ - [[eosio::action]] - void prntv2(string id) - { - const auto& psn = get2(id); - eosio::print("size of stored v:", psn.v.size()," vals:"); - for (const auto & ele : psn.v) - eosio::print(ele, ","); - } - - - //Example: cleos --verbose push action nestcontn2kv get3 '["name1"]' -p alice@active - [[eosio::action]] - person2kv get3(name id) - { - auto iter = mymap3.find(id); - check(iter != mymap3.end(), "Record does not exist"); - const auto& item_found = iter->second(); - return item_found; - } - - /*Examples: - * cleos --verbose push action nestcontn2kv setv3 '["name1",[103,203,303,603]]' -p alice@active - * cleos --verbose push action nestcontn2kv setv3 '["name2", []]' -p bob@active - */ - [[eosio::action]] - void setv3(name id, const vector& v) - { - SETCONTAINERVALN(3, v); - eosio::print("vector stored successfully"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntv3 '["name1"]' -p alice@active - * output: >> size of stored v:4 vals:103,203,303,603, - * - * cleos --verbose push action nestcontn2kv prntv3 '["name2"]' -p bob@active - * output: >> size of stored v:0 vals: - */ - [[eosio::action]] - void prntv3(name id) - { - const auto& psn = get3(id); - eosio::print("size of stored v:", psn.v.size()," vals:"); - for (const auto & ele : psn.v) - eosio::print(ele, ","); - } - - - //Example: cleos --verbose push action nestcontn2kv get4 '[{"_count":18, "_strID":"dumstr"}]' -p alice@active - [[eosio::action]] - person2kv get4(mystructrefl id) - { - auto iter = mymap4.find(id); - check(iter != mymap4.end(), "Record does not exist"); - const auto& item_found = iter->second(); - return item_found; - } - - /*Examples: - * cleos --verbose push action nestcontn2kv setv4 '[{"_count":18, "_strID":"dumstr"},[104,204,304,604]]' -p alice@active - * cleos --verbose push action nestcontn2kv setv4 '[{"_count":11, "_strID":"dumstr1"}, []]' -p bob@active - */ - [[eosio::action]] - void setv4(mystructrefl id, const vector& v) - { - SETCONTAINERVALN(4, v); - eosio::print("vector stored successfully"); - } - - /*Examples: - * cleos --verbose push action nestcontn2kv prntv4 '[{"_count":18, "_strID":"dumstr"}]' -p alice@active - * output: >> size of stored v:4 vals:104,204,304,604, - * - * cleos --verbose push action nestcontn2kv prntv4 '[{"_count":11, "_strID":"dumstr1"}]' -p bob@active - * output: >> size of stored v:0 vals: - */ - [[eosio::action]] - void prntv4(mystructrefl id) - { - const auto& psn = get4(id); - eosio::print("size of stored v:", psn.v.size()," vals:"); - for (const auto & ele : psn.v) - eosio::print(ele, ","); - } - - //The following are needed for eosio-cpp compiler to identify the actions in genearted .abi - using get_action = eosio::action_wrapper<"get"_n, &nestcontn2kv::get>; - using erase_action = eosio::action_wrapper<"erase"_n, &nestcontn2kv::erase>; - using prntallkeys_action = eosio::action_wrapper<"prntallkeys"_n, &nestcontn2kv::prntallkeys>; - - using setv_action = eosio::action_wrapper<"setv"_n, &nestcontn2kv::setv>; - using prntv_action = eosio::action_wrapper<"prntv"_n, &nestcontn2kv::prntv>; - using setst_action = eosio::action_wrapper<"setst"_n, &nestcontn2kv::setst>; - using prntst_action = eosio::action_wrapper<"prntst"_n, &nestcontn2kv::prntst>; - using setm_action = eosio::action_wrapper<"setm"_n, &nestcontn2kv::setm>; - using prntm_action = eosio::action_wrapper<"prntm"_n, &nestcontn2kv::prntm>; - using sets_action = eosio::action_wrapper<"sets"_n, &nestcontn2kv::sets>; - using prnts_action = eosio::action_wrapper<"prnts"_n, &nestcontn2kv::prnts>; - using sets2_action = eosio::action_wrapper<"sets2"_n, &nestcontn2kv::sets2>; - using prnts2_action = eosio::action_wrapper<"prnts2"_n, &nestcontn2kv::prnts2>; - using setvs_action = eosio::action_wrapper<"setvs"_n, &nestcontn2kv::setvs>; - using prntvs_action = eosio::action_wrapper<"prntvs"_n, &nestcontn2kv::prntvs>; - using seto_action = eosio::action_wrapper<"seto"_n, &nestcontn2kv::seto>; - using prnto_action = eosio::action_wrapper<"prnto"_n, &nestcontn2kv::prnto>; - using setp_action = eosio::action_wrapper<"setp"_n, &nestcontn2kv::setp>; - using prntp_action = eosio::action_wrapper<"prntp"_n, &nestcontn2kv::prntp>; - - using setstst_action = eosio::action_wrapper<"setstst"_n, &nestcontn2kv::setstst>; - using prntstst_action = eosio::action_wrapper<"prntstst"_n, &nestcontn2kv::prntstst>; - using setstv_action = eosio::action_wrapper<"setstv"_n, &nestcontn2kv::setstv>; - using prntstv_action = eosio::action_wrapper<"prntstv"_n, &nestcontn2kv::prntstv>; - using setsto_action = eosio::action_wrapper<"setsto"_n, &nestcontn2kv::setsto>; - using prntsto_action = eosio::action_wrapper<"prntsto"_n, &nestcontn2kv::prntsto>; - using setstm_action = eosio::action_wrapper<"setstm"_n, &nestcontn2kv::setstm>; - using prntstm_action = eosio::action_wrapper<"prntstm"_n, &nestcontn2kv::prntstm>; - using setstp_action = eosio::action_wrapper<"setstp"_n, &nestcontn2kv::setstp>; - using prntstp_action = eosio::action_wrapper<"prntstp"_n, &nestcontn2kv::prntstp>; - - using setvst_action = eosio::action_wrapper<"setvst"_n, &nestcontn2kv::setvst>; - using prntvst_action = eosio::action_wrapper<"prntvst"_n, &nestcontn2kv::prntvst>; - using setvv_action = eosio::action_wrapper<"setvv"_n, &nestcontn2kv::setvv>; - using prntvv_action = eosio::action_wrapper<"prntvv"_n, &nestcontn2kv::prntvv>; - using setvo_action = eosio::action_wrapper<"setvo"_n, &nestcontn2kv::setvo>; - using prntvo_action = eosio::action_wrapper<"prntvo"_n, &nestcontn2kv::prntvo>; - using setvm_action = eosio::action_wrapper<"setvm"_n, &nestcontn2kv::setvm>; - using prntvm_action = eosio::action_wrapper<"prntvm"_n, &nestcontn2kv::prntvm>; - using setvp_action = eosio::action_wrapper<"setvp"_n, &nestcontn2kv::setvp>; - using prntvp_action = eosio::action_wrapper<"prntvp"_n, &nestcontn2kv::prntvp>; - - using setost_action = eosio::action_wrapper<"setost"_n, &nestcontn2kv::setost>; - using prntost_action = eosio::action_wrapper<"prntost"_n, &nestcontn2kv::prntost>; - using setov_action = eosio::action_wrapper<"setov"_n, &nestcontn2kv::setov>; - using prntov_action = eosio::action_wrapper<"prntov"_n, &nestcontn2kv::prntov>; - using setoo_action = eosio::action_wrapper<"setoo"_n, &nestcontn2kv::setoo>; - using prntoo_action = eosio::action_wrapper<"prntoo"_n, &nestcontn2kv::prntoo>; - using setom_action = eosio::action_wrapper<"setom"_n, &nestcontn2kv::setom>; - using prntom_action = eosio::action_wrapper<"prntom"_n, &nestcontn2kv::prntom>; - using setop_action = eosio::action_wrapper<"setop"_n, &nestcontn2kv::setop>; - using prntop_action = eosio::action_wrapper<"prntop"_n, &nestcontn2kv::prntop>; - - using setmst_action = eosio::action_wrapper<"setmst"_n, &nestcontn2kv::setmst>; - using prntmst_action = eosio::action_wrapper<"prntmst"_n, &nestcontn2kv::prntmst>; - using setmv_action = eosio::action_wrapper<"setmv"_n, &nestcontn2kv::setmv>; - using prntmv_action = eosio::action_wrapper<"prntmv"_n, &nestcontn2kv::prntmv>; - using setmo_action = eosio::action_wrapper<"setmo"_n, &nestcontn2kv::setmo>; - using prntmo_action = eosio::action_wrapper<"prntmo"_n, &nestcontn2kv::prntmo>; - using setmm_action = eosio::action_wrapper<"setmm"_n, &nestcontn2kv::setmm>; - using prntmm_action = eosio::action_wrapper<"prntmm"_n, &nestcontn2kv::prntmm>; - using setmp_action = eosio::action_wrapper<"setmp"_n, &nestcontn2kv::setmp>; - using prntmp_action = eosio::action_wrapper<"prntmp"_n, &nestcontn2kv::prntmp>; - - using setpst_action = eosio::action_wrapper<"setpst"_n, &nestcontn2kv::setpst>; - using prntpst_action = eosio::action_wrapper<"prntpst"_n, &nestcontn2kv::prntpst>; - using setpv_action = eosio::action_wrapper<"setpv"_n, &nestcontn2kv::setpv>; - using prntpv_action = eosio::action_wrapper<"prntpv"_n, &nestcontn2kv::prntpv>; - using setpo_action = eosio::action_wrapper<"setpo"_n, &nestcontn2kv::setpo>; - using prntpo_action = eosio::action_wrapper<"prntpo"_n, &nestcontn2kv::prntpo>; - using setpm_action = eosio::action_wrapper<"setpm"_n, &nestcontn2kv::setpm>; - using prntpm_action = eosio::action_wrapper<"prntpm"_n, &nestcontn2kv::prntpm>; - using setpp_action = eosio::action_wrapper<"setpp"_n, &nestcontn2kv::setpp>; - using prntpp_action = eosio::action_wrapper<"prntpp"_n, &nestcontn2kv::prntpp>; - - using setovv_action = eosio::action_wrapper<"setovv"_n, &nestcontn2kv::setovv>; - using prntovv_action = eosio::action_wrapper<"prntovv"_n, &nestcontn2kv::prntovv>; - - using get2_action = eosio::action_wrapper<"get2"_n, &nestcontn2kv::get2>; - using setv2_action = eosio::action_wrapper<"setv2"_n, &nestcontn2kv::setv2>; - using prntv2_action = eosio::action_wrapper<"prntv2"_n, &nestcontn2kv::prntv2>; - - using get3_action = eosio::action_wrapper<"get3"_n, &nestcontn2kv::get3>; - using setv3_action = eosio::action_wrapper<"setv3"_n, &nestcontn2kv::setv3>; - using prntv3_action = eosio::action_wrapper<"prntv3"_n, &nestcontn2kv::prntv3>; - - using get4_action = eosio::action_wrapper<"get4"_n, &nestcontn2kv::get4>; - using setv4_action = eosio::action_wrapper<"setv4"_n, &nestcontn2kv::setv4>; - using prntv4_action = eosio::action_wrapper<"prntv4"_n, &nestcontn2kv::prntv4>; -}; - diff --git a/tests/toolchain/build-pass/nestcontn2kv.json b/tests/toolchain/build-pass/nestcontn2kv.json deleted file mode 100644 index b3598b0cf4..0000000000 --- a/tests/toolchain/build-pass/nestcontn2kv.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "tests": [ - { - "expected": { - "exit-code": 0 - } - } - ] -} - From 5a94dab43926c15243a74275f4fb27e89dc89c16 Mon Sep 17 00:00:00 2001 From: Chris Gundlach Date: Fri, 29 Jul 2022 09:18:13 -0500 Subject: [PATCH 10/12] removed kv tests --- tests/toolchain/build-pass/tupletestkv.cpp | 530 -------------------- tests/toolchain/build-pass/tupletestkv.json | 10 - 2 files changed, 540 deletions(-) delete mode 100644 tests/toolchain/build-pass/tupletestkv.cpp delete mode 100644 tests/toolchain/build-pass/tupletestkv.json diff --git a/tests/toolchain/build-pass/tupletestkv.cpp b/tests/toolchain/build-pass/tupletestkv.cpp deleted file mode 100644 index 61ba22f451..0000000000 --- a/tests/toolchain/build-pass/tupletestkv.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/* Verify the support of nested containers involving std::tuple for the new Key-value table eosio::kv::map - * This tupletestkv.cpp can be regarded as a continuation of ../nestcontn2kv.cpp - * For each action, an example regarding how to use the action with the cleos command line is given. - * - * Important Remarks: - * 1) The input of a std::tuple via cleos uses [ele0, ele1, ele2], it is the same as the input of a vector/set - * 2) However the input formats of settm,settp are different from those of corresponding setvm, setvp in nestcontn2a.cpp - * 3) More importantly, vector > and set > are NOT yet supported as shown in nestcontn2a.cpp, - * BUT tuple of optional is supported as shown here in this tupletest.cpp - * - * Expected printout: - * For each setx action, the printed result on the cleos console is given in its corresponding prntx action. - */ - - -//--- You might need to verify some eosio-defined types such as eosio::asset can be the values of kv::map - -#include -#include - -#include -#include -#include -#include -#include - -using namespace eosio; -using namespace std; - - -#define SETCONTAINERVAL(x) do { \ - person2kv obj = mymap[id]; \ - obj.x = x; \ - mymap[id] = obj; \ - }while(0) - -// use typedefs to make multi-layer nested containers work! -typedef vector vec_uint16; -typedef set set_uint16; -typedef optional op_uint16; -typedef map mp_uint16; -typedef pair pr_uint16; - -typedef tuple tup_uint16; - - -struct person2kv { - // Each container/object is represented by one letter: v-vector, m-map, s-mystruct,o-optional, p-pair, t-tuple - // with exceptions: s2 - mystruct2, st - set - - tuple t; //---new code on verifying std::tuple - - //Two-layer nested-container involving tuple - vector vt; - set stt; - optional ot; - map mt; - pair pt; - tuple tt; - - tuple tv; //tuple of vectors - tuple tst; - tuple to; - tuple tm; - tuple tp; //tuple of pairs - - tuple tmisc; //tuple of misc. types -}; - - -class [[eosio::contract("tupletestkv")]] tupletestkv : public eosio::contract { - using my_map_t = eosio::kv::map<"people2kv"_n, int, person2kv>; - private: - my_map_t mymap{}; - - public: - using contract::contract; - - tupletestkv(name receiver, name code, datastream ds): contract(receiver, code, ds) {} - - - //Example: cleos --verbose push action nestcontn2kv get '[1]' -p alice@active - [[eosio::action]] - person2kv get(int id) - { - //This action will be used by all prntx actions to retrieve item_found for given id - auto iter = mymap.find(id); - check(iter != mymap.end(), "Record does not exist"); - const auto& item_found = iter->second(); - return item_found; - } - - /*Examples: - * cleos --verbose push action tupletestkv sett '[1,[100,"str1"]]' -p alice@active - */ - [[eosio::action]] - void sett(int id, const tuple& t) - { - SETCONTAINERVAL(t); - eosio::print("tuple stored successfully"); - } - - - /*Examples: - * cleos --verbose push action tupletestkv prntt '[1]' -p alice@active - * output: >> elements of stored tuple t:100, str1 - */ - [[eosio::action]] - void prntt(int id) - { - const auto& psn = get(id); - eosio::print("elements of stored tuple t:", std::get<0>(psn.t), ", ", std::get<1>(psn.t)); - } - - //=== 1. Try other containers (vector,set,optional,map,pair,tuple) of tuples - - //Example: cleos --verbose push action tupletestkv setvt '[1, [[10,20],[30,40], [50,60]]]' -p alice@active - [[eosio::action]] - void setvt(int id, const vector& vt) - { - SETCONTAINERVAL(vt); - eosio::print("type defined vector stored successfully!"); - - } - - /*Example: - * cleos --verbose push action tupletestkv prntvt '[1]' -p alice@active - * output: >> stored vector> vals: - * >> 10 20 - * >> 30 40 - * >> 50 60 - */ - [[eosio::action]] - void prntvt(int id) - { - const auto& psn = get(id); - eosio::print("stored vector> vals:\n"); - for (int i=0 ; i < psn.vt.size(); i++) - { - eosio::print(std::get<0>(psn.vt[i]), " ", std::get<1>(psn.vt[i])); - eosio::print("\n"); - } - } - - //Example: cleos --verbose push action tupletestkv setstt '[1, [[1,2],[36,46], [56,66]]]' -p alice@active - [[eosio::action]] - void setstt(int id, const set& stt) - { - SETCONTAINERVAL(stt); - eosio::print("type defined set stored successfully!"); - - } - - /*Example: - * cleos --verbose push action tupletestkv prntstt '[1]' -p alice@active - * output: >> stored set> vals: - * >> 1 2 - * >> 36 46 - * >> 56 66 - */ - [[eosio::action]] - void prntstt(int id) - { - const auto& psn = get(id); - eosio::print("stored set> vals:\n"); - for (auto it1=psn.stt.begin(); it1!= psn.stt.end(); it1++) - { - eosio::print(std::get<0>(*it1), " ", std::get<1>(*it1)); - eosio::print("\n"); - } - } - - /*Examples: - * cleos --verbose push action tupletestkv setot '[1, null]' -p bob@active - * - * cleos --verbose push action tupletestkv setot '[2, [1001,2001]]' -p alice@active - */ - [[eosio::action]] - void setot(int id, const optional& ot) - { - SETCONTAINERVAL(ot); - eosio::print("type defined optional stored successfully!"); - } - - /*Examples: - * cleos --verbose push action tupletestkv prntot '[1]' -p bob@active - * output: >> stored optional vals: - * >> NULL or no value - * - * cleos --verbose push action tupletestkv prntot '[2]' -p alice@active - * output: >> stored optional vals: - * >> 1001 2001 - */ - [[eosio::action]] - void prntot(int id) - { - const auto& psn = get(id); - eosio::print("stored optional vals:\n"); - if (psn.ot) - { - eosio::print(std::get<0>(psn.ot.value()), " ", std::get<1>(psn.ot.value())); - } - else - eosio::print("NULL or no value"); - } - - /*Example: - * cleos --verbose push action tupletestkv setmt '[1, [{"key":1,"value":[10,11]}, {"key":2,"value":[200,300]} ]]' -p alice@active - */ - [[eosio::action]] - void setmt(int id, const map& mt) - { - SETCONTAINERVAL(mt); - eosio::print("type defined map stored successfully!"); - } - - /*Example: - * cleos --verbose push action tupletestkv prntmt '[1]' -p alice@active - * output: >> stored map: size=2 content: - * >> 1:vals 10 11 - * >> 2:vals 200 300 - */ - [[eosio::action]] - void prntmt(int id) - { - const auto& psn = get(id); - eosio::print("stored map: size=", psn.mt.size()," content:\n"); - for (auto it2 = psn.mt.begin(); it2 != psn.mt.end(); ++it2) - { - eosio::print(it2->first, ":", "vals "); - eosio::print(std::get<0>(it2->second), " ", std::get<1>(it2->second)); - eosio::print("\n"); - } - } - - - - /*Example: - * cleos --verbose push action tupletestkv setpt '[1, {"first":10, "second":[100,101]}]' -p alice@active - */ - [[eosio::action]] - void setpt(int id, const pair& pt) - { - SETCONTAINERVAL(pt); - eosio::print("type defined pair stored successfully!"); - } - - /*Example: - * cleos --verbose push action tupletestkv prntpt '[1]' -p alice@active - * output: >> content of stored pair: first=10 - * >> second=100 101 - */ - [[eosio::action]] - void prntpt(int id) - { - const auto& psn = get(id); - - eosio::print("content of stored pair: first=", psn.pt.first, "\nsecond="); - eosio::print(std::get<0>(psn.pt.second), " ", std::get<1>(psn.pt.second)); - } - - //Example: cleos --verbose push action tupletestkv settt '[1, [[1,2],[30,40], [50,60]]]' -p alice@active - [[eosio::action]] - void settt(int id, const tuple& tt) - { - SETCONTAINERVAL(tt); - eosio::print("type defined tuple > stored successfully!"); - - } - - /*Example: - * cleos --verbose push action tupletestkv prnttt '[1]' -p alice@active - * output: >> stored tuple vals: - * >> 1 2 - * >> 30 40 - * >> 50 60 - */ - [[eosio::action]] - void prnttt(int id) - { - const auto& psn = get(id); - eosio::print("stored tuple vals:\n"); - const auto& ele0 = std::get<0>(psn.tt); - const auto& ele1 = std::get<1>(psn.tt); - const auto& ele2 = std::get<2>(psn.tt); - - eosio::print(std::get<0>(ele0), " ", std::get<1>(ele0), "\n"); - eosio::print(std::get<0>(ele1), " ", std::get<1>(ele1), "\n"); - eosio::print(std::get<0>(ele2), " ", std::get<1>(ele2), "\n"); - } - - //=== 2. Try tuple of other containers (vector,set,optional,map,pair) - - //Example: cleos --verbose push action tupletestkv settv '[1, [16,[26,36], [46,506,606]]]' -p alice@active - [[eosio::action]] - void settv(int id, const tuple& tv) - { - SETCONTAINERVAL(tv); - eosio::print("type defined tuple stored successfully!"); - } - - /*Example: - * cleos --verbose push action tupletestkv prnttv '[1]' -p alice@active - * output: >> stored tuple vals: - * >> ele0: 16 - * >> ele1: 26 36 - * >> ele2: 46 506 606 - */ - [[eosio::action]] - void prnttv(int id) - { - const auto& psn = get(id); - eosio::print("stored tuple vals:\n"); - - auto printVec = [](vec_uint16 v) {//eosio-cpp compiler allows c++11 usage such as lambda - for (int i=0; i < v.size();i++) - eosio::print(v[i]," "); - eosio::print("\n"); - }; - eosio::print("ele0: ", std::get<0>(psn.tv),"\n"); - eosio::print("ele1: "); printVec(std::get<1>(psn.tv)); - eosio::print("ele2: "); printVec(std::get<2>(psn.tv)); - } - - //Example: cleos --verbose push action tupletestkv settst '[1, [10,[21,31], [41,51,61]]]' -p alice@active - [[eosio::action]] - void settst(int id, const tuple& tst) - { - SETCONTAINERVAL(tst); - eosio::print("type defined tuple stored successfully!"); - } - - /*Example: - * cleos --verbose push action tupletestkv prnttst '[1]' -p alice@active - * output: >> stored tuple vals: - * >> ele0: 10 - * >> ele1: 21 31 - * >> ele2: 41 51 61 - */ - [[eosio::action]] - void prnttst(int id) - { - const auto& psn = get(id); - eosio::print("stored tuple vals:\n"); - - auto printSet = [](set_uint16 s) { - for (auto it = s.begin(); it !=s.end(); it++ ) - eosio::print(*it, " "); - eosio::print("\n"); - }; - eosio::print("ele0: ", std::get<0>(psn.tst),"\n"); - eosio::print("ele1: "); printSet(std::get<1>(psn.tst)); - eosio::print("ele2: "); printSet(std::get<2>(psn.tst)); - } - - /*Examples: - * cleos --verbose push action tupletestkv setto '[1, [100, null, 200, null, 300]]' -p alice@active - * - * cleos --verbose push action tupletestkv setto '[2, [null, null, 10, null, 20]]' -p bob@active - * Remark: Yes, tuple of optionals is supported here ! - */ - [[eosio::action]] - void setto(int id, const tuple & to) - { - SETCONTAINERVAL(to); - eosio::print("type defined tuple stored successfully!"); - } - - /*Examples: - * cleos --verbose push action tupletest prntto '[1]' -p alice@active - * output: >> stored tuple vals: - * >> 100 NULL 200 NULL 300 - * - * cleos --verbose push action tupletest prntto '[2]' -p bob@active - * output: >> stored tuple vals: - * >> NULL NULL 10 NULL 20 - */ - [[eosio::action]] - void prntto(int id) - { - const auto& psn = get(id); - eosio::print("stored tuple vals:\n"); - auto printOptional = [](op_uint16 op) { - if (op) - eosio::print(op.value(), " "); - else - eosio::print("NULL", " "); - }; - - printOptional(std::get<0>(psn.to)); - printOptional(std::get<1>(psn.to)); - printOptional(std::get<2>(psn.to)); - printOptional(std::get<3>(psn.to)); - printOptional(std::get<4>(psn.to)); - eosio::print("\n"); - } - - - //Example: cleos --verbose push action tupletestkv settm '[1, [126, [{"key":10,"value":100},{"key":11,"value":101}], [{"key":80,"value":800},{"key":81,"value":9009}] ]]' -p alice@active - // ******Note: The input format of settm is different from that of setvm in nestcontn2a.cpp! - [[eosio::action]] - void settm(int id, const tuple& tm) - { - SETCONTAINERVAL(tm); - eosio::print("type defined tuple stored successfully!"); - } - - /*Example: - * cleos --verbose push action tupletestkv prnttm '[1]' -p alice@active - * output: >> stored tuple vals: - * >> ele0: 126 - * >> ele1: 10:100 11:101 - * >> ele2: 80:800 81:9009 - */ - [[eosio::action]] - void prnttm(int id) - { - const auto& psn = get(id); - eosio::print("stored tuple vals:\n"); - - auto printMap = [](mp_uint16 m) { - for (auto it = m.begin(); it !=m.end(); it++ ) - eosio::print(it->first, ":", it->second, " "); - eosio::print("\n"); - }; - eosio::print("ele0: ", std::get<0>(psn.tm),"\n"); - eosio::print("ele1: "); printMap(std::get<1>(psn.tm)); - eosio::print("ele2: "); printMap(std::get<2>(psn.tm)); - } - - //Example: cleos --verbose push action tupletestkv settp '[1, [127, {"key":18, "value":28}, {"key":19, "value":29}]]' -p alice@active - // ******Note: The input format of settp is different from that of setvp in nestcontn2a.cpp! - [[eosio::action]] - void settp(int id, const tuple& tp) - { - SETCONTAINERVAL(tp); - eosio::print("type defined tuple stored successfully!"); - } - - /*Example: - * cleos --verbose push action tupletestkv prnttp '[1]' -p alice@active - * output: >> stored tuple vals: - * >> ele0: 127 - * >> ele1: 18:28 - * >> ele2: 19:29 - */ - [[eosio::action]] - void prnttp(int id) - { - const auto& psn = get(id); - eosio::print("stored tuple vals:\n"); - - auto printPair = [](pr_uint16 p) { - eosio::print(p.first, ":", p.second); - eosio::print("\n"); - }; - eosio::print("ele0: ", std::get<0>(psn.tp),"\n"); - eosio::print("ele1: "); printPair(std::get<1>(psn.tp)); - eosio::print("ele2: "); printPair(std::get<2>(psn.tp)); - } - - //Example: cleos --verbose push action tupletestkv settmisc '[1, ["strHere", [10,11,12,16], {"key":86,"value":96}] ]' -p alice@active - [[eosio::action]] - void settmisc(int id, const tuple & tmisc) - { - SETCONTAINERVAL(tmisc); - eosio::print("type defined tuple stored successfully!"); - } - - /*Example: - * cleos --verbose push action tupletestkv prnttmisc '[1]' -p alice@active - * output: >> stored tuple vals: - * >> ele0: strHere - * >> ele1: 10 11 12 16 - * >> ele2: 86:96 - */ - [[eosio::action]] - void prnttmisc(int id) - { - const auto& psn = get(id); - eosio::print("stored tuple vals:\n"); - - auto printVec = [](vec_uint16 v) { - for (int i=0; i < v.size();i++) - eosio::print(v[i]," "); - eosio::print("\n"); - }; - - auto printPair = [](pr_uint16 p) { - eosio::print(p.first, ":", p.second); - eosio::print("\n"); - }; - eosio::print("ele0: ", std::get<0>(psn.tmisc),"\n"); - eosio::print("ele1: "); printVec(std::get<1>(psn.tmisc)); - eosio::print("ele2: "); printPair(std::get<2>(psn.tmisc)); - } - - //The following are needed for eosio-cpp compiler to identify the actions in genearted .abi - using get_action = eosio::action_wrapper<"get"_n, &tupletestkv::get>; - - using sett_action = eosio::action_wrapper<"sett"_n, &tupletestkv::sett>; - using prntt_action = eosio::action_wrapper<"prntt"_n, &tupletestkv::prntt>; - using setvt_action = eosio::action_wrapper<"setvt"_n, &tupletestkv::setvt>; - using prntvt_action = eosio::action_wrapper<"prntvt"_n, &tupletestkv::prntvt>; - using setstt_action = eosio::action_wrapper<"setstt"_n, &tupletestkv::setstt>; - using prntstt_action = eosio::action_wrapper<"prntstt"_n, &tupletestkv::prntstt>; - using setot_action = eosio::action_wrapper<"setot"_n, &tupletestkv::setot>; - using prntot_action = eosio::action_wrapper<"prntot"_n, &tupletestkv::prntot>; - using setmt_action = eosio::action_wrapper<"setmt"_n, &tupletestkv::setmt>; - using prntmt_action = eosio::action_wrapper<"prntmt"_n, &tupletestkv::prntmt>; - using setpt_action = eosio::action_wrapper<"setpt"_n, &tupletestkv::setpt>; - using prntpt_action = eosio::action_wrapper<"prntpt"_n, &tupletestkv::prntpt>; - using settt_action = eosio::action_wrapper<"settt"_n, &tupletestkv::settt>; - using prnttt_action = eosio::action_wrapper<"prnttt"_n, &tupletestkv::prnttt>; - - using settv_action = eosio::action_wrapper<"settv"_n, &tupletestkv::settv>; - using prnttv_action = eosio::action_wrapper<"prnttv"_n, &tupletestkv::prnttv>; - using settst_action = eosio::action_wrapper<"settst"_n, &tupletestkv::settst>; - using prnttst_action = eosio::action_wrapper<"prnttst"_n, &tupletestkv::prnttst>; - using setto_action = eosio::action_wrapper<"setto"_n, &tupletestkv::setto>; - using prntto_action = eosio::action_wrapper<"prntto"_n, &tupletestkv::prntto>; - using settm_action = eosio::action_wrapper<"settm"_n, &tupletestkv::settm>; - using prnttm_action = eosio::action_wrapper<"prnttm"_n, &tupletestkv::prnttm>; - using settp_action = eosio::action_wrapper<"settp"_n, &tupletestkv::settp>; - using prnttp_action = eosio::action_wrapper<"prnttp"_n, &tupletestkv::prnttp>; - using settmisc_action = eosio::action_wrapper<"settmisc"_n, &tupletestkv::settmisc>; - using prnttmisc_action = eosio::action_wrapper<"prnttmisc"_n, &tupletestkv::prnttmisc>; -}; - - diff --git a/tests/toolchain/build-pass/tupletestkv.json b/tests/toolchain/build-pass/tupletestkv.json deleted file mode 100644 index b3598b0cf4..0000000000 --- a/tests/toolchain/build-pass/tupletestkv.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "tests": [ - { - "expected": { - "exit-code": 0 - } - } - ] -} - From 930961c945b6b59b262c28bb5bfb4a73b593caeb Mon Sep 17 00:00:00 2001 From: Chris Gundlach Date: Fri, 29 Jul 2022 09:18:42 -0500 Subject: [PATCH 11/12] regenerated nested_container.abi --- .../abigen-pass/nested_container.abi | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/tests/toolchain/abigen-pass/nested_container.abi b/tests/toolchain/abigen-pass/nested_container.abi index 912d31d704..0f9d9055ce 100644 --- a/tests/toolchain/abigen-pass/nested_container.abi +++ b/tests/toolchain/abigen-pass/nested_container.abi @@ -1,7 +1,16 @@ { "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ", "version": "eosio::abi/1.2", - "types": [], + "types": [ + { + "new_type_name": "B_map_string_string_E", + "type": "pair_string_string[]" + }, + { + "new_type_name": "B_vector_int32_E", + "type": "int32[]" + } + ], "structs": [ { "name": "map2map", @@ -13,12 +22,12 @@ }, { "name": "m2m", - "type": "pair_string_pair_string_string[][]" + "type": "pair_string_B_map_string_string_E[]" } ] }, { - "name": "pair_string_pair_string_string", + "name": "pair_string_B_map_string_string_E", "base": "", "fields": [ { @@ -27,7 +36,7 @@ }, { "name": "value", - "type": "pair_string_string[]" + "type": "B_map_string_string_E" } ] }, @@ -55,7 +64,29 @@ }, { "name": "tp2", - "type": "tuple_int32_float64_string_int32[]" + "type": "tuple_int32_float64_string_B_vector_int32_E" + } + ] + }, + { + "name": "tuple_int32_float64_string_B_vector_int32_E", + "base": "", + "fields": [ + { + "name": "field_0", + "type": "int32" + }, + { + "name": "field_1", + "type": "float64" + }, + { + "name": "field_2", + "type": "string" + }, + { + "name": "field_3", + "type": "B_vector_int32_E" } ] } @@ -73,7 +104,6 @@ } ], "tables": [], - "kv_tables": {}, "ricardian_clauses": [], "variants": [], "action_results": [] From 94af9c859a29ea8e1ea5b58d2c1e4a5b6b487df9 Mon Sep 17 00:00:00 2001 From: Chris Gundlach Date: Fri, 29 Jul 2022 10:46:06 -0500 Subject: [PATCH 12/12] changed confusing variable name --- tools/include/eosio/abigen.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index b950c59232..3347553402 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -167,9 +167,9 @@ namespace eosio { namespace cdt { for (int i = 0; i < 2; ++i) { add_type(std::get(get_template_argument(type, i))); } - abi_struct kv; + abi_struct map_info; std::string name = get_type(type); - kv.name = name.substr(0, name.length() - 2); + map_info.name = name.substr(0, name.length() - 2); auto remove_ending_brackets = [&]( std::string name ) { int i = name.length()-1; for (; i >= 0; i--) @@ -177,12 +177,12 @@ namespace eosio { namespace cdt { break; return name.substr(0,i+1); }; - kv.name = remove_ending_brackets(name); - kv.fields.push_back( {"key", get_template_argument_as_string(type)} ); - kv.fields.push_back( {"value", get_template_argument_as_string(type, 1)} ); + map_info.name = remove_ending_brackets(name); + map_info.fields.push_back( {"key", get_template_argument_as_string(type)} ); + map_info.fields.push_back( {"value", get_template_argument_as_string(type, 1)} ); add_type(std::get(get_template_argument(type))); add_type(std::get(get_template_argument(type, 1))); - _abi.structs.insert(kv); + _abi.structs.insert(map_info); } void add_struct( const clang::CXXRecordDecl* decl, const std::string& rname="" ) {