-- 70f43a482d7d4ae4a255f17ca02b0106653dd600 by Shaindel Schwartz <shaindel@google.com>: Internal change PiperOrigin-RevId: 201571193 -- 93e6e9c2e683158be49d9dd1f5cb1a91d0c0f556 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 201567108 -- fbd8ee94fbe9f2448e5adf5e88706f9c8216048f by Juemin Yang <jueminyang@google.com>: str_format release PiperOrigin-RevId: 201565129 -- 387faa301555a8a888c4429df52734aa806dca46 by Abseil Team <absl-team@google.com>: Adds a defaulted allocator parameter to the size_type constructor of InlinedVector PiperOrigin-RevId: 201558711 -- 39b15ea2c68d7129d70cbde7e71af900032595ec by Matt Calabrese <calabrese@google.com>: Update the variant implementation to eliminate unnecessary checking on alternative access when the index is known or required to be correct. PiperOrigin-RevId: 201529535 -- adab77f1f7bb363aa534297f22aae2b0f08889ea by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 201458388 -- a701dc0ba62e3cadf0de14203415b91df4ee8151 by Greg Falcon <gfalcon@google.com>: Internal cleanup PiperOrigin-RevId: 201394836 -- 8a7191410b8f440fdfa27f722ff05e451502ab61 by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 201369269 GitOrigin-RevId: 70f43a482d7d4ae4a255f17ca02b0106653dd600 Change-Id: I8ab073b30b4e27405a3b6da2c826bb4f3f0b9af6
		
			
				
	
	
		
			189 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
 | |
| #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
 | |
| 
 | |
| #include <array>
 | |
| #include <cstdio>
 | |
| #include <sstream>
 | |
| #include <string>
 | |
| 
 | |
| #include "absl/base/port.h"
 | |
| #include "absl/container/inlined_vector.h"
 | |
| #include "absl/strings/internal/str_format/arg.h"
 | |
| #include "absl/strings/internal/str_format/checker.h"
 | |
| #include "absl/strings/internal/str_format/parser.h"
 | |
| #include "absl/types/span.h"
 | |
| 
 | |
| namespace absl {
 | |
| 
 | |
| class UntypedFormatSpec;
 | |
| 
 | |
| namespace str_format_internal {
 | |
| 
 | |
| class BoundConversion : public ConversionSpec {
 | |
|  public:
 | |
|   const FormatArgImpl* arg() const { return arg_; }
 | |
|   void set_arg(const FormatArgImpl* a) { arg_ = a; }
 | |
| 
 | |
|  private:
 | |
|   const FormatArgImpl* arg_;
 | |
| };
 | |
| 
 | |
| // This is the type-erased class that the implementation uses.
 | |
| class UntypedFormatSpecImpl {
 | |
|  public:
 | |
|   UntypedFormatSpecImpl() = delete;
 | |
| 
 | |
|   explicit UntypedFormatSpecImpl(string_view s) : str_(s), pc_() {}
 | |
|   explicit UntypedFormatSpecImpl(
 | |
|       const str_format_internal::ParsedFormatBase* pc)
 | |
|       : pc_(pc) {}
 | |
|   string_view str() const { return str_; }
 | |
|   const str_format_internal::ParsedFormatBase* parsed_conversion() const {
 | |
|     return pc_;
 | |
|   }
 | |
| 
 | |
|   template <typename T>
 | |
|   static const UntypedFormatSpecImpl& Extract(const T& s) {
 | |
|     return s.spec_;
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   string_view str_;
 | |
|   const str_format_internal::ParsedFormatBase* pc_;
 | |
| };
 | |
| 
 | |
| template <typename T, typename...>
 | |
| struct MakeDependent {
 | |
|   using type = T;
 | |
| };
 | |
| 
 | |
| // Implicitly convertible from `const char*`, `string_view`, and the
 | |
| // `ExtendedParsedFormat` type. This abstraction allows all format functions to
 | |
| // operate on any without providing too many overloads.
 | |
| template <typename... Args>
 | |
| class FormatSpecTemplate
 | |
|     : public MakeDependent<UntypedFormatSpec, Args...>::type {
 | |
|   using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
 | |
| 
 | |
|  public:
 | |
| #if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 | |
| 
 | |
|   // Honeypot overload for when the std::string is not constexpr.
 | |
|   // We use the 'unavailable' attribute to give a better compiler error than
 | |
|   // just 'method is deleted'.
 | |
|   FormatSpecTemplate(...)  // NOLINT
 | |
|       __attribute__((unavailable("Format std::string is not constexpr.")));
 | |
| 
 | |
|   // Honeypot overload for when the format is constexpr and invalid.
 | |
|   // We use the 'unavailable' attribute to give a better compiler error than
 | |
|   // just 'method is deleted'.
 | |
|   // To avoid checking the format twice, we just check that the format is
 | |
|   // constexpr. If is it valid, then the overload below will kick in.
 | |
|   // We add the template here to make this overload have lower priority.
 | |
|   template <typename = void>
 | |
|   FormatSpecTemplate(const char* s)  // NOLINT
 | |
|       __attribute__((
 | |
|           enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"),
 | |
|           unavailable(
 | |
|               "Format specified does not match the arguments passed.")));
 | |
| 
 | |
|   template <typename T = void>
 | |
|   FormatSpecTemplate(string_view s)  // NOLINT
 | |
|       __attribute__((enable_if(str_format_internal::EnsureConstexpr(s),
 | |
|                                "constexpr trap"))) {
 | |
|     static_assert(sizeof(T*) == 0,
 | |
|                   "Format specified does not match the arguments passed.");
 | |
|   }
 | |
| 
 | |
|   // Good format overload.
 | |
|   FormatSpecTemplate(const char* s)  // NOLINT
 | |
|       __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
 | |
|                                "bad format trap")))
 | |
|       : Base(s) {}
 | |
| 
 | |
|   FormatSpecTemplate(string_view s)  // NOLINT
 | |
|       __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
 | |
|                                "bad format trap")))
 | |
