Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //
0002 // Copyright 2017 The Abseil Authors.
0003 //
0004 // Licensed under the Apache License, Version 2.0 (the "License");
0005 // you may not use this file except in compliance with the License.
0006 // You may obtain a copy of the License at
0007 //
0008 //      https://www.apache.org/licenses/LICENSE-2.0
0009 //
0010 // Unless required by applicable law or agreed to in writing, software
0011 // distributed under the License is distributed on an "AS IS" BASIS,
0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013 // See the License for the specific language governing permissions and
0014 // limitations under the License.
0015 //
0016 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
0017 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
0018 
0019 
0020 #include <cstddef>
0021 #include <cstdint>
0022 #include <cstring>
0023 #include <ostream>
0024 #include <string>
0025 
0026 #include "absl/base/config.h"
0027 #include "absl/strings/internal/str_format/output.h"
0028 #include "absl/strings/string_view.h"
0029 
0030 namespace absl {
0031 ABSL_NAMESPACE_BEGIN
0032 
0033 enum class FormatConversionChar : uint8_t;
0034 enum class FormatConversionCharSet : uint64_t;
0035 enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
0036 
0037 namespace str_format_internal {
0038 
0039 class FormatRawSinkImpl {
0040  public:
0041   // Implicitly convert from any type that provides the hook function as
0042   // described above.
0043   template <typename T, decltype(str_format_internal::InvokeFlush(
0044                             std::declval<T*>(), string_view()))* = nullptr>
0045   FormatRawSinkImpl(T* raw)  // NOLINT
0046       : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {}
0047 
0048   void Write(string_view s) { write_(sink_, s); }
0049 
0050   template <typename T>
0051   static FormatRawSinkImpl Extract(T s) {
0052     return s.sink_;
0053   }
0054 
0055  private:
0056   template <typename T>
0057   static void Flush(void* r, string_view s) {
0058     str_format_internal::InvokeFlush(static_cast<T*>(r), s);
0059   }
0060 
0061   void* sink_;
0062   void (*write_)(void*, string_view);
0063 };
0064 
0065 // An abstraction to which conversions write their string data.
0066 class FormatSinkImpl {
0067  public:
0068   explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {}
0069 
0070   ~FormatSinkImpl() { Flush(); }
0071 
0072   void Flush() {
0073     raw_.Write(string_view(buf_, static_cast<size_t>(pos_ - buf_)));
0074     pos_ = buf_;
0075   }
0076 
0077   void Append(size_t n, char c) {
0078     if (n == 0) return;
0079     size_ += n;
0080     auto raw_append = [&](size_t count) {
0081       memset(pos_, c, count);
0082       pos_ += count;
0083     };
0084     while (n > Avail()) {
0085       n -= Avail();
0086       if (Avail() > 0) {
0087         raw_append(Avail());
0088       }
0089       Flush();
0090     }
0091     raw_append(n);
0092   }
0093 
0094   void Append(string_view v) {
0095     size_t n = v.size();
0096     if (n == 0) return;
0097     size_ += n;
0098     if (n >= Avail()) {
0099       Flush();
0100       raw_.Write(v);
0101       return;
0102     }
0103     memcpy(pos_, v.data(), n);
0104     pos_ += n;
0105   }
0106 
0107   size_t size() const { return size_; }
0108 
0109   // Put 'v' to 'sink' with specified width, precision, and left flag.
0110   bool PutPaddedString(string_view v, int width, int precision, bool left);
0111 
0112   template <typename T>
0113   T Wrap() {
0114     return T(this);
0115   }
0116 
0117   template <typename T>
0118   static FormatSinkImpl* Extract(T* s) {
0119     return s->sink_;
0120   }
0121 
0122  private:
0123   size_t Avail() const {
0124     return static_cast<size_t>(buf_ + sizeof(buf_) - pos_);
0125   }
0126 
0127   FormatRawSinkImpl raw_;
0128   size_t size_ = 0;
0129   char* pos_ = buf_;
0130   char buf_[1024];
0131 };
0132 
0133 enum class Flags : uint8_t {
0134   kBasic = 0,
0135   kLeft = 1 << 0,
0136   kShowPos = 1 << 1,
0137   kSignCol = 1 << 2,
0138   kAlt = 1 << 3,
0139   kZero = 1 << 4,
0140   // This is not a real flag. It just exists to turn off kBasic when no other
0141   // flags are set. This is for when width/precision are specified, or a length
0142   // modifier affects the behavior ("%lc").
0143   kNonBasic = 1 << 5,
0144 };
0145 
0146 constexpr Flags operator|(Flags a, Flags b) {
0147   return static_cast<Flags>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
0148 }
0149 
0150 constexpr bool FlagsContains(Flags haystack, Flags needle) {
0151   return (static_cast<uint8_t>(haystack) & static_cast<uint8_t>(needle)) ==
0152          static_cast<uint8_t>(needle);
0153 }
0154 
0155 std::string FlagsToString(Flags v);
0156 
0157 inline std::ostream& operator<<(std::ostream& os, Flags v) {
0158   return os << FlagsToString(v);
0159 }
0160 
0161 // clang-format off
0162 #define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
0163   /* text */ \
0164   X_VAL(c) X_SEP X_VAL(s) X_SEP \
0165   /* ints */ \
0166   X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
0167   X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
0168   /* floats */ \
0169   X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \
0170   X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
0171   /* misc */ \
0172   X_VAL(n) X_SEP X_VAL(p) X_SEP X_VAL(v)
0173 // clang-format on
0174 
0175 // This type should not be referenced, it exists only to provide labels
0176 // internally that match the values declared in FormatConversionChar in
0177 // str_format.h. This is meant to allow internal libraries to use the same
0178 // declared interface type as the public interface
0179 // (absl::StrFormatConversionChar) while keeping the definition in a public
0180 // header.
0181 // Internal libraries should use the form
0182 // `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for
0183 // comparisons.  Use in switch statements is not recommended due to a bug in how
0184 // gcc 4.9 -Wswitch handles declared but undefined enums.
0185 struct FormatConversionCharInternal {
0186   FormatConversionCharInternal() = delete;
0187 
0188  private:
0189   // clang-format off
0190   enum class Enum : uint8_t {
0191     c, s,                    // text
0192     d, i, o, u, x, X,        // int
0193     f, F, e, E, g, G, a, A,  // float
0194     n, p, v,                    // misc
0195     kNone
0196   };
0197   // clang-format on
0198  public:
0199 #define ABSL_INTERNAL_X_VAL(id)              \
0200   static constexpr FormatConversionChar id = \
0201       static_cast<FormatConversionChar>(Enum::id);
0202   ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
0203 #undef ABSL_INTERNAL_X_VAL
0204   static constexpr FormatConversionChar kNone =
0205       static_cast<FormatConversionChar>(Enum::kNone);
0206 };
0207 // clang-format on
0208 
0209 inline FormatConversionChar FormatConversionCharFromChar(char c) {
0210   switch (c) {
0211 #define ABSL_INTERNAL_X_VAL(id) \
0212   case #id[0]:                  \
0213     return FormatConversionCharInternal::id;
0214     ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
0215 #undef ABSL_INTERNAL_X_VAL
0216   }
0217   return FormatConversionCharInternal::kNone;
0218 }
0219 
0220 inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
0221   if (c == FormatConversionCharInternal::X ||
0222       c == FormatConversionCharInternal::F ||
0223       c == FormatConversionCharInternal::E ||
0224       c == FormatConversionCharInternal::G ||
0225       c == FormatConversionCharInternal::A) {
0226     return true;
0227   } else {
0228     return false;
0229   }
0230 }
0231 
0232 inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
0233   if (c == FormatConversionCharInternal::a ||
0234       c == FormatConversionCharInternal::e ||
0235       c == FormatConversionCharInternal::f ||
0236       c == FormatConversionCharInternal::g ||
0237       c == FormatConversionCharInternal::A ||
0238       c == FormatConversionCharInternal::E ||
0239       c == FormatConversionCharInternal::F ||
0240       c == FormatConversionCharInternal::G) {
0241     return true;
0242   } else {
0243     return false;
0244   }
0245 }
0246 
0247 inline char FormatConversionCharToChar(FormatConversionChar c) {
0248   if (c == FormatConversionCharInternal::kNone) {
0249     return '\0';
0250 
0251 #define ABSL_INTERNAL_X_VAL(e)                       \
0252   } else if (c == FormatConversionCharInternal::e) { \
0253     return #e[0];
0254 #define ABSL_INTERNAL_X_SEP
0255   ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
0256                                          ABSL_INTERNAL_X_SEP)
0257   } else {
0258     return '\0';
0259   }
0260 
0261 #undef ABSL_INTERNAL_X_VAL
0262 #undef ABSL_INTERNAL_X_SEP
0263 }
0264 
0265 // The associated char.
0266 inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
0267   char c = FormatConversionCharToChar(v);
0268   if (!c) c = '?';
0269   return os << c;
0270 }
0271 
0272 struct FormatConversionSpecImplFriend;
0273 
0274 class FormatConversionSpecImpl {
0275  public:
0276   // Width and precision are not specified, no flags are set.
0277   bool is_basic() const { return flags_ == Flags::kBasic; }
0278   bool has_left_flag() const { return FlagsContains(flags_, Flags::kLeft); }
0279   bool has_show_pos_flag() const {
0280     return FlagsContains(flags_, Flags::kShowPos);
0281   }
0282   bool has_sign_col_flag() const {
0283     return FlagsContains(flags_, Flags::kSignCol);
0284   }
0285   bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); }
0286   bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); }
0287 
0288   LengthMod length_mod() const { return length_mod_; }
0289 
0290   FormatConversionChar conversion_char() const {
0291     // Keep this field first in the struct . It generates better code when
0292     // accessing it when ConversionSpec is passed by value in registers.
0293     static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
0294     return conv_;
0295   }
0296 
0297   void set_conversion_char(FormatConversionChar c) { conv_ = c; }
0298 
0299   // Returns the specified width. If width is unspecfied, it returns a negative
0300   // value.
0301   int width() const { return width_; }
0302   // Returns the specified precision. If precision is unspecfied, it returns a
0303   // negative value.
0304   int precision() const { return precision_; }
0305 
0306   template <typename T>
0307   T Wrap() {
0308     return T(*this);
0309   }
0310 
0311  private:
0312   friend struct str_format_internal::FormatConversionSpecImplFriend;
0313   FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
0314   Flags flags_;
0315   LengthMod length_mod_ = LengthMod::none;
0316   int width_;
0317   int precision_;
0318 };
0319 
0320 struct FormatConversionSpecImplFriend final {
0321   static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
0322     conv->flags_ = f;
0323   }
0324   static void SetLengthMod(LengthMod l, FormatConversionSpecImpl* conv) {
0325     conv->length_mod_ = l;
0326   }
0327   static void SetConversionChar(FormatConversionChar c,
0328                                 FormatConversionSpecImpl* conv) {
0329     conv->conv_ = c;
0330   }
0331   static void SetWidth(int w, FormatConversionSpecImpl* conv) {
0332     conv->width_ = w;
0333   }
0334   static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
0335     conv->precision_ = p;
0336   }
0337   static std::string FlagsToString(const FormatConversionSpecImpl& spec) {
0338     return str_format_internal::FlagsToString(spec.flags_);
0339   }
0340 };
0341 
0342 // Type safe OR operator.
0343 // We need this for two reasons:
0344 //  1. operator| on enums makes them decay to integers and the result is an
0345 //     integer. We need the result to stay as an enum.
0346 //  2. We use "enum class" which would not work even if we accepted the decay.
0347 constexpr FormatConversionCharSet FormatConversionCharSetUnion(
0348     FormatConversionCharSet a) {
0349   return a;
0350 }
0351 
0352 template <typename... CharSet>
0353 constexpr FormatConversionCharSet FormatConversionCharSetUnion(
0354     FormatConversionCharSet a, CharSet... rest) {
0355   return static_cast<FormatConversionCharSet>(
0356       static_cast<uint64_t>(a) |
0357       static_cast<uint64_t>(FormatConversionCharSetUnion(rest...)));
0358 }
0359 
0360 constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {
0361   return uint64_t{1} << (1 + static_cast<uint8_t>(c));
0362 }
0363 
0364 constexpr uint64_t FormatConversionCharToConvInt(char conv) {
0365   return
0366 #define ABSL_INTERNAL_CHAR_SET_CASE(c)                                 \
0367   conv == #c[0]                                                        \
0368       ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
0369       :
0370       ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
0371 #undef ABSL_INTERNAL_CHAR_SET_CASE
0372                   conv == '*'
0373           ? 1
0374           : 0;
0375 }
0376 
0377 constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {
0378   return static_cast<FormatConversionCharSet>(
0379       FormatConversionCharToConvInt(conv));
0380 }
0381 
0382 struct FormatConversionCharSetInternal {
0383 #define ABSL_INTERNAL_CHAR_SET_CASE(c)         \
0384   static constexpr FormatConversionCharSet c = \
0385       FormatConversionCharToConvValue(#c[0]);
0386   ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
0387 #undef ABSL_INTERNAL_CHAR_SET_CASE
0388 
0389   // Used for width/precision '*' specification.
0390   static constexpr FormatConversionCharSet kStar =
0391       FormatConversionCharToConvValue('*');
0392 
0393   static constexpr FormatConversionCharSet kIntegral =
0394       FormatConversionCharSetUnion(d, i, u, o, x, X);
0395   static constexpr FormatConversionCharSet kFloating =
0396       FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);
0397   static constexpr FormatConversionCharSet kNumeric =
0398       FormatConversionCharSetUnion(kIntegral, kFloating);
0399   static constexpr FormatConversionCharSet kPointer = p;
0400 };
0401 
0402 // Type safe OR operator.
0403 // We need this for two reasons:
0404 //  1. operator| on enums makes them decay to integers and the result is an
0405 //     integer. We need the result to stay as an enum.
0406 //  2. We use "enum class" which would not work even if we accepted the decay.
0407 constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
0408                                             FormatConversionCharSet b) {
0409   return FormatConversionCharSetUnion(a, b);
0410 }
0411 
0412 // Overloaded conversion functions to support absl::ParsedFormat.
0413 // Get a conversion with a single character in it.
0414 constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
0415   return static_cast<FormatConversionCharSet>(
0416       FormatConversionCharToConvValue(c));
0417 }
0418 
0419 // Get a conversion with a single character in it.
0420 constexpr FormatConversionCharSet ToFormatConversionCharSet(
0421     FormatConversionCharSet c) {
0422   return c;
0423 }
0424 
0425 template <typename T>
0426 void ToFormatConversionCharSet(T) = delete;
0427 
0428 // Checks whether `c` exists in `set`.
0429 constexpr bool Contains(FormatConversionCharSet set, char c) {
0430   return (static_cast<uint64_t>(set) &
0431           static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
0432 }
0433 
0434 // Checks whether all the characters in `c` are contained in `set`
0435 constexpr bool Contains(FormatConversionCharSet set,
0436                         FormatConversionCharSet c) {
0437   return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
0438          static_cast<uint64_t>(c);
0439 }
0440 
0441 // Checks whether all the characters in `c` are contained in `set`
0442 constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
0443   return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
0444 }
0445 
0446 // Return capacity - used, clipped to a minimum of 0.
0447 inline size_t Excess(size_t used, size_t capacity) {
0448   return used < capacity ? capacity - used : 0;
0449 }
0450 
0451 }  // namespace str_format_internal
0452 
0453 ABSL_NAMESPACE_END
0454 }  // namespace absl
0455 
0456 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_