bind.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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 <array>
  17. #include <cstdio>
  18. #include <sstream>
  19. #include <string>
  20. #include "absl/base/port.h"
  21. #include "absl/strings/internal/str_format/arg.h"
  22. #include "absl/strings/internal/str_format/checker.h"
  23. #include "absl/strings/internal/str_format/parser.h"
  24. #include "absl/types/span.h"
  25. namespace absl {
  26. ABSL_NAMESPACE_BEGIN
  27. class UntypedFormatSpec;
  28. namespace str_format_internal {
  29. class BoundConversion : public FormatConversionSpecImpl {
  30. public:
  31. const FormatArgImpl* arg() const { return arg_; }
  32. void set_arg(const FormatArgImpl* a) { arg_ = a; }
  33. private:
  34. const FormatArgImpl* arg_;
  35. };
  36. // This is the type-erased class that the implementation uses.
  37. class UntypedFormatSpecImpl {
  38. public:
  39. UntypedFormatSpecImpl() = delete;
  40. explicit UntypedFormatSpecImpl(string_view s)
  41. : data_(s.data()), size_(s.size()) {}
  42. explicit UntypedFormatSpecImpl(
  43. const str_format_internal::ParsedFormatBase* pc)
  44. : data_(pc), size_(~size_t{}) {}
  45. bool has_parsed_conversion() const { return size_ == ~size_t{}; }
  46. string_view str() const {
  47. assert(!has_parsed_conversion());
  48. return string_view(static_cast<const char*>(data_), size_);
  49. }
  50. const str_format_internal::ParsedFormatBase* parsed_conversion() const {
  51. assert(has_parsed_conversion());
  52. return static_cast<const str_format_internal::ParsedFormatBase*>(data_);
  53. }
  54. template <typename T>
  55. static const UntypedFormatSpecImpl& Extract(const T& s) {
  56. return s.spec_;
  57. }
  58. private:
  59. const void* data_;
  60. size_t size_;
  61. };
  62. template <typename T, FormatConversionCharSet...>
  63. struct MakeDependent {
  64. using type = T;
  65. };
  66. // Implicitly convertible from `const char*`, `string_view`, and the
  67. // `ExtendedParsedFormat` type. This abstraction allows all format functions to
  68. // operate on any without providing too many overloads.
  69. template <FormatConversionCharSet... Args>
  70. class FormatSpecTemplate
  71. : public MakeDependent<UntypedFormatSpec, Args...>::type {
  72. using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
  73. public:
  74. #ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
  75. // Honeypot overload for when the string is not constexpr.
  76. // We use the 'unavailable' attribute to give a better compiler error than
  77. // just 'method is deleted'.
  78. FormatSpecTemplate(...) // NOLINT
  79. __attribute__((unavailable("Format string is not constexpr.")));
  80. // Honeypot overload for when the format is constexpr and invalid.
  81. // We use the 'unavailable' attribute to give a better compiler error than
  82. // just 'method is deleted'.
  83. // To avoid checking the format twice, we just check that the format is
  84. // constexpr. If it is valid, then the overload below will kick in.
  85. // We add the template here to make this overload have lower priority.
  86. template <typename = void>
  87. FormatSpecTemplate(const char* s) // NOLINT
  88. __attribute__((
  89. enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"),
  90. unavailable(
  91. "Format specified does not match the arguments passed.")));
  92. template <typename T = void>
  93. FormatSpecTemplate(string_view s) // NOLINT
  94. __attribute__((enable_if(str_format_internal::EnsureConstexpr(s),
  95. "constexpr trap"))) {
  96. static_assert(sizeof(T*) == 0,
  97. "Format specified does not match the arguments passed.");
  98. }
  99. // Good format overload.
  100. FormatSpecTemplate(const char* s) // NOLINT
  101. __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
  102. : Base(s) {}
  103. FormatSpecTemplate(string_view s) // NOLINT
  104. __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
  105. : Base(s) {}
  106. #else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
  107. FormatSpecTemplate(const char* s) : Base(s) {} // NOLINT
  108. FormatSpecTemplate(string_view s) : Base(s) {} // NOLINT
  109. #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
  110. template <
  111. FormatConversionCharSet... C,
  112. typename = typename std::enable_if<sizeof...(C) == sizeof...(Args)>::type,
  113. typename = typename std::enable_if<AllOf(Contains(Args,
  114. C)...)>::type>
  115. FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT
  116. : Base(&pc) {}
  117. };
  118. class Streamable {
  119. public:
  120. Streamable(const UntypedFormatSpecImpl& format,
  121. absl::Span<const FormatArgImpl> args)
  122. : format_(format) {
  123. if (args.size() <= ABSL_ARRAYSIZE(few_args_)) {
  124. for (size_t i = 0; i < args.size(); ++i) {
  125. few_args_[i] = args[i];
  126. }
  127. args_ = absl::MakeSpan(few_args_, args.size());
  128. } else {
  129. many_args_.assign(args.begin(), args.end());
  130. args_ = many_args_;
  131. }
  132. }
  133. std::ostream& Print(std::ostream& os) const;
  134. friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {
  135. return l.Print(os);
  136. }
  137. private:
  138. const UntypedFormatSpecImpl& format_;
  139. absl::Span<const FormatArgImpl> args_;
  140. // if args_.size() is 4 or less:
  141. FormatArgImpl few_args_[4] = {FormatArgImpl(0), FormatArgImpl(0),
  142. FormatArgImpl(0), FormatArgImpl(0)};
  143. // if args_.size() is more than 4:
  144. std::vector<FormatArgImpl> many_args_;
  145. };
  146. // for testing
  147. std::string Summarize(UntypedFormatSpecImpl format,
  148. absl::Span<const FormatArgImpl> args);
  149. bool BindWithPack(const UnboundConversion* props,
  150. absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
  151. bool FormatUntyped(FormatRawSinkImpl raw_sink,
  152. UntypedFormatSpecImpl format,
  153. absl::Span<const FormatArgImpl> args);
  154. std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
  155. absl::Span<const FormatArgImpl> args);
  156. std::string FormatPack(const UntypedFormatSpecImpl format,
  157. absl::Span<const FormatArgImpl> args);
  158. int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
  159. absl::Span<const FormatArgImpl> args);
  160. int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
  161. absl::Span<const FormatArgImpl> args);
  162. // Returned by Streamed(v). Converts via '%s' to the std::string created
  163. // by std::ostream << v.
  164. template <typename T>
  165. class StreamedWrapper {
  166. public:
  167. explicit StreamedWrapper(const T& v) : v_(v) { }
  168. private:
  169. template <typename S>
  170. friend ArgConvertResult<FormatConversionCharSetInternal::s> FormatConvertImpl(
  171. const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
  172. FormatSinkImpl* out);
  173. const T& v_;
  174. };
  175. } // namespace str_format_internal
  176. ABSL_NAMESPACE_END
  177. } // namespace absl
  178. #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_