| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 | //// POSIX spec://   http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html//#include "absl/strings/internal/str_format/arg.h"#include <cassert>#include <cerrno>#include <cstdlib>#include <string>#include <type_traits>#include "absl/base/port.h"#include "absl/strings/internal/str_format/float_conversion.h"#include "absl/strings/numbers.h"namespace absl {ABSL_NAMESPACE_BEGINnamespace str_format_internal {namespace {// Reduce *capacity by s.size(), clipped to a 0 minimum.void ReducePadding(string_view s, size_t *capacity) {  *capacity = Excess(s.size(), *capacity);}// Reduce *capacity by n, clipped to a 0 minimum.void ReducePadding(size_t n, size_t *capacity) {  *capacity = Excess(n, *capacity);}template <typename T>struct MakeUnsigned : std::make_unsigned<T> {};template <>struct MakeUnsigned<absl::int128> {  using type = absl::uint128;};template <>struct MakeUnsigned<absl::uint128> {  using type = absl::uint128;};template <typename T>struct IsSigned : std::is_signed<T> {};template <>struct IsSigned<absl::int128> : std::true_type {};template <>struct IsSigned<absl::uint128> : std::false_type {};// Integral digit printer.// Call one of the PrintAs* routines after construction once.// Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results.class IntDigits { public:  // Print the unsigned integer as octal.  // Supports unsigned integral types and uint128.  template <typename T>  void PrintAsOct(T v) {    static_assert(!IsSigned<T>::value, "");    char *p = storage_ + sizeof(storage_);    do {      *--p = static_cast<char>('0' + (static_cast<size_t>(v) & 7));      v >>= 3;    } while (v);    start_ = p;    size_ = storage_ + sizeof(storage_) - p;  }  // Print the signed or unsigned integer as decimal.  // Supports all integral types.  template <typename T>  void PrintAsDec(T v) {    static_assert(std::is_integral<T>::value, "");    start_ = storage_;    size_ = numbers_internal::FastIntToBuffer(v, storage_) - storage_;  }  void PrintAsDec(int128 v) {    auto u = static_cast<uint128>(v);    bool add_neg = false;    if (v < 0) {      add_neg = true;      u = uint128{} - u;    }    PrintAsDec(u, add_neg);  }  void PrintAsDec(uint128 v, bool add_neg = false) {    // This function can be sped up if needed. We can call FastIntToBuffer    // twice, or fix FastIntToBuffer to support uint128.    char *p = storage_ + sizeof(storage_);    do {      p -= 2;      numbers_internal::PutTwoDigits(static_cast<size_t>(v % 100), p);      v /= 100;    } while (v);    if (p[0] == '0') {      // We printed one too many hexits.      ++p;    }    if (add_neg) {      *--p = '-';    }    size_ = storage_ + sizeof(storage_) - p;    start_ = p;  }  // Print the unsigned integer as hex using lowercase.  // Supports unsigned integral types and uint128.  template <typename T>  void PrintAsHexLower(T v) {    static_assert(!IsSigned<T>::value, "");    char *p = storage_ + sizeof(storage_);    do {      p -= 2;      constexpr const char* table = numbers_internal::kHexTable;      std::memcpy(p, table + 2 * (static_cast<size_t>(v) & 0xFF), 2);      if (sizeof(T) == 1) break;      v >>= 8;    } while (v);    if (p[0] == '0') {      // We printed one too many digits.      ++p;    }    start_ = p;    size_ = storage_ + sizeof(storage_) - p;  }  // Print the unsigned integer as hex using uppercase.  // Supports unsigned integral types and uint128.  template <typename T>  void PrintAsHexUpper(T v) {    static_assert(!IsSigned<T>::value, "");    char *p = storage_ + sizeof(storage_);    // kHexTable is only lowercase, so do it manually for uppercase.    do {      *--p = "0123456789ABCDEF"[static_cast<size_t>(v) & 15];      v >>= 4;    } while (v);    start_ = p;    size_ = storage_ + sizeof(storage_) - p;  }  // The printed value including the '-' sign if available.  // For inputs of value `0`, this will return "0"  string_view with_neg_and_zero() const { return {start_, size_}; }  // The printed value not including the '-' sign.  // For inputs of value `0`, this will return "".  string_view without_neg_or_zero() const {    static_assert('-' < '0', "The check below verifies both.");    size_t advance = start_[0] <= '0' ? 1 : 0;    return {start_ + advance, size_ - advance};  }  bool is_negative() const { return start_[0] == '-'; } private:  const char *start_;  size_t size_;  // Max size: 128 bit value as octal -> 43 digits, plus sign char  char storage_[128 / 3 + 1 + 1];};// Note: 'o' conversions do not have a base indicator, it's just that// the '#' flag is specified to modify the precision for 'o' conversions.string_view BaseIndicator(const IntDigits &as_digits,                          const FormatConversionSpecImpl conv) {  // always show 0x for %p.  bool alt = conv.has_alt_flag() ||             conv.conversion_char() == FormatConversionCharInternal::p;  bool hex = (conv.conversion_char() == FormatConversionCharInternal::x ||              conv.conversion_char() == FormatConversionCharInternal::X ||              conv.conversion_char() == FormatConversionCharInternal::p);  // From the POSIX description of '#' flag:  //   "For x or X conversion specifiers, a non-zero result shall have  //   0x (or 0X) prefixed to it."  if (alt && hex && !as_digits.without_neg_or_zero().empty()) {    return conv.conversion_char() == FormatConversionCharInternal::X ? "0X"                                                                     : "0x";  }  return {};}string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {  if (conv.conversion_char() == FormatConversionCharInternal::d ||      conv.conversion_char() == FormatConversionCharInternal::i) {    if (neg) return "-";    if (conv.has_show_pos_flag()) return "+";    if (conv.has_sign_col_flag()) return " ";  }  return {};}bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,                     FormatSinkImpl *sink) {  size_t fill = 0;  if (conv.width() >= 0) fill = conv.width();  ReducePadding(1, &fill);  if (!conv.has_left_flag()) sink->Append(fill, ' ');  sink->Append(1, v);  if (conv.has_left_flag()) sink->Append(fill, ' ');  return true;}bool ConvertIntImplInnerSlow(const IntDigits &as_digits,                             const FormatConversionSpecImpl conv,                             FormatSinkImpl *sink) {  // Print as a sequence of Substrings:  //   [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]  size_t fill = 0;  if (conv.width() >= 0) fill = conv.width();  string_view formatted = as_digits.without_neg_or_zero();  ReducePadding(formatted, &fill);  string_view sign = SignColumn(as_digits.is_negative(), conv);  ReducePadding(sign, &fill);  string_view base_indicator = BaseIndicator(as_digits, conv);  ReducePadding(base_indicator, &fill);  int precision = conv.precision();  bool precision_specified = precision >= 0;  if (!precision_specified)    precision = 1;  if (conv.has_alt_flag() &&      conv.conversion_char() == FormatConversionCharInternal::o) {    // From POSIX description of the '#' (alt) flag:    //   "For o conversion, it increases the precision (if necessary) to    //   force the first digit of the result to be zero."    if (formatted.empty() || *formatted.begin() != '0') {      int needed = static_cast<int>(formatted.size()) + 1;      precision = std::max(precision, needed);    }  }  size_t num_zeroes = Excess(formatted.size(), precision);  ReducePadding(num_zeroes, &fill);  size_t num_left_spaces = !conv.has_left_flag() ? fill : 0;  size_t num_right_spaces = conv.has_left_flag() ? fill : 0;  // From POSIX description of the '0' (zero) flag:  //   "For d, i, o, u, x, and X conversion specifiers, if a precision  //   is specified, the '0' flag is ignored."  if (!precision_specified && conv.has_zero_flag()) {    num_zeroes += num_left_spaces;    num_left_spaces = 0;  }  sink->Append(num_left_spaces, ' ');  sink->Append(sign);  sink->Append(base_indicator);  sink->Append(num_zeroes, '0');  sink->Append(formatted);  sink->Append(num_right_spaces, ' ');  return true;}template <typename T>bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,                   FormatSinkImpl *sink) {  using U = typename MakeUnsigned<T>::type;  IntDigits as_digits;  switch (conv.conversion_char()) {    case FormatConversionCharInternal::c:      return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);    case FormatConversionCharInternal::o:      as_digits.PrintAsOct(static_cast<U>(v));      break;    case FormatConversionCharInternal::x:      as_digits.PrintAsHexLower(static_cast<U>(v));      break;    case FormatConversionCharInternal::X:      as_digits.PrintAsHexUpper(static_cast<U>(v));      break;    case FormatConversionCharInternal::u:      as_digits.PrintAsDec(static_cast<U>(v));      break;    case FormatConversionCharInternal::d:    case FormatConversionCharInternal::i:      as_digits.PrintAsDec(v);      break;    case FormatConversionCharInternal::a:    case FormatConversionCharInternal::e:    case FormatConversionCharInternal::f:    case FormatConversionCharInternal::g:    case FormatConversionCharInternal::A:    case FormatConversionCharInternal::E:    case FormatConversionCharInternal::F:    case FormatConversionCharInternal::G:      return ConvertFloatImpl(static_cast<double>(v), conv, sink);    default:       ABSL_INTERNAL_ASSUME(false);  }  if (conv.is_basic()) {    sink->Append(as_digits.with_neg_and_zero());    return true;  }  return ConvertIntImplInnerSlow(as_digits, conv, sink);}template <typename T>bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,                     FormatSinkImpl *sink) {  return FormatConversionCharIsFloat(conv.conversion_char()) &&         ConvertFloatImpl(v, conv, sink);}inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,                             FormatSinkImpl *sink) {  if (conv.is_basic()) {    sink->Append(v);    return true;  }  return sink->PutPaddedString(v, conv.width(), conv.precision(),                               conv.has_left_flag());}}  // namespace// ==================== Strings ====================StringConvertResult FormatConvertImpl(const std::string &v,                                      const FormatConversionSpecImpl conv,                                      FormatSinkImpl *sink) {  return {ConvertStringArg(v, conv, sink)};}StringConvertResult FormatConvertImpl(string_view v,                                      const FormatConversionSpecImpl conv,                                      FormatSinkImpl *sink) {  return {ConvertStringArg(v, conv, sink)};}ArgConvertResult<FormatConversionCharSetUnion(    FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,                  FormatSinkImpl *sink) {  if (conv.conversion_char() == FormatConversionCharInternal::p)    return {FormatConvertImpl(VoidPtr(v), conv, sink).value};  size_t len;  if (v == nullptr) {    len = 0;  } else if (conv.precision() < 0) {    len = std::strlen(v);  } else {    // If precision is set, we look for the NUL-terminator on the valid range.    len = std::find(v, v + conv.precision(), '\0') - v;  }  return {ConvertStringArg(string_view(v, len), conv, sink)};}// ==================== Raw pointers ====================ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(    VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) {  if (!v.value) {    sink->Append("(nil)");    return {true};  }  IntDigits as_digits;  as_digits.PrintAsHexLower(v.value);  return {ConvertIntImplInnerSlow(as_digits, conv, sink)};}// ==================== Floats ====================FloatingConvertResult FormatConvertImpl(float v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertFloatArg(v, conv, sink)};}FloatingConvertResult FormatConvertImpl(double v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertFloatArg(v, conv, sink)};}FloatingConvertResult FormatConvertImpl(long double v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertFloatArg(v, conv, sink)};}// ==================== Chars ====================IntegralConvertResult FormatConvertImpl(char v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(signed char v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(unsigned char v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}// ==================== Ints ====================IntegralConvertResult FormatConvertImpl(short v,  // NOLINT                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(int v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(unsigned v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(long v,  // NOLINT                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(absl::int128 v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}IntegralConvertResult FormatConvertImpl(absl::uint128 v,                                        const FormatConversionSpecImpl conv,                                        FormatSinkImpl *sink) {  return {ConvertIntArg(v, conv, sink)};}ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_();}  // namespace str_format_internalABSL_NAMESPACE_END}  // namespace absl
 |