00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
00017 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
00018
00019 #include <limits.h>
00020 #include <cstddef>
00021 #include <cstring>
00022 #include <ostream>
00023
00024 #include "absl/base/port.h"
00025 #include "absl/strings/internal/str_format/output.h"
00026 #include "absl/strings/string_view.h"
00027
00028 class Cord;
00029
00030 namespace absl {
00031
00032 namespace str_format_internal {
00033
00034 class FormatRawSinkImpl {
00035 public:
00036
00037
00038 template <typename T, decltype(str_format_internal::InvokeFlush(
00039 std::declval<T*>(), string_view()))* = nullptr>
00040 FormatRawSinkImpl(T* raw)
00041 : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {}
00042
00043 void Write(string_view s) { write_(sink_, s); }
00044
00045 template <typename T>
00046 static FormatRawSinkImpl Extract(T s) {
00047 return s.sink_;
00048 }
00049
00050 private:
00051 template <typename T>
00052 static void Flush(void* r, string_view s) {
00053 str_format_internal::InvokeFlush(static_cast<T*>(r), s);
00054 }
00055
00056 void* sink_;
00057 void (*write_)(void*, string_view);
00058 };
00059
00060
00061 class FormatSinkImpl {
00062 public:
00063 explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {}
00064
00065 ~FormatSinkImpl() { Flush(); }
00066
00067 void Flush() {
00068 raw_.Write(string_view(buf_, pos_ - buf_));
00069 pos_ = buf_;
00070 }
00071
00072 void Append(size_t n, char c) {
00073 if (n == 0) return;
00074 size_ += n;
00075 auto raw_append = [&](size_t count) {
00076 memset(pos_, c, count);
00077 pos_ += count;
00078 };
00079 while (n > Avail()) {
00080 n -= Avail();
00081 if (Avail() > 0) {
00082 raw_append(Avail());
00083 }
00084 Flush();
00085 }
00086 raw_append(n);
00087 }
00088
00089 void Append(string_view v) {
00090 size_t n = v.size();
00091 if (n == 0) return;
00092 size_ += n;
00093 if (n >= Avail()) {
00094 Flush();
00095 raw_.Write(v);
00096 return;
00097 }
00098 memcpy(pos_, v.data(), n);
00099 pos_ += n;
00100 }
00101
00102 size_t size() const { return size_; }
00103
00104
00105 bool PutPaddedString(string_view v, int w, int p, bool l);
00106
00107 template <typename T>
00108 T Wrap() {
00109 return T(this);
00110 }
00111
00112 template <typename T>
00113 static FormatSinkImpl* Extract(T* s) {
00114 return s->sink_;
00115 }
00116
00117 private:
00118 size_t Avail() const { return buf_ + sizeof(buf_) - pos_; }
00119
00120 FormatRawSinkImpl raw_;
00121 size_t size_ = 0;
00122 char* pos_ = buf_;
00123 char buf_[1024];
00124 };
00125
00126 struct Flags {
00127 bool basic : 1;
00128 bool left : 1;
00129 bool show_pos : 1;
00130 bool sign_col : 1;
00131 bool alt : 1;
00132 bool zero : 1;
00133 std::string ToString() const;
00134 friend std::ostream& operator<<(std::ostream& os, const Flags& v) {
00135 return os << v.ToString();
00136 }
00137 };
00138
00139 struct LengthMod {
00140 public:
00141 enum Id : uint8_t {
00142 h, hh, l, ll, L, j, z, t, q, none
00143 };
00144 static const size_t kNumValues = none + 1;
00145
00146 LengthMod() : id_(none) {}
00147
00148
00149
00150 static LengthMod FromIndex(size_t i) {
00151 return LengthMod(kSpecs[i].value);
00152 }
00153
00154 static LengthMod FromId(Id id) { return LengthMod(id); }
00155
00156
00157 string_view name() const {
00158 const Spec& spec = kSpecs[id_];
00159 return {spec.name, spec.name_length};
00160 }
00161
00162 Id id() const { return id_; }
00163
00164 friend bool operator==(const LengthMod& a, const LengthMod& b) {
00165 return a.id() == b.id();
00166 }
00167 friend bool operator!=(const LengthMod& a, const LengthMod& b) {
00168 return !(a == b);
00169 }
00170 friend std::ostream& operator<<(std::ostream& os, const LengthMod& v) {
00171 return os << v.name();
00172 }
00173
00174 private:
00175 struct Spec {
00176 Id value;
00177 const char *name;
00178 size_t name_length;
00179 };
00180 static const Spec kSpecs[];
00181
00182 explicit LengthMod(Id id) : id_(id) {}
00183
00184 Id id_;
00185 };
00186
00187
00188 #define ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
00189 \
00190 X_VAL(c) X_SEP X_VAL(C) X_SEP X_VAL(s) X_SEP X_VAL(S) X_SEP \
00191 \
00192 X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
00193 X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
00194 \
00195 X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \
00196 X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
00197 \
00198 X_VAL(n) X_SEP X_VAL(p)
00199
00200
00201 struct ConversionChar {
00202 public:
00203 enum Id : uint8_t {
00204 c, C, s, S,
00205 d, i, o, u, x, X,
00206 f, F, e, E, g, G, a, A,
00207 n, p,
00208 none
00209 };
00210 static const size_t kNumValues = none + 1;
00211
00212 ConversionChar() : id_(none) {}
00213
00214 public:
00215
00216
00217 static ConversionChar FromIndex(size_t i) {
00218 return ConversionChar(kSpecs[i].value);
00219 }
00220
00221 static ConversionChar FromChar(char c) {
00222 ConversionChar::Id out_id = ConversionChar::none;
00223 switch (c) {
00224 #define X_VAL(id) \
00225 case #id[0]: \
00226 out_id = ConversionChar::id; \
00227 break;
00228 ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, )
00229 #undef X_VAL
00230 default:
00231 break;
00232 }
00233 return ConversionChar(out_id);
00234 }
00235
00236 static ConversionChar FromId(Id id) { return ConversionChar(id); }
00237 Id id() const { return id_; }
00238
00239 int radix() const {
00240 switch (id()) {
00241 case x: case X: case a: case A: case p: return 16;
00242 case o: return 8;
00243 default: return 10;
00244 }
00245 }
00246
00247 bool upper() const {
00248 switch (id()) {
00249 case X: case F: case E: case G: case A: return true;
00250 default: return false;
00251 }
00252 }
00253
00254 bool is_signed() const {
00255 switch (id()) {
00256 case d: case i: return true;
00257 default: return false;
00258 }
00259 }
00260
00261 bool is_integral() const {
00262 switch (id()) {
00263 case d: case i: case u: case o: case x: case X:
00264 return true;
00265 default: return false;
00266 }
00267 }
00268
00269 bool is_float() const {
00270 switch (id()) {
00271 case a: case e: case f: case g: case A: case E: case F: case G:
00272 return true;
00273 default: return false;
00274 }
00275 }
00276
00277 bool IsValid() const { return id() != none; }
00278
00279
00280 char Char() const { return kSpecs[id_].name; }
00281
00282 friend bool operator==(const ConversionChar& a, const ConversionChar& b) {
00283 return a.id() == b.id();
00284 }
00285 friend bool operator!=(const ConversionChar& a, const ConversionChar& b) {
00286 return !(a == b);
00287 }
00288 friend std::ostream& operator<<(std::ostream& os, const ConversionChar& v) {
00289 char c = v.Char();
00290 if (!c) c = '?';
00291 return os << c;
00292 }
00293
00294 private:
00295 struct Spec {
00296 Id value;
00297 char name;
00298 };
00299 static const Spec kSpecs[];
00300
00301 explicit ConversionChar(Id id) : id_(id) {}
00302
00303 Id id_;
00304 };
00305
00306 class ConversionSpec {
00307 public:
00308 Flags flags() const { return flags_; }
00309 LengthMod length_mod() const { return length_mod_; }
00310 ConversionChar conv() const {
00311
00312
00313 static_assert(offsetof(ConversionSpec, conv_) == 0, "");
00314 return conv_;
00315 }
00316
00317
00318
00319 int width() const { return width_; }
00320
00321
00322 int precision() const { return precision_; }
00323
00324 void set_flags(Flags f) { flags_ = f; }
00325 void set_length_mod(LengthMod lm) { length_mod_ = lm; }
00326 void set_conv(ConversionChar c) { conv_ = c; }
00327 void set_width(int w) { width_ = w; }
00328 void set_precision(int p) { precision_ = p; }
00329 void set_left(bool b) { flags_.left = b; }
00330
00331 private:
00332 ConversionChar conv_;
00333 Flags flags_;
00334 LengthMod length_mod_;
00335 int width_;
00336 int precision_;
00337 };
00338
00339 constexpr uint64_t ConversionCharToConvValue(char conv) {
00340 return
00341 #define CONV_SET_CASE(c) \
00342 conv == #c[0] ? (uint64_t{1} << (1 + ConversionChar::Id::c)):
00343 ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
00344 #undef CONV_SET_CASE
00345 conv == '*'
00346 ? 1
00347 : 0;
00348 }
00349
00350 enum class Conv : uint64_t {
00351 #define CONV_SET_CASE(c) c = ConversionCharToConvValue(#c[0]),
00352 ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
00353 #undef CONV_SET_CASE
00354
00355
00356 star = ConversionCharToConvValue('*'),
00357
00358
00359 integral = d | i | u | o | x | X,
00360 floating = a | e | f | g | A | E | F | G,
00361 numeric = integral | floating,
00362 string = s,
00363 pointer = p
00364 };
00365
00366
00367
00368
00369
00370
00371 constexpr Conv operator|(Conv a, Conv b) {
00372 return Conv(static_cast<uint64_t>(a) | static_cast<uint64_t>(b));
00373 }
00374
00375
00376 constexpr Conv ConversionCharToConv(char c) {
00377 return Conv(ConversionCharToConvValue(c));
00378 }
00379
00380
00381 constexpr bool Contains(Conv set, char c) {
00382 return (static_cast<uint64_t>(set) & ConversionCharToConvValue(c)) != 0;
00383 }
00384
00385
00386 constexpr bool Contains(Conv set, Conv c) {
00387 return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
00388 static_cast<uint64_t>(c);
00389 }
00390
00391
00392
00393
00394 template <Conv C>
00395 struct ConvertResult {
00396 static constexpr Conv kConv = C;
00397 bool value;
00398 };
00399 template <Conv C>
00400 constexpr Conv ConvertResult<C>::kConv;
00401
00402
00403 inline size_t Excess(size_t used, size_t capacity) {
00404 return used < capacity ? capacity - used : 0;
00405 }
00406
00407 }
00408
00409 }
00410
00411 #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_