// 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. // This file contains string processing functions related to // numeric values. #include "absl/strings/numbers.h" #include <algorithm> #include <cassert> #include <cfloat> // for DBL_DIG and FLT_DIG #include <cmath> // for HUGE_VAL #include <cstdint> #include <cstdio> #include <cstdlib> #include <cstring> #include <iterator> #include <limits> #include <system_error> // NOLINT(build/c++11) #include <utility> #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/internal/endian.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/nullability.h" #include "absl/base/optimization.h" #include "absl/numeric/bits.h" #include "absl/numeric/int128.h" #include "absl/strings/ascii.h" #include "absl/strings/charconv.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN bool SimpleAtof(absl::string_view str, absl::Nonnull<float*> out) { … } bool SimpleAtod(absl::string_view str, absl::Nonnull<double*> out) { … } bool SimpleAtob(absl::string_view str, absl::Nonnull<bool*> out) { … } // ---------------------------------------------------------------------- // FastIntToBuffer() overloads // // Like the Fast*ToBuffer() functions above, these are intended for speed. // Unlike the Fast*ToBuffer() functions, however, these functions write // their output to the beginning of the buffer. The caller is responsible // for ensuring that the buffer has enough space to hold the output. // // Returns a pointer to the end of the string (i.e. the null character // terminating the string). // ---------------------------------------------------------------------- namespace { // Various routines to encode integers to strings. // We split data encodings into a group of 2 digits, 4 digits, 8 digits as // it's easier to combine powers of two into scalar arithmetic. // Previous implementation used a lookup table of 200 bytes for every 2 bytes // and it was memory bound, any L1 cache miss would result in a much slower // result. When benchmarking with a cache eviction rate of several percent, // this implementation proved to be better. // These constants represent '00', '0000' and '00000000' as ascii strings in // integers. We can add these numbers if we encode to bytes from 0 to 9. as // 'i' = '0' + i for 0 <= i <= 9. constexpr uint32_t kTwoZeroBytes = …; constexpr uint64_t kFourZeroBytes = …; constexpr uint64_t kEightZeroBytes = …; // * 103 / 1024 is a division by 10 for values from 0 to 99. It's also a // division of a structure [k takes 2 bytes][m takes 2 bytes], then * 103 / 1024 // will be [k / 10][m / 10]. It allows parallel division. constexpr uint64_t kDivisionBy10Mul = …; constexpr uint64_t kDivisionBy10Div = …; // * 10486 / 1048576 is a division by 100 for values from 0 to 9999. constexpr uint64_t kDivisionBy100Mul = …; constexpr uint64_t kDivisionBy100Div = …; // Encode functions write the ASCII output of input `n` to `out_str`. inline char* EncodeHundred(uint32_t n, absl::Nonnull<char*> out_str) { … } inline char* EncodeTenThousand(uint32_t n, absl::Nonnull<char*> out_str) { … } // Helper function to produce an ASCII representation of `i`. // // Function returns an 8-byte integer which when summed with `kEightZeroBytes`, // can be treated as a printable buffer with ascii representation of `i`, // possibly with leading zeros. // // Example: // // uint64_t buffer = PrepareEightDigits(102030) + kEightZeroBytes; // char* ascii = reinterpret_cast<char*>(&buffer); // // Note two leading zeros: // EXPECT_EQ(absl::string_view(ascii, 8), "00102030"); // // Pre-condition: `i` must be less than 100000000. inline uint64_t PrepareEightDigits(uint32_t i) { … } inline ABSL_ATTRIBUTE_ALWAYS_INLINE absl::Nonnull<char*> EncodeFullU32( uint32_t n, absl::Nonnull<char*> out_str) { … } inline ABSL_ATTRIBUTE_ALWAYS_INLINE char* EncodeFullU64(uint64_t i, char* buffer) { … } } // namespace void numbers_internal::PutTwoDigits(uint32_t i, absl::Nonnull<char*> buf) { … } absl::Nonnull<char*> numbers_internal::FastIntToBuffer( uint32_t n, absl::Nonnull<char*> out_str) { … } absl::Nonnull<char*> numbers_internal::FastIntToBuffer( int32_t i, absl::Nonnull<char*> buffer) { … } absl::Nonnull<char*> numbers_internal::FastIntToBuffer( uint64_t i, absl::Nonnull<char*> buffer) { … } absl::Nonnull<char*> numbers_internal::FastIntToBuffer( int64_t i, absl::Nonnull<char*> buffer) { … } // Given a 128-bit number expressed as a pair of uint64_t, high half first, // return that number multiplied by the given 32-bit value. If the result is // too large to fit in a 128-bit number, divide it by 2 until it fits. static std::pair<uint64_t, uint64_t> Mul32(std::pair<uint64_t, uint64_t> num, uint32_t mul) { … } // Compute num * 5 ^ expfive, and return the first 128 bits of the result, // where the first bit is always a one. So PowFive(1, 0) starts 0b100000, // PowFive(1, 1) starts 0b101000, PowFive(1, 2) starts 0b110010, etc. static std::pair<uint64_t, uint64_t> PowFive(uint64_t num, int expfive) { … } struct ExpDigits { … }; // SplitToSix converts value, a positive double-precision floating-point number, // into a base-10 exponent and 6 ASCII digits, where the first digit is never // zero. For example, SplitToSix(1) returns an exponent of zero and a digits // array of {'1', '0', '0', '0', '0', '0'}. If value is exactly halfway between // two possible representations, e.g. value = 100000.5, then "round to even" is // performed. static ExpDigits SplitToSix(const double value) { … } // Helper function for fast formatting of floating-point. // The result is the same as "%g", a.k.a. "%.6g". size_t numbers_internal::SixDigitsToBuffer(double d, absl::Nonnull<char*> const buffer) { … } namespace … // anonymous namespace namespace numbers_internal { // Digit conversion. ABSL_CONST_INIT ABSL_DLL const char kHexChar[] = …; ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] = …; bool safe_strto32_base(absl::string_view text, absl::Nonnull<int32_t*> value, int base) { … } bool safe_strto64_base(absl::string_view text, absl::Nonnull<int64_t*> value, int base) { … } bool safe_strto128_base(absl::string_view text, absl::Nonnull<int128*> value, int base) { … } bool safe_strtou32_base(absl::string_view text, absl::Nonnull<uint32_t*> value, int base) { … } bool safe_strtou64_base(absl::string_view text, absl::Nonnull<uint64_t*> value, int base) { … } bool safe_strtou128_base(absl::string_view text, absl::Nonnull<uint128*> value, int base) { … } } // namespace numbers_internal ABSL_NAMESPACE_END } // namespace absl