提交 557cf4ba 编写于 作者: D Daniel Larimer

Implement Name base 32 - #56

This implements the Name type which interprets a 60 bit integer has
base32 with the characters '.abcdefghijklmnopqrstuvwxyz012345' and will
trim trailing '.' when converting to a string. This allows names up to
12 characters long.  Internal '.' is allowed.
上级 14ad6430
......@@ -5,6 +5,7 @@
#include <functional>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <fc/variant.hpp>
#include <fc/crypto/base64.hpp>
......@@ -54,6 +55,55 @@ namespace eos { namespace types {
using Int128 = boost::multiprecision::int128_t;
using Int256 = boost::multiprecision::int256_t;
struct Name {
uint64_t value = 0;
Name( const String& str ) {
FC_ASSERT( str.size() <= 12 );
for( uint32_t i = 0; i < str.size(); ++i ) {
value <<= 5;
value |= char_to_symbol( str[ str.size() -1 - i ] );
}
}
char char_to_symbol( char c ) const {
if( c >= 'a' && c <= 'z' )
return (c - 'a') + 1;
if( c >= '1' && c <= '5' )
return (c - '1') + 26;
FC_ASSERT( c == '.', "invalid character '${c}' (${i}) in Name string", ("c", String(&c,1))("i",int(c)) );
return 0;
}
Name( uint64_t v = 0 ):value(v){
FC_ASSERT( !(v>>(5*12)), "invalid name id" );
};
operator String()const {
static const char* charmap = ".abcdefghijklmnopqrstuvwxyz12345";
String str;
uint64_t tmp = value;
for( uint32_t i = 0; i < 12; ++i ) {
char c = charmap[tmp & 0x1f ];
str += c;
tmp >>= 5;
}
boost::algorithm::trim_right_if( str, []( char c ){ return c == '.'; } );
return str;
}
Name& operator=( uint64_t v ) {
FC_ASSERT( !(v>>(5*12)), "invalid name id" );
value = v;
return *this;
}
Name& operator=( const String& n ) {
value = Name(n).value;
return *this;
}
operator uint64_t()const { return value; }
};
struct Field {
FieldName name;
TypeName type;
......@@ -114,11 +164,14 @@ namespace eos { namespace types {
}} // namespace eos::types
namespace fc {
void to_variant(const eos::types::Name& c, fc::variant& v);
void from_variant(const fc::variant& v, eos::types::Name& check);
void to_variant(const std::vector<eos::types::Field>& c, fc::variant& v);
void from_variant(const fc::variant& v, std::vector<eos::types::Field>& check);
void to_variant(const std::map<std::string,eos::types::Struct>& c, fc::variant& v);
void from_variant(const fc::variant& v, std::map<std::string,eos::types::Struct>& check);
}
FC_REFLECT(eos::types::Name, (value))
FC_REFLECT(eos::types::Field, (name)(type))
FC_REFLECT(eos::types::Struct, (name)(base)(fields))
......@@ -6,6 +6,9 @@
#include <fc/reflect/variant.hpp>
namespace fc {
void to_variant(const eos::types::Name& c, fc::variant& v) { v = std::string(c); }
void from_variant(const fc::variant& v, eos::types::Name& check) { check = v.get_string(); }
void to_variant(const std::vector<eos::types::Field>& c, fc::variant& v) {
fc::mutable_variant_object mvo; mvo.reserve(c.size());
for(const auto& f : c) {
......
......@@ -48,6 +48,22 @@ using namespace chain;
BOOST_AUTO_TEST_SUITE(block_tests)
BOOST_AUTO_TEST_CASE(name_test) {
using eos::types::Name;
Name temp;
temp = "temp";
BOOST_CHECK_EQUAL( String("temp"), String(temp) );
BOOST_CHECK_EQUAL( String("temp.temp"), String(Name("temp.temp")) );
BOOST_CHECK_EQUAL( String(""), String(Name()) );
BOOST_CHECK_EQUAL( String("hello"), String(Name("hello")) );
BOOST_REQUIRE_THROW( Name(-1), fc::exception ); // only lower 60 bits are valid
BOOST_REQUIRE_THROW( Name("Hello"), fc::exception ); // capital invalid
BOOST_REQUIRE_THROW( Name("9ello"), fc::exception ); // number 9 invalid
BOOST_REQUIRE_THROW( Name("6ello"), fc::exception ); // number 6 invalid
}
// Simple test of block production and head_block_num tracking
BOOST_FIXTURE_TEST_CASE(produce_blocks, testing_fixture)
{ try {
......
......@@ -6,6 +6,7 @@ namespace eos { namespace types {
BOOST_AUTO_TEST_SUITE(types_tests)
/// Put the SimpleSymbolTable through its paces
BOOST_AUTO_TEST_CASE(basic_simple_symbol_table_test)
{ try {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册