Allow folly to compile cleanly with most of the rest of MSVC's sign mismatch warnings
[folly.git] / folly / Conv.h
index 468d33cb08a74d467b9ed9366499f30aa87dc88e..b034e2ef27f3517078abcbc70d87aced4219c65a 100644 (file)
@@ -43,6 +43,7 @@
 #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>
 
@@ -382,12 +383,12 @@ inline uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer) {
     // 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;
 }
 
@@ -556,9 +557,10 @@ toAppend(Src value, Tgt * result) {
   char buffer[20];
   if (value < 0) {
     result->push_back('-');
-    result->append(buffer, uint64ToBufferUnsafe(-uint64_t(value), buffer));
+    result->append(
+        buffer, uint64ToBufferUnsafe(uint64_t(-uint64_t(value)), buffer));
   } else {
-    result->append(buffer, uint64ToBufferUnsafe(value, buffer));
+    result->append(buffer, uint64ToBufferUnsafe(uint64_t(value), buffer));
   }
 }
 
@@ -680,14 +682,14 @@ toAppend(
       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);
 }
@@ -729,7 +731,9 @@ estimateSpaceNeeded(Src value) {
       // 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
 }
 
 /**
@@ -1174,6 +1178,19 @@ parseTo(StringPiece src, Tgt& out) {
 
 namespace detail {
 
+/**
+ * Bool to integral 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,
+    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
@@ -1489,7 +1506,7 @@ Expected<Tgt, detail::ParseToError<Tgt>> tryTo(StringPiece* src) {
 
 template <class Tgt>
 Tgt to(StringPiece* src) {
-  Tgt result;
+  Tgt result{};
   using Error = detail::ParseToError<Tgt>;
   return parseTo(*src, result)
       .thenOrThrow(