|       : Base(s) {}
 | |
| 
 | |
| #else  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 | |
| 
 | |
|   FormatSpecTemplate(const char* s) : Base(s) {}  // NOLINT
 | |
|   FormatSpecTemplate(string_view s) : Base(s) {}  // NOLINT
 | |
| 
 | |
| #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 | |
| 
 | |
|   template <Conv... C, typename = typename std::enable_if<
 | |
|                            sizeof...(C) == sizeof...(Args) &&
 | |
|                            AllOf(Contains(ArgumentToConv<Args>(),
 | |
|                                           C)...)>::type>
 | |
|   FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc)  // NOLINT
 | |
|       : Base(&pc) {}
 | |
| };
 | |
| 
 | |
| template <typename... Args>
 | |
| struct FormatSpecDeductionBarrier {
 | |
|   using type = FormatSpecTemplate<Args...>;
 | |
| };
 | |
| 
 | |
| class Streamable {
 | |
|  public:
 | |
|   Streamable(const UntypedFormatSpecImpl& format,
 | |
|              absl::Span<const FormatArgImpl> args)
 | |
|       : format_(format), args_(args.begin(), args.end()) {}
 | |
| 
 | |
|   std::ostream& Print(std::ostream& os) const;
 | |
| 
 | |
|   friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {
 | |
|     return l.Print(os);
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   const UntypedFormatSpecImpl& format_;
 | |
|   absl::InlinedVector<FormatArgImpl, 4> args_;
 | |
| };
 | |
| 
 | |
| // for testing
 | |
| std::string Summarize(const UntypedFormatSpecImpl& format,
 | |
|                  absl::Span<const FormatArgImpl> args);
 | |
| bool BindWithPack(const UnboundConversion* props,
 | |
|                   absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
 | |
| 
 | |
| bool FormatUntyped(FormatRawSinkImpl raw_sink,
 | |
|                    const UntypedFormatSpecImpl& format,
 | |
|                    absl::Span<const FormatArgImpl> args);
 | |
| 
 | |
| std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl& format,
 | |
|                    absl::Span<const FormatArgImpl> args);
 | |
| 
 | |
| inline std::string FormatPack(const UntypedFormatSpecImpl& format,
 | |
|                          absl::Span<const FormatArgImpl> args) {
 | |
|   std::string out;
 | |
|   AppendPack(&out, format, args);
 | |
|   return out;
 | |
| }
 | |
| 
 | |
| int FprintF(std::FILE* output, const UntypedFormatSpecImpl& format,
 | |
|             absl::Span<const FormatArgImpl> args);
 | |
| int SnprintF(char* output, size_t size, const UntypedFormatSpecImpl& format,
 | |
|              absl::Span<const FormatArgImpl> args);
 | |
| 
 | |
| // Returned by Streamed(v). Converts via '%s' to the std::string created
 | |
| // by std::ostream << v.
 | |
| template <typename T>
 | |
| class StreamedWrapper {
 | |
|  public:
 | |
|   explicit StreamedWrapper(const T& v) : v_(v) { }
 | |
| 
 | |
|  private:
 | |
|   template <typename S>
 | |
|   friend ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<S>& v,
 | |
|                                                   const ConversionSpec& conv,
 | |
|                                                   FormatSinkImpl* out);
 | |
|   const T& v_;
 | |
| };
 | |
| 
 | |
| }  // namespace str_format_internal
 | |
| }  // namespace absl
 | |
| 
 | |
| #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
 |