bind.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // Copyright 2020 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
  15. #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
  16. #include <cassert>
  17. #include <cstdio>
  18. #include <ostream>
  19. #include <string>
  20. #include "absl/base/config.h"
  21. #include "absl/container/inlined_vector.h"
  22. #include "absl/strings/internal/str_format/arg.h"
  23. #include "absl/strings/internal/str_format/checker.h"
  24. #include "absl/strings/internal/str_format/constexpr_parser.h"
  25. #include "absl/strings/internal/str_format/extension.h"
  26. #include "absl/strings/internal/str_format/parser.h"
  27. #include "absl/strings/string_view.h"
  28. #include "absl/types/span.h"
  29. #include "absl/utility/utility.h"
  30. namespace absl {
  31. ABSL_NAMESPACE_BEGIN
  32. class UntypedFormatSpec;
  33. namespace str_format_internal {
  34. class BoundConversion : public FormatConversionSpecImpl {
  35. public:
  36. const FormatArgImpl* arg() const { return arg_; }
  37. void set_arg(const FormatArgImpl* a) { arg_ = a; }
  38. private:
  39. const FormatArgImpl* arg_;
  40. };
  41. // This is the type-erased class that the implementation uses.
  42. class UntypedFormatSpecImpl {
  43. public:
  44. UntypedFormatSpecImpl() = delete;
  45. explicit UntypedFormatSpecImpl(string_view s)
  46. : data_(s.data()), size_(s.size()) {}
  47. explicit UntypedFormatSpecImpl(
  48. const str_format_internal::ParsedFormatBase* pc)
  49. : data_(pc), size_(~size_t{}) {}
  50. bool has_parsed_conversion() const { return size_ == ~size_t{}; }
  51. string_view str() const {
  52. assert(!has_parsed_conversion());
  53. return string_view(static_cast<const char*>(data_), size_);
  54. }
  55. const str_format_internal::ParsedFormatBase* parsed_conversion() const {
  56. assert(has_parsed_conversion());
  57. return static_cast<const str_format_internal::ParsedFormatBase*>(data_);
  58. }
  59. template <typename T>
  60. static const UntypedFormatSpecImpl& Extract(const T& s) {
  61. return s.spec_;
  62. }
  63. private:
  64. const void* data_;
  65. size_t size_;
  66. };
  67. template <typename T, FormatConversionCharSet...>
  68. struct MakeDependent {
  69. using type = T;
  70. };
  71. // Implicitly convertible from `const char*`, `string_view`, and the
  72. // `ExtendedParsedFormat` type. This abstraction allows all format functions to
  73. // operate on any without providing too many overloads.
  74. template <FormatConversionCharSet... Args>
  75. class FormatSpecTemplate
  76. : public MakeDependent<UntypedFormatSpec, Args...>::type {
  77. using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
  78. template <bool res>
  79. struct ErrorMaker {
  80. constexpr bool operator()(int) const { return res; }
  81. };
  82. template <int i, int j>
  83. static constexpr bool CheckArity(ErrorMaker<true> SpecifierCount = {},
  84. ErrorMaker<i == j> ParametersPassed = {}) {
  85. static_assert(SpecifierCount(i) == ParametersPassed(j),
  86. "Number of arguments passed must match the number of "
  87. "conversion specifiers.");
  88. return true;
  89. }
  90. template <FormatConversionCharSet specified, FormatConversionCharSet passed,
  91. int arg>
  92. static constexpr bool CheckMatch(
  93. ErrorMaker<Contains(specified, passed)> MismatchedArgumentNumber = {}) {
  94. static_assert(MismatchedArgumentNumber(arg),
  95. "Passed argument must match specified format.");
  96. return true;
  97. }
  98. template <FormatConversionCharSet... C, size_t... I>
  99. static bool CheckMatches(absl::index_sequence<I...>) {
  100. bool res[] = {true, CheckMatch<Args, C, I + 1>()...};
  101. (void)res;
  102. return true;
  103. }
  104. public:
  105. #ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
  106. // Honeypot overload for when the string is not constexpr.
  107. // We use the 'unavailable' attribute to give a better compiler error than
  108. // just 'method is deleted'.
  109. FormatSpecTemplate(...) // NOLINT
  110. __attribute__((unavailable("Format string is not constexpr.")));
  111. // Honeypot overload for when the format is constexpr and invalid.
  112. // We use the 'unavailable' attribute to give a better compiler error than
  113. // just 'method is deleted'.
  114. // To avoid checking the format twice, we just check that the format is
  115. // constexpr. If it is valid, then the overload below will kick in.
  116. // We add the template here to make this overload have lower priority.
  117. template <typename = void>
  118. FormatSpecTemplate(const char* s) // NOLINT
  119. __attribute__((
  120. enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"),
  121. unavailable(
  122. "Format specified does not match the arguments passed.")));
  123. template <typename T = void>
  124. FormatSpecTemplate(string_view s) // NOLINT
  125. __attribute__((enable_if(str_format_internal::EnsureConstexpr(s),
  126. "constexpr trap")))
  127. : Base("to avoid noise in the compiler error") {
  128. static_assert(sizeof(T*) == 0,
  129. "Format specified does not match the arguments passed.");
  130. }
  131. // Good format overload.
  132. FormatSpecTemplate(const char* s) // NOLINT
  133. __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
  134. : Base(s) {}
  135. FormatSpecTemplate(string_view s) // NOLINT
  136. __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
  137. : Base(s) {}
  138. #else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
  139. FormatSpecTemplate(const char* s) : Base(s) {} // NOLINT
  140. FormatSpecTemplate(string_view s) : Base(s) {} // NOLINT
  141. #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
  142. template <FormatConversionCharSet... C>
  143. FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT
  144. : Base(&pc) {
  145. CheckArity<sizeof...(C), sizeof...(Args)>();
  146. CheckMatches<C...>(absl::make_index_sequence<sizeof...(C)>{});
  147. }
  148. };
  149. class Streamable {
  150. public:
  151. Streamable(const UntypedFormatSpecImpl& format,
  152. absl::Span<const FormatArgImpl> args)
  153. : format_(format), args_(args.begin(), args.end()) {}
  154. std::ostream& Print(std::ostream& os) const;
  155. friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {
  156. return l.Print(os);
  157. }
  158. private:
  159. const UntypedFormatSpecImpl& format_;
  160. absl::InlinedVector<FormatArgImpl, 4> args_;
  161. };
  162. // for testing
  163. std::string Summarize(UntypedFormatSpecImpl format,
  164. absl::Span<const FormatArgImpl> args);
  165. bool BindWithPack(const UnboundConversion* props,
  166. absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
  167. bool FormatUntyped(FormatRawSinkImpl raw_sink, UntypedFormatSpecImpl format,
  168. absl::Span<const FormatArgImpl> args);
  169. std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
  170. absl::Span<const FormatArgImpl> args);
  171. std::string FormatPack(UntypedFormatSpecImpl format,
  172. absl::Span<const FormatArgImpl> args);
  173. int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
  174. absl::Span<const FormatArgImpl> args);
  175. int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
  176. absl::Span<const FormatArgImpl> args);
  177. // Returned by Streamed(v). Converts via '%s' to the std::string created
  178. // by std::ostream << v.
  179. template <typename T>
  180. class StreamedWrapper {
  181. public:
  182. explicit StreamedWrapper(const T& v) : v_(v) {}
  183. private:
  184. template <typename S>
  185. friend ArgConvertResult<FormatConversionCharSetUnion(
  186. FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::v)>
  187. FormatConvertImpl(const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
  188. FormatSinkImpl* out);
  189. const T& v_;
  190. };
  191. } // namespace str_format_internal
  192. ABSL_NAMESPACE_END
  193. } // namespace absl
  194. #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_