folly: fix sysMembarrier() with newer kernel headers
[folly.git] / folly / FixedString.h
index 6291ffeb709519bbd9c42351d285b69e2cdbaa9b..ece7691b74d09b43a7e0b413394cce2b939410eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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 <type_traits>
 #include <utility>
 
+#include <folly/ConstexprMath.h>
+#include <folly/Portability.h>
+#include <folly/Range.h>
+#include <folly/Utility.h>
 #include <folly/portability/BitsFunctexcept.h>
 #include <folly/portability/Constexpr.h>
 
-// Define FOLLY_USE_CPP14_CONSTEXPR to be true if the compiler's C++14
-// constexpr support is "good enough".
-#ifndef FOLLY_USE_CPP14_CONSTEXPR
-#if defined(__clang__)
-#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201300L
-#elif defined(__GNUC__)
-#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201304L
-#else
-#define FOLLY_USE_CPP14_CONSTEXPR 0 // MSVC?
-#endif
-#endif
-
-#if FOLLY_USE_CPP14_CONSTEXPR
-#define FOLLY_CPP14_CONSTEXPR constexpr
-#else
-#define FOLLY_CPP14_CONSTEXPR inline
-#endif
-
 namespace folly {
 
 template <class Char, std::size_t N>
@@ -72,16 +58,6 @@ constexpr std::size_t FixedStringBase_<Void>::npos;
 
 using FixedStringBase = FixedStringBase_<>;
 
-template <class Char, std::size_t N>
-constexpr std::size_t size(const Char (&)[N]) noexcept {
-  return N - 1u;
-}
-
-template <class Char, std::size_t N>
-constexpr std::size_t size(const BasicFixedString<Char, N>& s) noexcept {
-  return s.size();
-}
-
 // Intentionally NOT constexpr. By making this not constexpr, we make
 // checkOverflow below ill-formed in a constexpr context when the condition
 // it's testing for fails. In this way, precondition violations are reported
@@ -126,6 +102,13 @@ constexpr const Char (&checkNullTerminated(const Char (&a)[N]) noexcept)[N] {
 
 enum class Cmp : int { LT = -1, EQ = 0, GT = 1 };
 
+// Rather annoyingly, GCC's -Warray-bounds warning issues false positives for
+// this code. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61971
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+
 template <class Left, class Right>
 constexpr Cmp compare_(
     const Left& left,
@@ -161,18 +144,21 @@ constexpr bool equal_(
 }
 
 template <class Char, class Left, class Right>
-constexpr Char
-char_at_(const Left& left, const Right& right, std::size_t i) noexcept {
-  return i < fixedstring::size(left)
+constexpr Char char_at_(
+    const Left& left,
+    std::size_t left_count,
+    const Right& right,
+    std::size_t right_count,
+    std::size_t i) noexcept {
+  return i < left_count
       ? left[i]
-      : i < (fixedstring::size(left) + fixedstring::size(right))
-          ? right[i - fixedstring::size(left)]
-          : Char(0);
+      : i < (left_count + right_count) ? right[i - left_count] : Char(0);
 }
 
 template <class Char, class Left, class Right>
 constexpr Char char_at_(
     const Left& left,
+    std::size_t left_size,
     std::size_t left_pos,
     std::size_t left_count,
     const Right& right,
@@ -181,11 +167,10 @@ constexpr Char char_at_(
     std::size_t i) noexcept {
   return i < left_pos
       ? left[i]
-      : (i < right_count + left_pos
-             ? right[i - left_pos + right_pos]
-             : (i < fixedstring::size(left) - left_count + right_count
-                    ? left[i - right_count + left_count]
-                    : Char(0)));
+      : (i < right_count + left_pos ? right[i - left_pos + right_pos]
+                                    : (i < left_size - left_count + right_count
+                                           ? left[i - right_count + left_count]
+                                           : Char(0)));
 }
 
 template <class Left, class Right>
@@ -208,14 +193,14 @@ find_one_of_at_(Char ch, const Right& right, std::size_t pos) noexcept {
 template <class Left, class Right>
 constexpr std::size_t find_(
     const Left& left,
+    std::size_t left_size,
     const Right& right,
     std::size_t pos,
     std::size_t count) noexcept {
-  return find_at_(left, right, pos, count)
-      ? pos
-      : fixedstring::size(left) <= pos + count
+  return find_at_(left, right, pos, count) ? pos
+                                           : left_size <= pos + count
           ? FixedStringBase::npos
-          : find_(left, right, pos + 1u, count);
+          : find_(left, left_size, right, pos + 1u, count);
 }
 
 template <class Left, class Right>
@@ -233,27 +218,27 @@ constexpr std::size_t rfind_(
 template <class Left, class Right>
 constexpr std::size_t find_first_of_(
     const Left& left,
+    std::size_t left_size,
     const Right& right,
     std::size_t pos,
     std::size_t count) noexcept {
-  return find_one_of_at_(left[pos], right, count)
-      ? pos
-      : fixedstring::size(left) <= pos + 1u
+  return find_one_of_at_(left[pos], right, count) ? pos
+                                                  : left_size <= pos + 1u
           ? FixedStringBase::npos
-          : find_first_of_(left, right, pos + 1u, count);
+          : find_first_of_(left, left_size, right, pos + 1u, count);
 }
 
 template <class Left, class Right>
 constexpr std::size_t find_first_not_of_(
     const Left& left,
+    std::size_t left_size,
     const Right& right,
     std::size_t pos,
     std::size_t count) noexcept {
-  return !find_one_of_at_(left[pos], right, count)
-      ? pos
-      : fixedstring::size(left) <= pos + 1u
+  return !find_one_of_at_(left[pos], right, count) ? pos
+                                                   : left_size <= pos + 1u
           ? FixedStringBase::npos
-          : find_first_not_of_(left, right, pos + 1u, count);
+          : find_first_not_of_(left, left_size, right, pos + 1u, count);
 }
 
 template <class Left, class Right>
@@ -284,24 +269,44 @@ struct Helper {
   template <class Char, class Left, class Right, std::size_t... Is>
   static constexpr BasicFixedString<Char, sizeof...(Is)> concat_(
       const Left& left,
+      std::size_t left_count,
       const Right& right,
-      std::index_sequence<Is...> is) noexcept {
-    return {left, right, is};
+      std::size_t right_count,
+      folly::index_sequence<Is...> is) noexcept {
+    return {left, left_count, right, right_count, is};
   }
 
   template <class Char, class Left, class Right, std::size_t... Is>
   static constexpr BasicFixedString<Char, sizeof...(Is)> replace_(
       const Left& left,
+      std::size_t left_size,
       std::size_t left_pos,
       std::size_t left_count,
       const Right& right,
       std::size_t right_pos,
       std::size_t right_count,
-      std::index_sequence<Is...> is) noexcept {
-    return {left, left_pos, left_count, right, right_pos, right_count, is};
+      folly::index_sequence<Is...> is) noexcept {
+    return {left,
+            left_size,
+            left_pos,
+            left_count,
+            right,
+            right_pos,
+            right_count,
+            is};
+  }
+
+  template <class Char, std::size_t N>
+  static constexpr const Char (
+      &data_(const BasicFixedString<Char, N>& that) noexcept)[N + 1u] {
+    return that.data_;
   }
 };
 
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 4
+#pragma GCC diagnostic pop
+#endif
+
 template <class T>
 FOLLY_CPP14_CONSTEXPR void constexpr_swap(T& a, T& b) noexcept(
     noexcept(a = T(std::move(a)))) {
@@ -310,18 +315,6 @@ FOLLY_CPP14_CONSTEXPR void constexpr_swap(T& a, T& b) noexcept(
   b = std::move(tmp);
 }
 
-// FUTURE: use const_log2 to fold instantiations of BasicFixedString together.
-// All BasicFixedString<C, N> instantiations could share the implementation
-// of BasicFixedString<C, M>, where M is the next highest power of 2 after N.
-//
-// Also, because of alignment of the data_ and size_ members, N should never be
-// smaller than `(alignof(std::size_t)/sizeof(C))-1` (-1 because of the null
-// terminator). OR, create a specialization for BasicFixedString<C, 0u> that
-// does not have a size_ member, since it is unnecessary.
-constexpr std::size_t const_log2(std::size_t N, std::size_t log2 = 0u) {
-  return N / 2u == 0u ? log2 : const_log2(N / 2u, log2 + 1u);
-}
-
 // For constexpr reverse iteration over a BasicFixedString
 template <class T>
 struct ReverseIterator {
@@ -416,11 +409,7 @@ struct ReverseIterator {
 } // namespace fixedstring
 } // namespace detail
 
-// Defined in folly/Range.h
-template <class Iter>
-class Range;
-
-// Defined in folly/Hash.h
+// Defined in folly/hash/Hash.h
 std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len);
 
 /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** *
@@ -483,7 +472,7 @@ std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len);
  * of types `FixedString<4>`, `FixedString<8>`, etc. For example:
  * \par
  * \code
- * using namespace folly::StringLiterals;
+ * using namespace folly::string_literals;
  * constexpr auto hello = "hello"_fs8; // A FixedString<8> containing "hello"
  * \endcode
  * \par
@@ -495,7 +484,7 @@ std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len);
  * the right size. For example:
  * \par
  * \code
- * using namespace folly::StringLiterals;
+ * using namespace folly::string_literals;
  * // NOTE: Only works on compilers with GNU extensions enabled. Clang and
  * // gcc support this (-Wgnu-string-literal-operator-template):
  * constexpr auto hello = "hello"_fs; // A FixedString<5> containing "hello"
@@ -528,16 +517,25 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
   friend class BasicFixedString;
   friend struct detail::fixedstring::Helper;
 
+  // FUTURE: use constexpr_log2 to fold instantiations of BasicFixedString
+  // together. All BasicFixedString<C, N> instantiations could share the
+  // implementation of BasicFixedString<C, M>, where M is the next highest power
+  // of 2 after N.
+  //
+  // Also, because of alignment of the data_ and size_ members, N should never
+  // be smaller than `(alignof(std::size_t)/sizeof(C))-1` (-1 because of the
+  // null terminator). OR, create a specialization for BasicFixedString<C, 0u>
+  // that does not have a size_ member, since it is unnecessary.
   Char data_[N + 1u]; // +1 for the null terminator
   std::size_t size_; // Nbr of chars, not incl. null terminator. size_ <= N.
 
-  using Indices = std::make_index_sequence<N>;
+  using Indices = folly::make_index_sequence<N>;
 
   template <class That, std::size_t... Is>
   constexpr BasicFixedString(
       const That& that,
       std::size_t size,
-      std::index_sequence<Is...>,
+      folly::index_sequence<Is...>,
       std::size_t pos = 0,
       std::size_t count = npos) noexcept
       : data_{(Is < (size - pos) && Is < count ? that[Is + pos] : Char(0))...,
@@ -548,31 +546,40 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
   constexpr BasicFixedString(
       std::size_t count,
       Char ch,
-      std::index_sequence<Is...>) noexcept
+      folly::index_sequence<Is...>) noexcept
       : data_{((Is < count) ? ch : Char(0))..., Char(0)}, size_{count} {}
 
   // Concatenation constructor
   template <class Left, class Right, std::size_t... Is>
   constexpr BasicFixedString(
       const Left& left,
+      std::size_t left_size,
       const Right& right,
-      std::index_sequence<Is...>) noexcept
-      : data_{detail::fixedstring::char_at_<Char>(left, right, Is)..., Char(0)},
-        size_{detail::fixedstring::size(left) +
-              detail::fixedstring::size(right)} {}
+      std::size_t right_size,
+      folly::index_sequence<Is...>) noexcept
+      : data_{detail::fixedstring::char_at_<Char>(
+                  left,
+                  left_size,
+                  right,
+                  right_size,
+                  Is)...,
+              Char(0)},
+        size_{left_size + right_size} {}
 
   // Replace constructor
   template <class Left, class Right, std::size_t... Is>
   constexpr BasicFixedString(
       const Left& left,
+      std::size_t left_size,
       std::size_t left_pos,
       std::size_t left_count,
       const Right& right,
       std::size_t right_pos,
       std::size_t right_count,
-      std::index_sequence<Is...>) noexcept
+      folly::index_sequence<Is...>) noexcept
       : data_{detail::fixedstring::char_at_<Char>(
                   left,
+                  left_size,
                   left_pos,
                   left_count,
                   right,
@@ -580,7 +587,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
                   right_count,
                   Is)...,
               Char(0)},
-        size_{detail::fixedstring::size(left) - left_count + right_count} {}
+        size_{left_size - left_count + right_count} {}
 
  public:
   using size_type = std::size_t;
@@ -658,7 +665,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       : BasicFixedString{
             that.data_,
             that.size_,
-            std::make_index_sequence<(M < N ? M : N)>{},
+            folly::make_index_sequence<(M < N ? M : N)>{},
             pos,
             detail::fixedstring::checkOverflow(
                 detail::fixedstring::checkOverflowOrNpos(
@@ -679,7 +686,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
   constexpr /* implicit */ BasicFixedString(const Char (&that)[M]) noexcept
       : BasicFixedString{detail::fixedstring::checkNullTerminated(that),
                          M - 1u,
-                         std::make_index_sequence<M - 1u>{}} {}
+                         folly::make_index_sequence<M - 1u>{}} {}
 
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
    * Construct from a `const Char*` and count
@@ -783,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()}`
@@ -1258,8 +1242,9 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t count,
       Char ch) noexcept(false) {
     detail::fixedstring::checkOverflow(count, N - size_);
-    for (std::size_t i = 0u; i < count; ++i)
+    for (std::size_t i = 0u; i < count; ++i) {
       data_[size_ + i] = ch;
+    }
     size_ += count;
     data_[size_] = Char(0);
     return *this;
@@ -1306,8 +1291,9 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     detail::fixedstring::checkOverflow(pos, that.size_);
     count = detail::fixedstring::checkOverflowOrNpos(count, that.size_ - pos);
     detail::fixedstring::checkOverflow(count, N - size_);
-    for (std::size_t i = 0u; i < count; ++i)
-      data_[size_ + i] = that[pos + i];
+    for (std::size_t i = 0u; i < count; ++i) {
+      data_[size_ + i] = that.data_[pos + i];
+    }
     size_ += count;
     data_[size_] = Char(0);
     return *this;
@@ -1334,8 +1320,9 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const Char* that,
       std::size_t count) noexcept(false) {
     detail::fixedstring::checkOverflow(count, N - size_);
-    for (std::size_t i = 0u; i < count; ++i)
+    for (std::size_t i = 0u; i < count; ++i) {
       data_[size_ + i] = that[i];
+    }
     size_ += count;
     data_[size_] = Char(0);
     return *this;
@@ -1559,11 +1546,11 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t that_pos,
       std::size_t that_count) const noexcept(false) {
     return static_cast<int>(detail::fixedstring::compare_(
-        *this,
+        data_,
         detail::fixedstring::checkOverflow(this_pos, size_),
         detail::fixedstring::checkOverflow(this_count, size_ - this_pos) +
             this_pos,
-        that,
+        that.data_,
         detail::fixedstring::checkOverflow(that_pos, that.size_),
         detail::fixedstring::checkOverflow(that_count, that.size_ - that_pos) +
             that_pos));
@@ -1577,6 +1564,13 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return compare(0u, size_, that, folly::constexpr_strlen(that));
   }
 
+  /**
+   * \overload
+   */
+  constexpr int compare(Range<const Char*> that) const noexcept {
+    return compare(0u, size_, that.begin(), that.size());
+  }
+
   /**
    * Compare two strings for lexicographical ordering.
    * \note Equivalent to
@@ -1589,6 +1583,16 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return compare(this_pos, this_count, that, folly::constexpr_strlen(that));
   }
 
+  /**
+   * \overload
+   */
+  constexpr int compare(
+      std::size_t this_pos,
+      std::size_t this_count,
+      Range<const Char*> that) const noexcept(false) {
+    return compare(this_pos, this_count, that.begin(), that.size());
+  }
+
   /**
    * Compare two strings for lexicographical ordering.
    *
@@ -1610,7 +1614,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const Char* that,
       std::size_t that_count) const noexcept(false) {
     return static_cast<int>(detail::fixedstring::compare_(
-        *this,
+        data_,
         detail::fixedstring::checkOverflow(this_pos, size_),
         detail::fixedstring::checkOverflowOrNpos(this_count, size_ - this_pos) +
             this_pos,
@@ -1619,6 +1623,18 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
         that_count));
   }
 
+  constexpr int compare(
+      std::size_t this_pos,
+      std::size_t this_count,
+      Range<const Char*> that,
+      std::size_t that_count) const noexcept(false) {
+    return compare(
+        this_pos,
+        this_count,
+        that.begin(),
+        detail::fixedstring::checkOverflow(that_count, that.size()));
+  }
+
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
    * Return a substring from `pos` to the end of the string.
    * \note Equivalent to `BasicFixedString{*this, pos}`
@@ -1739,7 +1755,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const Char* that,
       std::size_t that_count) noexcept(false) {
     return *this = detail::fixedstring::Helper::replace_<Char>(
-               *this,
+               data_,
+               size_,
                detail::fixedstring::checkOverflow(this_pos, size_),
                detail::fixedstring::checkOverflowOrNpos(
                    this_count, size_ - this_pos),
@@ -1847,14 +1864,15 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t that_pos,
       std::size_t that_count) const noexcept(false) {
     return detail::fixedstring::Helper::replace_<Char>(
-        *this,
+        data_,
+        size_,
         detail::fixedstring::checkOverflow(this_pos, size_),
         detail::fixedstring::checkOverflowOrNpos(this_count, size_ - this_pos),
-        that,
+        that.data_,
         detail::fixedstring::checkOverflow(that_pos, that.size_),
         detail::fixedstring::checkOverflowOrNpos(
             that_count, that.size_ - that_pos),
-        std::make_index_sequence<N + M>{});
+        folly::make_index_sequence<N + M>{});
   }
 
   /**
@@ -1947,13 +1965,14 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t that_pos,
       std::size_t that_count) const noexcept(false) {
     return detail::fixedstring::Helper::replace_<Char>(
-        *this,
+        data_,
+        size_,
         detail::fixedstring::checkOverflow(this_pos, size_),
         detail::fixedstring::checkOverflowOrNpos(this_count, size_ - this_pos),
         detail::fixedstring::checkNullTerminated(that),
         detail::fixedstring::checkOverflow(that_pos, M - 1u),
         detail::fixedstring::checkOverflowOrNpos(that_count, M - 1u - that_pos),
-        std::make_index_sequence<N + M - 1u>{});
+        folly::make_index_sequence<N + M - 1u>{});
   }
 
   /**
@@ -2011,8 +2030,9 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
   copy(Char* dest, std::size_t count, std::size_t pos) const noexcept(false) {
     detail::fixedstring::checkOverflow(pos, size_);
     for (std::size_t i = 0u; i < count; ++i) {
-      if (i + pos == size_)
+      if (i + pos == size_) {
         return size_;
+      }
       dest[i] = data_[i + pos];
     }
     return count;
@@ -2067,7 +2087,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const BasicFixedString<Char, M>& that,
       std::size_t pos) const noexcept(false) {
     return that.size_ <= size_ - detail::fixedstring::checkOverflow(pos, size_)
-        ? detail::fixedstring::find_(*this, that, pos, that.size_)
+        ? detail::fixedstring::find_(data_, size_, that.data_, pos, that.size_)
         : npos;
   }
 
@@ -2106,7 +2126,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t pos,
       std::size_t count) const noexcept(false) {
     return count <= size_ - detail::fixedstring::checkOverflow(pos, size_)
-        ? detail::fixedstring::find_(*this, that, pos, count)
+        ? detail::fixedstring::find_(data_, size_, that, pos, count)
         : npos;
   }
 
@@ -2128,7 +2148,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     using A = const Char[1u];
     return 0u == size_ - detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_(*this, A{ch}, pos, 1u);
+        : detail::fixedstring::find_(data_, size_, A{ch}, pos, 1u);
   }
 
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
@@ -2153,8 +2173,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t pos) const noexcept(false) {
     return that.size_ <= size_
         ? detail::fixedstring::rfind_(
-              *this,
-              that,
+              data_,
+              that.data_,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_),
                   size_ - that.size_),
@@ -2198,7 +2218,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t count) const noexcept(false) {
     return count <= size_
         ? detail::fixedstring::rfind_(
-              *this,
+              data_,
               that,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_),
@@ -2226,7 +2246,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::rfind_(
-              *this,
+              data_,
               A{ch},
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2254,7 +2274,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t pos) const noexcept(false) {
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_of_(*this, that, pos, that.size_);
+        : detail::fixedstring::find_first_of_(
+              data_, size_, that.data_, pos, that.size_);
   }
 
   /**
@@ -2295,7 +2316,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t count) const noexcept(false) {
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_of_(*this, that, pos, count);
+        : detail::fixedstring::find_first_of_(data_, size_, that, pos, count);
   }
 
   /**
@@ -2316,7 +2337,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     using A = const Char[1u];
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_of_(*this, A{ch}, pos, 1u);
+        : detail::fixedstring::find_first_of_(data_, size_, A{ch}, pos, 1u);
   }
 
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
@@ -2339,7 +2360,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t pos) const noexcept(false) {
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_not_of_(*this, that, pos, that.size_);
+        : detail::fixedstring::find_first_not_of_(
+              data_, size_, that.data_, pos, that.size_);
   }
 
   /**
@@ -2380,7 +2402,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t count) const noexcept(false) {
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_not_of_(*this, that, pos, count);
+        : detail::fixedstring::find_first_not_of_(
+              data_, size_, that, pos, count);
   }
 
   /**
@@ -2400,7 +2423,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       noexcept(false) {
     using A = const Char[1u];
     return 1u <= size_ - detail::fixedstring::checkOverflow(pos, size_)
-        ? detail::fixedstring::find_first_not_of_(*this, A{ch}, pos, 1u)
+        ? detail::fixedstring::find_first_not_of_(data_, size_, A{ch}, pos, 1u)
         : npos;
   }
 
@@ -2426,8 +2449,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_of_(
-              *this,
-              that,
+              data_,
+              that.data_,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
               that.size_);
@@ -2472,7 +2495,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_of_(
-              *this,
+              data_,
               that,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2498,7 +2521,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_of_(
-              *this,
+              data_,
               A{ch},
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2527,8 +2550,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_not_of_(
-              *this,
-              that,
+              data_,
+              that.data_,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
               that.size_);
@@ -2573,7 +2596,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_not_of_(
-              *this,
+              data_,
               that,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2599,7 +2622,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_not_of_(
-              *this,
+              data_,
               A{ch},
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2613,7 +2636,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const Char* a,
       const BasicFixedString& b) noexcept {
     return detail::fixedstring::equal_(
-        a, folly::constexpr_strlen(a), b, b.size());
+        a, folly::constexpr_strlen(a), b.data_, b.size_);
   }
 
   /**
@@ -2625,6 +2648,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return b == a;
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator==(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return detail::fixedstring::equal_(a.begin(), a.size(), b.data_, b.size_);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator==(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return b == a;
+  }
+
   friend constexpr bool operator!=(
       const Char* a,
       const BasicFixedString& b) noexcept {
@@ -2640,12 +2681,30 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return !(b == a);
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator!=(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return !(a == b);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator!=(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return !(a == b);
+  }
+
   friend constexpr bool operator<(
       const Char* a,
       const BasicFixedString& b) noexcept {
     return detail::fixedstring::Cmp::LT ==
         detail::fixedstring::compare_(
-               a, 0u, folly::constexpr_strlen(a), b, 0u, b.size_);
+               a, 0u, folly::constexpr_strlen(a), b.data_, 0u, b.size_);
   }
 
   /**
@@ -2656,7 +2715,29 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const Char* b) noexcept {
     return detail::fixedstring::Cmp::LT ==
         detail::fixedstring::compare_(
-               a, 0u, a.size_, b, 0u, folly::constexpr_strlen(b));
+               a.data_, 0u, a.size_, b, 0u, folly::constexpr_strlen(b));
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator<(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return detail::fixedstring::Cmp::LT ==
+        detail::fixedstring::compare_(
+               a.begin(), 0u, a.size(), b.data_, 0u, b.size_);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator<(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return detail::fixedstring::Cmp::LT ==
+        detail::fixedstring::compare_(
+               a.data_, 0u, a.size_, b.begin(), 0u, b.size());
   }
 
   friend constexpr bool operator>(
@@ -2674,6 +2755,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return b < a;
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator>(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return b < a;
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator>(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return b < a;
+  }
+
   friend constexpr bool operator<=(
       const Char* a,
       const BasicFixedString& b) noexcept {
@@ -2689,6 +2788,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return !(b < a);
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator<=(
+      Range<const Char*> const& a,
+      const BasicFixedString& b) noexcept {
+    return !(b < a);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator<=(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return !(b < a);
+  }
+
   friend constexpr bool operator>=(
       const Char* a,
       const BasicFixedString& b) noexcept {
@@ -2704,6 +2821,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return !(a < b);
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator>=(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return !(a < b);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator>=(
+      const BasicFixedString& a,
+      Range<const Char*> const& b) noexcept {
+    return !(a < b);
+  }
+
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
    * Asymmetric concatenation
    */
@@ -2713,8 +2848,10 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const BasicFixedString& b) noexcept {
     return detail::fixedstring::Helper::concat_<Char>(
         detail::fixedstring::checkNullTerminated(a),
-        b,
-        std::make_index_sequence<N + M - 1u>{});
+        M - 1u,
+        b.data_,
+        b.size_,
+        folly::make_index_sequence<N + M - 1u>{});
   }
 
   /**
@@ -2725,9 +2862,11 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const BasicFixedString& a,
       const Char (&b)[M]) noexcept {
     return detail::fixedstring::Helper::concat_<Char>(
-        a,
+        a.data_,
+        a.size_,
         detail::fixedstring::checkNullTerminated(b),
-        std::make_index_sequence<N + M - 1u>{});
+        M - 1u,
+        folly::make_index_sequence<N + M - 1u>{});
   }
 
   /**
@@ -2738,7 +2877,11 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const BasicFixedString& b) noexcept {
     using A = const Char[2u];
     return detail::fixedstring::Helper::concat_<Char>(
-        A{a, Char(0)}, b, std::make_index_sequence<N + 1u>{});
+        A{a, Char(0)},
+        1u,
+        b.data_,
+        b.size_,
+        folly::make_index_sequence<N + 1u>{});
   }
 
   /**
@@ -2749,10 +2892,23 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       Char b) noexcept {
     using A = const Char[2u];
     return detail::fixedstring::Helper::concat_<Char>(
-        a, A{b, Char(0)}, std::make_index_sequence<N + 1u>{});
+        a.data_,
+        a.size_,
+        A{b, Char(0)},
+        1u,
+        folly::make_index_sequence<N + 1u>{});
   }
 };
 
+template <class C, std::size_t N>
+inline std::basic_ostream<C>& operator<<(
+    std::basic_ostream<C>& os,
+    const BasicFixedString<C, N>& string) {
+  using StreamSize = decltype(os.width());
+  os.write(string.begin(), static_cast<StreamSize>(string.size()));
+  return os;
+}
+
 /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  * Symmetric relational operators
  */
@@ -2760,7 +2916,11 @@ template <class Char, std::size_t A, std::size_t B>
 constexpr bool operator==(
     const BasicFixedString<Char, A>& a,
     const BasicFixedString<Char, B>& b) noexcept {
-  return detail::fixedstring::equal_(a, a.size(), b, b.size());
+  return detail::fixedstring::equal_(
+      detail::fixedstring::Helper::data_(a),
+      a.size(),
+      detail::fixedstring::Helper::data_(b),
+      b.size());
 }
 
 template <class Char, std::size_t A, std::size_t B>
@@ -2775,7 +2935,13 @@ constexpr bool operator<(
     const BasicFixedString<Char, A>& a,
     const BasicFixedString<Char, B>& b) noexcept {
   return detail::fixedstring::Cmp::LT ==
-      detail::fixedstring::compare_(a, 0u, a.size(), b, 0u, b.size());
+      detail::fixedstring::compare_(
+             detail::fixedstring::Helper::data_(a),
+             0u,
+             a.size(),
+             detail::fixedstring::Helper::data_(b),
+             0u,
+             b.size());
 }
 
 template <class Char, std::size_t A, std::size_t B>
@@ -2807,7 +2973,11 @@ constexpr BasicFixedString<Char, N + M> operator+(
     const BasicFixedString<Char, N>& a,
     const BasicFixedString<Char, M>& b) noexcept {
   return detail::fixedstring::Helper::concat_<Char>(
-      a, b, std::make_index_sequence<N + M>{});
+      detail::fixedstring::Helper::data_(a),
+      a.size(),
+      detail::fixedstring::Helper::data_(b),
+      b.size(),
+      folly::make_index_sequence<N + M>{});
 }
 
 /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
@@ -2834,13 +3004,13 @@ FOLLY_CPP14_CONSTEXPR void swap(
   a.swap(b);
 }
 
-inline namespace Literals {
-inline namespace StringLiterals {
+inline namespace literals {
+inline namespace string_literals {
 inline namespace {
 // "const std::size_t&" is so that folly::npos has the same address in every
 // translation unit. This is to avoid potential violations of the ODR.
 constexpr const std::size_t& npos = detail::fixedstring::FixedStringBase::npos;
-}
+} // namespace
 
 #if defined(__GNUC__)
 #pragma GCC diagnostic push
@@ -2854,7 +3024,7 @@ constexpr const std::size_t& npos = detail::fixedstring::FixedStringBase::npos;
  * \par Example:
  * \par
  * \code
- * using namespace folly::StringLiterals;
+ * using namespace folly::string_literals;
  * constexpr auto hello = "hello world!"_fs;
  * \endcode
  *
@@ -2893,8 +3063,8 @@ FOLLY_DEFINE_FIXED_STRING_UDL(64)
 FOLLY_DEFINE_FIXED_STRING_UDL(128)
 
 #undef FOLLY_DEFINE_FIXED_STRING_UDL
-}
-}
+} // namespace string_literals
+} // namespace literals
 
 // TODO:
 // // numeric conversions:
@@ -2929,4 +3099,4 @@ FOLLY_DEFINE_FIXED_STRING_UDL(128)
 // constexpr FixedString</*...*/> to_fixed_string_ll() noexcept
 // template <unsigned long long val>
 // constexpr FixedString</*...*/> to_fixed_string_ull() noexcept;
-}
+} // namespace folly