00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #ifndef ABSL_STRINGS_STR_CAT_H_
00053 #define ABSL_STRINGS_STR_CAT_H_
00054
00055 #include <array>
00056 #include <cstdint>
00057 #include <string>
00058 #include <type_traits>
00059 #include <vector>
00060
00061 #include "absl/base/port.h"
00062 #include "absl/strings/numbers.h"
00063 #include "absl/strings/string_view.h"
00064
00065 namespace absl {
00066
00067 namespace strings_internal {
00068
00069
00070
00071 template <size_t max_size>
00072 struct AlphaNumBuffer {
00073 std::array<char, max_size> data;
00074 size_t size;
00075 };
00076
00077 }
00078
00079
00080
00081
00082
00083 enum PadSpec : uint8_t {
00084 kNoPad = 1,
00085 kZeroPad2,
00086 kZeroPad3,
00087 kZeroPad4,
00088 kZeroPad5,
00089 kZeroPad6,
00090 kZeroPad7,
00091 kZeroPad8,
00092 kZeroPad9,
00093 kZeroPad10,
00094 kZeroPad11,
00095 kZeroPad12,
00096 kZeroPad13,
00097 kZeroPad14,
00098 kZeroPad15,
00099 kZeroPad16,
00100 kZeroPad17,
00101 kZeroPad18,
00102 kZeroPad19,
00103 kZeroPad20,
00104
00105 kSpacePad2 = kZeroPad2 + 64,
00106 kSpacePad3,
00107 kSpacePad4,
00108 kSpacePad5,
00109 kSpacePad6,
00110 kSpacePad7,
00111 kSpacePad8,
00112 kSpacePad9,
00113 kSpacePad10,
00114 kSpacePad11,
00115 kSpacePad12,
00116 kSpacePad13,
00117 kSpacePad14,
00118 kSpacePad15,
00119 kSpacePad16,
00120 kSpacePad17,
00121 kSpacePad18,
00122 kSpacePad19,
00123 kSpacePad20,
00124 };
00125
00126
00127
00128
00129
00130
00131
00132 struct Hex {
00133 uint64_t value;
00134 uint8_t width;
00135 char fill;
00136
00137 template <typename Int>
00138 explicit Hex(
00139 Int v, PadSpec spec = absl::kNoPad,
00140 typename std::enable_if<sizeof(Int) == 1 &&
00141 !std::is_pointer<Int>::value>::type* = nullptr)
00142 : Hex(spec, static_cast<uint8_t>(v)) {}
00143 template <typename Int>
00144 explicit Hex(
00145 Int v, PadSpec spec = absl::kNoPad,
00146 typename std::enable_if<sizeof(Int) == 2 &&
00147 !std::is_pointer<Int>::value>::type* = nullptr)
00148 : Hex(spec, static_cast<uint16_t>(v)) {}
00149 template <typename Int>
00150 explicit Hex(
00151 Int v, PadSpec spec = absl::kNoPad,
00152 typename std::enable_if<sizeof(Int) == 4 &&
00153 !std::is_pointer<Int>::value>::type* = nullptr)
00154 : Hex(spec, static_cast<uint32_t>(v)) {}
00155 template <typename Int>
00156 explicit Hex(
00157 Int v, PadSpec spec = absl::kNoPad,
00158 typename std::enable_if<sizeof(Int) == 8 &&
00159 !std::is_pointer<Int>::value>::type* = nullptr)
00160 : Hex(spec, static_cast<uint64_t>(v)) {}
00161 template <typename Pointee>
00162 explicit Hex(Pointee* v, PadSpec spec = absl::kNoPad)
00163 : Hex(spec, reinterpret_cast<uintptr_t>(v)) {}
00164
00165 private:
00166 Hex(PadSpec spec, uint64_t v)
00167 : value(v),
00168 width(spec == absl::kNoPad
00169 ? 1
00170 : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
00171 : spec - absl::kZeroPad2 + 2),
00172 fill(spec >= absl::kSpacePad2 ? ' ' : '0') {}
00173 };
00174
00175
00176
00177
00178
00179
00180
00181
00182 struct Dec {
00183 uint64_t value;
00184 uint8_t width;
00185 char fill;
00186 bool neg;
00187
00188 template <typename Int>
00189 explicit Dec(Int v, PadSpec spec = absl::kNoPad,
00190 typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr)
00191 : value(v >= 0 ? static_cast<uint64_t>(v)
00192 : uint64_t{0} - static_cast<uint64_t>(v)),
00193 width(spec == absl::kNoPad
00194 ? 1
00195 : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
00196 : spec - absl::kZeroPad2 + 2),
00197 fill(spec >= absl::kSpacePad2 ? ' ' : '0'),
00198 neg(v < 0) {}
00199 };
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 class AlphaNum {
00210 public:
00211
00212
00213
00214 AlphaNum(int x)
00215 : piece_(digits_,
00216 numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
00217 AlphaNum(unsigned int x)
00218 : piece_(digits_,
00219 numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
00220 AlphaNum(long x)
00221 : piece_(digits_,
00222 numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
00223 AlphaNum(unsigned long x)
00224 : piece_(digits_,
00225 numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
00226 AlphaNum(long long x)
00227 : piece_(digits_,
00228 numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
00229 AlphaNum(unsigned long long x)
00230 : piece_(digits_,
00231 numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
00232
00233 AlphaNum(float f)
00234 : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
00235 AlphaNum(double f)
00236 : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
00237
00238 AlphaNum(Hex hex);
00239 AlphaNum(Dec dec);
00240
00241 template <size_t size>
00242 AlphaNum(
00243 const strings_internal::AlphaNumBuffer<size>& buf)
00244 : piece_(&buf.data[0], buf.size) {}
00245
00246 AlphaNum(const char* c_str) : piece_(c_str) {}
00247 AlphaNum(absl::string_view pc) : piece_(pc) {}
00248
00249 template <typename Allocator>
00250 AlphaNum(
00251 const std::basic_string<char, std::char_traits<char>, Allocator>& str)
00252 : piece_(str) {}
00253
00254
00255 AlphaNum(char c) = delete;
00256
00257 AlphaNum(const AlphaNum&) = delete;
00258 AlphaNum& operator=(const AlphaNum&) = delete;
00259
00260 absl::string_view::size_type size() const { return piece_.size(); }
00261 const char* data() const { return piece_.data(); }
00262 absl::string_view Piece() const { return piece_; }
00263
00264
00265
00266 template <typename T,
00267 typename = typename std::enable_if<
00268 std::is_enum<T>{} && !std::is_convertible<T, int>{}>::type>
00269 AlphaNum(T e)
00270 : AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {}
00271
00272
00273
00274 template <
00275 typename T,
00276 typename std::enable_if<
00277 std::is_class<T>::value &&
00278 (std::is_same<T, std::vector<bool>::reference>::value ||
00279 std::is_same<T, std::vector<bool>::const_reference>::value)>::type* =
00280 nullptr>
00281 AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {}
00282
00283 private:
00284 absl::string_view piece_;
00285 char digits_[numbers_internal::kFastToBufferSize];
00286 };
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 namespace strings_internal {
00316
00317
00318 std::string CatPieces(std::initializer_list<absl::string_view> pieces);
00319 void AppendPieces(std::string* dest,
00320 std::initializer_list<absl::string_view> pieces);
00321
00322 }
00323
00324 ABSL_MUST_USE_RESULT inline std::string StrCat() { return std::string(); }
00325
00326 ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a) {
00327 return std::string(a.data(), a.size());
00328 }
00329
00330 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
00331 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
00332 const AlphaNum& c);
00333 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
00334 const AlphaNum& c, const AlphaNum& d);
00335
00336
00337 template <typename... AV>
00338 ABSL_MUST_USE_RESULT inline std::string StrCat(
00339 const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
00340 const AlphaNum& e, const AV&... args) {
00341 return strings_internal::CatPieces(
00342 {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
00343 static_cast<const AlphaNum&>(args).Piece()...});
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 inline void StrAppend(std::string*) {}
00374 void StrAppend(std::string* dest, const AlphaNum& a);
00375 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b);
00376 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
00377 const AlphaNum& c);
00378 void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
00379 const AlphaNum& c, const AlphaNum& d);
00380
00381
00382 template <typename... AV>
00383 inline void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
00384 const AlphaNum& c, const AlphaNum& d, const AlphaNum& e,
00385 const AV&... args) {
00386 strings_internal::AppendPieces(
00387 dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
00388 static_cast<const AlphaNum&>(args).Piece()...});
00389 }
00390
00391
00392
00393 inline strings_internal::AlphaNumBuffer<
00394 numbers_internal::kSixDigitsToBufferSize>
00395 SixDigits(double d) {
00396 strings_internal::AlphaNumBuffer<numbers_internal::kSixDigitsToBufferSize>
00397 result;
00398 result.size = numbers_internal::SixDigitsToBuffer(d, &result.data[0]);
00399 return result;
00400 }
00401
00402 }
00403
00404 #endif // ABSL_STRINGS_STR_CAT_H_