| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 | 
							- //
 
- // Copyright 2017 The Abseil Authors.
 
- //
 
- // Licensed under the Apache License, Version 2.0 (the "License");
 
- // you may not use this file except in compliance with the License.
 
- // You may obtain a copy of the License at
 
- //
 
- //      https://www.apache.org/licenses/LICENSE-2.0
 
- //
 
- // Unless required by applicable law or agreed to in writing, software
 
- // distributed under the License is distributed on an "AS IS" BASIS,
 
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
- // See the License for the specific language governing permissions and
 
- // limitations under the License.
 
- //
 
- // -----------------------------------------------------------------------------
 
- // File: str_cat.h
 
- // -----------------------------------------------------------------------------
 
- //
 
- // This package contains functions for efficiently concatenating and appending
 
- // strings: `StrCat()` and `StrAppend()`. Most of the work within these routines
 
- // is actually handled through use of a special AlphaNum type, which was
 
- // designed to be used as a parameter type that efficiently manages conversion
 
- // to strings and avoids copies in the above operations.
 
- //
 
- // Any routine accepting either a string or a number may accept `AlphaNum`.
 
- // The basic idea is that by accepting a `const AlphaNum &` as an argument
 
- // to your function, your callers will automagically convert bools, integers,
 
- // and floating point values to strings for you.
 
- //
 
- // NOTE: Use of `AlphaNum` outside of the //absl/strings package is unsupported
 
- // except for the specific case of function parameters of type `AlphaNum` or
 
- // `const AlphaNum &`. In particular, instantiating `AlphaNum` directly as a
 
- // stack variable is not supported.
 
- //
 
- // Conversion from 8-bit values is not accepted because, if it were, then an
 
- // attempt to pass ':' instead of ":" might result in a 58 ending up in your
 
- // result.
 
- //
 
- // Bools convert to "0" or "1". Pointers to types other than `char *` are not
 
- // valid inputs. No output is generated for null `char *` pointers.
 
- //
 
- // Floating point numbers are formatted with six-digit precision, which is
 
- // the default for "std::cout <<" or printf "%g" (the same as "%.6g").
 
- //
 
- // You can convert to hexadecimal output rather than decimal output using the
 
- // `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
 
- // `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
 
- // a `PadSpec` enum.
 
- //
 
- // -----------------------------------------------------------------------------
 
- #ifndef ABSL_STRINGS_STR_CAT_H_
 
- #define ABSL_STRINGS_STR_CAT_H_
 
- #include <array>
 
- #include <cstdint>
 
- #include <string>
 
- #include <type_traits>
 
- #include <vector>
 
- #include "absl/base/port.h"
 
- #include "absl/strings/numbers.h"
 
- #include "absl/strings/string_view.h"
 
