Make Range.h and FBString.h mutually independent
authorYedidya Feldblum <yfeldblum@fb.com>
Tue, 17 Oct 2017 03:10:35 +0000 (20:10 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Tue, 17 Oct 2017 03:21:22 +0000 (20:21 -0700)
Summary:
[Folly] Make `Range.h` and `FBString.h` mutually independent.

This means that `Range` cannot directly know about `fbstring`, so any interactions between the two types must be indirected through templates.

Motivation: `FBString.h` is a relatively heaviweight `#include` for things that need `Range.h` but which do not use `fbstring`.

Reviewed By: ericniebler

Differential Revision: D6062434

fbshipit-source-id: e2f21c33f482eadffd0a8679eff4ece59bab53e9

folly/FBString.h
folly/FixedString.h
folly/Format-inl.h
folly/IPAddressV4.h
folly/IPAddressV6.h
folly/Range.h
folly/ThreadName.cpp

index 90728601fbc7b1cd06dbcb375d1f6470db2444d6..b566d1191cffa9bc063190c192aad7d533da3cdf 100644 (file)
@@ -2894,3 +2894,13 @@ FOLLY_POP_WARNING
 #undef FBSTRING_LIKELY
 #undef FBSTRING_UNLIKELY
 #undef FBSTRING_ASSERT
+
+#ifndef _LIBSTDCXX_FBSTRING
+namespace folly {
+template <class T>
+struct IsSomeString;
+
+template <>
+struct IsSomeString<fbstring> : std::true_type {};
+} // namespace folly
+#endif
index 1465070cbb77881ece63c6248f5a85f42c5b245e..732ae6ac61ae0df886e5462992f8edb88d3de7f0 100644 (file)
@@ -790,29 +790,6 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return *this;
   }
 
-  /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
-   * Conversion to folly::Range
-   * \return `Range<Iter>{begin(), end()}`
-   */
-  template <
-      class Iter,
-      class = typename std::enable_if<
-          std::is_convertible<Char*, Iter>::value>::type>
-  FOLLY_CPP14_CONSTEXPR /* implicit */ operator Range<Iter>() noexcept {
-    return {begin(), end()};
-  }
-
-  /**
-   * \overload
-   */
-  template <
-      class Iter,
-      class = typename std::enable_if<
-          std::is_convertible<const Char*, Iter>::value>::type>
-  constexpr /* implicit */ operator Range<Iter>() const noexcept {
-    return {begin(), end()};
-  }
-
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
    * Conversion to folly::Range
    * \return `Range<Char*>{begin(), end()}`
index 940224c2bf60e39a2cad2eda016d681d454b550e..60fdf2452c62a1a27768ed9668c0b588e8cf7525 100644 (file)
@@ -931,7 +931,7 @@ template <>
 struct KeyFromStringPiece<fbstring> : public FormatTraitsBase {
   typedef fbstring key_type;
   static fbstring convert(StringPiece s) {
-    return s.toFbstring();
+    return s.to<fbstring>();
   }
 };
 
index 4b0b8799feb960e0c2c2b4d3266fafd710b76b21..96de8adda6add3a61ab4b09a3e2c3274caf9addb 100644 (file)
@@ -22,6 +22,7 @@
 #include <functional>
 #include <iosfwd>
 
+#include <folly/FBString.h>
 #include <folly/Hash.h>
 #include <folly/Range.h>
 #include <folly/detail/IPAddress.h>
index 23c19e50c011ac7dd85136532d7f613e5061217c..f641bdcd85e988fa8562a0f986cb0aa467597f2a 100644 (file)
@@ -24,6 +24,7 @@
 #include <map>
 #include <stdexcept>
 
+#include <folly/FBString.h>
 #include <folly/Hash.h>
 #include <folly/Optional.h>
 #include <folly/Range.h>
index d1fa497c1eb9156c30144393bce0efd0bc309d40..ce3e1fe8065346a54a2363045283c7faaaa8bde3 100644 (file)
@@ -19,7 +19,6 @@
 
 #pragma once
 
-#include <folly/FBString.h>
 #include <folly/Portability.h>
 #include <folly/hash/SpookyHashV2.h>
 #include <folly/portability/BitsFunctexcept.h>
@@ -30,6 +29,7 @@
 #include <glog/logging.h>
 #include <algorithm>
 #include <array>
+#include <cassert>
 #include <climits>
 #include <cstddef>
 #include <cstring>
 #include <string>
 #include <type_traits>
 
-// libc++ doesn't provide this header, nor does msvc
-#ifdef FOLLY_HAVE_BITS_CXXCONFIG_H
-// This file appears in two locations: inside fbcode and in the
-// libstdc++ source code (when embedding fbstring as std::string).
-// To aid in this schizophrenic use, two macros are defined in
-// c++config.h:
-//   _LIBSTDCXX_FBSTRING - Set inside libstdc++.  This is useful to
-//      gate use inside fbcode v. libstdc++
-#include <bits/c++config.h>
-#endif
-
 #include <folly/CpuId.h>
 #include <folly/Likely.h>
 #include <folly/Traits.h>
