Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:23

0001 // Copyright 2020 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
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 // This is the type-erased class that the implementation uses.
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 // Implicitly convertible from `const char*`, `string_view`, and the
0088 // `ExtendedParsedFormat` type. This abstraction allows all format functions to
0089 // operate on any without providing too many overloads.
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   // Honeypot overload for when the string is not constexpr.
0129   // We use the 'unavailable' attribute to give a better compiler error than
0130   // just 'method is deleted'.
0131   FormatSpecTemplate(...)  // NOLINT
0132       __attribute__((unavailable("Format string is not constexpr.")));
0133 
0134   // Honeypot overload for when the format is constexpr and invalid.
0135   // We use the 'unavailable' attribute to give a better compiler error than
0136   // just 'method is deleted'.
0137   // To avoid checking the format twice, we just check that the format is
0138   // constexpr. If it is valid, then the overload below will kick in.
0139   // We add the template here to make this overload have lower priority.
0140   template <typename = void>
0141   FormatSpecTemplate(const char* s)  // NOLINT
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)  // NOLINT
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   // Good format overload.
0157   FormatSpecTemplate(const char* s)  // NOLINT
0158       __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
0159       : Base(s) {}
0160 
0161   FormatSpecTemplate(string_view s)  // NOLINT
0162       __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
0163       : Base(s) {}
0164 
0165 #else  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
0166 
0167   FormatSpecTemplate(const char* s) : Base(s) {}  // NOLINT
0168   FormatSpecTemplate(string_view s) : Base(s) {}  // NOLINT
0169 
0170 #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
0171 
0172   template <FormatConversionCharSet... C>
0173   FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc)  // NOLINT
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 // for testing
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 // Returned by Streamed(v). Converts via '%s' to the std::string created
0218 // by std::ostream << v.
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 }  // namespace str_format_internal
0234 ABSL_NAMESPACE_END
0235 }  // namespace absl
0236 
0237 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_