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

Commit

Permalink
Merge pull request #9917 from EOSIO/jjz-epe530-kv-next_key
Browse files Browse the repository at this point in the history
Create a fix to support requested encoding type in next_key
  • Loading branch information
nickjjzhao authored Jan 20, 2021
2 parents 438b625 + 1a86555 commit 240d7ac
Show file tree
Hide file tree
Showing 3 changed files with 451 additions and 0 deletions.
127 changes: 127 additions & 0 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2408,9 +2408,136 @@ read_only::get_table_rows_result read_only::get_kv_table_rows_context( const rea
walk_table_row_range( lb_itr, ub_itr, false );
}

// Set result.next_key
set_kv_next_key(p.encode_type, index_type, result);

return result;
}

namespace {
template <typename UInt, typename T>
UInt float_from_bytes(T& t, const std::string& next_key_bytes) {
std::stringstream ss;
ss << std::hex << next_key_bytes;
UInt val;
ss >> val;
UInt mask = 0;
UInt signbit = (static_cast<UInt>(1) << (std::numeric_limits<UInt>::digits - 1));
if (!(val & signbit)) //flip mask if val is positive
mask = ~mask;
val ^=(mask | signbit);
return val;
}
template <typename T>
void convert_from_bytes( T& t, const std::string& next_key_bytes) {
if constexpr (std::is_floating_point_v<T>) {
if constexpr (sizeof(T) == 4) {
uint32_t val = float_from_bytes<uint32_t>(t, next_key_bytes);
std::memcpy(&t, &val, sizeof(T));
}else {
static_assert(sizeof(T) == 8, "Unknown floating point type");
uint64_t val = float_from_bytes<uint64_t>(t, next_key_bytes);
std::memcpy(&t, &val, sizeof(T));
}
}else if constexpr (std::is_integral_v<T>) {
std::stringstream ss;
ss << std::hex << next_key_bytes;
auto unsigned_val = static_cast<std::make_unsigned_t<T>>(t);
ss >> unsigned_val;
if (unsigned_val > std::numeric_limits<T>::max()) {
t = unsigned_val + static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::min());
}
else {
t = unsigned_val + std::numeric_limits<T>::min();
}
}else {
FC_THROW_EXCEPTION(chain::contract_table_query_exception, "Unsupported type to convert from bytes");
}
}
void convert_to_hex(const int& n, string& str) {
std::stringstream ss1;
ss1<< std::hex << std::uppercase << n;
ss1 >> str;
}
template<typename T>
void hex_from_bytes(string& next_key, const string& next_key_bytes) {
T val;
convert_from_bytes(val, next_key_bytes);
convert_to_hex(val, next_key);
}
template<typename T>
void dec_from_bytes(string& next_key, const string& next_key_bytes) {
T val;
convert_from_bytes(val, next_key_bytes);
next_key = std::to_string(val);
}
}

void read_only::set_kv_next_key(const string& encode_type, const string& index_type, read_only::get_table_rows_result& result) const {
if (result.more == true) {
if (encode_type == "bytes") {
result.next_key = result.next_key_bytes;
}else if (encode_type == "string") {
result.next_key = boost::algorithm::unhex(result.next_key_bytes);
boost::algorithm::trim_right_if( result.next_key, []( char c ){ return c == '\0'; } );
}else if (encode_type == "name") {
uint64_t ull;
convert_from_bytes(ull, result.next_key_bytes);
name nm(ull);
result.next_key = nm.to_string();
}else if (encode_type == "hex") {
if (index_type == "uint64") {
hex_from_bytes<uint64_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "uint32") {
hex_from_bytes<uint32_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "uint16") {
hex_from_bytes<uint16_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "uint8") {
hex_from_bytes<uint8_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "int64") {
hex_from_bytes<int64_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "int32") {
hex_from_bytes<int32_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "int16") {
hex_from_bytes<int16_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "int8") {
hex_from_bytes<int8_t>(result.next_key, result.next_key_bytes);
}else if( index_type == "sha256" || index_type == "i256" ) {
result.next_key = result.next_key_bytes;
} else if( index_type == "ripemd160" ) {
result.next_key = result.next_key_bytes;
}else {
FC_THROW_EXCEPTION(chain::contract_table_query_exception, "Unsupported index type/encode_type: ${t}/${e} ", ("t", index_type)("e", encode_type));
}
}else if (encode_type == "dec") {
if (index_type == "float64") {
dec_from_bytes<double>(result.next_key, result.next_key_bytes);
}else if (index_type == "float32") {
dec_from_bytes<float>(result.next_key, result.next_key_bytes);
}else if (index_type == "uint64" ) {
dec_from_bytes<uint64_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "uint32") {
dec_from_bytes<uint32_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "uint16") {
dec_from_bytes<uint16_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "uint8") {
dec_from_bytes<uint8_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "int64") {
dec_from_bytes<int64_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "int32") {
dec_from_bytes<int32_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "int16") {
dec_from_bytes<int16_t>(result.next_key, result.next_key_bytes);
}else if (index_type == "int8") {
dec_from_bytes<int8_t>(result.next_key, result.next_key_bytes);
}else {
FC_THROW_EXCEPTION(chain::contract_table_query_exception, "Unsupported index type/encode_type: ${t}/${e} ", ("t", index_type)("e", encode_type));
}
}
}
}


struct table_receiver
: chain::backing_store::table_only_error_receiver<table_receiver, chain::contract_table_query_exception> {
table_receiver(read_only::get_table_by_scope_result& result, const read_only::get_table_by_scope_params& params)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ class read_only {
void make_prefix(eosio::name table_name, eosio::name index_name, uint8_t status, vector<char> &prefix)const;
get_table_rows_result get_kv_table_rows( const get_kv_table_rows_params& params )const;
get_table_rows_result get_kv_table_rows_context( const read_only::get_kv_table_rows_params& p, eosio::chain::kv_context &kv_context, const abi_def &abi )const;
void set_kv_next_key(const string& encode_type, const string& index_type, read_only::get_table_rows_result& result) const;

struct get_table_by_scope_params {
name code; // mandatory
Expand Down
Loading

0 comments on commit 240d7ac

Please sign in to comment.