/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <folly/FBString.h>
#include <folly/Likely.h>
#include <folly/Range.h>
+#include <folly/Traits.h>
#include <folly/Unit.h>
#include <folly/portability/Math.h>
// Keep these together so a peephole optimization "sees" them and
// computes them in one shot.
auto const q = v / 10;
- auto const r = static_cast<uint32_t>(v % 10);
+ auto const r = static_cast<char>(v % 10);
buffer[pos--] = '0' + r;
v = q;
}
// Last digit is trivial to handle
- buffer[pos] = static_cast<uint32_t>(v) + '0';
+ buffer[pos] = static_cast<char>(v) + '0';
return result;
}
char buffer[20];
if (value < 0) {
result->push_back('-');
- result->append(buffer, uint64ToBufferUnsafe(-uint64_t(value), buffer));
+ result->append(
+ buffer,
+ uint64ToBufferUnsafe(~static_cast<uint64_t>(value) + 1, buffer));
} else {
- result->append(buffer, uint64ToBufferUnsafe(value, buffer));
+ result->append(buffer, uint64ToBufferUnsafe(uint64_t(value), buffer));
}
}
conv.ToShortest(value, &builder);
break;
case DoubleToStringConverter::FIXED:
- conv.ToFixed(value, numDigits, &builder);
+ conv.ToFixed(value, int(numDigits), &builder);
break;
default:
CHECK(mode == DoubleToStringConverter::PRECISION);
- conv.ToPrecision(value, numDigits, &builder);
+ conv.ToPrecision(value, int(numDigits), &builder);
break;
}
- const size_t length = builder.position();
+ const size_t length = size_t(builder.position());
builder.Finalize();
result->append(buffer, length);
}
// so 21 is the longest non-exponential number > 1.
detail::kConvMaxDecimalInShortestHigh
});
- return kMaxPositiveSpace + (value < 0); // +1 for minus sign, if negative
+ return size_t(
+ kMaxPositiveSpace +
+ (value < 0 ? 1 : 0)); // +1 for minus sign, if negative
}
/**
* Parsing strings to numeric types.
*/
template <typename Tgt>
-FOLLY_WARN_UNUSED_RESULT inline typename std::enable_if<
+FOLLY_NODISCARD inline typename std::enable_if<
std::is_arithmetic<Tgt>::value,
Expected<StringPiece, ConversionCode>>::type
parseTo(StringPiece src, Tgt& out) {
namespace detail {
+/**
+ * Bool to integral/float doesn't need any special checks, and this
+ * overload means we aren't trying to see if a bool is less than
+ * an integer.
+ */
+template <class Tgt>
+typename std::enable_if<
+ !std::is_same<Tgt, bool>::value &&
+ (std::is_integral<Tgt>::value || std::is_floating_point<Tgt>::value),
+ Expected<Tgt, ConversionCode>>::type
+convertTo(const bool& value) noexcept {
+ return static_cast<Tgt>(value ? 1 : 0);
+}
+
/**
* Checked conversion from integral to integral. The checks are only
* performed when meaningful, e.g. conversion from int to long goes
Expected<Tgt, ConversionCode>>::type
convertTo(const Src& value) noexcept {
/* static */ if (
- std::numeric_limits<Tgt>::max() < std::numeric_limits<Src>::max()) {
+ folly::_t<std::make_unsigned<Tgt>>(std::numeric_limits<Tgt>::max()) <
+ folly::_t<std::make_unsigned<Src>>(std::numeric_limits<Src>::max())) {
if (greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)) {
return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
}
return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
}
}
- return boost::implicit_cast<Tgt>(value);
+ return static_cast<Tgt>(value);
}
/**
* }
******************************************************************************/
template <class T>
-FOLLY_WARN_UNUSED_RESULT typename std::enable_if<
+FOLLY_NODISCARD typename std::enable_if<
std::is_enum<T>::value,
Expected<StringPiece, ConversionCode>>::type
parseTo(StringPiece in, T& out) noexcept {
return restOrError;
}
-FOLLY_WARN_UNUSED_RESULT
+FOLLY_NODISCARD
inline Expected<StringPiece, ConversionCode> parseTo(
StringPiece in,
StringPiece& out) noexcept {
return StringPiece{in.end(), in.end()};
}
-FOLLY_WARN_UNUSED_RESULT
+FOLLY_NODISCARD
inline Expected<StringPiece, ConversionCode> parseTo(
StringPiece in,
std::string& out) {
return StringPiece{in.end(), in.end()};
}
-FOLLY_WARN_UNUSED_RESULT
+FOLLY_NODISCARD
inline Expected<StringPiece, ConversionCode> parseTo(
StringPiece in,
fbstring& out) {
template <class Tgt>
Tgt to(StringPiece* src) {
- Tgt result;
+ Tgt result{};
using Error = detail::ParseToError<Tgt>;
return parseTo(*src, result)
.thenOrThrow(
template <class Tgt, class Src>
typename std::enable_if<
std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value,
- Tgt>::type
+ Expected<Tgt, ConversionCode>>::type
tryTo(const Src& value) {
using I = typename std::underlying_type<Tgt>::type;
return tryTo<I>(value).then([](I i) { return static_cast<Tgt>(i); });