File indexing completed on 2025-01-18 09:27:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
0042
0043 template <typename T, decltype(str_format_internal::InvokeFlush(
0044 std::declval<T*>(), string_view()))* = nullptr>
0045 FormatRawSinkImpl(T* raw)
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
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
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
0141
0142
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
0162 #define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
0163 \
0164 X_VAL(c) X_SEP X_VAL(s) X_SEP \
0165 \
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 \
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 \
0172 X_VAL(n) X_SEP X_VAL(p) X_SEP X_VAL(v)
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 struct FormatConversionCharInternal {
0186 FormatConversionCharInternal() = delete;
0187
0188 private:
0189
0190 enum class Enum : uint8_t {
0191 c, s,
0192 d, i, o, u, x, X,
0193 f, F, e, E, g, G, a, A,
0194 n, p, v,
0195 kNone
0196 };
0197
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
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
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
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
0292
0293 static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
0294 return conv_;
0295 }
0296
0297 void set_conversion_char(FormatConversionChar c) { conv_ = c; }
0298
0299
0300
0301 int width() const { return width_; }
0302
0303
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
0343
0344
0345
0346
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
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
0403
0404
0405
0406
0407 constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
0408 FormatConversionCharSet b) {
0409 return FormatConversionCharSetUnion(a, b);
0410 }
0411
0412
0413
0414 constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
0415 return static_cast<FormatConversionCharSet>(
0416 FormatConversionCharToConvValue(c));
0417 }
0418
0419
0420 constexpr FormatConversionCharSet ToFormatConversionCharSet(
0421 FormatConversionCharSet c) {
0422 return c;
0423 }
0424
0425 template <typename T>
0426 void ToFormatConversionCharSet(T) = delete;
0427
0428
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
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
0442 constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
0443 return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
0444 }
0445
0446
0447 inline size_t Excess(size_t used, size_t capacity) {
0448 return used < capacity ? capacity - used : 0;
0449 }
0450
0451 }
0452
0453 ABSL_NAMESPACE_END
0454 }
0455
0456 #endif