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
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
00069
00070
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
00080
00081
00082 FormatSpecTemplate(...)
00083 __attribute__((unavailable("Format std::string is not constexpr.")));
00084
00085
00086
00087
00088
00089
00090
00091 template <typename = void>
00092 FormatSpecTemplate(const char* s)
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)
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
00107 FormatSpecTemplate(const char* s)
00108 __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
00109 "bad format trap")))
00110 : Base(s) {}
00111
00112 FormatSpecTemplate(string_view s)
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) {}
00120 FormatSpecTemplate(string_view s) : Base(s) {}
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)
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
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
00180
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 }
00195 }
00196
00197 #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_