Move IPAddress definitions to source files
authorYedidya Feldblum <yfeldblum@fb.com>
Sat, 9 Jul 2016 09:40:45 +0000 (02:40 -0700)
committerFacebook Github Bot 2 <facebook-github-bot-2-bot@fb.com>
Sat, 9 Jul 2016 09:53:41 +0000 (02:53 -0700)
Summary:
[Folly] Move `IPAddress` definitions to source files.

And to internal header files. Keeping headers lightweight can help with build times.

Reviewed By: simpkins

Differential Revision: D3514455

fbshipit-source-id: de78f4ef9e70e7ddd7fb666348ed705c5228531c

22 files changed:
folly/Conv.h
folly/IPAddress.cpp
folly/IPAddress.h
folly/IPAddressException.h
folly/IPAddressV4.cpp
folly/IPAddressV4.h
folly/IPAddressV6.cpp
folly/IPAddressV6.h
folly/MacAddress.cpp
folly/MacAddress.h
folly/Makefile.am
folly/Range.h
folly/SocketAddress.cpp
folly/SocketAddress.h
folly/detail/IPAddress.cpp [new file with mode: 0644]
folly/detail/IPAddress.h
folly/detail/IPAddressSource.h [new file with mode: 0644]
folly/io/async/AsyncServerSocket.cpp
folly/io/async/test/SocketClient.cpp
folly/test/IPAddressTest.cpp
folly/test/MacAddressTest.cpp
folly/test/SocketAddressTest.cpp

index 0af04cf6ca72ebf5af9af224d808f5bf1001ca06..df34f2faedbc002ac2dbd2f01038d232aefcf708 100644 (file)
@@ -357,14 +357,6 @@ estimateSpaceNeeded(T) {
   return 1;
 }
 
-/**
- * Ubiquitous helper template for writing string appenders
- */
-template <class T> struct IsSomeString {
-  enum { value = std::is_same<T, std::string>::value
-         || std::is_same<T, fbstring>::value };
-};
-
 /**
  * Everything implicitly convertible to const char* gets appended.
  */
index 9fa6c59d63a52de8abab265ba140b0436d56fea5..c4a51007d58504c766ecb52a4dec4a6c31db770c 100644 (file)
@@ -21,7 +21,9 @@
 #include <string>
 #include <vector>
 
+#include <folly/Conv.h>
 #include <folly/String.h>
+#include <folly/detail/IPAddressSource.h>
 
 using std::ostream;
 using std::string;
@@ -79,9 +81,12 @@ CIDRNetwork IPAddress::createNetwork(StringPiece ipSlashCidr,
 
   if (elemCount == 0 || // weird invalid string
       elemCount > 2) { // invalid string (IP/CIDR/extras)
-    throw IPAddressFormatException("Invalid ipSlashCidr specified. ",
-                                   "Expected IP/CIDR format, got ",
-                                   "'", ipSlashCidr, "'");
+    throw IPAddressFormatException(to<std::string>(
+        "Invalid ipSlashCidr specified. ",
+        "Expected IP/CIDR format, got ",
+        "'",
+        ipSlashCidr,
+        "'"));
   }
   IPAddress subnet(vec.at(0));
   uint8_t cidr = (defaultCidr > -1) ? defaultCidr : (subnet.isV4() ? 32 : 128);
@@ -90,18 +95,28 @@ CIDRNetwork IPAddress::createNetwork(StringPiece ipSlashCidr,
     try {
       cidr = to<uint8_t>(vec.at(1));
     } catch (...) {
-      throw IPAddressFormatException("Mask value ",
-                                     "'", vec.at(1), "' not a valid mask");
+      throw IPAddressFormatException(
+          to<std::string>("Mask value ", "'", vec.at(1), "' not a valid mask"));
     }
   }
   if (cidr > subnet.bitCount()) {
-    throw IPAddressFormatException("CIDR value '", cidr, "' ",
-                                   "is > network bit count ",
-                                   "'", subnet.bitCount(), "'");
+    throw IPAddressFormatException(to<std::string>(
+        "CIDR value '",
+        cidr,
+        "' ",
+        "is > network bit count ",
+        "'",
+        subnet.bitCount(),
+        "'"));
   }
   return std::make_pair(applyMask ? subnet.mask(cidr) : subnet, cidr);
 }
 
