folly/folly/Conv.cpp

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * 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
 *
 *     http://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.
 */

#include <folly/Conv.h>

#include <array>
#include <istream>

#include <folly/lang/SafeAssert.h>

namespace folly {
namespace detail {

namespace {

/**
 * Finds the first non-digit in a string. The number of digits
 * searched depends on the precision of the Tgt integral. Assumes the
 * string starts with NO whitespace and NO sign.
 *
 * The semantics of the routine is:
 *   for (;; ++b) {
 *     if (b >= e || !isdigit(*b)) return b;
 *   }
 *
 *  Complete unrolling marks bottom-line (i.e. entire conversion)
 *  improvements of 20%.
 */
inline const char* findFirstNonDigit(const char* b, const char* e) {}

// Maximum value of number when represented as a string
template <class T>
struct MaxString {};

template <>
const char* const MaxString<uint8_t>::value =;
template <>
const char* const MaxString<uint16_t>::value =;
template <>
const char* const MaxString<uint32_t>::value =;
#if __SIZEOF_LONG__ == 4
template <>
const char* const MaxString<unsigned long>::value = "4294967295";
#else
template <>
const char* const MaxString<unsigned long>::value =;
#endif
static_assert;
template <>
const char* const MaxString<unsigned long long>::value =;
static_assert;

#if FOLLY_HAVE_INT128_T
template <>
const char* const MaxString<__uint128_t>::value =
    "340282366920938463463374607431768211455";
#endif

/*
 * Lookup tables that converts from a decimal character value to an integral
 * binary value, shifted by a decimal "shift" multiplier.
 * For all character values in the range '0'..'9', the table at those
 * index locations returns the actual decimal value shifted by the multiplier.
 * For all other values, the lookup table returns an invalid OOR value.
 */
// Out-of-range flag value, larger than the largest value that can fit in
// four decimal bytes (9999), but four of these added up together should
// still not overflow uint16_t.
constexpr int32_t OOR =;

alignas(16) constexpr uint16_t shift1[] =;

alignas(16) constexpr uint16_t shift10[] =;

alignas(16) constexpr uint16_t shift100[] =;

alignas(16) constexpr uint16_t shift1000[] =;

struct ErrorString {};

// Keep this in sync with ConversionCode in Conv.h
constexpr const std::array<
    ErrorString,
    static_cast<std::size_t>(ConversionCode::NUM_ERROR_CODES)>
    kErrorStrings{};

// Check if ASCII is really ASCII
IsAscii;

// The code in this file that uses tolower() really only cares about
// 7-bit ASCII characters, so we can take a nice shortcut here.
inline char tolower_ascii(char in) {}

inline bool bool_str_cmp(const char** b, size_t len, const char* value) {}

} // namespace

Expected<bool, ConversionCode> str_to_bool(StringPiece* src) noexcept {}

/**
 * StringPiece to double, with progress information. Alters the
 * StringPiece parameter to munch the already-parsed characters.
 */
template <class Tgt>
Expected<Tgt, ConversionCode> str_to_floating(StringPiece* src) noexcept {}

template Expected<float, ConversionCode> str_to_floating<float>(
    StringPiece* src) noexcept;
template Expected<double, ConversionCode> str_to_floating<double>(
    StringPiece* src) noexcept;

namespace {

/**
 * This class takes care of additional processing needed for signed values,
 * like leading sign character and overflow checks.
 */
template <typename T, bool IsSigned = is_signed_v<T>>
class SignedValueHandler;

SignedValueHandler<T, true>;

// For unsigned types, we don't need any extra processing
SignedValueHandler<T, false>;

} // namespace

/**
 * String represented as a pair of pointers to char to signed/unsigned
 * integrals. Assumes NO whitespace before or after, and also that the
 * string is composed entirely of digits (and an optional sign only for
 * signed types). String may be empty, in which case digits_to returns
 * an appropriate error.
 */
template <class Tgt>
inline Expected<Tgt, ConversionCode> digits_to(
    const char* b, const char* const e) noexcept {}

template Expected<char, ConversionCode> digits_to<char>(
    const char*, const char*) noexcept;
template Expected<signed char, ConversionCode> digits_to<signed char>(
    const char*, const char*) noexcept;
template Expected<unsigned char, ConversionCode> digits_to<unsigned char>(
    const char*, const char*) noexcept;

template Expected<short, ConversionCode> digits_to<short>(
    const char*, const char*) noexcept;
template Expected<unsigned short, ConversionCode> digits_to<unsigned short>(
    const char*, const char*) noexcept;

template Expected<int, ConversionCode> digits_to<int>(
    const char*, const char*) noexcept;
template Expected<unsigned int, ConversionCode> digits_to<unsigned int>(
    const char*, const char*) noexcept;

template Expected<long, ConversionCode> digits_to<long>(
    const char*, const char*) noexcept;
template Expected<unsigned long, ConversionCode> digits_to<unsigned long>(
    const char*, const char*) noexcept;

template Expected<long long, ConversionCode> digits_to<long long>(
    const char*, const char*) noexcept;
template Expected<unsigned long long, ConversionCode>
digits_to<unsigned long long>(const char*, const char*) noexcept;

#if FOLLY_HAVE_INT128_T
template Expected<__int128, ConversionCode> digits_to<__int128>(
    const char*, const char*) noexcept;
template Expected<unsigned __int128, ConversionCode>
digits_to<unsigned __int128>(const char*, const char*) noexcept;
#endif

/**
 * StringPiece to integrals, with progress information. Alters the
 * StringPiece parameter to munch the already-parsed characters.
 */
template <class Tgt>
Expected<Tgt, ConversionCode> str_to_integral(StringPiece* src) noexcept {}

template Expected<char, ConversionCode> str_to_integral<char>(
    StringPiece* src) noexcept;
template Expected<signed char, ConversionCode> str_to_integral<signed char>(
    StringPiece* src) noexcept;
template Expected<unsigned char, ConversionCode> str_to_integral<unsigned char>(
    StringPiece* src) noexcept;

template Expected<short, ConversionCode> str_to_integral<short>(
    StringPiece* src) noexcept;
template Expected<unsigned short, ConversionCode>
str_to_integral<unsigned short>(StringPiece* src) noexcept;

template Expected<int, ConversionCode> str_to_integral<int>(
    StringPiece* src) noexcept;
template Expected<unsigned int, ConversionCode> str_to_integral<unsigned int>(
    StringPiece* src) noexcept;

template Expected<long, ConversionCode> str_to_integral<long>(
    StringPiece* src) noexcept;
template Expected<unsigned long, ConversionCode> str_to_integral<unsigned long>(
    StringPiece* src) noexcept;

template Expected<long long, ConversionCode> str_to_integral<long long>(
    StringPiece* src) noexcept;
template Expected<unsigned long long, ConversionCode>
str_to_integral<unsigned long long>(StringPiece* src) noexcept;

#if FOLLY_HAVE_INT128_T
template Expected<__int128, ConversionCode> str_to_integral<__int128>(
    StringPiece* src) noexcept;
template Expected<unsigned __int128, ConversionCode>
str_to_integral<unsigned __int128>(StringPiece* src) noexcept;
#endif

#if defined(FOLLY_CONV_AVALIABILITY_TO_CHARS_FLOATING_POINT) && \
    FOLLY_CONV_AVALIABILITY_TO_CHARS_FLOATING_POINT == 1
DtoaFlagsSet::DtoaFlagsSet(DtoaFlags flags) :{}

bool DtoaFlagsSet::isSet(DtoaFlags flag) const {}

bool DtoaFlagsSet::emitPositiveExponentSign() const {}

bool DtoaFlagsSet::emitTrailingDecimalPoint() const {}

bool DtoaFlagsSet::emitTrailingZeroAfterPoint() const {}

bool DtoaFlagsSet::uniqueZero() const {}

bool DtoaFlagsSet::noTrailingZero() const {}

int ParsedDecimal::numPrecisionFigures() const {}

std::optional<detail::ParsedDecimal::FractionalSuffix>
ParsedDecimal::fractionalSuffix() const {}

void ParsedDecimal::shiftFractionalSuffixPtrs(size_t amount) {}

namespace {

struct Stream : std::istream {};

} // namespace

ParsedDecimal::ParsedDecimal(char* begin, char* end) {}

std::pair<char*, char*> formatAsDoubleConversion(
    bool valueIsZero,
    DtoaMode mode,
    unsigned int numDigits,
    DtoaFlags flags,
    char* resultBegin,
    char* resultEnd,
    char* bufferEnd) {}
#endif // FOLLY_CONV_AVALIABILITY_TO_CHARS_FLOATING_POINT
} // namespace detail

ConversionError makeConversionError(ConversionCode code, StringPiece input) {}

} // namespace folly