Fix the assumption in the propagate_const test about local layout
[folly.git] / folly / detail / IPAddressSource.h
index 9447812d63018372830aebe15b8bcd3746de9233..4a29d0307ef19e6b22d0f1a5bc46ba56c5e64d1b 100644 (file)
@@ -24,7 +24,7 @@
 #include <string>
 #include <type_traits>
 
-#include <folly/Conv.h>
+#include <folly/Format.h>
 #include <folly/detail/IPAddress.h>
 
 // BSDish platforms don't provide standard access to s6_addr16
@@ -51,7 +51,7 @@ struct Bytes {
     std::size_t asize = a.size();
     std::array<uint8_t, N> ba{{0}};
     for (std::size_t i = 0; i < asize; i++) {
-      ba[i] = a[i] & b[i];
+      ba[i] = uint8_t(a[i] & b[i]);
     }
     return ba;
   }
@@ -74,11 +74,9 @@ struct Bytes {
         0xff // /8
     }};
     if (oneMask > kBitCount || twoMask > kBitCount) {
-      throw std::invalid_argument(folly::to<std::string>(
-          "Invalid mask "
-          "length: ",
-          oneMask > twoMask ? oneMask : twoMask,
-          ". Mask length must be <= ",
+      throw std::invalid_argument(sformat(
+          "Invalid mask length: {}. Mask length must be <= {}",
+          std::max(oneMask, twoMask),
           kBitCount));
     }
 
@@ -92,17 +90,21 @@ struct Bytes {
       ba[byteIndex] = one[byteIndex];
       ++byteIndex;
     }
-    auto bitIndex = std::min(mask, (uint8_t)(byteIndex * 8));
+    auto bitIndex = std::min(mask, uint8_t(byteIndex * 8));
+    uint8_t bI = uint8_t(bitIndex / 8);
+    uint8_t bM = uint8_t(bitIndex % 8);
     // Compute the bit up to which the two byte arrays match in the
     // unmatched byte.
     // Here the check is bitIndex < mask since the 0th mask entry in
     // kMasks array holds the mask for masking the MSb in this byte.
     // We could instead make it hold so that no 0th entry masks no
     // bits but thats a useless iteration.
-    while (bitIndex < mask && ((one[bitIndex / 8] & kMasks[bitIndex % 8]) ==
-                               (two[bitIndex / 8] & kMasks[bitIndex % 8]))) {
-      ba[bitIndex / 8] = one[bitIndex / 8] & kMasks[bitIndex % 8];
+    while (bitIndex < mask &&
+           ((one[bI] & kMasks[bM]) == (two[bI] & kMasks[bM]))) {
+      ba[bI] = uint8_t(one[bI] & kMasks[bM]);
       ++bitIndex;
+      bI = uint8_t(bitIndex / 8);
+      bM = uint8_t(bitIndex % 8);
     }
     return {ba, bitIndex};
   }
@@ -174,7 +176,7 @@ struct Bytes {
 template <
     class IntegralType,
     IntegralType DigitCount,
-    IntegralType Base = 10,
+    IntegralType Base = IntegralType(10),
     bool PrintAllDigits = false,
     class = typename std::enable_if<
         std::is_integral<IntegralType>::value &&
@@ -190,14 +192,14 @@ inline void writeIntegerString(IntegralType val, char** buffer) {
   }
 
   IntegralType powerToPrint = 1;
-  for (int i = 1; i < DigitCount; ++i) {
+  for (IntegralType i = 1; i < DigitCount; ++i) {
     powerToPrint *= Base;
   }
 
   bool found = PrintAllDigits;
   while (powerToPrint) {
     if (found || powerToPrint <= val) {
-      IntegralType value = val / powerToPrint;
+      IntegralType value = IntegralType(val / powerToPrint);
       if (Base == 10 || value < 10) {
         value += '0';
       } else {
@@ -214,9 +216,8 @@ inline void writeIntegerString(IntegralType val, char** buffer) {
   *buffer = buf;
 }
 
-inline std::string fastIpv4ToString(const in_addr& inAddr) {
+inline size_t fastIpV4ToBufferUnsafe(const in_addr& inAddr, char* str) {
   const uint8_t* octets = reinterpret_cast<const uint8_t*>(&inAddr.s_addr);
-  char str[sizeof("255.255.255.255")];
   char* buf = str;
 
   writeIntegerString<uint8_t, 3>(octets[0], &buf);
@@ -227,16 +228,25 @@ inline std::string fastIpv4ToString(const in_addr& inAddr) {
   *(buf++) = '.';
   writeIntegerString<uint8_t, 3>(octets[3], &buf);
 
-  return std::string(str, size_t(buf - str));
+  return buf - str;
 }
 
-inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
+inline std::string fastIpv4ToString(const in_addr& inAddr) {
+  char str[sizeof("255.255.255.255")];
+  return std::string(str, fastIpV4ToBufferUnsafe(inAddr, str));
+}
+
+inline void fastIpv4AppendToString(const in_addr& inAddr, std::string& out) {
+  char str[sizeof("255.255.255.255")];
+  out.append(str, fastIpV4ToBufferUnsafe(inAddr, str));
+}
+
+inline size_t fastIpv6ToBufferUnsafe(const in6_addr& in6Addr, char* str) {
 #ifdef _MSC_VER
   const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.u.Word);
 #else
   const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.s6_addr16);
 #endif
-  char str[sizeof("2001:0db8:0000:0000:0000:ff00:0042:8329")];
   char* buf = str;
 
   for (int i = 0; i < 8; ++i) {
@@ -251,7 +261,17 @@ inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
     }
   }
 
-  return std::string(str, size_t(buf - str));
+  return buf - str;
 }
+
+inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
+  char str[sizeof("2001:0db8:0000:0000:0000:ff00:0042:8329")];
+  return std::string(str, fastIpv6ToBufferUnsafe(in6Addr, str));
 }
+
+inline void fastIpv6AppendToString(const in6_addr& in6Addr, std::string& out) {
+  char str[sizeof("2001:0db8:0000:0000:0000:ff00:0042:8329")];
+  out.append(str, fastIpv6ToBufferUnsafe(in6Addr, str));
 }
+} // namespace detail
+} // namespace folly