bind.h
Go to the documentation of this file.
00001 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
00002 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
00003 
00004 #include <array>
00005 #include <cstdio>
00006 #include <sstream>
00007 #include <string>
00008 
00009 #include "absl/base/port.h"
00010 #include "absl/container/inlined_vector.h"
00011 #include "absl/strings/internal/str_format/arg.h"
00012 #include "absl/strings/internal/str_format/checker.h"
00013 #include "absl/strings/internal/str_format/parser.h"
00014 #include "absl/types/span.h"
00015 
00016 namespace absl {
00017 
00018 class UntypedFormatSpec;
00019 
00020 namespace str_format_internal {
00021 
00022 class BoundConversion : public ConversionSpec {
00023  public:
00024   const FormatArgImpl* arg() const { return arg_; }
00025   void set_arg(const FormatArgImpl* a) { arg_ = a; }
00026 
00027  private:
00028   const FormatArgImpl* arg_;
00029 };
00030 
00031 // This is the type-erased class that the implementation uses.
00032 class UntypedFormatSpecImpl {
00033  public:
00034   UntypedFormatSpecImpl() = delete;
00035 
00036   explicit UntypedFormatSpecImpl(string_view s)
00037       : data_(s.data()), size_(s.size()) {}
00038   explicit UntypedFormatSpecImpl(
00039       const str_format_internal::ParsedFormatBase* pc)
00040       : data_(pc), size_(~size_t{}) {}
00041 
00042   bool has_parsed_conversion() const { return size_ == ~size_t{}; }
00043 
00044   string_view str() const {
00045     assert(!has_parsed_conversion());
00046     return string_view(static_cast<const char*>(data_), size_);
00047   }
00048   const str_format_internal::ParsedFormatBase* parsed_conversion() const {
00049     assert(has_parsed_conversion());
00050     return static_cast<const str_format_internal::ParsedFormatBase*>(data_);
00051   }
00052 
00053   template <typename T>
00054   static const UntypedFormatSpecImpl& Extract(const T& s) {
00055     return s.spec_;
00056   }
00057 
00058  private:
00059   const void* data_;
00060   size_t size_;
00061 };
00062 
00063 template <typename T, typename...>
00064 struct MakeDependent {
00065   using type = T;
00066 };
00067 
00068 // Implicitly convertible from `const char*`, `string_view`, and the
00069 // `ExtendedParsedFormat` type. This abstraction allows all format functions to
00070 // operate on any without providing too many overloads.
00071 template <typename... Args>
00072 class FormatSpecTemplate
00073     : public MakeDependent<UntypedFormatSpec, Args...>::type {
00074   using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
00075 
00076  public:
00077 #if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
00078 
00079   // Honeypot overload for when the std::string is not constexpr.
00080   // We use the 'unavailable' attribute to give a better compiler error than
00081   // just 'method is deleted'.
00082   FormatSpecTemplate(...)  // NOLINT
00083       __attribute__((unavailable("Format std::string is not constexpr.")));
00084 
00085   // Honeypot overload for when the format is constexpr and invalid.
00086   // We use the 'unavailable' attribute to give a better compiler error than
00087   // just 'method is deleted'.
00088   // To avoid checking the format twice, we just check that the format is
00089   // constexpr. If is it valid, then the overload below will kick in.
00090   // We add the template here to make this overload have lower priority.
00091   template <typename = void>
00092   FormatSpecTemplate(const char* s)  // NOLINT
00093       __attribute__((
00094           enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"),
00095           unavailable(
00096               "Format specified does not match the arguments passed.")));
00097 
00098   template <typename T = void>
00099   FormatSpecTemplate(string_view s)  // NOLINT
00100       __attribute__((enable_if(str_format_internal::EnsureConstexpr(s),
00101                                "constexpr trap"))) {
00102     static_assert(sizeof(T*) == 0,
00103                   "Format specified does not match the arguments passed.");
00104   }
00105 
00106   // Good format overload.
00107   FormatSpecTemplate(const char* s)  // NOLINT
00108       __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
00109                                "bad format trap")))
00110       : Base(s) {}
00111 
00112   FormatSpecTemplate(string_view s)  // NOLINT
00113       __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
00114                                "bad format trap")))
00115       : Base(s) {}
00116 
00117 #else  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
00118 
00119   FormatSpecTemplate(const char* s) : Base(s) {}  // NOLINT
00120   FormatSpecTemplate(string_view s) : Base(s) {}  // NOLINT
00121 
00122 #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
00123 
00124   template <Conv... C, typename = typename std::enable_if<
00125                            sizeof...(C) == sizeof...(Args) &&
00126                            AllOf(Contains(ArgumentToConv<Args>(),
00127                                           C)...)>::type>
00128   FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc)  // NOLINT
00129       : Base(&pc) {}
00130 };
00131 
00132 template <typename... Args>
00133 struct FormatSpecDeductionBarrier {
00134   using type = FormatSpecTemplate<Args...>;
00135 };
00136 
00137 class Streamable {
00138  public:
00139   Streamable(const UntypedFormatSpecImpl& format,
00140              absl::Span<const FormatArgImpl> args)
00141       : format_(format), args_(args.begin(), args.end()) {}
00142 
00143   std::ostream& Print(std::ostream& os) const;
00144 
00145   friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {
00146     return l.Print(os);
00147   }
00148 
00149  private:
00150   const UntypedFormatSpecImpl& format_;
00151   absl::InlinedVector<FormatArgImpl, 4> args_;
00152 };
00153 
00154 // for testing
00155 std::string Summarize(UntypedFormatSpecImpl format,
00156                       absl::Span<const FormatArgImpl> args);
00157 bool BindWithPack(const UnboundConversion* props,
00158                   absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
00159 
00160 bool FormatUntyped(FormatRawSinkImpl raw_sink,
00161                    UntypedFormatSpecImpl format,
00162                    absl::Span<const FormatArgImpl> args);
00163 
00164 std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
00165                         absl::Span<const FormatArgImpl> args);
00166 
00167 inline std::string FormatPack(const UntypedFormatSpecImpl format,
00168                               absl::Span<const FormatArgImpl> args) {
00169   std::string out;
00170   AppendPack(&out, format, args);
00171   return out;
00172 }
00173 
00174 int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
00175             absl::Span<const FormatArgImpl> args);
00176 int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
00177              absl::Span<const FormatArgImpl> args);
00178 
00179 // Returned by Streamed(v). Converts via '%s' to the std::string created
00180 // by std::ostream << v.
00181 template <typename T>
00182 class StreamedWrapper {
00183  public:
00184   explicit StreamedWrapper(const T& v) : v_(v) { }
00185 
00186  private:
00187   template <typename S>
00188   friend ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<S>& v,
00189                                                   ConversionSpec conv,
00190                                                   FormatSinkImpl* out);
00191   const T& v_;
00192 };
00193 
00194 }  // namespace str_format_internal
00195 }  // namespace absl
00196 
00197 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14