@@ -61,6 +50,15 @@ FOLLY_GCC_DISABLE_WARNING("-Wshadow")
 
 namespace folly {
 
+/**
+ * Ubiquitous helper template for knowing what's a string.
+ */
+template <class T>
+struct IsSomeString : std::false_type {};
+
+template <>
+struct IsSomeString<std::string> : std::true_type {};
+
 template <class Iter>
 class Range;
 
@@ -251,30 +249,58 @@ class Range : private boost::totally_ordered<Range<Iter>> {
   Range(const Range& other, size_type first, size_type length = npos)
       : Range(other.subpiece(first, length)) {}
 
-  template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
-  /* implicit */ Range(const fbstring& str)
-      : b_(str.data()), e_(b_ + str.size()) {}
+  template <
+      class Container,
+      class = typename std::enable_if<
+          std::is_same<Iter, typename Container::const_pointer>::value>::type,
+      class = decltype(
+          Iter(std::declval<Container const&>().data()),
+          Iter(
+              std::declval<Container const&>().data() +
+              std::declval<Container const&>().size()))>
+  /* implicit */ constexpr Range(Container const& container)
+      : b_(container.data()), e_(b_ + container.size()) {}
 
-  template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
-  Range(const fbstring& str, fbstring::size_type startFrom) {
-    if (UNLIKELY(startFrom > str.size())) {
+  template <
+      class Container,
+      class = typename std::enable_if<
+          std::is_same<Iter, typename Container::const_pointer>::value>::type,
+      class = decltype(
+          Iter(std::declval<Container const&>().data()),
+          Iter(
+              std::declval<Container const&>().data() +
+              std::declval<Container const&>().size()))>
+  Range(Container const& container, typename Container::size_type startFrom) {
+    auto const cdata = container.data();
+    auto const csize = container.size();
+    if (UNLIKELY(startFrom > csize)) {
       std::__throw_out_of_range("index out of range");
     }
-    b_ = str.data() + startFrom;
-    e_ = str.data() + str.size();
+    b_ = cdata + startFrom;
+    e_ = cdata + csize;
   }
 
-  template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
+  template <
+      class Container,
+      class = typename std::enable_if<
+          std::is_same<Iter, typename Container::const_pointer>::value>::type,
+      class = decltype(
+          Iter(std::declval<Container const&>().data()),
+          Iter(
+              std::declval<Container const&>().data() +
+              std::declval<Container const&>().size()))>
   Range(
-      const fbstring& str,
-      fbstring::size_type startFrom,
-      fbstring::size_type size) {
-    if (UNLIKELY(startFrom > str.size())) {
+      Container const& container,
+      typename Container::size_type startFrom,
+      typename Container::size_type size) {
+    auto const cdata = container.data();
+    auto const csize = container.size();
+    if (UNLIKELY(startFrom > csize)) {
       std::__throw_out_of_range("index out of range");
     }
-    b_ = str.data() + startFrom;
-    if (str.size() - startFrom < size) {
-      e_ = str.data() + str.size();
+    b_ = cdata + startFrom;
+    if (csize - startFrom < size) {
+      e_ = cdata + csize;
     } else {
       e_ = b_ + size;
     }
@@ -448,19 +474,22 @@ class Range : private boost::totally_ordered<Range<Iter>> {
     assert(b_ < e_);
     return detail::value_before(e_);
   }
-  // Works only for Range<const char*> and Range<char*>
-  std::string str() const {
-    return std::string(b_, size());
-  }
-  std::string toString() const {
-    return str();
+
+  template <typename Tgt>
+  auto to() const
+      -> decltype(Tgt(std::declval<Iter const&>(), std::declval<size_type>())) {
+    return Tgt(b_, size());
   }
   // Works only for Range<const char*> and Range<char*>
-  fbstring fbstr() const {
-    return fbstring(b_, size());
+  template <typename Tgt = std::string>
+  auto str() const
+      -> decltype(Tgt(std::declval<Iter const&>(), std::declval<size_type>())) {
+    return to<Tgt>();
   }
-  fbstring toFbstring() const {
-    return fbstr();
+  template <typename Tgt = std::string>
+  auto toString() const
+      -> decltype(Tgt(std::declval<Iter const&>(), std::declval<size_type>())) {
+    return to<Tgt>();
   }
 
   const_range_type castToConst() const {
@@ -1314,17 +1343,6 @@ struct hasher<
   }
 };
 
-/**
- * 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
-  };
-};
-
 /**
  * _sp is a user-defined literal suffix to make an appropriate Range
  * specialization from a literal string.
index 919a01122735f86a1d8caf65133f8b70c59369c1..ed11c10e2b798fd67c77669af8d8e63657713e2b 100644 (file)
@@ -102,15 +102,20 @@ bool setThreadName(std::thread::id tid, StringPiece name) {
 #if !FOLLY_HAVE_PTHREAD || _WIN32
   return false;
 #else
-  auto trimmedName = name.fbstr().substr(0, kMaxThreadNameLength - 1);
+  auto const piece = name.subpiece(0, kMaxThreadNameLength - 1);
+  auto const data = piece.data();
+  auto const size = piece.size();
+  char trimmedName[kMaxThreadNameLength];
+  std::memcpy(trimmedName, data, size);
+  std::memset(trimmedName + size, 0, kMaxThreadNameLength - size);
   auto id = stdTidToPthreadId(tid);
 #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME
-  return 0 == pthread_setname_np(id, trimmedName.c_str());
+  return 0 == pthread_setname_np(id, const_cast<char const*>(trimmedName));
 #elif FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
   // Since OS X 10.6 it is possible for a thread to set its own name,
   // but not that of some other thread.
   if (pthread_equal(pthread_self(), id)) {
-    return 0 == pthread_setname_np(trimmedName.c_str());
+    return 0 == pthread_setname_np(const_cast<char const*>(trimmedName));
   }
   return false;
 #else