File indexing completed on 2025-01-18 09:27:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
0016 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
0017
0018 #include <cassert>
0019 #include <cstdio>
0020 #include <ostream>
0021 #include <string>
0022
0023 #include "absl/base/config.h"
0024 #include "absl/container/inlined_vector.h"
0025 #include "absl/strings/internal/str_format/arg.h"
0026 #include "absl/strings/internal/str_format/checker.h"
0027 #include "absl/strings/internal/str_format/constexpr_parser.h"
0028 #include "absl/strings/internal/str_format/extension.h"
0029 #include "absl/strings/internal/str_format/parser.h"
0030 #include "absl/strings/string_view.h"
0031 #include "absl/types/span.h"
0032 #include "absl/utility/utility.h"
0033
0034 namespace absl {
0035 ABSL_NAMESPACE_BEGIN
0036
0037 class UntypedFormatSpec;
0038
0039 namespace str_format_internal {
0040
0041 class BoundConversion : public FormatConversionSpecImpl {
0042 public:
0043 const FormatArgImpl* arg() const { return arg_; }
0044 void set_arg(const FormatArgImpl* a) { arg_ = a; }
0045
0046 private:
0047 const FormatArgImpl* arg_;
0048 };
0049
0050
0051 class UntypedFormatSpecImpl {
0052 public:
0053 UntypedFormatSpecImpl() = delete;
0054
0055 explicit UntypedFormatSpecImpl(string_view s)
0056 : data_(s.data()), size_(s.size()) {}
0057 explicit UntypedFormatSpecImpl(
0058 const str_format_internal::ParsedFormatBase* pc)
0059 : data_(pc), size_(~size_t{}) {}
0060
0061 bool has_parsed_conversion() const { return size_ == ~size_t{}; }
0062
0063 string_view str() const {
0064 assert(!has_parsed_conversion());
0065 return string_view(static_cast<const char*>(data_), size_);
0066 }
0067 const str_format_internal::ParsedFormatBase* parsed_conversion() const {
0068 assert(has_parsed_conversion());
0069 return static_cast<const str_format_internal::ParsedFormatBase*>(data_);
0070 }
0071
0072 template <typename T>
0073 static const UntypedFormatSpecImpl& Extract(const T& s) {
0074 return s.spec_;
0075 }
0076
0077 private:
0078 const void* data_;
0079 size_t size_;
0080 };
0081
0082 template <typename T, FormatConversionCharSet...>
0083 struct MakeDependent {
0084 using type = T;
0085 };
0086
0087
0088
0089
0090 template <FormatConversionCharSet... Args>
0091 class FormatSpecTemplate
0092 : public MakeDependent<UntypedFormatSpec, Args...>::type {
0093 using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
0094
0095 template <bool res>
0096 struct ErrorMaker {
0097 constexpr bool operator()(int) const { return res; }
0098 };
0099
0100 template <int i, int j>
0101 static constexpr bool CheckArity(ErrorMaker<true> SpecifierCount = {},
0102 ErrorMaker<i == j> ParametersPassed = {}) {
0103 static_assert(SpecifierCount(i) == ParametersPassed(j),
0104 "Number of arguments passed must match the number of "
0105 "conversion specifiers.");
0106 return true;
0107 }
0108
0109 template <FormatConversionCharSet specified, FormatConversionCharSet passed,
0110 int arg>
0111 static constexpr bool CheckMatch(
0112 ErrorMaker<Contains(specified, passed)> MismatchedArgumentNumber = {}) {
0113 static_assert(MismatchedArgumentNumber(arg),
0114 "Passed argument must match specified format.");
0115 return true;
0116 }
0117
0118 template <FormatConversionCharSet... C, size_t... I>
0119 static bool CheckMatches(absl::index_sequence<I...>) {
0120 bool res[] = {true, CheckMatch<Args, C, I + 1>()...};
0121 (void)res;
0122 return true;
0123 }
0124
0125 public:
0126 #ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
0127
0128
0129
0130
0131 FormatSpecTemplate(...)
0132 __attribute__((unavailable("Format string is not constexpr.")));
0133
0134
0135
0136
0137
0138
0139
0140 template <typename = void>
0141 FormatSpecTemplate(const char* s)
0142 __attribute__((
0143 enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"),
0144 unavailable(
0145 "Format specified does not match the arguments passed.")));
0146
0147 template <typename T = void>
0148 FormatSpecTemplate(string_view s)
0149 __attribute__((enable_if(str_format_internal::EnsureConstexpr(s),
0150 "constexpr trap")))
0151 : Base("to avoid noise in the compiler error") {
0152 static_assert(sizeof(T*) == 0,
0153 "Format specified does not match the arguments passed.");
0154 }
0155
0156
0157 FormatSpecTemplate(const char* s)
0158 __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
0159 : Base(s) {}
0160
0161 FormatSpecTemplate(string_view s)
0162 __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
0163 : Base(s) {}
0164
0165 #else
0166
0167 FormatSpecTemplate(const char* s) : Base(s) {}
0168 FormatSpecTemplate(string_view s) : Base(s) {}
0169
0170 #endif
0171
0172 template <FormatConversionCharSet... C>
0173 FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc)
0174 : Base(&pc) {
0175 CheckArity<sizeof...(C), sizeof...(Args)>();
0176 CheckMatches<C...>(absl::make_index_sequence<sizeof...(C)>{});
0177 }
0178 };
0179
0180 class Streamable {
0181 public:
0182 Streamable(const UntypedFormatSpecImpl& format,
0183 absl::Span<const FormatArgImpl> args)
0184 : format_(format), args_(args.begin(), args.end()) {}
0185
0186 std::ostream& Print(std::ostream& os) const;
0187
0188 friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {
0189 return l.Print(os);
0190 }
0191
0192 private:
0193 const UntypedFormatSpecImpl& format_;
0194 absl::InlinedVector<FormatArgImpl, 4> args_;
0195 };
0196
0197
0198 std::string Summarize(UntypedFormatSpecImpl format,
0199 absl::Span<const FormatArgImpl> args);
0200 bool BindWithPack(const UnboundConversion* props,
0201 absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
0202
0203 bool FormatUntyped(FormatRawSinkImpl raw_sink, UntypedFormatSpecImpl format,
0204 absl::Span<const FormatArgImpl> args);
0205
0206 std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
0207 absl::Span<const FormatArgImpl> args);
0208
0209 std::string FormatPack(UntypedFormatSpecImpl format,
0210 absl::Span<const FormatArgImpl> args);
0211
0212 int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
0213 absl::Span<const FormatArgImpl> args);
0214 int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
0215 absl::Span<const FormatArgImpl> args);
0216
0217
0218
0219 template <typename T>
0220 class StreamedWrapper {
0221 public:
0222 explicit StreamedWrapper(const T& v) : v_(v) {}
0223
0224 private:
0225 template <typename S>
0226 friend ArgConvertResult<FormatConversionCharSetUnion(
0227 FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::v)>
0228 FormatConvertImpl(const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
0229 FormatSinkImpl* out);
0230 const T& v_;
0231 };
0232
0233 }
0234 ABSL_NAMESPACE_END
0235 }
0236
0237 #endif