Export of internal Abseil changes.
-- 821196cfb2a3b943ffdc4c9e75daec92d7ffb28b by Abseil Team <absl-team@google.com>: Performance improvements PiperOrigin-RevId: 212668992 -- 704858e2e767016bad27d53eec01d9d48e546b23 by Abseil Team <absl-team@google.com>: Low-level Portability enchancements for Abseil Mutex on WebAssembly. Emscripten Pthreads do not use signals, so remove use of pthread_sigmask or other async-signal-safe related handling code. PiperOrigin-RevId: 212527958 -- be3e38cb4d493b755132d20c8c2d1a51e45d5449 by Jon Cohen <cohenjon@google.com>: Internal change. PiperOrigin-RevId: 212523797 GitOrigin-RevId: 821196cfb2a3b943ffdc4c9e75daec92d7ffb28b Change-Id: I5694e23e4e09364a15dd6fc4e2e3f15e38835687
This commit is contained in:
		
							parent
							
								
									02451914b9
								
							
						
					
					
						commit
						8ff1374008
					
				
					 9 changed files with 198 additions and 170 deletions
				
			
		|  | @ -112,7 +112,7 @@ class ConvertedIntInfo { | |||
| // Note: 'o' conversions do not have a base indicator, it's just that
 | ||||
| // the '#' flag is specified to modify the precision for 'o' conversions.
 | ||||
| string_view BaseIndicator(const ConvertedIntInfo &info, | ||||
|                           const ConversionSpec &conv) { | ||||
|                           const ConversionSpec conv) { | ||||
|   bool alt = conv.flags().alt; | ||||
|   int radix = conv.conv().radix(); | ||||
|   if (conv.conv().id() == ConversionChar::p) | ||||
|  | @ -127,7 +127,7 @@ string_view BaseIndicator(const ConvertedIntInfo &info, | |||
|   return {}; | ||||
| } | ||||
| 
 | ||||
| string_view SignColumn(bool neg, const ConversionSpec &conv) { | ||||
| string_view SignColumn(bool neg, const ConversionSpec conv) { | ||||
|   if (conv.conv().is_signed()) { | ||||
|     if (neg) return "-"; | ||||
|     if (conv.flags().show_pos) return "+"; | ||||
|  | @ -136,7 +136,7 @@ string_view SignColumn(bool neg, const ConversionSpec &conv) { | |||
|   return {}; | ||||
| } | ||||
| 
 | ||||
| bool ConvertCharImpl(unsigned char v, const ConversionSpec &conv, | ||||
| bool ConvertCharImpl(unsigned char v, const ConversionSpec conv, | ||||
|                      FormatSinkImpl *sink) { | ||||
|   size_t fill = 0; | ||||
|   if (conv.width() >= 0) fill = conv.width(); | ||||
|  | @ -148,7 +148,7 @@ bool ConvertCharImpl(unsigned char v, const ConversionSpec &conv, | |||
| } | ||||
| 
 | ||||
| bool ConvertIntImplInner(const ConvertedIntInfo &info, | ||||
|                          const ConversionSpec &conv, FormatSinkImpl *sink) { | ||||
|                          const ConversionSpec conv, FormatSinkImpl *sink) { | ||||
|   // Print as a sequence of Substrings:
 | ||||
|   //   [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
 | ||||
|   size_t fill = 0; | ||||
|  | @ -202,8 +202,7 @@ bool ConvertIntImplInner(const ConvertedIntInfo &info, | |||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| bool ConvertIntImplInner(T v, const ConversionSpec &conv, | ||||
|                          FormatSinkImpl *sink) { | ||||
| bool ConvertIntImplInner(T v, const ConversionSpec conv, FormatSinkImpl *sink) { | ||||
|   ConvertedIntInfo info(v, conv.conv()); | ||||
|   if (conv.flags().basic && conv.conv().id() != ConversionChar::p) { | ||||
|     if (info.is_neg()) sink->Append(1, '-'); | ||||
|  | @ -218,7 +217,7 @@ bool ConvertIntImplInner(T v, const ConversionSpec &conv, | |||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| bool ConvertIntArg(T v, const ConversionSpec &conv, FormatSinkImpl *sink) { | ||||
| bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) { | ||||
|   if (conv.conv().is_float()) { | ||||
|     return FormatConvertImpl(static_cast<double>(v), conv, sink).value; | ||||
|   } | ||||
|  | @ -234,11 +233,11 @@ bool ConvertIntArg(T v, const ConversionSpec &conv, FormatSinkImpl *sink) { | |||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| bool ConvertFloatArg(T v, const ConversionSpec &conv, FormatSinkImpl *sink) { | ||||
| bool ConvertFloatArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) { | ||||
|   return conv.conv().is_float() && ConvertFloatImpl(v, conv, sink); | ||||
| } | ||||
| 
 | ||||
| inline bool ConvertStringArg(string_view v, const ConversionSpec &conv, | ||||
| inline bool ConvertStringArg(string_view v, const ConversionSpec conv, | ||||
|                              FormatSinkImpl *sink) { | ||||
|   if (conv.conv().id() != ConversionChar::s) | ||||
|     return false; | ||||
|  | @ -254,19 +253,19 @@ inline bool ConvertStringArg(string_view v, const ConversionSpec &conv, | |||
| 
 | ||||
| // ==================== Strings ====================
 | ||||
| ConvertResult<Conv::s> FormatConvertImpl(const std::string &v, | ||||
|                                          const ConversionSpec &conv, | ||||
|                                          const ConversionSpec conv, | ||||
|                                          FormatSinkImpl *sink) { | ||||
|   return {ConvertStringArg(v, conv, sink)}; | ||||
| } | ||||
| 
 | ||||
| ConvertResult<Conv::s> FormatConvertImpl(string_view v, | ||||
|                                          const ConversionSpec &conv, | ||||
|                                          const ConversionSpec conv, | ||||
|                                          FormatSinkImpl *sink) { | ||||
|   return {ConvertStringArg(v, conv, sink)}; | ||||
| } | ||||
| 
 | ||||
| ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char *v, | ||||
|                                                    const ConversionSpec &conv, | ||||
|                                                    const ConversionSpec conv, | ||||
|                                                    FormatSinkImpl *sink) { | ||||
|   if (conv.conv().id() == ConversionChar::p) | ||||
|     return {FormatConvertImpl(VoidPtr(v), conv, sink).value}; | ||||
|  | @ -283,7 +282,7 @@ ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char *v, | |||
| } | ||||
| 
 | ||||
| // ==================== Raw pointers ====================
 | ||||
| ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, const ConversionSpec &conv, | ||||
| ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, const ConversionSpec conv, | ||||
|                                          FormatSinkImpl *sink) { | ||||
|   if (conv.conv().id() != ConversionChar::p) | ||||
|     return {false}; | ||||
|  | @ -295,104 +294,83 @@ ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, const ConversionSpec &conv, | |||
| } | ||||
| 
 | ||||
| // ==================== Floats ====================
 | ||||
| FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec &conv, | ||||
| FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertFloatArg(v, conv, sink)}; | ||||
| } | ||||
| FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec &conv, | ||||
| FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertFloatArg(v, conv, sink)}; | ||||
| } | ||||
| FloatingConvertResult FormatConvertImpl(long double v, | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertFloatArg(v, conv, sink)}; | ||||
| } | ||||
| 
 | ||||
| // ==================== Chars ====================
 | ||||
| IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec &conv, | ||||
| IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(signed char v, | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(unsigned char v, | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| 
 | ||||
| // ==================== Ints ====================
 | ||||
| IntegralConvertResult FormatConvertImpl(short v,  // NOLINT
 | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT
 | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec &conv, | ||||
| IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec &conv, | ||||
| IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(long v,  // NOLINT
 | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT
 | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT
 | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT
 | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| IntegralConvertResult FormatConvertImpl(absl::uint128 v, | ||||
|                                         const ConversionSpec &conv, | ||||
|                                         const ConversionSpec conv, | ||||
|                                         FormatSinkImpl *sink) { | ||||
|   return {ConvertIntArg(v, conv, sink)}; | ||||
| } | ||||
| 
 | ||||
| template struct FormatArgImpl::TypedVTable<str_format_internal::VoidPtr>; | ||||
| ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(); | ||||
| 
 | ||||
| template struct FormatArgImpl::TypedVTable<bool>; | ||||
| template struct FormatArgImpl::TypedVTable<char>; | ||||
| template struct FormatArgImpl::TypedVTable<signed char>; | ||||
| template struct FormatArgImpl::TypedVTable<unsigned char>; | ||||
| template struct FormatArgImpl::TypedVTable<short>;           // NOLINT
 | ||||
| template struct FormatArgImpl::TypedVTable<unsigned short>;  // NOLINT
 | ||||
| template struct FormatArgImpl::TypedVTable<int>; | ||||
| template struct FormatArgImpl::TypedVTable<unsigned>; | ||||
| template struct FormatArgImpl::TypedVTable<long>;                // NOLINT
 | ||||
| template struct FormatArgImpl::TypedVTable<unsigned long>;       // NOLINT
 | ||||
| template struct FormatArgImpl::TypedVTable<long long>;           // NOLINT
 | ||||
| template struct FormatArgImpl::TypedVTable<unsigned long long>;  // NOLINT
 | ||||
| template struct FormatArgImpl::TypedVTable<absl::uint128>; | ||||
| 
 | ||||
| template struct FormatArgImpl::TypedVTable<float>; | ||||
| template struct FormatArgImpl::TypedVTable<double>; | ||||
| template struct FormatArgImpl::TypedVTable<long double>; | ||||
| 
 | ||||
| template struct FormatArgImpl::TypedVTable<const char *>; | ||||
| template struct FormatArgImpl::TypedVTable<std::string>; | ||||
| template struct FormatArgImpl::TypedVTable<string_view>; | ||||
| 
 | ||||
| }  // namespace str_format_internal
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ struct HasUserDefinedConvert : std::false_type {}; | |||
| template <typename T> | ||||
| struct HasUserDefinedConvert< | ||||
|     T, void_t<decltype(AbslFormatConvert( | ||||
|            std::declval<const T&>(), std::declval<const ConversionSpec&>(), | ||||
|            std::declval<const T&>(), std::declval<ConversionSpec>(), | ||||
|            std::declval<FormatSink*>()))>> : std::true_type {}; | ||||
| template <typename T> | ||||
| class StreamedWrapper; | ||||
|  | @ -50,25 +50,23 @@ struct VoidPtr { | |||
|       : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {} | ||||
|   uintptr_t value; | ||||
| }; | ||||
| ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, const ConversionSpec& conv, | ||||
| ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, ConversionSpec conv, | ||||
|                                          FormatSinkImpl* sink); | ||||
| 
 | ||||
| // Strings.
 | ||||
| ConvertResult<Conv::s> FormatConvertImpl(const std::string& v, | ||||
|                                          const ConversionSpec& conv, | ||||
| ConvertResult<Conv::s> FormatConvertImpl(const std::string& v, ConversionSpec conv, | ||||
|                                          FormatSinkImpl* sink); | ||||
| ConvertResult<Conv::s> FormatConvertImpl(string_view v, | ||||
|                                          const ConversionSpec& conv, | ||||
| ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv, | ||||
|                                          FormatSinkImpl* sink); | ||||
| ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char* v, | ||||
|                                                    const ConversionSpec& conv, | ||||
|                                                    ConversionSpec conv, | ||||
|                                                    FormatSinkImpl* sink); | ||||
| template <class AbslCord, | ||||
|           typename std::enable_if< | ||||
|               std::is_same<AbslCord, ::Cord>::value>::type* = nullptr, | ||||
|           class AbslCordReader = ::CordReader> | ||||
| ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value, | ||||
|                                          const ConversionSpec& conv, | ||||
|                                          ConversionSpec conv, | ||||
|                                          FormatSinkImpl* sink) { | ||||
|   if (conv.conv().id() != ConversionChar::s) return {false}; | ||||
| 
 | ||||
|  | @ -104,51 +102,48 @@ using IntegralConvertResult = | |||
| using FloatingConvertResult = ConvertResult<Conv::floating>; | ||||
| 
 | ||||
| // Floats.
 | ||||
| FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec& conv, | ||||
| FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec& conv, | ||||
| FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| FloatingConvertResult FormatConvertImpl(long double v, | ||||
|                                         const ConversionSpec& conv, | ||||
| FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| 
 | ||||
| // Chars.
 | ||||
| IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec& conv, | ||||
| IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(signed char v, | ||||
|                                         const ConversionSpec& conv, | ||||
| IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(unsigned char v, | ||||
|                                         const ConversionSpec& conv, | ||||
| IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| 
 | ||||
| // Ints.
 | ||||
| IntegralConvertResult FormatConvertImpl(short v,  // NOLINT
 | ||||
|                                         const ConversionSpec& conv, | ||||
|                                         ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT
 | ||||
|                                         const ConversionSpec& conv, | ||||
|                                         ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec& conv, | ||||
| IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec& conv, | ||||
| IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(long v,  // NOLINT
 | ||||
|                                         const ConversionSpec& conv, | ||||
|                                         ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT
 | ||||
|                                         const ConversionSpec& conv, | ||||
|                                         ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT
 | ||||
|                                         const ConversionSpec& conv, | ||||
|                                         ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT
 | ||||
|                                         const ConversionSpec& conv, | ||||
|                                         ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| IntegralConvertResult FormatConvertImpl(uint128 v, const ConversionSpec& conv, | ||||
| IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink); | ||||
| template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0> | ||||
| IntegralConvertResult FormatConvertImpl(T v, const ConversionSpec& conv, | ||||
| IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv, | ||||
|                                         FormatSinkImpl* sink) { | ||||
|   return FormatConvertImpl(static_cast<int>(v), conv, sink); | ||||
| } | ||||
|  | @ -159,11 +154,11 @@ template <typename T> | |||
| typename std::enable_if<std::is_enum<T>::value && | ||||
|                             !HasUserDefinedConvert<T>::value, | ||||
|                         IntegralConvertResult>::type | ||||
| FormatConvertImpl(T v, const ConversionSpec& conv, FormatSinkImpl* sink); | ||||
| FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink); | ||||
| 
 | ||||
| template <typename T> | ||||
| ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v, | ||||
|                                          const ConversionSpec& conv, | ||||
|                                          ConversionSpec conv, | ||||
|                                          FormatSinkImpl* out) { | ||||
|   std::ostringstream oss; | ||||
|   oss << v.v_; | ||||
|  | @ -176,7 +171,7 @@ ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v, | |||
| struct FormatCountCaptureHelper { | ||||
|   template <class T = int> | ||||
|   static ConvertResult<Conv::n> ConvertHelper(const FormatCountCapture& v, | ||||
|                                               const ConversionSpec& conv, | ||||
|                                               ConversionSpec conv, | ||||
|                                               FormatSinkImpl* sink) { | ||||
|     const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v; | ||||
| 
 | ||||
|  | @ -189,7 +184,7 @@ struct FormatCountCaptureHelper { | |||
| 
 | ||||
| template <class T = int> | ||||
| ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v, | ||||
|                                          const ConversionSpec& conv, | ||||
|                                          ConversionSpec conv, | ||||
|                                          FormatSinkImpl* sink) { | ||||
|   return FormatCountCaptureHelper::ConvertHelper(v, conv, sink); | ||||
| } | ||||
|  | @ -199,20 +194,20 @@ ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v, | |||
| struct FormatArgImplFriend { | ||||
|   template <typename Arg> | ||||
|   static bool ToInt(Arg arg, int* out) { | ||||
|     if (!arg.vtbl_->to_int) return false; | ||||
|     *out = arg.vtbl_->to_int(arg.data_); | ||||
|     return true; | ||||
|     // A value initialized ConversionSpec has a `none` conv, which tells the
 | ||||
|     // dispatcher to run the `int` conversion.
 | ||||
|     return arg.dispatcher_(arg.data_, {}, out); | ||||
|   } | ||||
| 
 | ||||
|   template <typename Arg> | ||||
|   static bool Convert(Arg arg, const str_format_internal::ConversionSpec& conv, | ||||
|   static bool Convert(Arg arg, str_format_internal::ConversionSpec conv, | ||||
|                       FormatSinkImpl* out) { | ||||
|     return arg.vtbl_->convert(arg.data_, conv, out); | ||||
|     return arg.dispatcher_(arg.data_, conv, out); | ||||
|   } | ||||
| 
 | ||||
|   template <typename Arg> | ||||
|   static const void* GetVTablePtrForTest(Arg arg) { | ||||
|     return arg.vtbl_; | ||||
|   static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) { | ||||
|     return arg.dispatcher_; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
|  | @ -229,11 +224,7 @@ class FormatArgImpl { | |||
|     char buf[kInlinedSpace]; | ||||
|   }; | ||||
| 
 | ||||
|   struct VTable { | ||||
|     bool (*convert)(Data, const str_format_internal::ConversionSpec& conv, | ||||
|                     FormatSinkImpl* out); | ||||
|     int (*to_int)(Data); | ||||
|   }; | ||||
|   using Dispatcher = bool (*)(Data, ConversionSpec, void* out); | ||||
| 
 | ||||
|   template <typename T> | ||||
|   struct store_by_value | ||||
|  | @ -253,10 +244,6 @@ class FormatArgImpl { | |||
|                                                                 : ByPointer))> { | ||||
|   }; | ||||
| 
 | ||||
|   // An instance of an FormatArgImpl::VTable suitable for 'T'.
 | ||||
|   template <typename T> | ||||
|   struct TypedVTable; | ||||
| 
 | ||||
|   // To reduce the number of vtables we will decay values before hand.
 | ||||
|   // Anything with a user-defined Convert will get its own vtable.
 | ||||
|   // For everything else:
 | ||||
|  | @ -338,7 +325,10 @@ class FormatArgImpl { | |||
|   }; | ||||
| 
 | ||||
|   template <typename T> | ||||
|   void Init(const T& value); | ||||
|   void Init(const T& value) { | ||||
|     data_ = Manager<T>::SetValue(value); | ||||
|     dispatcher_ = &Dispatch<T>; | ||||
|   } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   static int ToIntVal(const T& val) { | ||||
|  | @ -355,79 +345,75 @@ class FormatArgImpl { | |||
|     return static_cast<int>(val); | ||||
|   } | ||||
| 
 | ||||
|   Data data_; | ||||
|   const VTable* vtbl_; | ||||
| }; | ||||
|   template <typename T> | ||||
|   static bool ToInt(Data arg, int* out, std::true_type /* is_integral */, | ||||
|                     std::false_type) { | ||||
|     *out = ToIntVal(Manager<T>::Value(arg)); | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
| template <typename T> | ||||
| struct FormatArgImpl::TypedVTable { | ||||
|  private: | ||||
|   static bool ConvertImpl(Data arg, | ||||
|                           const str_format_internal::ConversionSpec& conv, | ||||
|                           FormatSinkImpl* out) { | ||||
|     return str_format_internal::FormatConvertImpl(Manager<T>::Value(arg), conv, | ||||
|                                                   out) | ||||
|   template <typename T> | ||||
|   static bool ToInt(Data arg, int* out, std::false_type, | ||||
|                     std::true_type /* is_enum */) { | ||||
|     *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>( | ||||
|         Manager<T>::Value(arg))); | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   static bool ToInt(Data, int*, std::false_type, std::false_type) { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   template <typename T> | ||||
|   static bool Dispatch(Data arg, ConversionSpec spec, void* out) { | ||||
|     // A `none` conv indicates that we want the `int` conversion.
 | ||||
|     if (ABSL_PREDICT_FALSE(spec.conv().id() == ConversionChar::none)) { | ||||
|       return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(), | ||||
|                       std::is_enum<T>()); | ||||
|     } | ||||
| 
 | ||||
|     return str_format_internal::FormatConvertImpl( | ||||
|                Manager<T>::Value(arg), spec, static_cast<FormatSinkImpl*>(out)) | ||||
|         .value; | ||||
|   } | ||||
| 
 | ||||
|   template <typename U = T, typename = void> | ||||
|   struct ToIntImpl { | ||||
|     static constexpr int (*value)(Data) = nullptr; | ||||
|   }; | ||||
| 
 | ||||
|   template <typename U> | ||||
|   struct ToIntImpl<U, | ||||
|                    typename std::enable_if<std::is_integral<U>::value>::type> { | ||||
|     static int Invoke(Data arg) { return ToIntVal(Manager<T>::Value(arg)); } | ||||
|     static constexpr int (*value)(Data) = &Invoke; | ||||
|   }; | ||||
| 
 | ||||
|   template <typename U> | ||||
|   struct ToIntImpl<U, typename std::enable_if<std::is_enum<U>::value>::type> { | ||||
|     static int Invoke(Data arg) { | ||||
|       return ToIntVal(static_cast<typename std::underlying_type<T>::type>( | ||||
|           Manager<T>::Value(arg))); | ||||
|     } | ||||
|     static constexpr int (*value)(Data) = &Invoke; | ||||
|   }; | ||||
| 
 | ||||
|  public: | ||||
|   static constexpr VTable value{&ConvertImpl, ToIntImpl<>::value}; | ||||
|   Data data_; | ||||
|   Dispatcher dispatcher_; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| constexpr FormatArgImpl::VTable FormatArgImpl::TypedVTable<T>::value; | ||||
| #define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \ | ||||
|   E template bool FormatArgImpl::Dispatch<T>(Data, ConversionSpec, void*) | ||||
| 
 | ||||
| template <typename T> | ||||
| void FormatArgImpl::Init(const T& value) { | ||||
|   data_ = Manager<T>::SetValue(value); | ||||
|   vtbl_ = &TypedVTable<T>::value; | ||||
| } | ||||
| #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...)                   \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr,     \ | ||||
|                                              __VA_ARGS__);                     \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__);               \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__);               \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__);        \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__);      \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short,      /* NOLINT */ \ | ||||
|                                              __VA_ARGS__);                     \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__);                \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__);       \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */  \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long,      /* NOLINT */  \ | ||||
|                                              __VA_ARGS__);                     \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */           \ | ||||
|                                              __VA_ARGS__);                     \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */  \ | ||||
|                                              __VA_ARGS__);                     \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__);            \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__);              \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__);        \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__);        \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);             \ | ||||
|   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__) | ||||
| 
 | ||||
| extern template struct FormatArgImpl::TypedVTable<str_format_internal::VoidPtr>; | ||||
| ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern); | ||||
| 
 | ||||
| extern template struct FormatArgImpl::TypedVTable<bool>; | ||||
| extern template struct FormatArgImpl::TypedVTable<char>; | ||||
| extern template struct FormatArgImpl::TypedVTable<signed char>; | ||||
| extern template struct FormatArgImpl::TypedVTable<unsigned char>; | ||||
| extern template struct FormatArgImpl::TypedVTable<short>;           // NOLINT
 | ||||
| extern template struct FormatArgImpl::TypedVTable<unsigned short>;  // NOLINT
 | ||||
| extern template struct FormatArgImpl::TypedVTable<int>; | ||||
| extern template struct FormatArgImpl::TypedVTable<unsigned>; | ||||
| extern template struct FormatArgImpl::TypedVTable<long>;           // NOLINT
 | ||||
| extern template struct FormatArgImpl::TypedVTable<unsigned long>;  // NOLINT
 | ||||
| extern template struct FormatArgImpl::TypedVTable<long long>;      // NOLINT
 | ||||
| extern template struct FormatArgImpl::TypedVTable< | ||||
|     unsigned long long>;  // NOLINT
 | ||||
| extern template struct FormatArgImpl::TypedVTable<uint128>; | ||||
| 
 | ||||
| extern template struct FormatArgImpl::TypedVTable<float>; | ||||
| extern template struct FormatArgImpl::TypedVTable<double>; | ||||
| extern template struct FormatArgImpl::TypedVTable<long double>; | ||||
| 
 | ||||
| extern template struct FormatArgImpl::TypedVTable<const char*>; | ||||
| extern template struct FormatArgImpl::TypedVTable<std::string>; | ||||
| extern template struct FormatArgImpl::TypedVTable<string_view>; | ||||
| }  // namespace str_format_internal
 | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -186,7 +186,7 @@ class StreamedWrapper { | |||
|  private: | ||||
|   template <typename S> | ||||
|   friend ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<S>& v, | ||||
|                                                   const ConversionSpec& conv, | ||||
|                                                   ConversionSpec conv, | ||||
|                                                   FormatSinkImpl* out); | ||||
|   const T& v_; | ||||
| }; | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ | |||
| #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ | ||||
| 
 | ||||
| #include <limits.h> | ||||
| #include <cstddef> | ||||
| #include <cstring> | ||||
| #include <ostream> | ||||
| 
 | ||||
|  | @ -307,7 +308,12 @@ class ConversionSpec { | |||
|  public: | ||||
|   Flags flags() const { return flags_; } | ||||
|   LengthMod length_mod() const { return length_mod_; } | ||||
|   ConversionChar conv() const { return conv_; } | ||||
|   ConversionChar conv() const { | ||||
|     // Keep this field first in the struct . It generates better code when
 | ||||
|     // accessing it when ConversionSpec is passed by value in registers.
 | ||||
|     static_assert(offsetof(ConversionSpec, conv_) == 0, ""); | ||||
|     return conv_; | ||||
|   } | ||||
| 
 | ||||
|   // Returns the specified width. If width is unspecfied, it returns a negative
 | ||||
|   // value.
 | ||||
|  | @ -324,9 +330,9 @@ class ConversionSpec { | |||
|   void set_left(bool b) { flags_.left = b; } | ||||
| 
 | ||||
|  private: | ||||
|   ConversionChar conv_; | ||||
|   Flags flags_; | ||||
|   LengthMod length_mod_; | ||||
|   ConversionChar conv_; | ||||
|   int width_; | ||||
|   int precision_; | ||||
| }; | ||||
|  |  | |||
|  | @ -601,3 +601,39 @@ TEST_F(ParsedFormatTest, RegressionMixPositional) { | |||
| 
 | ||||
| }  // namespace
 | ||||
| }  // namespace absl
 | ||||
| 
 | ||||
| // Some codegen thunks that we can use to easily dump the generated assembly for
 | ||||
| // different StrFormat calls.
 | ||||
| 
 | ||||
| inline std::string CodegenAbslStrFormatInt(int i) { | ||||
|   return absl::StrFormat("%d", i); | ||||
| } | ||||
| 
 | ||||
| inline std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s, | ||||
|                                                  int64_t i64) { | ||||
|   return absl::StrFormat("%d %s %d", i, s, i64); | ||||
| } | ||||
| 
 | ||||
| inline void CodegenAbslStrAppendFormatInt(std::string* out, int i) { | ||||
|   absl::StrAppendFormat(out, "%d", i); | ||||
| } | ||||
| 
 | ||||
| inline void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i, | ||||
|                                                      const std::string& s, | ||||
|                                                      int64_t i64) { | ||||
|   absl::StrAppendFormat(out, "%d %s %d", i, s, i64); | ||||
| } | ||||
| 
 | ||||
| auto absl_internal_str_format_force_codegen_funcs = std::make_tuple( | ||||
|     CodegenAbslStrFormatInt, CodegenAbslStrFormatIntStringInt64, | ||||
|     CodegenAbslStrAppendFormatInt, CodegenAbslStrAppendFormatIntStringInt64); | ||||
| 
 | ||||
| bool absl_internal_str_format_force_codegen_always_false; | ||||
| // Force the compiler to generate the functions by making it look like we
 | ||||
| // escape the function pointers.
 | ||||
| // It can't statically know that
 | ||||
| // absl_internal_str_format_force_codegen_always_false is not changed by someone
 | ||||
| // else.
 | ||||
| bool absl_internal_str_format_force_codegen = | ||||
|     absl_internal_str_format_force_codegen_always_false && | ||||
|     printf("%p", &absl_internal_str_format_force_codegen_funcs) == 0; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue