Facebook的c++开源库folly介绍

Facebook的c++开源库folly介绍folly 在 Facebook 内部广泛使用的一个 c 库 是开源的 github 地址 https github com facebook folly 之前的 boost 库给我们带来了很多方便 比如智能指针之类的 从 c 11 开始 对 std 标准库有了很大的补充 大大方便了 c 程序员 folly 是 Facebookopen 的缩写 其中用到了大量的 C 11 新标准 代

folly是Facebook open source library的缩写,其中用到了大量的C++11新标准,代码也是极其的规范,所以即使我们没必要使用folly这个库,我们也可以偶尔读一段它的源码,体验一下C++11带来的变化。

Conv.cpp
先贴一段代码,

/* * Copyright 2016 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include 
    #include 
    namespace folly { namespace detail { namespace { / * Finds the first non-digit in a string. The number of digits * searched depends on the precision of the Tgt integral. Assumes the * string starts with NO whitespace and NO sign. * * The semantics of the routine is: * for (;; ++b) { * if (b >= e || !isdigit(*b)) return b; * } * * Complete unrolling marks bottom-line (i.e. entire conversion) * improvements of 20%. */ inline const char* findFirstNonDigit(const char* b, const char* e) { for (; b < e; ++b) { auto const c = static_cast<unsigned>(*b) - '0'; if (c >= 10) { break; } } return b; } // Maximum value of number when represented as a string template <class T> struct MaxString { static const char* const value; }; template <> const char *const MaxString 
  
    ::value = 
   "255"; 
   template <> 
   const 
   char * 
   const MaxString 
   
     ::value = 
    "65535"; 
    template <> 
    const 
    char * 
    const MaxString 
    
      ::value = 
     ""; 
     #if __SIZEOF_LONG__ == 4 
     template <> 
     const 
     char * 
     const MaxString< 
     unsigned 
     long>::value = 
     ""; 
     #else 
     template <> 
     const 
     char * 
     const MaxString< 
     unsigned 
     long>::value = 
     ""; 
     #endif 
     static_assert( 
     sizeof( 
     unsigned 
     long) >= 
     4, 
     "Wrong value for MaxString 
      
        ::value," 
       
     " please update."); 
     template <> 
     const 
     char * 
     const MaxString< 
     unsigned 
     long 
     long>::value = 
     ""; 
     static_assert( 
     sizeof( 
     unsigned 
     long 
     long) >= 
     8, 
     "Wrong value for MaxString 
      
        ::value" 
       
     ", please update."); 
     #if FOLLY_HAVE_INT128_T 
     template <> 
     const 
     char * 
     const MaxString<__uint128_t>::value = 
     "011455"; 
     #endif 
     /* * Lookup tables that converts from a decimal character value to an integral * binary value, shifted by a decimal "shift" multiplier. * For all character values in the range '0'..'9', the table at those * index locations returns the actual decimal value shifted by the multiplier. * For all other values, the lookup table returns an invalid OOR value. */ 
     // Out-of-range flag value, larger than the largest value that can fit in 
     // four decimal bytes (9999), but four of these added up together should 
     // still not overflow uint16_t. 
     constexpr int32_t OOR = 
     10000; FOLLY_ALIGNED( 
     16) 
     constexpr uint16_t shift1[] = { OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 0-9 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 10 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 20 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 30 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     0, 
     // 40 
     1, 
     2, 
     3, 
     4, 
     5, 
     6, 
     7, 
     8, 
     9, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 60 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 70 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 80 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 90 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 100 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 110 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 120 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 130 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 140 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 150 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 160 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 170 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 180 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 190 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 200 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 210 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 220 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 230 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 240 OOR, OOR, OOR, OOR, OOR, OOR 
     // 250 }; FOLLY_ALIGNED( 
     16) 
     constexpr uint16_t shift10[] = { OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 0-9 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 10 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 20 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 30 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     0, 
     // 40 
     10, 
     20, 
     30, 
     40, 
     50, 
     60, 
     70, 
     80, 
     90, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 60 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 70 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 80 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 90 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 100 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 110 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 120 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 130 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 140 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 150 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 160 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 170 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 180 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 190 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 200 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 210 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 220 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 230 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 240 OOR, OOR, OOR, OOR, OOR, OOR 
     // 250 }; FOLLY_ALIGNED( 
     16) 
     constexpr uint16_t shift100[] = { OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 0-9 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 10 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 20 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 30 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     0, 
     // 40 
     100, 
     200, 
     300, 
     400, 
     500, 
     600, 
     700, 
     800, 
     900, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 60 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 70 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 80 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 90 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 100 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 110 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 120 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 130 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 140 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 150 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 160 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 170 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 180 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 190 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 200 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 210 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 220 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 230 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 240 OOR, OOR, OOR, OOR, OOR, OOR 
     // 250 }; FOLLY_ALIGNED( 
     16) 
     constexpr uint16_t shift1000[] = { OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 0-9 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 10 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 20 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 30 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     0, 
     // 40 
     1000, 
     2000, 
     3000, 
     4000, 
     5000, 
     6000, 
     7000, 
     8000, 
     9000, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 60 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 70 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 80 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 90 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 100 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 110 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 120 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 130 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 140 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 150 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 160 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 170 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 180 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 190 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 200 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 210 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 220 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 230 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 
     // 240 OOR, OOR, OOR, OOR, OOR, OOR 
     // 250 }; 
     struct ErrorString { 
     const 
     char* 
     string; 
     bool quote; }; 
     // Keep this in sync with ConversionCode in Conv.h 
     constexpr 
     const 
     std:: 
     array< ErrorString, static_cast<std::size_t>(ConversionCode::NUM_ERROR_CODES)> kErrorStrings{ 
     { { 
      
     "Success", 
     true}, { 
      
     "Empty input string", 
     true}, { 
      
     "No digits found in input string", 
     true}, { 
      
     "Integer overflow when parsing bool (must be 0 or 1)", 
     true}, { 
      
     "Invalid value for bool", 
     true}, { 
      
     "Non-digit character found", 
     true}, { 
      
     "Invalid leading character", 
     true}, { 
      
     "Overflow during conversion", 
     true}, { 
      
     "Negative overflow during conversion", 
     true}, { 
      
     "Unable to convert string to floating point value", 
     true}, { 
      
     "Non-whitespace character found after end of conversion", 
     true}, { 
      
     "Overflow during arithmetic conversion", 
     false}, { 
      
     "Negative overflow during arithmetic conversion", 
     false}, { 
      
     "Loss of precision during arithmetic conversion", 
     false}, }}; 
     // Check if ASCII is really ASCII 
     using IsAscii = 
     std:: integral_constant< 
     bool, 
     'A' == 
     65 && 
     'Z' == 
     90 && 
     'a' == 
     97 && 
     'z' == 
     122>; 
     // The code in this file that uses tolower() really only cares about 
     // 7-bit ASCII characters, so we can take a nice shortcut here. 
     inline 
     char tolower_ascii( 
     char in) { 
     return IsAscii::value ? in | 
     0x20 : 
     std:: 
     tolower(in); } 
     inline 
     bool bool_str_cmp( 
     const 
     char b, size_t len, 
     const 
     char* value) { 
     // Can't use strncasecmp, since we want to ensure that the full value matches 
     const 
     char* p = *b; 
     const 
     char* e = *b + len; 
     const 
     char* v = value; 
     while (*v != 
     '\0') { 
     if (p == e || tolower_ascii(*p) != *v) { 
     // value is already lowercase 
     return 
     false; } ++p; ++v; } *b = p; 
     return 
     true; } } 
     // anonymous namespace Expected< 
     bool, ConversionCode> str_to_bool(StringPiece* src) 
     noexcept { 
     auto b = src->begin(), e = src->end(); 
     for (;; ++b) { 
     if (b >= e) { 
     return makeUnexpected(ConversionCode::EMPTY_INPUT_STRING); } 
     if (! 
     std:: 
     isspace(*b)) { 
     break; } } 
     bool result; size_t len = e - b; 
     switch (*b) { 
     case 
     '0': 
     case 
     '1': { result = 
     false; 
     for (; b < e && 
     isdigit(*b); ++b) { 
     if (result || (*b != 
     '0' && *b != 
     '1')) { 
     return makeUnexpected(ConversionCode::BOOL_OVERFLOW); } result = (*b == 
     '1'); } 
     break; } 
     case 
     'y': 
     case 
     'Y': result = 
     true; 
     if (!bool_str_cmp(&b, len, 
     "yes")) { ++b; 
     // accept the single 'y' character } 
     break; 
     case 
     'n': 
     case 
     'N': result = 
     false; 
     if (!bool_str_cmp(&b, len, 
     "no")) { ++b; } 
     break; 
     case 
     't': 
     case 
     'T': result = 
     true; 
     if (!bool_str_cmp(&b, len, 
     "true")) { ++b; } 
     break; 
     case 
     'f': 
     case 
     'F': result = 
     false; 
     if (!bool_str_cmp(&b, len, 
     "false")) { ++b; } 
     break; 
     case 
     'o': 
     case 
     'O': 
     if (bool_str_cmp(&b, len, 
     "on")) { result = 
     true; } 
     else 
     if (bool_str_cmp(&b, len, 
     "off")) { result = 
     false; } 
     else { 
     return makeUnexpected(ConversionCode::BOOL_INVALID_VALUE); } 
     break; 
     default: 
     return makeUnexpected(ConversionCode::BOOL_INVALID_VALUE); } src->assign(b, e); 
     return result; } 
     / * StringPiece to double, with progress information. Alters the * StringPiece parameter to munch the already-parsed characters. */ 
     template < 
     class Tgt> Expected 
     
       str_to_floating(StringPiece* src) 
      noexcept { 
      using 
      namespace double_conversion; 
      static StringToDoubleConverter conv(StringToDoubleConverter::ALLOW_TRAILING_JUNK | StringToDoubleConverter::ALLOW_LEADING_SPACES, 
      0.0, 
      // return this for junk input string 
      std::numeric_limits< 
      double>::quiet_NaN(), 
      nullptr, 
      nullptr); 
      if (src->empty()) { 
      return makeUnexpected(ConversionCode::EMPTY_INPUT_STRING); } 
      int length; 
      auto result = conv.StringToDouble(src->data(), 
      static_cast< 
      int>(src->size()), &length); 
      // processed char count 
      if (! 
      std::isnan(result)) { 
      // If we get here with length = 0, the input string is empty. 
      // If we get here with result = 0.0, it's either because the string 
      // contained only whitespace, or because we had an actual zero value 
      // (with potential trailing junk). If it was only whitespace, we 
      // want to raise an error; length will point past the last character 
      // that was processed, so we need to check if that character was 
      // whitespace or not. 
      if (length == 
      0 || (result == 
      0.0 && 
      std:: 
      isspace((*src)[length - 
      1]))) { 
      return makeUnexpected(ConversionCode::EMPTY_INPUT_STRING); } src->advance(length); 
      return result; } 
      auto* e = src->end(); 
      auto* b = 
      std::find_if_not(src->begin(), e, []( 
      char c) { 
      return 
      std:: 
      isspace(c); }); 
      // There must be non-whitespace, otherwise we would have caught this above assert(b < e); size_t size = e - b; 
      bool negative = 
      false; 
      if (*b == 
      '-') { negative = 
      true; ++b; --size; } result = 
      0.0; 
      switch (tolower_ascii(*b)) { 
      case 
      'i': 
      if (size >= 
      3 && tolower_ascii(b[ 
      1]) == 
      'n' && tolower_ascii(b[ 
      2]) == 
      'f') { 
      if (size >= 
      8 && tolower_ascii(b[ 
      3]) == 
      'i' && tolower_ascii(b[ 
      4]) == 
      'n' && tolower_ascii(b[ 
      5]) == 
      'i' && tolower_ascii(b[ 
      6]) == 
      't' && tolower_ascii(b[ 
      7]) == 
      'y') { b += 
      8; } 
      else { b += 
      3; } result = 
      std::numeric_limits 
      
        ::infinity(); } 
       break; 
       case 
       'n': 
       if (size >= 
       3 && tolower_ascii(b[ 
       1]) == 
       'a' && tolower_ascii(b[ 
       2]) == 
       'n') { b += 
       3; result = 
       std::numeric_limits 
       
         ::quiet_NaN(); } 
        break; 
        default: 
        break; } 
        if (result == 
        0.0) { 
        // All bets are off 
        return makeUnexpected(ConversionCode::STRING_TO_FLOAT_ERROR); } 
        if (negative) { result = -result; } src->assign(b, e); 
        return result; } 
        template Expected< 
        float, ConversionCode> str_to_floating< 
        float>( StringPiece* src) 
        noexcept; 
        template Expected< 
        double, ConversionCode> str_to_floating< 
        double>( StringPiece* src) 
        noexcept; 
        / * This class takes care of additional processing needed for signed values, * like leading sign character and overflow checks. */ 
        template < 
        typename T, 
        bool IsSigned = 
        std::is_signed 
        
          ::value> 
         class SignedValueHandler; 
         template < 
         typename T> 
         class SignedValueHandler 
         
           true> { 
          public: ConversionCode init( 
          const 
          char*& b) { negative_ = 
          false; 
          if (! 
          std:: 
          isdigit(*b)) { 
          if (*b == 
          '-') { negative_ = 
          true; } 
          else 
          if (UNLIKELY(*b != 
          '+')) { 
          return ConversionCode::INVALID_LEADING_CHAR; } ++b; } 
          return ConversionCode::SUCCESS; } ConversionCode overflow() { 
          return negative_ ? ConversionCode::NEGATIVE_OVERFLOW : ConversionCode::POSITIVE_OVERFLOW; } 
          template < 
          typename U> Expected 
          
            finalize(U value) { T rv; 
           if (negative_) { rv = -value; 
           if (UNLIKELY(rv > 
           0)) { 
           return makeUnexpected(ConversionCode::NEGATIVE_OVERFLOW); } } 
           else { rv = value; 
           if (UNLIKELY(rv < 
           0)) { 
           return makeUnexpected(ConversionCode::POSITIVE_OVERFLOW); } } 
           return rv; } 
           private: 
           bool negative_; }; 
           // For unsigned types, we don't need any extra processing 
           template < 
           typename T> 
           class SignedValueHandler 
           
             false> { 
            public: ConversionCode init( 
            const 
            char*&) { 
            return ConversionCode::SUCCESS; } ConversionCode overflow() { 
            return ConversionCode::POSITIVE_OVERFLOW; } Expected 
            
              finalize(T value) { 
             return value; } }; 
             / * String represented as a pair of pointers to char to signed/unsigned * integrals. Assumes NO whitespace before or after, and also that the * string is composed entirely of digits (and an optional sign only for * signed types). String may be empty, in which case digits_to returns * an appropriate error. */ 
             template < 
             class Tgt> 
             inline Expected 
             
               digits_to( 
              const 
              char* b, 
              const 
              char* 
              const e) 
              noexcept { 
              using UT = 
              typename 
              std::make_unsigned 
              
                ::type; assert(b <= e); SignedValueHandler 
               
                 sgn; 
                auto err = sgn.init(b); 
                if (UNLIKELY(err != ConversionCode::SUCCESS)) { 
                return makeUnexpected(err); } size_t size = e - b; 
                /* Although the string is entirely made of digits, we still need to * check for overflow. */ 
                if (size > 
                std::numeric_limits 
                
                  ::digits10) { 
                 // Leading zeros? 
                 if (b < e && *b == 
                 '0') { 
                 for (++b;; ++b) { 
                 if (b == e) { 
                 return Tgt( 
                 0); 
                 // just zeros, e.g. "0000" } 
                 if (*b != 
                 '0') { size = e - b; 
                 break; } } } 
                 if (size > 
                 std::numeric_limits 
                 
                   ::digits10 && (size != 
                  std::numeric_limits 
                  
                    ::digits10 + 
                   1 || 
                   strncmp(b, MaxString 
                   
                     ::value, size) > 
                    0)) { 
                    return makeUnexpected(sgn.overflow()); } } 
                    // Here we know that the number won't overflow when 
                    // converted. Proceed without checks. UT result = 
                    0; 
                    for (; e - b >= 
                    4; b += 
                    4) { result *= 
                    10000; 
                    const int32_t r0 = shift1000[ 
                    static_cast 
                    
                      (b[ 
                     0])]; 
                     const int32_t r1 = shift100[ 
                     static_cast 
                     
                       (b[ 
                      1])]; 
                      const int32_t r2 = shift10[ 
                      static_cast 
                      
                        (b[ 
                       2])]; 
                       const int32_t r3 = shift1[ 
                       static_cast 
                       
                         (b[ 
                        3])]; 
                        const 
                        auto sum = r0 + r1 + r2 + r3; 
                        if (sum >= OOR) { 
                        goto outOfRange; } result += sum; } 
                        switch (e - b) { 
                        case 
                        3: { 
                        const int32_t r0 = shift100[ 
                        static_cast 
                        
                          (b[ 
                         0])]; 
                         const int32_t r1 = shift10[ 
                         static_cast 
                         
                           (b[ 
                          1])]; 
                          const int32_t r2 = shift1[ 
                          static_cast 
                          
                            (b[ 
                           2])]; 
                           const 
                           auto sum = r0 + r1 + r2; 
                           if (sum >= OOR) { 
                           goto outOfRange; } result = 
                           1000 * result + sum; 
                           break; } 
                           case 
                           2: { 
                           const int32_t r0 = shift10[ 
                           static_cast 
                           
                             (b[ 
                            0])]; 
                            const int32_t r1 = shift1[ 
                            static_cast 
                            
                              (b[ 
                             1])]; 
                             const 
                             auto sum = r0 + r1; 
                             if (sum >= OOR) { 
                             goto outOfRange; } result = 
                             100 * result + sum; 
                             break; } 
                             case 
                             1: { 
                             const int32_t sum = shift1[ 
                             static_cast 
                             
                               (b[ 
                              0])]; 
                              if (sum >= OOR) { 
                              goto outOfRange; } result = 
                              10 * result + sum; 
                              break; } 
                              default: assert(b == e); 
                              if (size == 
                              0) { 
                              return makeUnexpected(ConversionCode::NO_DIGITS); } 
                              break; } 
                              return sgn.finalize(result); outOfRange: 
                              return makeUnexpected(ConversionCode::NON_DIGIT_CHAR); } 
                              template Expected< 
                              char, ConversionCode> digits_to< 
                              char>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              signed 
                              char, ConversionCode> digits_to< 
                              signed 
                              char>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              unsigned 
                              char, ConversionCode> digits_to< 
                              unsigned 
                              char>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              short, ConversionCode> digits_to< 
                              short>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              unsigned 
                              short, ConversionCode> digits_to< 
                              unsigned 
                              short>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              int, ConversionCode> digits_to< 
                              int>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              unsigned 
                              int, ConversionCode> digits_to< 
                              unsigned 
                              int>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              long, ConversionCode> digits_to< 
                              long>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              unsigned 
                              long, ConversionCode> digits_to< 
                              unsigned 
                              long>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              long 
                              long, ConversionCode> digits_to< 
                              long 
                              long>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              unsigned 
                              long 
                              long, ConversionCode> digits_to< 
                              unsigned 
                              long 
                              long>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              #if FOLLY_HAVE_INT128_T 
                              template Expected<__int128, ConversionCode> digits_to<__int128>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              template Expected< 
                              unsigned __int128, ConversionCode> digits_to< 
                              unsigned __int128>( 
                              const 
                              char*, 
                              const 
                              char*) 
                              noexcept; 
                              #endif 
                              / * StringPiece to integrals, with progress information. Alters the * StringPiece parameter to munch the already-parsed characters. */ 
                              template < 
                              class Tgt> Expected 
                              
                                str_to_integral(StringPiece* src) 
                               noexcept { 
                               using UT = 
                               typename 
                               std::make_unsigned 
                               
                                 ::type; 
                                auto b = src->data(), past = src->data() + src->size(); 
                                for (;; ++b) { 
                                if (UNLIKELY(b >= past)) { 
                                return makeUnexpected(ConversionCode::EMPTY_INPUT_STRING); } 
                                if (! 
                                std:: 
                                isspace(*b)) { 
                                break; } } SignedValueHandler 
                                
                                  sgn; 
                                 auto err = sgn.init(b); 
                                 if (UNLIKELY(err != ConversionCode::SUCCESS)) { 
                                 return makeUnexpected(err); } 
                                 if ( 
                                 std::is_signed 
                                 
                                   ::value && UNLIKELY(b >= past)) { 
                                  return makeUnexpected(ConversionCode::NO_DIGITS); } 
                                  if (UNLIKELY(! 
                                  isdigit(*b))) { 
                                  return makeUnexpected(ConversionCode::NON_DIGIT_CHAR); } 
                                  auto m = findFirstNonDigit(b + 
                                  1, past); 
                                  auto tmp = digits_to 
                                  
                                    (b, m); 
                                   if (UNLIKELY(!tmp.hasValue())) { 
                                   return makeUnexpected( tmp.error() == ConversionCode::POSITIVE_OVERFLOW ? sgn.overflow() : tmp.error()); } 
                                   auto res = sgn.finalize(tmp.value()); 
                                   if (res.hasValue()) { src->advance(m - src->data()); } 
                                   return res; } 
                                   template Expected< 
                                   char, ConversionCode> str_to_integral< 
                                   char>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   signed 
                                   char, ConversionCode> str_to_integral< 
                                   signed 
                                   char>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   unsigned 
                                   char, ConversionCode> str_to_integral< 
                                   unsigned 
                                   char>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   short, ConversionCode> str_to_integral< 
                                   short>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   unsigned 
                                   short, ConversionCode> str_to_integral< 
                                   unsigned 
                                   short>(StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   int, ConversionCode> str_to_integral< 
                                   int>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   unsigned 
                                   int, ConversionCode> str_to_integral< 
                                   unsigned 
                                   int>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   long, ConversionCode> str_to_integral< 
                                   long>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   unsigned 
                                   long, ConversionCode> str_to_integral< 
                                   unsigned 
                                   long>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   long 
                                   long, ConversionCode> str_to_integral< 
                                   long 
                                   long>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   unsigned 
                                   long 
                                   long, ConversionCode> str_to_integral< 
                                   unsigned 
                                   long 
                                   long>(StringPiece* src) 
                                   noexcept; 
                                   #if FOLLY_HAVE_INT128_T 
                                   template Expected<__int128, ConversionCode> str_to_integral<__int128>( StringPiece* src) 
                                   noexcept; 
                                   template Expected< 
                                   unsigned __int128, ConversionCode> str_to_integral< 
                                   unsigned __int128>(StringPiece* src) 
                                   noexcept; 
                                   #endif } 
                                   // namespace detail ConversionError makeConversionError(ConversionCode code, StringPiece input) { 
                                   using 
                                   namespace detail; 
                                   static_assert( 
                                   std::is_unsigned< 
                                   std::underlying_type 
                                   
                                     ::type>::value, 
                                    "ConversionCode should be unsigned"); assert(( 
                                    std::size_t)code < kErrorStrings.size()); 
                                    const ErrorString& err = kErrorStrings[( 
                                    std::size_t)code]; 
                                    if (code == ConversionCode::EMPTY_INPUT_STRING && input.empty()) { 
                                    return {err. 
                                    string, code}; } 
                                    std:: 
                                    string tmp(err. 
                                    string); tmp.append( 
                                    ": "); 
                                    if (err.quote) { tmp.append( 
                                    1, 
                                    '"'); } 
                                    if (input.size() > 
                                    0) { tmp.append(input.data(), input.size()); } 
                                    if (err.quote) { tmp.append( 
                                    1, 
                                    '"'); } 
                                    return {tmp, code}; } } 
                                    // namespace folly 
                                    
                                   
                                  
                                 
                                
                               
                              
                             
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
       
      
     
    
  

当然还有很多,闲着的时候可以看看。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/202589.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午11:47
下一篇 2026年3月19日 下午11:47


相关推荐

  • 网站加载速度优化的14个技巧

    网站加载速度优化的14个技巧

    2021年10月14日
    62
  • 网络监视--netstat命令详解

    网络监视--netstat命令详解在 InternetRFC 标准中 Netstat 的定义是 Netstat 是在内核中访问网络及相关信息的程序 它能提供 TCP 连接 TCP 和 UDP 监听 进程内存管理的相关报告 Netstat 是控制台命令 是一个监控 TCP IP 网络的非常有用的工具 它可以显示路由表 实际的网络连接以及每一个网络接口设备的状态信息 Netstat 用于显示与 IP TCP UDP 和 ICMP 协议相关的统计数据 一般用于检

    2026年3月26日
    2
  • CC2530之OLED12864程序详解

    CC2530之OLED12864程序详解暂时先贴上程序 我再整理整理 include code tab h defineLCD SCLP0 4 串行时钟输入 defineLCD SDAP0 5 串行数据输入 defineLCD RSTP0 6 复位输入端 defineLCD DCP0 7 数据 命令控制 defineXLevel

    2026年3月26日
    3
  • 向量投影推导

    向量投影推导给定一个向量 u 和 v 求 u 在 v 上的投影向量 如下图 假设 u 在 v 上的投影向量是 u 且向量 u 和 v 的夹角为 theta 一个向量有两个属性 大小和方向 我们先确定 u 的大小 即长度 或者模 从 u 的末端做 v 的垂线 那么 d 就是 u 的长度 而 u 和 v 的方向是相同的 v 的方向 v v 也就是 u 的方向 所以有 1 再求 d 的长度 2 最后求 cos theta

    2026年3月18日
    2
  • 常见积分不等式

    常见积分不等式文章目录①柯西施瓦茨不等式②6.75③3.132④3.133⑤3.134⑥3.142①柯西施瓦茨不等式[∫f(x)∗g(x)dx]2≤∫f2(x)dx⋅∫g2(x)dx[\intf(x)*g(x)dx]^2\leq\intf^2(x)dx\cdot\intg^2(x)dx[∫f(x)∗g(x)dx]2≤∫f2(x)dx⋅∫g2(x)dx这个在张…

    2022年6月3日
    40
  • The Debian menu 转自openbox官方网站

    The Debian menu 转自openbox官方网站

    2021年7月25日
    67

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号