- namespace absl {
 
- ABSL_NAMESPACE_BEGIN
 
- namespace strings_internal {
 
- // AlphaNumBuffer allows a way to pass a string to StrCat without having to do
 
- // memory allocation.  It is simply a pair of a fixed-size character array, and
 
- // a size.  Please don't use outside of absl, yet.
 
- template <size_t max_size>
 
- struct AlphaNumBuffer {
 
-   std::array<char, max_size> data;
 
-   size_t size;
 
- };
 
- }  // namespace strings_internal
 
- // Enum that specifies the number of significant digits to return in a `Hex` or
 
- // `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
 
- // would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value
 
- // would produce hexadecimal strings such as "    a","    f".
 
- enum PadSpec : uint8_t {
 
-   kNoPad = 1,
 
-   kZeroPad2,
 
-   kZeroPad3,
 
-   kZeroPad4,
 
-   kZeroPad5,
 
-   kZeroPad6,
 
-   kZeroPad7,
 
-   kZeroPad8,
 
-   kZeroPad9,
 
-   kZeroPad10,
 
-   kZeroPad11,
 
-   kZeroPad12,
 
-   kZeroPad13,
 
-   kZeroPad14,
 
-   kZeroPad15,
 
-   kZeroPad16,
 
-   kZeroPad17,
 
-   kZeroPad18,
 
-   kZeroPad19,
 
-   kZeroPad20,
 
-   kSpacePad2 = kZeroPad2 + 64,
 
-   kSpacePad3,
 
-   kSpacePad4,
 
-   kSpacePad5,
 
-   kSpacePad6,
 
-   kSpacePad7,
 
-   kSpacePad8,
 
-   kSpacePad9,
 
-   kSpacePad10,
 
-   kSpacePad11,
 
-   kSpacePad12,
 
-   kSpacePad13,
 
-   kSpacePad14,
 
-   kSpacePad15,
 
-   kSpacePad16,
 
-   kSpacePad17,
 
-   kSpacePad18,
 
-   kSpacePad19,
 
-   kSpacePad20,
 
- };
 
- // -----------------------------------------------------------------------------
 
- // Hex
 
- // -----------------------------------------------------------------------------
 
- //
 
- // `Hex` stores a set of hexadecimal string conversion parameters for use
 
- // within `AlphaNum` string conversions.
 
- struct Hex {
 
-   uint64_t value;
 
-   uint8_t width;
 
-   char fill;
 
-   template <typename Int>
 
-   explicit Hex(
 
-       Int v, PadSpec spec = absl::kNoPad,
 
-       typename std::enable_if<sizeof(Int) == 1 &&
 
-                               !std::is_pointer<Int>::value>::type* = nullptr)
 
-       : Hex(spec, static_cast<uint8_t>(v)) {}
 
-   template <typename Int>
 
-   explicit Hex(
 
-       Int v, PadSpec spec = absl::kNoPad,
 
-       typename std::enable_if<sizeof(Int) == 2 &&
 
-                               !std::is_pointer<Int>::value>::type* = nullptr)
 
-       : Hex(spec, static_cast<uint16_t>(v)) {}
 
-   template <typename Int>
 
-   explicit Hex(
 
-       Int v, PadSpec spec = absl::kNoPad,
 
-       typename std::enable_if<sizeof(Int) == 4 &&
 
-                               !std::is_pointer<Int>::value>::type* = nullptr)
 
-       : Hex(spec, static_cast<uint32_t>(v)) {}
 
-   template <typename Int>
 
-   explicit Hex(
 
-       Int v, PadSpec spec = absl::kNoPad,
 
-       typename std::enable_if<sizeof(Int) == 8 &&
 
-                               !std::is_pointer<Int>::value>::type* = nullptr)
 
-       : Hex(spec, static_cast<uint64_t>(v)) {}
 
-   template <typename Pointee>
 
-   explicit Hex(Pointee* v, PadSpec spec = absl::kNoPad)
 
-       : Hex(spec, reinterpret_cast<uintptr_t>(v)) {}
 
-  private:
 
-   Hex(PadSpec spec, uint64_t v)
 
-       : value(v),
 
-         width(spec == absl::kNoPad
 
-                   ? 1
 
-                   : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
 
-                                              : spec - absl::kZeroPad2 + 2),
 
-         fill(spec >= absl::kSpacePad2 ? ' ' : '0') {}
 
- };
 
- // -----------------------------------------------------------------------------
 
- // Dec
 
- // -----------------------------------------------------------------------------
 
- //
 
- // `Dec` stores a set of decimal string conversion parameters for use
 
- // within `AlphaNum` string conversions.  Dec is slower than the default
 
- // integer conversion, so use it only if you need padding.
 
- struct Dec {
 
-   uint64_t value;
 
-   uint8_t width;
 
-   char fill;
 
-   bool neg;
 
-   template <typename Int>
 
-   explicit Dec(Int v, PadSpec spec = absl::kNoPad,
 
-                typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr)
 
-       : value(v >= 0 ? static_cast<uint64_t>(v)
 
-                      : uint64_t{0} - static_cast<uint64_t>(v)),
 
-         width(spec == absl::kNoPad
 
-                   ? 1
 
-                   : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
 
-                                              : spec - absl::kZeroPad2 + 2),
 
-         fill(spec >= absl::kSpacePad2 ? ' ' : '0'),
 
-         neg(v < 0) {}
 
- };
 
- // -----------------------------------------------------------------------------
 
- // AlphaNum
 
- // -----------------------------------------------------------------------------
 
- //
 
- // The `AlphaNum` class acts as the main parameter type for `StrCat()` and
 
- // `StrAppend()`, providing efficient conversion of numeric, boolean, and
 
- // hexadecimal values (through the `Hex` type) into strings.
 
- class AlphaNum {
 
-  public:
 
-   // No bool ctor -- bools convert to an integral type.
 
-   // A bool ctor would also convert incoming pointers (bletch).
 
-   AlphaNum(int x)  // NOLINT(runtime/explicit)
 
-       : piece_(digits_,
 
-                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
 
-   AlphaNum(unsigned int x)  // NOLINT(runtime/explicit)
 
-       : piece_(digits_,
 
-                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
 
-   AlphaNum(long x)  // NOLINT(*)
 
-       : piece_(digits_,
 
-                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
 
-   AlphaNum(unsigned long x)  // NOLINT(*)
 
-       : piece_(digits_,
 
-                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
 
-   AlphaNum(long long x)  // NOLINT(*)
 
-       : piece_(digits_,
 
-                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
 
-   AlphaNum(unsigned long long x)  // NOLINT(*)
 
-       : piece_(digits_,
 
-                numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
 
-   AlphaNum(float f)  // NOLINT(runtime/explicit)
 
-       : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
 
-   AlphaNum(double f)  // NOLINT(runtime/explicit)
 
-       : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
 
-   AlphaNum(Hex hex);  // NOLINT(runtime/explicit)
 
-   AlphaNum(Dec dec);  // NOLINT(runtime/explicit)
 
-   template <size_t size>
 
-   AlphaNum(  // NOLINT(runtime/explicit)
 
-       const strings_internal::AlphaNumBuffer<size>& buf)
 
-       : piece_(&buf.data[0], buf.size) {}
 
-   AlphaNum(const char* c_str) : piece_(c_str) {}  // NOLINT(runtime/explicit)
 
-   AlphaNum(absl::string_view pc) : piece_(pc) {}  // NOLINT(runtime/explicit)
 
-   template <typename Allocator>
 
-   AlphaNum(  // NOLINT(runtime/explicit)
 
-       const std::basic_string<char, std::char_traits<char>, Allocator>& str)
 
-       : piece_(str) {}
 
-   // Use string literals ":" instead of character literals ':'.
 
-   AlphaNum(char c) = delete;  // NOLINT(runtime/explicit)
 
-   AlphaNum(const AlphaNum&) = delete;
 
-   AlphaNum& operator=(const AlphaNum&) = delete;
 
-   absl::string_view::size_type size() const { return piece_.size(); }
 
-   const char* data() const { return piece_.data(); }
 
-   absl::string_view Piece() const { return piece_; }
 
-   // Normal enums are already handled by the integer formatters.
 
-   // This overload matches only scoped enums.
 
-   template <typename T,
 
-             typename = typename std::enable_if<
 
-                 std::is_enum<T>{} && !std::is_convertible<T, int>{}>::type>
 
-   AlphaNum(T e)  // NOLINT(runtime/explicit)
 
-       : AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {}
 
-   // vector<bool>::reference and const_reference require special help to
 
-   // convert to `AlphaNum` because it requires two user defined conversions.
 
-   template <
 
-       typename T,
 
-       typename std::enable_if<
 
-           std::is_class<T>::value &&
 
-           (std::is_same<T, std::vector<bool>::reference>::value ||
 
-            std::is_same<T, std::vector<bool>::const_reference>::value)>::type* =
 
-           nullptr>
 
-   AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {}  // NOLINT(runtime/explicit)
 
-  private:
 
-   absl::string_view piece_;
 
-   char digits_[numbers_internal::kFastToBufferSize];
 
- };
 
- // -----------------------------------------------------------------------------
 
- // StrCat()
 
- // -----------------------------------------------------------------------------
 
- //
 
- // Merges given strings or numbers, using no delimiter(s), returning the merged
 
- // result as a string.
 
- //
 
- // `StrCat()` is designed to be the fastest possible way to construct a string
 
- // out of a mix of raw C strings, string_views, strings, bool values,
 
- // and numeric values.
 
- //
 
- // Don't use `StrCat()` for user-visible strings. The localization process
 
- // works poorly on strings built up out of fragments.
 
- //
 
- // For clarity and performance, don't use `StrCat()` when appending to a
 
- // string. Use `StrAppend()` instead. In particular, avoid using any of these
 
- // (anti-)patterns:
 
- //
 
- //   str.append(StrCat(...))
 
- //   str += StrCat(...)
 
- //   str = StrCat(str, ...)
 
- //
 
- // The last case is the worst, with a potential to change a loop
 
- // from a linear time operation with O(1) dynamic allocations into a
 
- // quadratic time operation with O(n) dynamic allocations.
 
- //
 
- // See `StrAppend()` below for more information.
 
- namespace strings_internal {
 
- // Do not call directly - this is not part of the public API.
 
- std::string CatPieces(std::initializer_list<absl::string_view> pieces);
 
- void AppendPieces(std::string* dest,
 
-                   std::initializer_list<absl::string_view> pieces);
 
- }  // namespace strings_internal
 
- ABSL_MUST_USE_RESULT inline std::string StrCat() { return std::string(); }
 
- ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a) {
 
-   return std::string(a.data(), a.size());
 
- }
 
- ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
 
- ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
 
-                                         const AlphaNum& c);
 
- ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
 
-                                         const AlphaNum& c, const AlphaNum& d);
 
- // Support 5 or more arguments
 
- template <typename... AV>
 
- ABSL_MUST_USE_RESULT inline std::string StrCat(
 
-     const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
 
-     const AlphaNum& e, const AV&... args) {
 
-   return strings_internal::CatPieces(
 
-       {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
 
-        static_cast<const AlphaNum&>(args).Piece()...});
 
- }
 
- // -----------------------------------------------------------------------------
 
- // StrAppend()
 
- // -----------------------------------------------------------------------------
 
- //
 
- // Appends a string or set of strings to an existing string, in a similar
 
- // fashion to `StrCat()`.
 
- //
 
- // WARNING: `StrAppend(&str, a, b, c, ...)` requires that none of the
 
- // a, b, c, parameters be a reference into str. For speed, `StrAppend()` does
 
- // not try to check each of its input arguments to be sure that they are not
 
- // a subset of the string being appended to. That is, while this will work:
 
- //
 
- //   std::string s = "foo";
 
- //   s += s;
 
- //
 
- // This output is undefined:
 
- //
 
- //   std::string s = "foo";
 
- //   StrAppend(&s, s);
 
- //
 
- // This output is undefined as well, since `absl::string_view` does not own its
 
- // data:
 
- //
 
- //   std::string s = "foobar";
 
- //   absl::string_view p = s;
 
- //   StrAppend(&s, p);
 
- inline void StrAppend(std::string*) {}
 
- void StrAppend(std::string* dest, const AlphaNum& a);
 
- void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b);
 
- void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
 
-                const AlphaNum& c);
 
- void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
 
-                const AlphaNum& c, const AlphaNum& d);
 
- // Support 5 or more arguments
 
- template <typename... AV>
 
- inline void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
 
-                       const AlphaNum& c, const AlphaNum& d, const AlphaNum& e,
 
-                       const AV&... args) {
 
-   strings_internal::AppendPieces(
 
-       dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
 
-              static_cast<const AlphaNum&>(args).Piece()...});
 
- }
 
- // Helper function for the future StrCat default floating-point format, %.6g
 
- // This is fast.
 
- inline strings_internal::AlphaNumBuffer<
 
-     numbers_internal::kSixDigitsToBufferSize>
 
- SixDigits(double d) {
 
-   strings_internal::AlphaNumBuffer<numbers_internal::kSixDigitsToBufferSize>
 
-       result;
 
-   result.size = numbers_internal::SixDigitsToBuffer(d, &result.data[0]);
 
-   return result;
 
- }
 
- ABSL_NAMESPACE_END
 
- }  // namespace absl
 
- #endif  // ABSL_STRINGS_STR_CAT_H_
 
 
  |