+// public static
+std::string IPAddress::networkToString(const CIDRNetwork& network) {
+  return network.first.str() + "/" + folly::to<std::string>(network.second);
+}
+
 // public static
 IPAddress IPAddress::fromBinary(ByteRange bytes) {
   if (bytes.size() == 4) {
@@ -110,8 +125,8 @@ IPAddress IPAddress::fromBinary(ByteRange bytes) {
     return IPAddress(IPAddressV6::fromBinary(bytes));
   } else {
     string hexval = detail::Bytes::toHex(bytes.data(), bytes.size());
-    throw IPAddressFormatException("Invalid address with hex value ",
-                                   "'", hexval, "'");
+    throw IPAddressFormatException(
+        to<std::string>("Invalid address with hex value ", "'", hexval, "'"));
   }
 }
 
@@ -137,7 +152,8 @@ IPAddress::IPAddress(StringPiece addr)
 {
   string ip = addr.str();  // inet_pton() needs NUL-terminated string
   auto throwFormatException = [&](const string& msg) {
-    throw IPAddressFormatException("Invalid IP '", ip, "': ", msg);
+    throw IPAddressFormatException(
+        to<std::string>("Invalid IP '", ip, "': ", msg));
   };
 
   if (ip.size() < 2) {
@@ -406,4 +422,17 @@ IPAddress::longestCommonPrefix(const CIDRNetwork& one, const CIDRNetwork& two) {
   return {IPAddress(0), 0};
 }
 
+[[noreturn]] void IPAddress::asV4Throw() const {
+  auto fam = detail::familyNameStr(family());
+  throw InvalidAddressFamilyException(to<std::string>(
+      "Can't convert address with family ", fam, " to AF_INET address"));
+}
+
+[[noreturn]] void IPAddress::asV6Throw() const {
+  auto fam = detail::familyNameStr(family());
+  throw InvalidAddressFamilyException(to<std::string>(
+      "Can't convert address with family ", fam, " to AF_INET6 address"));
+}
+
+
 }  // folly
index c5f31c778336802610cbd601adfd4a7d6a4c57ab..df21342e8d1658361b9fe3fdfaac7ddb507cc818 100644 (file)
 #pragma once
 
 #include <functional>
-#include <iostream>
+#include <iosfwd>
 #include <memory>
 #include <string>
 #include <utility> // std::pair
 
-#include <boost/operators.hpp>
-
-#include <folly/Conv.h>
-#include <folly/Format.h>
 #include <folly/Range.h>
 #include <folly/IPAddressException.h>
 #include <folly/IPAddressV4.h>
@@ -68,7 +64,7 @@ typedef std::pair<IPAddress, uint8_t> CIDRNetwork;
  *   CHECK(IPAddress::createIPv6(v4addr) == v6map.asV6());
  * @encode
  */
-class IPAddress : boost::totally_ordered<IPAddress> {
+class IPAddress {
  public:
   // returns true iff the input string can be parsed as an ip-address
   static bool validate(StringPiece ip);
@@ -101,9 +97,7 @@ class IPAddress : boost::totally_ordered<IPAddress> {
    *
    * @return string representing the netblock
    */
-  static std::string networkToString(const CIDRNetwork& network) {
-    return network.first.str() + "/" + folly::to<std::string>(network.second);
-  }
+  static std::string networkToString(const CIDRNetwork& network);
 
   /**
    * Create a new IPAddress instance from the provided binary data
@@ -170,10 +164,8 @@ class IPAddress : boost::totally_ordered<IPAddress> {
    * @throws IPAddressFormatException is not a V4 instance
    */
   const IPAddressV4& asV4() const {
-    if (!isV4()) {
-      auto familyName = detail::familyNameStr(family());
-      throw InvalidAddressFamilyException("Can't convert address with family ",
-                                          familyName, " to AF_INET address");
+    if (UNLIKELY(!isV4())) {
+      asV4Throw();
     }
     return addr_.ipV4Addr;
   }
@@ -183,10 +175,8 @@ class IPAddress : boost::totally_ordered<IPAddress> {
    * @throws InvalidAddressFamilyException is not a V6 instance
    */
   const IPAddressV6& asV6() const {
-    if (!isV6()) {
-      auto familyName = detail::familyNameStr(family());
-      throw InvalidAddressFamilyException("Can't convert address with family ",
-                                          familyName, " to AF_INET6 address");
+    if (UNLIKELY(!isV6())) {
+      asV6Throw();
     }
     return addr_.ipV6Addr;
   }
@@ -411,6 +401,9 @@ class IPAddress : boost::totally_ordered<IPAddress> {
   }
 
  private:
+  [[noreturn]] void asV4Throw() const;
+  [[noreturn]] void asV6Throw() const;
+
   typedef union IPAddressV46 {
     IPAddressV4 ipV4Addr;
     IPAddressV6 ipV6Addr;
@@ -444,6 +437,19 @@ void toAppend(IPAddress addr, fbstring* result);
 bool operator==(const IPAddress& addr1, const IPAddress& addr2);
 // Return true if addr1 < addr2
 bool operator<(const IPAddress& addr1, const IPAddress& addr2);
+// Derived operators
+inline bool operator!=(const IPAddress& a, const IPAddress& b) {
+  return !(a == b);
+}
+inline bool operator>(const IPAddress& a, const IPAddress& b) {
+  return b < a;
+}
+inline bool operator<=(const IPAddress& a, const IPAddress& b) {
+  return !(a > b);
+}
+inline bool operator>=(const IPAddress& a, const IPAddress& b) {
+  return !(a < b);
+}
 
 }  // folly
 
index 9ef8ca85c51050b95d412b2cc8ae20e30857012b..1b5253ea4e90d6fd45c92f9b0bbd52548f1cefaf 100644 (file)
@@ -18,8 +18,8 @@
 
 #include <exception>
 #include <string>
+#include <utility>
 
-#include <folly/Conv.h>
 #include <folly/detail/IPAddress.h>
 
 namespace folly {
@@ -29,13 +29,13 @@ namespace folly {
  */
 class IPAddressFormatException : public std::exception {
  public:
-  explicit IPAddressFormatException(const std::string& msg)
-      : msg_(msg) {}
-  IPAddressFormatException(
-    const IPAddressFormatException&) = default;
-  template<typename... Args>
-  explicit IPAddressFormatException(Args&&... args)
-      : msg_(to<std::string>(std::forward<Args>(args)...)) {}
+  explicit IPAddressFormatException(std::string msg) noexcept
+      : msg_(std::move(msg)) {}
+  IPAddressFormatException(const IPAddressFormatException&) = default;
+  IPAddressFormatException(IPAddressFormatException&&) = default;
+  IPAddressFormatException& operator=(const IPAddressFormatException&) =
+      default;
+  IPAddressFormatException& operator=(IPAddressFormatException&&) = default;
 
   virtual ~IPAddressFormatException() noexcept {}
   virtual const char *what(void) const noexcept {
@@ -43,22 +43,23 @@ class IPAddressFormatException : public std::exception {
   }
 
  private:
-  const std::string msg_;
+  std::string msg_;
 };
 
 class InvalidAddressFamilyException : public IPAddressFormatException {
  public:
-  explicit InvalidAddressFamilyException(const std::string& msg)
-      : IPAddressFormatException(msg) {}
-  InvalidAddressFamilyException(
-    const InvalidAddressFamilyException&) = default;
-  explicit InvalidAddressFamilyException(sa_family_t family)
-      : IPAddressFormatException("Address family " +
-                                 detail::familyNameStr(family) +
-                                 " is not AF_INET or AF_INET6") {}
-  template<typename... Args>
-  explicit InvalidAddressFamilyException(Args&&... args)
-      : IPAddressFormatException(std::forward<Args>(args)...) {}
+  explicit InvalidAddressFamilyException(std::string msg) noexcept
+      : IPAddressFormatException(std::move(msg)) {}
+  explicit InvalidAddressFamilyException(sa_family_t family) noexcept
+      : InvalidAddressFamilyException(
+            "Address family " + detail::familyNameStr(family) +
+            " is not AF_INET or AF_INET6") {}
+  InvalidAddressFamilyException(const InvalidAddressFamilyException&) = default;
+  InvalidAddressFamilyException(InvalidAddressFamilyException&&) = default;
+  InvalidAddressFamilyException& operator=(
+      const InvalidAddressFamilyException&) = default;
+  InvalidAddressFamilyException& operator=(InvalidAddressFamilyException&&) =
+      default;
 };
 
 }  // folly
index ff44cee80acca2f9096e20c0cd1254f21b21fbf5..b8a0e0e2f847ad45935fac2b6881fd6db526c467 100644 (file)
@@ -22,6 +22,7 @@
 #include <folly/Format.h>
 #include <folly/IPAddress.h>
 #include <folly/IPAddressV6.h>
+#include <folly/detail/IPAddressSource.h>
 
 using std::ostream;
 using std::string;
@@ -72,8 +73,8 @@ uint32_t IPAddressV4::toLong(StringPiece ip) {
   auto str = ip.str();
   in_addr addr;
   if (inet_pton(AF_INET, str.c_str(), &addr) != 1) {
-    throw IPAddressFormatException("Can't convert invalid IP '", ip, "' ",
-                                   "to long");
+    throw IPAddressFormatException(
+        to<std::string>("Can't convert invalid IP '", ip, "' ", "to long"));
   }
   return addr.s_addr;
 }
@@ -99,7 +100,8 @@ IPAddressV4::IPAddressV4(StringPiece addr)
 {
   auto ip = addr.str();
   if (inet_pton(AF_INET, ip.c_str(), &addr_.inAddr_) != 1) {
-    throw IPAddressFormatException("Invalid IPv4 address '", addr, "'");
+    throw IPAddressFormatException(
+        to<std::string>("Invalid IPv4 address '", addr, "'"));
   }
 }
 
@@ -112,8 +114,10 @@ IPAddressV4::IPAddressV4(const in_addr src)
 // public
 void IPAddressV4::setFromBinary(ByteRange bytes) {
   if (bytes.size() != 4) {
-    throw IPAddressFormatException("Invalid IPv4 binary data: length must "
-                                   "be 4 bytes, got ", bytes.size());
+    throw IPAddressFormatException(to<std::string>(
+        "Invalid IPv4 binary data: length must ",
+        "be 4 bytes, got ",
+        bytes.size()));
   }
   memcpy(&addr_.inAddr_.s_addr, bytes.data(), sizeof(in_addr));
 }
@@ -147,8 +151,8 @@ bool IPAddressV4::inSubnet(StringPiece cidrNetwork) const {
   auto subnetInfo = IPAddress::createNetwork(cidrNetwork);
   auto addr = subnetInfo.first;
   if (!addr.isV4()) {
-    throw IPAddressFormatException("Address '", addr.toJson(), "' ",
-                                   "is not a V4 address");
+    throw IPAddressFormatException(to<std::string>(
+        "Address '", addr.toJson(), "' ", "is not a V4 address"));
   }
   return inSubnetWithMask(addr.asV4(), fetchMask(subnetInfo.second));
 }
@@ -207,8 +211,8 @@ bool IPAddressV4::isMulticast() const {
 IPAddressV4 IPAddressV4::mask(size_t numBits) const {
   static const auto bits = bitCount();
   if (numBits > bits) {
-    throw IPAddressFormatException("numBits(", numBits,
-                                   ") > bitsCount(", bits, ")");
+    throw IPAddressFormatException(
+        to<std::string>("numBits(", numBits, ") > bitsCount(", bits, ")"));
   }
 
   ByteArray4 ba = detail::Bytes::mask(fetchMask(numBits), addr_.bytes_);
@@ -234,11 +238,20 @@ uint8_t IPAddressV4::getNthMSByte(size_t byteIndex) const {
 const ByteArray4 IPAddressV4::fetchMask(size_t numBits) {
   static const uint8_t bits = bitCount();
   if (numBits > bits) {
-    throw IPAddressFormatException("IPv4 addresses are 32 bits");
+    throw IPAddressFormatException(
+        to<std::string>("IPv4 addresses are 32 bits"));
   }
   // masks_ is backed by an array so is zero indexed
   return masks_[numBits];
 }
+// public static
+CIDRNetworkV4 IPAddressV4::longestCommonPrefix(
+    const CIDRNetworkV4& one,
+    const CIDRNetworkV4& two) {
+  auto prefix = detail::Bytes::longestCommonPrefix(
+      one.first.addr_.bytes_, one.second, two.first.addr_.bytes_, two.second);
+  return {IPAddressV4(prefix.first), prefix.second};
+}
 
 // static private
 const std::array<ByteArray4, 33> IPAddressV4::masks_ = {{
index fa4d46d277702133484cbe3baf8e420dd68c7c1a..7d3106685bfb11d7724fb36f3a1a393688cc439f 100644 (file)
 
 #pragma once
 
-#include <functional>
-#include <iostream>
+#include <cstring>
 
-#include <boost/operators.hpp>
+#include <array>
+#include <functional>
+#include <iosfwd>
 
 #include <folly/Hash.h>
 #include <folly/Range.h>
@@ -51,7 +52,7 @@ typedef std::array<uint8_t, 4> ByteArray4;
  *
  * @see IPAddress
  */
-class IPAddressV4 : boost::totally_ordered<IPAddressV4> {
+class IPAddressV4 {
  public:
   // returns true iff the input string can be parsed as an ipv4-address
   static bool validate(StringPiece ip);
@@ -168,7 +169,8 @@ class IPAddressV4 : boost::totally_ordered<IPAddressV4> {
 
   // @see IPAddress#isZero
   bool isZero() const {
-    return detail::Bytes::isZero(bytes(), 4);
+    constexpr auto zero = ByteArray4{{}};
+    return 0 == std::memcmp(bytes(), zero.data(), zero.size());
   }
 
   bool isLinkLocalBroadcast() const {
@@ -214,15 +216,11 @@ class IPAddressV4 : boost::totally_ordered<IPAddressV4> {
    */
   static const ByteArray4 fetchMask(size_t numBits);
 
-  // Given 2 IPAddressV4,mask pairs extract the longest common IPAddress,
+  // Given 2 IPAddressV4, mask pairs extract the longest common IPAddress,
   // mask pair
   static CIDRNetworkV4 longestCommonPrefix(
-    const CIDRNetworkV4& one, const CIDRNetworkV4& two) {
-    auto prefix =
-      detail::Bytes::longestCommonPrefix(one.first.addr_.bytes_, one.second,
-                                         two.first.addr_.bytes_, two.second);
-    return {IPAddressV4(prefix.first), prefix.second};
-  }
+      const CIDRNetworkV4& one,
+      const CIDRNetworkV4& two);
   // Number of bytes in the address representation.
   static size_t byteCount() { return 4; }
   //get nth most significant bit - 0 indexed
@@ -282,6 +280,19 @@ inline bool operator==(const IPAddressV4& addr1, const IPAddressV4& addr2) {
 inline bool operator<(const IPAddressV4& addr1, const IPAddressV4& addr2) {
   return (addr1.toLongHBO() < addr2.toLongHBO());
 }
+// Derived operators
+inline bool operator!=(const IPAddressV4& a, const IPAddressV4& b) {
+  return !(a == b);
+}
+inline bool operator>(const IPAddressV4& a, const IPAddressV4& b) {
+  return b < a;
+}
+inline bool operator<=(const IPAddressV4& a, const IPAddressV4& b) {
+  return !(a > b);
+}
+inline bool operator>=(const IPAddressV4& a, const IPAddressV4& b) {
+  return !(a < b);
+}
 
 }  // folly
 
index d092788270da7eb4f8590e9c99ca38300e231017..9904c406a5fc0f7d6142bda7a12fec87bfb12737 100644 (file)
@@ -23,6 +23,7 @@
 #include <folly/IPAddress.h>
 #include <folly/IPAddressV4.h>
 #include <folly/MacAddress.h>
+#include <folly/detail/IPAddressSource.h>
 
 using std::ostream;
 using std::string;
@@ -72,8 +73,8 @@ IPAddressV6::IPAddressV6(StringPiece addr) {
 
   // Allow addresses surrounded in brackets
   if (ip.size() < 2) {
-    throw IPAddressFormatException("Invalid IPv6 address '", ip,
-                                   "': address too short");
+    throw IPAddressFormatException(
+        to<std::string>("Invalid IPv6 address '", ip, "': address too short"));
   }
   if (ip.front() == '[' && ip.back() == ']') {
     ip = ip.substr(1, ip.size() - 2);
@@ -91,7 +92,8 @@ IPAddressV6::IPAddressV6(StringPiece addr) {
     scope_ = ipAddr->sin6_scope_id;
     freeaddrinfo(result);
   } else {
-    throw IPAddressFormatException("Invalid IPv6 address '", ip, "'");
+    throw IPAddressFormatException(
+        to<std::string>("Invalid IPv6 address '", ip, "'"));
   }
 }
 
@@ -136,8 +138,10 @@ IPAddressV6::AddressStorage::AddressStorage(MacAddress mac) {
 
 void IPAddressV6::setFromBinary(ByteRange bytes) {
   if (bytes.size() != 16) {
-    throw IPAddressFormatException("Invalid IPv6 binary data: length must "
-                                   "be 16 bytes, got ", bytes.size());
+    throw IPAddressFormatException(to<std::string>(
+        "Invalid IPv6 binary data: length must ",
+        "be 16 bytes, got ",
+        bytes.size()));
   }
   memcpy(&addr_.in6Addr_.s6_addr, bytes.data(), sizeof(in6_addr));
   scope_ = 0;
@@ -252,8 +256,8 @@ bool IPAddressV6::inSubnet(StringPiece cidrNetwork) const {
   auto subnetInfo = IPAddress::createNetwork(cidrNetwork);
   auto addr = subnetInfo.first;
   if (!addr.isV6()) {
-    throw IPAddressFormatException("Address '", addr.toJson(), "' ",
-                                   "is not a V6 address");
+    throw IPAddressFormatException(to<std::string>(
+        "Address '", addr.toJson(), "' ", "is not a V6 address"));
   }
   return inSubnetWithMask(addr.asV6(), fetchMask(subnetInfo.second));
 }
@@ -336,8 +340,8 @@ IPAddressV6 IPAddressV6::getSolicitedNodeAddress() const {
 IPAddressV6 IPAddressV6::mask(size_t numBits) const {
   static const auto bits = bitCount();
   if (numBits > bits) {
-    throw IPAddressFormatException("numBits(", numBits, ") > bitCount(",
-                                   bits, ")");
+    throw IPAddressFormatException(
+        to<std::string>("numBits(", numBits, ") > bitCount(", bits, ")"));
   }
   ByteArray16 ba = detail::Bytes::mask(fetchMask(numBits), addr_.bytes_);
   return IPAddressV6(ba);
@@ -354,8 +358,11 @@ string IPAddressV6::str() const {
     string ip(buffer);
     return ip;
   } else {
-    throw IPAddressFormatException("Invalid address with hex ",
-                                   "'", detail::Bytes::toHex(bytes(), 16), "'");
+    throw IPAddressFormatException(to<std::string>(
+        "Invalid address with hex ",
+        "'",
+        detail::Bytes::toHex(bytes(), 16),
+        "'"));
   }
 }
 
@@ -385,6 +392,15 @@ const ByteArray16 IPAddressV6::fetchMask(size_t numBits) {
   return masks_[numBits];
 }
 
+// public static
+CIDRNetworkV6 IPAddressV6::longestCommonPrefix(
+    const CIDRNetworkV6& one,
+    const CIDRNetworkV6& two) {
+  auto prefix = detail::Bytes::longestCommonPrefix(
+      one.first.addr_.bytes_, one.second, two.first.addr_.bytes_, two.second);
+  return {IPAddressV6(prefix.first), prefix.second};
+}
+
 // protected
 bool IPAddressV6::inBinarySubnet(const std::array<uint8_t, 2> addr,
                                  size_t numBits) const {
index 703f9da71e5ffeca96047bf5a8ab80bcc1fab66f..db70d09323d9e1d41535c466d37d9cf5a55080cc 100644 (file)
 
 #pragma once
 
+#include <cstring>
+
+#include <array>
 #include <functional>
-#include <iostream>
+#include <iosfwd>
 #include <map>
 #include <stdexcept>
 
-#include <boost/operators.hpp>
-
 #include <folly/Hash.h>
 #include <folly/Range.h>
 #include <folly/detail/IPAddress.h>
@@ -63,7 +64,7 @@ typedef std::array<uint8_t, 16> ByteArray16;
  * Serializing / Deserializing IPAddressB6's on different hosts
  * that use link-local scoping probably won't work.
  */
-class IPAddressV6 : boost::totally_ordered<IPAddressV6> {
+class IPAddressV6 {
  public:
   // V6 Address Type
   enum Type {
@@ -227,7 +228,8 @@ class IPAddressV6 : boost::totally_ordered<IPAddressV6> {
 
   // @see IPAddress#isZero
   bool isZero() const {
-    return detail::Bytes::isZero(bytes(), 16);
+    constexpr auto zero = ByteArray16{{}};
+    return 0 == std::memcmp(bytes(), zero.data(), zero.size());
   }
 
   bool isLinkLocalBroadcast() const;
@@ -283,13 +285,9 @@ class IPAddressV6 : boost::totally_ordered<IPAddressV6> {
   static const ByteArray16 fetchMask(size_t numBits);
   // Given 2 IPAddressV6,mask pairs extract the longest common IPAddress,
   // mask pair
-  static CIDRNetworkV6 longestCommonPrefix(const CIDRNetworkV6& one,
-                                           const CIDRNetworkV6& two) {
-    auto prefix = detail::Bytes::longestCommonPrefix(
-      one.first.addr_.bytes_, one.second,
-      two.first.addr_.bytes_, two.second);
-    return {IPAddressV6(prefix.first), prefix.second};
-  }
+  static CIDRNetworkV6 longestCommonPrefix(
+      const CIDRNetworkV6& one,
+      const CIDRNetworkV6& two);
   // Number of bytes in the address representation.
   static constexpr size_t byteCount() { return 16; }
 
@@ -367,6 +365,19 @@ inline bool operator<(const IPAddressV6& addr1, const IPAddressV6& addr2) {
     return cmp;
   }
 }
+// Derived operators
+inline bool operator!=(const IPAddressV6& a, const IPAddressV6& b) {
+  return !(a == b);
+}
+inline bool operator>(const IPAddressV6& a, const IPAddressV6& b) {
+  return b < a;
+}
+inline bool operator<=(const IPAddressV6& a, const IPAddressV6& b) {
+  return !(a > b);
+}
+inline bool operator>=(const IPAddressV6& a, const IPAddressV6& b) {
+  return !(a < b);
+}
 
 }  // folly
 
index f458138f40f7c8f69604552813fc934fff231ac0..bdc54a3a57a942237f529824f9762fc39225dc9e 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <folly/MacAddress.h>
 
+#include <iostream>
+
 #include <folly/Exception.h>
 #include <folly/IPAddressV6.h>
 
index 49852edba60b6bbcb4be9934b7c5881d93d2f722..309a427b02cb392017800e8654eb97849e8f575d 100644 (file)
 
 #pragma once
 
-#include <iostream>
-
-#include <boost/operators.hpp>
+#include <iosfwd>
 
 #include <folly/Bits.h>
-#include <folly/Conv.h>
+#include <folly/Range.h>
 
 namespace folly {
 
@@ -30,7 +28,7 @@ class IPAddressV6;
 /*
  * MacAddress represents an IEEE 802 MAC address.
  */
-class MacAddress : private boost::totally_ordered<MacAddress> {
+class MacAddress {
  public:
   static constexpr size_t SIZE = 6;
   static const MacAddress BROADCAST;
@@ -167,8 +165,7 @@ class MacAddress : private boost::totally_ordered<MacAddress> {
     return getByte(0) & 0x2;
   }
 
-  // Equality and less-than operators.
-  // boost::totally_ordered provides the other comparison operators.
+  // Comparison operators.
 
   bool operator==(const MacAddress& other) const {
     // All constructors and modifying methods make sure padding is 0,
@@ -180,6 +177,22 @@ class MacAddress : private boost::totally_ordered<MacAddress> {
     return u64HBO() < other.u64HBO();
   }
 
+  bool operator!=(const MacAddress& other) const {
+    return !(*this == other);
+  }
+
+  bool operator>(const MacAddress& other) const {
+    return other < *this;
+  }
+
+  bool operator>=(const MacAddress& other) const {
+    return !(*this < other);
+  }
+
+  bool operator<=(const MacAddress& other) const {
+    return !(*this > other);
+  }
+
  private:
   explicit MacAddress(uint64_t valueNBO) {
     memcpy(&bytes_, &valueNBO, 8);
index 381bd1bb809af572b6c51dae7113e19edb15e81d..695592251d027fe94d584d2e3bf98cbaaf07979b 100644 (file)
@@ -63,6 +63,7 @@ nobase_follyinclude_HEADERS = \
        detail/Futex.h \
        detail/GroupVarintDetail.h \
        detail/IPAddress.h \
+       detail/IPAddressSource.h \
        detail/Malloc.h \
        detail/MemoryIdler.h \
        detail/MPMCPipelineDetail.h \
@@ -363,6 +364,7 @@ libfolly_la_SOURCES = \
        Bits.cpp \
        Checksum.cpp \
        detail/CacheLocality.cpp \
+       detail/IPAddress.cpp \
        dynamic.cpp \
        File.cpp \
        FileUtil.cpp \
index e4be2b0680cfcc5f6c5f475a709b77538aee0710..0b63f45770efa5f29ec579b48d23c86d37bdd962 100644 (file)
@@ -1162,6 +1162,14 @@ struct hasher<folly::Range<T*>,
   }
 };
 
+/**
+ * Ubiquitous helper template for knowing what's a string
+ */
+template <class T> struct IsSomeString {
+  enum { value = std::is_same<T, std::string>::value
+         || std::is_same<T, fbstring>::value };
+};
+
 }  // !namespace folly
 
 #pragma GCC diagnostic pop
index dbeff61bf958dbc32666457d17b5bb4566764460..6a13554ae18359bab12b43ffbf1ba113c92aa403 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <folly/SocketAddress.h>
 
+#include <folly/Exception.h>
 #include <folly/Hash.h>
 
 #include <boost/functional/hash.hpp>
@@ -28,6 +29,7 @@
 #include <errno.h>
 #include <sstream>
 #include <string>
+#include <system_error>
 
 namespace {
 
index d48f3ccc81bf43ca88d7b8daef4637f356b831e8..688dcf92c5129ae40ed7ec85d2e3396c6c051c6d 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <sys/types.h>
 #include <cstddef>
-#include <iostream>
+#include <iosfwd>
 #include <string>
 
 #include <folly/IPAddress.h>
diff --git a/folly/detail/IPAddress.cpp b/folly/detail/IPAddress.cpp
new file mode 100644 (file)
index 0000000..85fa093
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * 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/detail/IPAddress.h>
+
+#include <folly/Format.h>
+
+namespace folly { namespace detail {
+
+std::string familyNameStrDefault(sa_family_t family) {
+  return folly::sformat("sa_family_t({})", folly::to<std::string>(family));
+}
+
+[[noreturn]] void getNthMSBitImplThrow(size_t bitCount, sa_family_t family) {
+  throw std::invalid_argument(folly::to<std::string>(
+      "Bit index must be < ",
+      bitCount,
+      " for addresses of type :",
+      familyNameStr(family)));
+}
+
+}}
index b92ce65785888e8c0a9d605a5fc87b2017432a8e..3abaefc3a428e2383d66dc0d057eee19cc532ec9 100644 (file)
 
 #pragma once
 
-#include <boost/noncopyable.hpp>
-#include <glog/logging.h>
-
-#include <algorithm>
-#include <array>
-#include <cstring>
 #include <string>
-#include <sstream>
-#include <type_traits>
-#include <vector>
 #include <sys/types.h>
-
-#include <folly/Conv.h>
-#include <folly/Format.h>
 #include <folly/portability/Sockets.h>
 
-// BSDish platforms don't provide standard access to s6_addr16
-#ifndef s6_addr16
-# if defined(__APPLE__) || defined(__FreeBSD__) || \
-     defined(__NetBSD__) || defined(__OpenBSD__)
-#  define s6_addr16 __u6_addr.__u6_addr16
-# endif
-#endif
-
 namespace folly { namespace detail {
 
+std::string familyNameStrDefault(sa_family_t family);
+
 inline std::string familyNameStr(sa_family_t family) {
   switch (family) {
     case AF_INET:
@@ -53,242 +35,20 @@ inline std::string familyNameStr(sa_family_t family) {
     case AF_UNIX:
       return "AF_UNIX";
     default:
-      return folly::format("sa_family_t({})",
-          folly::to<std::string>(family)).str();
+      return familyNameStrDefault(family);
   }
 }
 
-template<typename IPAddrType>
-inline bool getNthMSBitImpl(const IPAddrType& ip, uint8_t bitIndex,
-    sa_family_t family) {
+[[noreturn]] void getNthMSBitImplThrow(size_t bitCount, sa_family_t family);
+
+template <typename IPAddrType>
+inline bool
+getNthMSBitImpl(const IPAddrType& ip, uint8_t bitIndex, sa_family_t family) {
   if (bitIndex >= ip.bitCount()) {
-    throw std::invalid_argument(folly::to<std::string>("Bit index must be < ",
-          ip.bitCount(), " for addresses of type :", familyNameStr(family)));
+    getNthMSBitImplThrow(ip.bitCount(), family);
   }
   //Underlying bytes are in n/w byte order
   return (ip.getNthMSByte(bitIndex / 8) & (0x80 >> (bitIndex % 8))) != 0;
 }
 
-/**
- * Helper for working with unsigned char* or uint8_t* ByteArray values
- */
-struct Bytes : private boost::noncopyable {
-  // return true if all values of src are zero
-  static bool isZero(const uint8_t* src, std::size_t len) {
-    for (std::size_t i = 0; i < len; i++) {
-      if (src[i] != 0x00) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  // mask the values from two byte arrays, returning a new byte array
-  template<std::size_t N>
-  static std::array<uint8_t, N> mask(const std::array<uint8_t, N>& a,
-                                     const std::array<uint8_t, N>& b) {
-    static_assert(N > 0, "Can't mask an empty ByteArray");
-    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];
-    }
-    return ba;
-  }
-
-  template<std::size_t N>
-  static std::pair<std::array<uint8_t, N>, uint8_t>
-  longestCommonPrefix(
-    const std::array<uint8_t, N>& one, uint8_t oneMask,
-    const std::array<uint8_t, N>& two, uint8_t twoMask) {
-    static constexpr auto kBitCount = N * 8;
-    static constexpr std::array<uint8_t, 8> kMasks {{
-      0x80, // /1
-      0xc0, // /2
-      0xe0, // /3
-      0xf0, // /4
-      0xf8, // /5
-      0xfc, // /6
-      0xfe, // /7
-      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 <= ", kBitCount));
-    }
-
-    auto mask = std::min(oneMask, twoMask);
-    uint8_t byteIndex = 0;
-    std::array<uint8_t, N> ba{{0}};
-    // Compare a byte at a time. Note - I measured compared this with
-    // going multiple bytes at a time (8, 4, 2 and 1). It turns out
-    // to be 20 - 25% slower for 4 and 16 byte arrays.
-    while (byteIndex * 8 < mask && one[byteIndex] == two[byteIndex]) {
-      ba[byteIndex] = one[byteIndex];
-      ++byteIndex;
-    }
-    auto bitIndex = std::min(mask, (uint8_t)(byteIndex * 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];
-      ++bitIndex;
-    }
-    return {ba, bitIndex};
-  }
-
-  // create an in_addr from an uint8_t*
-  static inline in_addr mkAddress4(const uint8_t* src) {
-    union {
-      in_addr addr;
-      uint8_t bytes[4];
-    } addr;
-    std::memset(&addr, 0, 4);
-    std::memcpy(addr.bytes, src, 4);
-    return addr.addr;
-  }
-
-  // create an in6_addr from an uint8_t*
-  static inline in6_addr mkAddress6(const uint8_t* src) {
-    in6_addr addr;
-    std::memset(&addr, 0, 16);
-    std::memcpy(addr.s6_addr, src, 16);
-    return addr;
-  }
-
-  // convert an uint8_t* to its hex value
-  static std::string toHex(const uint8_t* src, std::size_t len) {
-    static const char* const lut = "0123456789abcdef";
-    std::stringstream ss;
-    for (std::size_t i = 0; i < len; i++) {
-      const unsigned char c = src[i];
-      ss << lut[c >> 4] << lut[c & 15];
-    }
-    return ss.str();
-  }
-
- private:
-  Bytes() = delete;
-  ~Bytes() = delete;
-};
-
-//
-// Write a maximum amount of base-converted character digits, of a
-// given base, from an unsigned integral type into a byte buffer of
-// sufficient size.
-//
-// This function does not append null terminators.
-//
-// Output buffer size must be guaranteed by caller (indirectly
-// controlled by DigitCount template parameter).
-//
-// Having these parameters at compile time allows compiler to
-// precompute several of the values, use smaller instructions, and
-// better optimize surrounding code.
-//
-// IntegralType:
-//   - Something like uint8_t, uint16_t, etc
-//
-// DigitCount is the maximum number of digits to be printed
-//   - This is tied to IntegralType and Base. For example:
-//     - uint8_t in base 10 will print at most 3 digits ("255")
-//     - uint16_t in base 16 will print at most 4 hex digits ("FFFF")
-//
-// Base is the desired output base of the string
-//   - Base 10 will print [0-9], base 16 will print [0-9a-f]
-//
-// PrintAllDigits:
-//   - Whether or not leading zeros should be printed
-//
-template<class IntegralType,
-         IntegralType DigitCount,
-         IntegralType Base = 10,
-         bool PrintAllDigits = false,
-         class = typename std::enable_if<
-           std::is_integral<IntegralType>::value &&
-           std::is_unsigned<IntegralType>::value,
-           bool>::type>
-  inline void writeIntegerString(
-    IntegralType val,
-    char** buffer) {
-  char* buf = *buffer;
-
-  if (!PrintAllDigits && val == 0) {
-    *(buf++) = '0';
-    *buffer = buf;
-    return;
-  }
-
-  IntegralType powerToPrint = 1;
-  for (int i = 1; i < DigitCount; ++i) {
-    powerToPrint *= Base;
-  }
-
-  bool found = PrintAllDigits;
-  while (powerToPrint) {
-
-    if (found || powerToPrint <= val) {
-      IntegralType value = val/powerToPrint;
-      if (Base == 10 || value < 10) {
-        value += '0';
-      } else {
-        value += ('a'-10);
-      }
-      *(buf++) = value;
-      val %= powerToPrint;
-      found = true;
-    }
-
-    powerToPrint /= Base;
-  }
-
-  *buffer = buf;
-}
-
-inline std::string fastIpv4ToString(
-  const in_addr& inAddr) {
-  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);
-  *(buf++) = '.';
-  writeIntegerString<uint8_t, 3>(octets[1], &buf);
-  *(buf++) = '.';
-  writeIntegerString<uint8_t, 3>(octets[2], &buf);
-  *(buf++) = '.';
-  writeIntegerString<uint8_t, 3>(octets[3], &buf);
-
-  return std::string(str, buf-str);
-}
-
-inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
-#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) {
-    writeIntegerString<uint16_t,
-                       4,  // at most 4 hex digits per ushort
-                       16, // base 16 (hex)
-                       true>(htons(bytes[i]), &buf);
-
-    if(i != 7) {
-      *(buf++) = ':';
-    }
-  }
-
-  return std::string(str, buf-str);
-}
-
 }}  // folly::detail
diff --git a/folly/detail/IPAddressSource.h b/folly/detail/IPAddressSource.h
new file mode 100644 (file)
index 0000000..e8a1811
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <glog/logging.h>
+#include <sys/types.h>
+#include <algorithm>
+#include <array>
+#include <cstring>
+#include <string>
+#include <type_traits>
+
+#include <folly/Conv.h>
+#include <folly/detail/IPAddress.h>
+
+// BSDish platforms don't provide standard access to s6_addr16
+#ifndef s6_addr16
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+    defined(__OpenBSD__)
+#define s6_addr16 __u6_addr.__u6_addr16
+#endif
+#endif
+
+namespace folly {
+namespace detail {
+
+/**
+ * Helper for working with unsigned char* or uint8_t* ByteArray values
+ */
+struct Bytes {
+  // mask the values from two byte arrays, returning a new byte array
+  template <std::size_t N>
+  static std::array<uint8_t, N> mask(
+      const std::array<uint8_t, N>& a,
+      const std::array<uint8_t, N>& b) {
+    static_assert(N > 0, "Can't mask an empty ByteArray");
+    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];
+    }
+    return ba;
+  }
+
+  template <std::size_t N>
+  static std::pair<std::array<uint8_t, N>, uint8_t> longestCommonPrefix(
+      const std::array<uint8_t, N>& one,
+      uint8_t oneMask,
+      const std::array<uint8_t, N>& two,
+      uint8_t twoMask) {
+    static constexpr auto kBitCount = N * 8;
+    static constexpr std::array<uint8_t, 8> kMasks{{
+        0x80, // /1
+        0xc0, // /2
+        0xe0, // /3
+        0xf0, // /4
+        0xf8, // /5
+        0xfc, // /6
+        0xfe, // /7
+        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 <= ",
+          kBitCount));
+    }
+
+    auto mask = std::min(oneMask, twoMask);
+    uint8_t byteIndex = 0;
+    std::array<uint8_t, N> ba{{0}};
+    // Compare a byte at a time. Note - I measured compared this with
+    // going multiple bytes at a time (8, 4, 2 and 1). It turns out
+    // to be 20 - 25% slower for 4 and 16 byte arrays.
+    while (byteIndex * 8 < mask && one[byteIndex] == two[byteIndex]) {
+      ba[byteIndex] = one[byteIndex];
+      ++byteIndex;
+    }
+    auto bitIndex = std::min(mask, (uint8_t)(byteIndex * 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];
+      ++bitIndex;
+    }
+    return {ba, bitIndex};
+  }
+
+  // create an in_addr from an uint8_t*
+  static inline in_addr mkAddress4(const uint8_t* src) {
+    union {
+      in_addr addr;
+      uint8_t bytes[4];
+    } addr;
+    std::memset(&addr, 0, 4);
+    std::memcpy(addr.bytes, src, 4);
+    return addr.addr;
+  }
+
+  // create an in6_addr from an uint8_t*
+  static inline in6_addr mkAddress6(const uint8_t* src) {
+    in6_addr addr;
+    std::memset(&addr, 0, 16);
+    std::memcpy(addr.s6_addr, src, 16);
+    return addr;
+  }
+
+  // convert an uint8_t* to its hex value
+  static std::string toHex(const uint8_t* src, std::size_t len) {
+    static const char* const lut = "0123456789abcdef";
+    std::string out(len * 2, 0);
+    for (std::size_t i = 0; i < len; i++) {
+      const unsigned char c = src[i];
+      out[i * 2 + 0] = lut[c >> 4];
+      out[i + 2 + 1] = lut[c & 15];
+    }
+    return out;
+  }
+
+ private:
+  Bytes() = delete;
+  ~Bytes() = delete;
+};
+
+//
+// Write a maximum amount of base-converted character digits, of a
+// given base, from an unsigned integral type into a byte buffer of
+// sufficient size.
+//
+// This function does not append null terminators.
+//
+// Output buffer size must be guaranteed by caller (indirectly
+// controlled by DigitCount template parameter).
+//
+// Having these parameters at compile time allows compiler to
+// precompute several of the values, use smaller instructions, and
+// better optimize surrounding code.
+//
+// IntegralType:
+//   - Something like uint8_t, uint16_t, etc
+//
+// DigitCount is the maximum number of digits to be printed
+//   - This is tied to IntegralType and Base. For example:
+//     - uint8_t in base 10 will print at most 3 digits ("255")
+//     - uint16_t in base 16 will print at most 4 hex digits ("FFFF")
+//
+// Base is the desired output base of the string
+//   - Base 10 will print [0-9], base 16 will print [0-9a-f]
+//
+// PrintAllDigits:
+//   - Whether or not leading zeros should be printed
+//
+template <
+    class IntegralType,
+    IntegralType DigitCount,
+    IntegralType Base = 10,
+    bool PrintAllDigits = false,
+    class = typename std::enable_if<
+        std::is_integral<IntegralType>::value &&
+            std::is_unsigned<IntegralType>::value,
+        bool>::type>
+inline void writeIntegerString(IntegralType val, char** buffer) {
+  char* buf = *buffer;
+
+  if (!PrintAllDigits && val == 0) {
+    *(buf++) = '0';
+    *buffer = buf;
+    return;
+  }
+
+  IntegralType powerToPrint = 1;
+  for (int i = 1; i < DigitCount; ++i) {
+    powerToPrint *= Base;
+  }
+
+  bool found = PrintAllDigits;
+  while (powerToPrint) {
+    if (found || powerToPrint <= val) {
+      IntegralType value = val / powerToPrint;
+      if (Base == 10 || value < 10) {
+        value += '0';
+      } else {
+        value += ('a' - 10);
+      }
+      *(buf++) = value;
+      val %= powerToPrint;
+      found = true;
+    }
+
+    powerToPrint /= Base;
+  }
+
+  *buffer = buf;
+}
+
+inline std::string fastIpv4ToString(const in_addr& inAddr) {
+  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);
+  *(buf++) = '.';
+  writeIntegerString<uint8_t, 3>(octets[1], &buf);
+  *(buf++) = '.';
+  writeIntegerString<uint8_t, 3>(octets[2], &buf);
+  *(buf++) = '.';
+  writeIntegerString<uint8_t, 3>(octets[3], &buf);
+
+  return std::string(str, buf - str);
+}
+
+inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
+#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) {
+    writeIntegerString<
+        uint16_t,
+        4, // at most 4 hex digits per ushort
+        16, // base 16 (hex)
+        true>(htons(bytes[i]), &buf);
+
+    if (i != 7) {
+      *(buf++) = ':';
+    }
+  }
+
+  return std::string(str, buf - str);
+}
+}
+}
index bc68a3096a27c9d735ce1ef8480687c7477829be..f740c2de08d04c7a5cd06609249c9012b54cd7cc 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <folly/FileUtil.h>
 #include <folly/SocketAddress.h>
+#include <folly/String.h>
 #include <folly/detail/SocketFastOpen.h>
 #include <folly/io/async/EventBase.h>
 #include <folly/io/async/NotificationQueue.h>
index 23bef722934fc51d60aa2734c9c351e175735482..957ec9d04991e0ac77689047fce559f593250aa5 100644 (file)
@@ -15,6 +15,8 @@
  */
 #include <folly/io/async/test/BlockingSocket.h>
 
+#include <iostream>
+
 #include <folly/ExceptionWrapper.h>
 #include <gflags/gflags.h>
 
index 566a73cf7edea5d1f841dee638b2cc77172570c5..a8b5e752e84e08756c429cd58c635d33299ac51c 100644 (file)
@@ -20,8 +20,9 @@
 
 #include <folly/Bits.h>
 #include <folly/Format.h>
-#include <folly/String.h>
 #include <folly/MacAddress.h>
+#include <folly/String.h>
+#include <folly/detail/IPAddressSource.h>
 
 using namespace folly;
 using namespace std;
index d4b833e5545d9c509a7903e12c42a3dd5d3bfcc9..b97ea211484987f5c00d70dbf07db73d9e6c26b4 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <gtest/gtest.h>
 
+#include <folly/Conv.h>
 #include <folly/IPAddressV6.h>
 #include <folly/MacAddress.h>
 
index 07a140eab7c1719412cd3228d2417dc0048e3f31..20a4fc0f5d06103db45c39d38ea69c78f22ef831 100644 (file)
@@ -19,6 +19,8 @@
 #include <gtest/gtest.h>
 #include <iostream>
 #include <sstream>
+#include <system_error>
+
 #include <folly/test/SocketAddressTestHelper.h>
 
 using namespace boost;