34 #include <type_traits> 38 #include <double-conversion/double-conversion.h> 72 using std::range_error::range_error;
142 template <
class Tgt,
class Src>
143 typename std::enable_if<
147 return std::forward<Src>(
value);
150 template <
class Tgt,
class Src>
151 typename std::enable_if<
155 return std::forward<Src>(
value);
167 template <
class Tgt,
class Src>
168 typename std::enable_if<
173 return value != Src();
176 template <
class Tgt,
class Src>
177 typename std::enable_if<
179 std::is_same<Tgt, bool>::value,
182 return value != Src();
197 template <
typename... Ts>
199 std::forward_as_tuple(std::forward<Ts>(ts)...))) {
201 std::forward_as_tuple(std::forward<Ts>(ts)...));
206 template <
size_t size,
typename... Ts>
207 struct LastElementType : std::tuple_element<size - 1, std::tuple<Ts...>> {};
210 struct LastElementType<0> {
214 template <
class... Ts>
216 : std::decay<typename LastElementType<sizeof...(Ts), Ts...>::type> {};
218 template <
typename... Ts>
223 template <
typename Head,
typename... Ts>
225 template <
typename Last>
227 return std::forward<Last>(last);
231 template <
typename... Ts>
237 template <
class... Ts>
239 LastElementImpl<Ts...>::call(std::declval<Ts>()...))> {
249 #if FOLLY_HAVE_INT128_T 252 template <
typename IntegerType>
253 constexpr
unsigned int digitsEnough() {
254 return (
unsigned int)(
ceil(
sizeof(IntegerType) * CHAR_BIT * M_LN2 / M_LN10));
258 unsafeTelescope128(
char*
buffer,
size_t room,
unsigned __int128
x) {
259 typedef unsigned __int128 Usrc;
262 while (x >= (Usrc(1) << 64)) {
263 const auto y = x / 10;
264 const auto digit = x % 10;
266 buffer[p--] =
static_cast<char>(
'0' + digit);
273 const auto y = xx / 10ULL;
274 const auto digit = xx % 10ULL;
276 buffer[p--] =
static_cast<char>(
'0' + digit);
280 buffer[p] =
static_cast<char>(
'0' + xx);
305 alignas(64)
static const uint64_t powersOf10[20] = {
325 10000000000000000000UL,
334 const uint32_t leadingZeroes = __builtin_clzll(v);
335 const auto bits = 63 - leadingZeroes;
340 const uint32_t minLength = 1 + ((bits * 77) >> 8);
344 return minLength +
uint32_t(v >= powersOf10[minLength]);
392 auto const q = v / 10;
393 auto const r = v % 10;
394 buffer[pos--] =
static_cast<char>(
'0' + r);
398 buffer[pos] =
static_cast<char>(v +
'0');
424 template <
class Tgt,
class Src>
425 typename std::enable_if<
433 result->append(value);
455 typename std::enable_if<
470 typename std::enable_if<
475 return value->size();
481 template <
class Tgt,
class Src>
482 typename std::enable_if<
485 result->append(value);
495 result->append(value.
data(), value.
size());
506 result->append(value.
data(), value.
size());
509 #if FOLLY_HAVE_INT128_T 516 typedef unsigned __int128 Usrc;
517 char buffer[detail::digitsEnough<unsigned __int128>() + 1];
521 p = detail::unsafeTelescope128(
buffer,
sizeof(
buffer), -Usrc(value));
524 p = detail::unsafeTelescope128(
buffer,
sizeof(
buffer), value);
531 void toAppend(
unsigned __int128 value, Tgt* result) {
532 char buffer[detail::digitsEnough<unsigned __int128>()];
535 p = detail::unsafeTelescope128(
buffer,
sizeof(
buffer), value);
544 return detail::digitsEnough<__int128>();
548 constexpr
typename std:: 551 return detail::digitsEnough<unsigned __int128>();
564 template <
class Tgt,
class Src>
565 typename std::enable_if<
571 result->push_back(
'-');
581 typename std::enable_if<
583 sizeof(Src) >= 4 &&
sizeof(Src) < 16,
590 return 1 +
digits10(~static_cast<uint64_t>(value) + 1);
593 return digits10(static_cast<uint64_t>(value));
599 template <
class Tgt,
class Src>
600 typename std::enable_if<
609 typename std::enable_if<
611 sizeof(Src) >= 4 &&
sizeof(Src) < 16,
621 template <
class Tgt,
class Src>
622 typename std::enable_if<
624 sizeof(Src) < 4>::
type 629 toAppend<Tgt>(
static_cast<Intermediate
>(
value), result);
633 typename std::enable_if<
647 template <
class Tgt,
class Src>
648 typename std::enable_if<
667 constexpr
int kConvMaxDecimalInShortestLow = -6;
668 constexpr
int kConvMaxDecimalInShortestHigh = 21;
672 template <
class Tgt,
class Src>
673 typename std::enable_if<
678 double_conversion::DoubleToStringConverter::DtoaMode
mode,
679 unsigned int numDigits) {
680 using namespace double_conversion;
681 DoubleToStringConverter conv(
682 DoubleToStringConverter::NO_FLAGS,
686 detail::kConvMaxDecimalInShortestLow,
687 detail::kConvMaxDecimalInShortestHigh,
691 StringBuilder
builder(buffer,
sizeof(buffer));
693 case DoubleToStringConverter::SHORTEST:
694 conv.ToShortest(value, &builder);
696 case DoubleToStringConverter::SHORTEST_SINGLE:
697 conv.ToShortestSingle(static_cast<float>(value), &builder);
699 case DoubleToStringConverter::FIXED:
700 conv.ToFixed(value,
int(numDigits), &builder);
703 CHECK(mode == DoubleToStringConverter::PRECISION);
704 conv.ToPrecision(value,
int(numDigits), &builder);
707 const size_t length = size_t(builder.position());
709 result->append(buffer, length);
715 template <
class Tgt,
class Src>
716 typename std::enable_if<
720 value, result, double_conversion::DoubleToStringConverter::SHORTEST, 0);
733 constexpr
int kMaxMantissaSpace =
734 double_conversion::DoubleToStringConverter::kBase10MaximalLength + 1;
736 constexpr
int kMaxExponentSpace = 2 + 3;
737 static const int kMaxPositiveSpace =
std::max({
739 kMaxMantissaSpace + kMaxExponentSpace,
741 kMaxMantissaSpace - detail::kConvMaxDecimalInShortestLow,
745 detail::kConvMaxDecimalInShortestHigh,
749 (value < 0 ? 1 : 0));
761 constexpr
typename std::enable_if<
763 #if FOLLY_HAVE_INT128_T 774 return sizeof(Src) + 1;
781 estimateSpaceToReserve(
size_t sofar, Tgt*) {
785 template <
class T,
class... Ts>
786 size_t estimateSpaceToReserve(
size_t sofar,
const T&
v,
const Ts&... vs) {
790 template <
class... Ts>
791 void reserveInTarget(
const Ts&... vs) {
797 static_assert(
sizeof...(vs) >= 2,
"Needs at least 2 args");
798 size_t fordelim = (
sizeof...(vs) - 2) *
799 estimateSpaceToReserve(0, d, static_cast<std::string*>(
nullptr));
800 getLastElement(vs...)->reserve(estimateSpaceToReserve(fordelim, vs...));
806 template <
class T,
class Tgt>
807 typename std::enable_if<
813 template <
class T,
class... Ts>
814 typename std::enable_if<
815 sizeof...(Ts) >= 2 &&
823 template <
class Delimiter,
class T,
class Tgt>
824 typename std::enable_if<
826 toAppendDelimStrImpl(
const Delimiter& ,
const T& v, Tgt result) {
830 template <
class Delimiter,
class T,
class... Ts>
831 typename std::enable_if<
832 sizeof...(Ts) >= 2 &&
835 toAppendDelimStrImpl(
const Delimiter& delim,
const T& v,
const Ts&... vs) {
841 toAppendDelimStrImpl(delim, vs...);
866 template <
class... Ts>
867 typename std::enable_if<
868 sizeof...(Ts) >= 3 &&
895 template <
class... Ts>
896 typename std::enable_if<
IsSomeString<
typename std::remove_pointer<
898 toAppendFit(
const Ts&... vs) {
899 ::folly::detail::reserveInTarget(vs...);
904 void toAppendFit(
const Ts&) {}
916 template <
class Delimiter,
class Tgt>
924 template <
class Delimiter,
class T,
class Tgt>
926 toAppendDelim(
const Delimiter& ,
const T& v, Tgt* tgt) {
935 typename std::enable_if<
936 sizeof...(Ts) >= 3 &&
939 toAppendDelim(
const Delimiter& delim,
const Ts&... vs) {
940 detail::toAppendDelimStrImpl(delim, vs...);
947 typename std::enable_if<
IsSomeString<
typename std::remove_pointer<
949 toAppendDelimFit(
const Delimiter& delim,
const Ts&... vs) {
951 toAppendDelim(delim, vs...);
954 template <
class De,
class Ts>
955 void toAppendDelimFit(
const De&,
const Ts&) {}
961 template <
class Tgt,
class... Ts>
962 typename std::enable_if<
964 (
sizeof...(Ts) != 1 ||
968 to(
const Ts&... vs) {
970 toAppendFit(vs..., &result);
985 template <
class Tgt,
class Src>
986 typename std::enable_if<
998 template <
class Tgt,
class Delim,
class Src>
999 typename std::enable_if<
1003 toDelim(
const Delim& , Src&& value) {
1004 return std::forward<Src>(
value);
1011 template <
class Tgt,
class Delim,
class... Ts>
1012 typename std::enable_if<
1014 (
sizeof...(Ts) != 1 ||
1018 toDelim(
const Delim& delim,
const Ts&... vs) {
1020 toAppendDelimFit(delim, vs..., &result);
1032 template <
typename T>
1040 template <
class Tgt>
1045 const char*) noexcept;
1048 const char*) noexcept;
1054 const char*) noexcept;
1060 const char*) noexcept;
1063 const char*) noexcept;
1067 const char*) noexcept;
1073 const char*) noexcept;
1077 #if FOLLY_HAVE_INT128_T 1080 const char*) noexcept;
1082 digits_to<unsigned __int128>(
const char*,
const char*) noexcept;
1115 #if FOLLY_HAVE_INT128_T 1119 str_to_integral<unsigned __int128>(
StringPiece* src) noexcept;
1122 template <
typename T>
1129 template <
typename T>
1130 typename std::enable_if<
1134 return str_to_floating<T>(src);
1137 template <
typename T>
1138 typename std::enable_if<
1142 return str_to_integral<T>(src);
1151 template <
typename Tgt>
1152 typename std::enable_if<
1155 tryTo(
const char*
b,
const char* e) {
1156 return detail::digits_to<Tgt>(
b, e);
1159 template <
typename Tgt>
1160 typename std::enable_if<
1163 to(
const char* b,
const char* e) {
1164 return tryTo<Tgt>(
b, e).thenOrThrow(
1165 [](Tgt res) {
return res; },
1178 template <
typename Tgt>
1183 return detail::convertTo<Tgt>(&src).then(
1184 [&](Tgt res) {
return void(out = res), src; });
1198 template <
class Tgt>
1199 typename std::enable_if<
1200 !std::is_same<Tgt, bool>::value &&
1204 return static_cast<Tgt
>(value ? 1 : 0);
1212 template <
class Tgt,
class Src>
1213 typename std::enable_if<
1232 return static_cast<Tgt
>(
value);
1240 template <
class Tgt,
class Src>
1241 typename std::enable_if<
1251 if (value < std::numeric_limits<Tgt>::lowest()) {
1255 return static_cast<Tgt
>(
value);
1262 template <
typename Tgt,
typename Src>
1263 inline typename std::enable_if<
1264 std::is_floating_point<Src>::value && std::is_integral<Tgt>::value &&
1265 !std::is_same<Tgt, bool>::value,
1270 if (value >= tgtMaxAsSrc) {
1271 if (value > tgtMaxAsSrc) {
1274 const Src mmax = folly::nextafter(tgtMaxAsSrc, Src());
1275 if (static_cast<Tgt>(value - mmax) >
1280 if (value < tgtMinAsSrc) {
1283 const Src mmin = folly::nextafter(tgtMinAsSrc, Src());
1284 if (static_cast<Tgt>(value - mmin) <
1293 template <
typename Tgt,
typename Src>
1294 constexpr
typename std::enable_if<
1303 template <
typename Tgt,
typename Src>
1304 constexpr
typename std::enable_if<
1305 std::is_floating_point<Src>::value && std::is_same<Tgt, bool>::value,
1318 template <
typename Tgt,
typename Src>
1319 typename std::enable_if<
1321 (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
1324 if (
LIKELY(checkConversion<Tgt>(value))) {
1325 Tgt result =
static_cast<Tgt
>(
value);
1326 if (
LIKELY(checkConversion<Src>(result))) {
1327 Src witness =
static_cast<Src
>(result);
1328 if (
LIKELY(value == witness)) {
1336 template <
typename Tgt,
typename Src>
1338 #ifdef FOLLY_HAS_RTTI 1339 return to<std::string>(
"(",
demangle(
typeid(Tgt)),
") ",
value);
1341 return to<std::string>(
value);
1345 template <
typename Tgt,
typename Src>
1352 template <
typename Tgt,
typename Src>
1353 typename std::enable_if<
1357 return detail::convertTo<Tgt>(
value);
1360 template <
typename Tgt,
typename Src>
1363 return tryTo<Tgt>(
value).thenOrThrow(
1364 [](Tgt res) {
return res; },
1388 auto restOrError =
parseTo(in, tmp);
1389 out =
static_cast<T>(tmp);
1420 template <
typename Tgt>
1433 template <
class Error>
1443 template <
class Tgt>
1444 inline typename std::enable_if<
1445 std::is_void<ParseToResult<Tgt>>
::value,
1452 template <
class Tgt>
1453 inline typename std::enable_if<
1454 !std::is_void<ParseToResult<Tgt>>
::value,
1460 template <
typename Tgt>
1471 template <
class Tgt>
1472 inline typename std::enable_if<
1478 using Check =
typename std::conditional<
1479 std::is_arithmetic<Tgt>::value,
1482 return parseTo(src, result).then(Check(), [&](
Unit) {
1487 template <
class Tgt,
class Src>
1488 inline typename std::enable_if<
1492 return to<Tgt>(
StringPiece(src.data(), src.size()));
1495 template <
class Tgt>
1501 using Check =
typename std::conditional<
1502 std::is_arithmetic<Tgt>::value,
1522 template <
class Tgt>
1531 template <
class Tgt>
1548 template <
class Tgt,
class Src>
1549 typename std::enable_if<
1555 return tryTo<Tgt>(
static_cast<I
>(
value));
1558 template <
class Tgt,
class Src>
1559 typename std::enable_if<
1565 return tryTo<I>(
value).then([](I
i) {
return static_cast<Tgt
>(
i); });
1568 template <
class Tgt,
class Src>
1569 typename std::enable_if<
1577 template <
class Tgt,
class Src>
1578 typename std::enable_if<
std::vector< uint8_t > buffer(kBufferSize+16)
bool_constant< !std::is_same< Tgt, Src >::value &&!std::is_same< Tgt, bool >::value &&std::is_arithmetic< Src >::value &&std::is_arithmetic< Tgt >::value > IsArithToArith
template Expected< unsigned long long, ConversionCode > digits_to< unsigned long long >(const char *, const char *) noexcept
template Expected< unsigned long, ConversionCode > digits_to< unsigned long >(const char *, const char *) noexcept
constexpr To ceil(std::chrono::duration< Rep, Period > const &d)
template Expected< double, ConversionCode > str_to_floating< double >(StringPiece *src) noexcept
std::enable_if< std::is_void< ParseToResult< Tgt > >::value, Expected< StringPiece, ConversionCode > >::type parseToWrap(StringPiece sp, Tgt &out)
uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer)
template Expected< unsigned long long, ConversionCode > str_to_integral< unsigned long long >(StringPiece *src) noexcept
template Expected< short, ConversionCode > str_to_integral< short >(StringPiece *src) noexcept
template Expected< long, ConversionCode > digits_to< long >(const char *, const char *) noexcept
T convertTo(const dynamic &)
bool less_than(LHS const lhs)
template Expected< unsigned char, ConversionCode > digits_to< unsigned char >(const char *, const char *) noexcept
uint32_t digits10(uint64_t v)
constexpr detail::Map< Move > move
constexpr size_type size() const
void enforceWhitespace(StringPiece sp)
constexpr std::enable_if< std::is_floating_point< Src >::value &&std::is_same< Tgt, bool >::value, bool >::type checkConversion(const Src &)
constexpr std::enable_if< std::is_same< T, char >::value, size_t >::type estimateSpaceNeeded(T)
bool greater_than(LHS const lhs)
FOLLY_NODISCARD std::enable_if< std::is_arithmetic< Tgt >::value, Expected< StringPiece, ConversionCode > >::type parseTo(StringPiece src, Tgt &out)
—— Concurrent Priority Queue Implementation ——
template Expected< unsigned char, ConversionCode > str_to_integral< unsigned char >(StringPiece *src) noexcept
requires E e noexcept(noexcept(s.error(std::move(e))))
ConversionError(const std::string &str, ConversionCode code)
template Expected< char, ConversionCode > digits_to< char >(const char *, const char *) noexcept
folly::Optional< PskKeyExchangeMode > mode
ConversionCode errorCode() const
template Expected< short, ConversionCode > digits_to< short >(const char *, const char *) noexcept
constexpr auto size(C const &c) -> decltype(c.size())
const value_type * data() const
std::integral_constant< bool, B > bool_constant
std::enable_if< detail::is_chrono_conversion< Tgt, Src >::value, Tgt >::type to(const Src &value)
decltype(parseTo(StringPiece{}, std::declval< Tgt & >())) ParseToResult
constexpr Unexpected< typename std::decay< Error >::type > makeUnexpected(Error &&)
auto getLastElement(const Ts &...ts) -> decltype(LastElementImpl< Ts... >::call(ts...))
constexpr Iter data() const
template Expected< long, ConversionCode > str_to_integral< long >(StringPiece *src) noexcept
template Expected< int, ConversionCode > str_to_integral< int >(StringPiece *src) noexcept
void reserveInTargetDelim(const Delimiter &d, const Ts &...vs)
template Expected< int, ConversionCode > digits_to< int >(const char *, const char *) noexcept
ConversionCode enforceWhitespaceErr(StringPiece sp)
static const char *const value
template Expected< long long, ConversionCode > str_to_integral< long long >(StringPiece *src) noexcept
void toAppend(char value, Tgt *result)
template Expected< signed char, ConversionCode > digits_to< signed char >(const char *, const char *) noexcept
template Expected< unsigned short, ConversionCode > digits_to< unsigned short >(const char *, const char *) noexcept
constexpr Iter end() const
template Expected< unsigned int, ConversionCode > str_to_integral< unsigned int >(StringPiece *src) noexcept
template Expected< unsigned short, ConversionCode > str_to_integral< unsigned short >(StringPiece *src) noexcept
template Expected< char, ConversionCode > str_to_integral< char >(StringPiece *src) noexcept
template Expected< float, ConversionCode > str_to_floating< float >(StringPiece *src) noexcept
Expected< Unit, ConversionCode > operator()(StringPiece sp) const
Expected< Tgt, ConversionCode > digits_to(const char *b, const char *const e) noexcept
std::string errorValue(const Src &value)
typename std::remove_reference< Expected >::type::error_type ExpectedErrorType
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
bool_constant< false > false_type
std::enable_if< detail::is_duration< Tgt >::value, Expected< Tgt, ConversionCode > >::type tryTo(const struct timespec &ts)
Expected< Tgt, ConversionCode > str_to_integral(StringPiece *src) noexcept
template Expected< unsigned int, ConversionCode > digits_to< unsigned int >(const char *, const char *) noexcept
template Expected< unsigned long, ConversionCode > str_to_integral< unsigned long >(StringPiece *src) noexcept
Expected< Tgt, ConversionCode > str_to_floating(StringPiece *src) noexcept
basic_fbstring & append(const basic_fbstring &str)
Range< const char * > StringPiece
Expected< bool, ConversionCode > str_to_bool(StringPiece *src) noexcept
std::enable_if< !std::is_void< ParseToResult< Tgt > >::value, ParseToResult< Tgt > >::type parseToWrap(StringPiece sp, Tgt &out)
std::enable_if< IsSomeString< typename std::remove_pointer< Tgt >::type >::value >::type toAppendStrImpl(const T &v, Tgt result)
static void call(Ignored< Ts >...)
template Expected< signed char, ConversionCode > str_to_integral< signed char >(StringPiece *src) noexcept
PUSHMI_INLINE_VAR constexpr detail::get_fn< T > get
ConversionError(const char *str, ConversionCode code)
template Expected< long long, ConversionCode > digits_to< long long >(const char *, const char *) noexcept
fbstring demangle(const char *name)
static Last call(Ignored< Ts >..., Last &&last)
FOLLY_NOINLINE FOLLY_COLD void throw_exception(Ex &&ex)
ConversionError makeConversionError(ConversionCode code, StringPiece input)
constexpr Expected< Unit, Error > operator()(T &&) const
ExpectedErrorType< decltype(detail::parseToWrap(StringPiece{}, std::declval< Tgt & >()))> ParseToError