EOS 智能合约源代码解读 (1)name.hpp

/// Immutable except for fc::from_variant.
   struct name {
   private:
      friend struct fc::reflector<name>;
      friend void fc::from_variant(const fc::variant& v, tafsys::chain::name& check);

      void set( std::string_view str );

      std::string to_string()const;
      constexpr uint64_t to_uint64_t()const { return value; }

// 构建一个新的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};  
   }  

   // 重载运算符等于号
   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;  
   }  

   // 重载运算符小于号
   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) )  
}; 

   // Each char of the string is encoded into 5-bit chunk and left-shifted
   // to its 5-bit slot starting with the highest slot for the first char.
   // The 13th char, if str is long enough, is encoded into 4-bit chunk
   // and placed in the lowest 4 bits. 64 = 12 * 5 + 4
   static constexpr name string_to_name( std::string_view str )
   {
      return name( string_to_uint64_t( str ) );
   }




上一篇:C++ const (二) constexpr和常量表达式,constexpr函数


下一篇:c++ constexpr用法