【精】EOS智能合约:system系统合约源码分析 (3)

name结构体定义在libraries\eosiolib\name.hpp,源码注释如下:

struct name { public: enum class raw : uint64_t {}; // 构建一个新的name对象,初始化默认为0 constexpr name() : value(0) {} // 使用给定的unit64_t类型的值构建一个新的name对象。 constexpr explicit name( uint64_t v ) :value(v) {} // 使用给定的一个范围的枚举类型,构建一个新的name对象。 constexpr explicit name( name::raw r ) :value(static_cast<uint64_t>(r)) {} // 使用给定的字符串构建一个新的name对象。 constexpr explicit name( std::string_view str ) :value(0) { if( str.size() > 13 ) { // 字符串最长不能超过12 eosio::check( false, "string is too long to be a valid name" ); } if( str.empty() ) { return; } // 将字符串转为uint64_t auto n = std::min( (uint32_t)str.size(), (uint32_t)12u ); for( decltype(n) i = 0; i < n; ++i ) { value <<= 5; value |= char_to_value( str[i] ); } value <<= ( 4 + 5*(12 - n) ); if( str.size() == 13 ) { uint64_t v = char_to_value( str[12] ); if( v > 0x0Full ) { eosio::check(false, "thirteenth character in name cannot be a letter that comes after j"); } value |= v; } } // 将一个Base32符号的char转换为它对应的值。 static constexpr uint8_t char_to_value( char c ) { if( c == '.') return 0; else if( c >= '1' && c <= '5' ) return (c - '1') + 1; else if( c >= 'a' && c <= 'z' ) return (c - 'a') + 6; else // 字符中出现了不允许的内容。 eosio::check( false, "character is not in allowed character set for names" ); return 0; // 流程控制将不会到达这里,这一行是为了防止warn信息。 } // 返回一个name对象的长度,运算方法。 constexpr uint8_t length()const { constexpr uint64_t mask = 0xF800000000000000ull; if( value == 0 ) return 0; uint8_t l = 0; uint8_t i = 0; for( auto v = value; i < 13; ++i, v <<= 5 ) { if( (v & mask) > 0 ) { l = i; } } return l + 1; } // 返回一个name对象的后缀,完整的运算方法。 constexpr name suffix()const { uint32_t remaining_bits_after_last_actual_dot = 0; uint32_t tmp = 0; for( int32_t remaining_bits = 59; remaining_bits >= 4; remaining_bits -= 5 ) { // remaining_bits必须保持有符号整数 // 从左到右依次遍历name中的字符,共12次 auto c = (value >> remaining_bits) & 0x1Full; if( !c ) { // 如果当前字符是点 tmp = static_cast<uint32_t>(remaining_bits); } else { // 如果当前字符不是点 remaining_bits_after_last_actual_dot = tmp; } } uint64_t thirteenth_character = value & 0x0Full; if( thirteenth_character ) { // 如果第13个字符不是点 remaining_bits_after_last_actual_dot = tmp; } if( remaining_bits_after_last_actual_dot == 0 ) // 除了潜在的前导点之外,name中没有实际的点 return name{value}; // 此时,remaining_bits_after_last_actual_dot必须在4到59的范围内(并且限制为5的增量)。 // 除了4个最低有效位(对应于第13个字符)之外,对应于最后一个实际点之后的字符的剩余位的掩码。 uint64_t mask = (1ull << remaining_bits_after_last_actual_dot) - 16; uint32_t shift = 64 - remaining_bits_after_last_actual_dot; return name{ ((value & mask) << shift) + (thirteenth_character << (shift-1)) }; } // 将name类型转为raw枚举类型:基于name对象的值,返回一个raw枚举类型的实例。 constexpr operator raw()const { return raw(value); } // 显式转换一个name的uint64_t值为bool,如果name的值不为0,返回true。 constexpr explicit operator bool()const { return value != 0; } // 根据给定的char缓冲区,以字符串的类型写入name对象。参数begin:char缓冲区的开头,参数end:刚好超过char缓冲区的位置,作为结尾。 char* write_as_string( char* begin, char* end )const { static const char* charmap = ".12345abcdefghijklmnopqrstuvwxyz"; constexpr uint64_t mask = 0xF800000000000000ull; if( (begin + 13) < begin || (begin + 13) > end ) return begin; auto v = value; for( auto i = 0; i < 13; ++i, v <<= 5 ) { if( v == 0 ) return begin; auto indx = (v & mask) >> (i == 12 ? 60 : 59); *begin = charmap[indx]; ++begin; } return begin; } // 将name对象转为一个字符串返回。 std::string to_string()const { char buffer[13]; auto end = write_as_string( buffer, buffer + sizeof(buffer) ); return {buffer, end}; } // 重载运算符等于号,给定两个name对象,如果他们的value相等,则返回true,说明对象也相等。 friend constexpr bool operator == ( const name& a, const name& b ) { return a.value == b.value; } // 重载运算符符不等于,如果给定的两个name对象的value不相等,则返回true,说明对象也不相等。 friend constexpr bool operator != ( const name& a, const name& b ) { return a.value != b.value; } // 重载运算符小于号,原理同上。 friend constexpr bool operator < ( const name& a, const name& b ) { return a.value < b.value; } uint64_t value = 0; // 其实name对象只有一个有效属性,就是value,以上都是name对象的构造方式、限制条件、各种转型以及运算符重载的内容。 EOSLIB_SERIALIZE( name, (value) ) }; 三、exchange_state.hpp

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsspgz.html