Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Support std::array by adding ABI symbol T[N] #1196

Merged
merged 4 commits into from
Sep 8, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tests/unit/test_contracts/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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(kv_single_index_tests kv_single_index_tests kv_single_index_tests.cpp)
Expand Down
125 changes: 125 additions & 0 deletions tests/unit/test_contracts/array_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#include <eosio/eosio.hpp>
softprofe marked this conversation as resolved.
Show resolved Hide resolved
#include <eosio/transaction.hpp>

using namespace eosio;

class [[eosio::contract]] array_tests : public contract {
public:
using contract::contract;

TABLE tests {
uint64_t id;
std::array<uint8_t,32> str;
uint64_t primary_key() const { return id; }
};
struct info {
int age;
std::string name;
};
typedef multi_index<name("tests"), tests> tests_table;
softprofe marked this conversation as resolved.
Show resolved Hide resolved

// test inside using std::array
[[eosio::action]]
void testin(std::string message) {
tests_table _tests(get_self(), get_self().value);

std::array<uint8_t, 32> 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<uint8_t, 32> 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, 2> 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<int,4> input){
std::array<int,4> 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<int,4> testre(std::array<int,4> input){
//std::array<char,7> arr = {'a','b','c','d','e','f','g'};
std::array<int,4> 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<int> testrev(std::vector<int> input){
std::vector<int> vec = input;
for(auto & v : vec) v += 1;
return vec;
}

// test nested array
[[eosio::action]]
void testne() {
std::array<tests,2> nest;
std::array<uint8_t, 32> 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";
}
}

// test complex data
[[eosio::action]]
void testcom(name user) {
require_auth(user);
tests_table _tests(get_self(), get_self().value);

std::array<uint8_t, 32> str = {'a','a','a','a','a','a','a','a',
softprofe marked this conversation as resolved.
Show resolved Hide resolved
'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;
});
}

};


4 changes: 3 additions & 1 deletion tools/include/eosio/abigen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include <memory>
#include <set>
#include <map>

#include <array>
#include <jsoncons/json.hpp>

using namespace llvm;
Expand Down Expand Up @@ -404,6 +404,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<clang::QualType>(get_template_argument(type, 0)));
else if (is_template_specialization(type, {"variant"}))
add_variant(type);
else if (is_template_specialization(type, {})) {
Expand Down
17 changes: 17 additions & 0 deletions tools/include/eosio/gen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,23 @@ 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);
for(auto & c : digits) {
bogniq marked this conversation as resolved.
Show resolved Hide resolved
if(c >= '0' && c <= '9' ){
ret += c;
}
}
ret += ']';
return ret;
}
else if ( is_template_specialization( type, {} )) {
auto pt = llvm::dyn_cast<clang::ElaboratedType>(type.getTypePtr());
auto tst = llvm::dyn_cast<clang::TemplateSpecializationType>(pt ? pt->desugar().getTypePtr() : type.getTypePtr() );
Expand Down