Copyright 2014->2015
[folly.git] / folly / FBString.h
index e80eba5914434885ffb28a82f37ca0d8baa339ff..e492e8f560f04eb317c340f6965528f298d13c50 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -36,9 +36,9 @@
 // either before or after this inclusion.
 #ifdef FOLLY_MALLOC_H_
 #undef FOLLY_MALLOC_H_
-#include "basic_fbstring_malloc.h"
+#include "basic_fbstring_malloc.h" // nolint
 #else
-#include "basic_fbstring_malloc.h"
+#include "basic_fbstring_malloc.h" // nolint
 #undef FOLLY_MALLOC_H_
 #endif
 
@@ -86,6 +86,7 @@
 
 // FBString cannot use throw when replacing std::string, though it may still
 // use std::__throw_*
+// nolint
 #define throw FOLLY_FBSTRING_MAY_NOT_USE_THROW
 
 #ifdef _LIBSTDCXX_FBSTRING
@@ -1968,11 +1969,18 @@ public:
     return find_last_not_of(&c, pos, 1);
   }
 
-  basic_fbstring substr(size_type pos = 0, size_type n = npos) const {
+  basic_fbstring substr(size_type pos = 0, size_type n = npos) const& {
     enforce(pos <= size(), std::__throw_out_of_range, "");
     return basic_fbstring(data() + pos, std::min(n, size() - pos));
   }
 
+  basic_fbstring substr(size_type pos = 0, size_type n = npos) && {
+    enforce(pos <= size(), std::__throw_out_of_range, "");
+    erase(0, pos);
+    if (n < size()) resize(n);
+    return std::move(*this);
+  }
+
   int compare(const basic_fbstring& str) const {
     // FIX due to Goncalo N M de Carvalho July 18, 2005
     return compare(0, size(), str);
@@ -2020,7 +2028,7 @@ private:
 };
 
 // non-member functions
-// C++11 21.4.8.1/2
+// C++11 21.4.8.1/1
 template <typename E, class T, class A, class S>
 inline
 basic_fbstring<E, T, A, S> operator+(const basic_fbstring<E, T, A, S>& lhs,
@@ -2062,24 +2070,44 @@ basic_fbstring<E, T, A, S> operator+(basic_fbstring<E, T, A, S>&& lhs,
   return std::move(lhs.append(rhs));
 }
 
+// C++11 21.4.8.1/5
 template <typename E, class T, class A, class S>
 inline
 basic_fbstring<E, T, A, S> operator+(
-  const typename basic_fbstring<E, T, A, S>::value_type* lhs,
+  const E* lhs,
   const basic_fbstring<E, T, A, S>& rhs) {
   //
   basic_fbstring<E, T, A, S> result;
-  const typename basic_fbstring<E, T, A, S>::size_type len =
-    basic_fbstring<E, T, A, S>::traits_type::length(lhs);
+  const auto len = basic_fbstring<E, T, A, S>::traits_type::length(lhs);
+  result.reserve(len + rhs.size());
+  result.append(lhs, len).append(rhs);
+  return result;
+}
+
+// C++11 21.4.8.1/6
+template <typename E, class T, class A, class S>
+inline
+basic_fbstring<E, T, A, S> operator+(
+  const E* lhs,
+  basic_fbstring<E, T, A, S>&& rhs) {
+  //
+  const auto len = basic_fbstring<E, T, A, S>::traits_type::length(lhs);
+  if (rhs.capacity() >= len + rhs.size()) {
+    // Good, at least we don't need to reallocate
+    return std::move(rhs.insert(rhs.begin(), lhs, lhs + len));
+  }
+  // Meh, no go. Do it by hand since we have len already.
+  basic_fbstring<E, T, A, S> result;
   result.reserve(len + rhs.size());
   result.append(lhs, len).append(rhs);
   return result;
 }
 
+// C++11 21.4.8.1/7
 template <typename E, class T, class A, class S>
 inline
 basic_fbstring<E, T, A, S> operator+(
-  typename basic_fbstring<E, T, A, S>::value_type lhs,
+  E lhs,
   const basic_fbstring<E, T, A, S>& rhs) {
 
   basic_fbstring<E, T, A, S> result;
@@ -2089,11 +2117,28 @@ basic_fbstring<E, T, A, S> operator+(
   return result;
 }
 
+// C++11 21.4.8.1/8
+template <typename E, class T, class A, class S>
+inline
+basic_fbstring<E, T, A, S> operator+(
+  E lhs,
+  basic_fbstring<E, T, A, S>&& rhs) {
+  //
+  if (rhs.capacity() > rhs.size()) {
+    // Good, at least we don't need to reallocate
+    return std::move(rhs.insert(rhs.begin(), lhs));
+  }
+  // Meh, no go. Forward to operator+(E, const&).
+  auto const& rhsC = rhs;
+  return lhs + rhsC;
+}
+
+// C++11 21.4.8.1/9
 template <typename E, class T, class A, class S>
 inline
 basic_fbstring<E, T, A, S> operator+(
   const basic_fbstring<E, T, A, S>& lhs,
-  const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
+  const E* rhs) {
 
   typedef typename basic_fbstring<E, T, A, S>::size_type size_type;
   typedef typename basic_fbstring<E, T, A, S>::traits_type traits_type;
@@ -2105,11 +2150,22 @@ basic_fbstring<E, T, A, S> operator+(
   return result;
 }
 
+// C++11 21.4.8.1/10
+template <typename E, class T, class A, class S>
+inline
+basic_fbstring<E, T, A, S> operator+(
+  basic_fbstring<E, T, A, S>&& lhs,
+  const E* rhs) {
+  //
+  return std::move(lhs += rhs);
+}
+
+// C++11 21.4.8.1/11
 template <typename E, class T, class A, class S>
 inline
 basic_fbstring<E, T, A, S> operator+(
   const basic_fbstring<E, T, A, S>& lhs,
-  typename basic_fbstring<E, T, A, S>::value_type rhs) {
+  E rhs) {
 
   basic_fbstring<E, T, A, S> result;
   result.reserve(lhs.size() + 1);
@@ -2118,6 +2174,16 @@ basic_fbstring<E, T, A, S> operator+(
   return result;
 }
 
+// C++11 21.4.8.1/12
+template <typename E, class T, class A, class S>
+inline
+basic_fbstring<E, T, A, S> operator+(
+  basic_fbstring<E, T, A, S>&& lhs,
+  E rhs) {
+  //
+  return std::move(lhs += rhs);
+}
+
 template <typename E, class T, class A, class S>
 inline
 bool operator==(const basic_fbstring<E, T, A, S>& lhs,
@@ -2252,20 +2318,20 @@ std::basic_istream<
   auto err = __ios_base::goodbit;
   if (sentry) {
     auto n = is.width();
-    if (n == 0) {
+    if (n <= 0) {
       n = str.max_size();
     }
     str.erase();
-    auto got = is.rdbuf()->sgetc();
-    for (; extracted != n && got != T::eof() && !isspace(got); ++extracted) {
-      // Whew. We get to store this guy
+    for (auto got = is.rdbuf()->sgetc(); extracted != size_t(n); ++extracted) {
+      if (got == T::eof()) {
+        err |= __ios_base::eofbit;
+        is.width(0);
+        break;
+      }
+      if (isspace(got)) break;
       str.push_back(got);
       got = is.rdbuf()->snextc();
     }
-    if (got == T::eof()) {
-      err |= __ios_base::eofbit;
-      is.width(0);
-    }
   }
   if (!extracted) {
     err |= __ios_base::failbit;