From dff24ff9ab40244a55122e1f420b169950b2d13a Mon Sep 17 00:00:00 2001 From: Andrei Alexandrescu Date: Wed, 17 Dec 2014 13:16:07 -0800 Subject: [PATCH] Bring fbstring::operator+ to date with C++11 Summary: Some overloads, particularly with rvalue references, were missing. Also this fixes https://our.intern.facebook.com/intern/tasks/?t=5849579 Test Plan: unittests Reviewed By: simpkins@fb.com Subscribers: trunkagent, las, net-systems@, njormrod, folly-diffs@ FB internal diff: D1746319 Tasks: 5849579 Signature: t1:1746319:1418875228:febb965cf52710a5e76b7c1cce5aec601086ad90 --- folly/FBString.h | 81 +++++++++++++++++++++--- folly/test/FBStringTest.cpp | 119 ++++++++++++++++++++++++++++++++++-- 2 files changed, 187 insertions(+), 13 deletions(-) diff --git a/folly/FBString.h b/folly/FBString.h index 6190230c..0d177bca 100644 --- a/folly/FBString.h +++ b/folly/FBString.h @@ -1969,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); @@ -2021,7 +2028,7 @@ private: }; // non-member functions -// C++11 21.4.8.1/2 +// C++11 21.4.8.1/1 template inline basic_fbstring operator+(const basic_fbstring& lhs, @@ -2063,24 +2070,44 @@ basic_fbstring operator+(basic_fbstring&& lhs, return std::move(lhs.append(rhs)); } +// C++11 21.4.8.1/5 template inline basic_fbstring operator+( - const typename basic_fbstring::value_type* lhs, + const E* lhs, const basic_fbstring& rhs) { // basic_fbstring result; - const typename basic_fbstring::size_type len = - basic_fbstring::traits_type::length(lhs); + const auto len = basic_fbstring::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 inline basic_fbstring operator+( - typename basic_fbstring::value_type lhs, + const E* lhs, + basic_fbstring&& rhs) { + // + const auto len = basic_fbstring::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 result; + result.reserve(len + rhs.size()); + result.append(lhs, len).append(rhs); + return result; +} + +// C++11 21.4.8.1/7 +template +inline +basic_fbstring operator+( + E lhs, const basic_fbstring& rhs) { basic_fbstring result; @@ -2090,11 +2117,28 @@ basic_fbstring operator+( return result; } +// C++11 21.4.8.1/8 +template +inline +basic_fbstring operator+( + E lhs, + basic_fbstring&& 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 inline basic_fbstring operator+( const basic_fbstring& lhs, - const typename basic_fbstring::value_type* rhs) { + const E* rhs) { typedef typename basic_fbstring::size_type size_type; typedef typename basic_fbstring::traits_type traits_type; @@ -2106,11 +2150,22 @@ basic_fbstring operator+( return result; } +// C++11 21.4.8.1/10 +template +inline +basic_fbstring operator+( + basic_fbstring&& lhs, + const E* rhs) { + // + return std::move(lhs += rhs); +} + +// C++11 21.4.8.1/11 template inline basic_fbstring operator+( const basic_fbstring& lhs, - typename basic_fbstring::value_type rhs) { + E rhs) { basic_fbstring result; result.reserve(lhs.size() + 1); @@ -2119,6 +2174,16 @@ basic_fbstring operator+( return result; } +// C++11 21.4.8.1/12 +template +inline +basic_fbstring operator+( + basic_fbstring&& lhs, + E rhs) { + // + return std::move(lhs += rhs); +} + template inline bool operator==(const basic_fbstring& lhs, diff --git a/folly/test/FBStringTest.cpp b/folly/test/FBStringTest.cpp index 65df20ba..2e2a9617 100644 --- a/folly/test/FBStringTest.cpp +++ b/folly/test/FBStringTest.cpp @@ -603,6 +603,21 @@ template void clause11_21_4_7_2_a(String & test) { Num2String(test, test.find(str, random(0, test.size()))); } +template void clause11_21_4_7_2_a1(String & test) { + String str = String(test).substr( + random(0, test.size()), + random(0, test.size())); + Num2String(test, test.find(str, random(0, test.size()))); +} + +template void clause11_21_4_7_2_a2(String & test) { + auto const& cTest = test; + String str = cTest.substr( + random(0, test.size()), + random(0, test.size())); + Num2String(test, test.find(str, random(0, test.size()))); +} + template void clause11_21_4_7_2_b(String & test) { auto from = random(0, test.size()); auto length = random(0, test.size() - from); @@ -612,6 +627,25 @@ template void clause11_21_4_7_2_b(String & test) { random(0, str.size()))); } +template void clause11_21_4_7_2_b1(String & test) { + auto from = random(0, test.size()); + auto length = random(0, test.size() - from); + String str = String(test).substr(from, length); + Num2String(test, test.find(str.c_str(), + random(0, test.size()), + random(0, str.size()))); +} + +template void clause11_21_4_7_2_b2(String & test) { + auto from = random(0, test.size()); + auto length = random(0, test.size() - from); + const auto& cTest = test; + String str = cTest.substr(from, length); + Num2String(test, test.find(str.c_str(), + random(0, test.size()), + random(0, str.size()))); +} + template void clause11_21_4_7_2_c(String & test) { String str = test.substr( random(0, test.size()), @@ -620,6 +654,23 @@ template void clause11_21_4_7_2_c(String & test) { random(0, test.size()))); } +template void clause11_21_4_7_2_c1(String & test) { + String str = String(test).substr( + random(0, test.size()), + random(0, test.size())); + Num2String(test, test.find(str.c_str(), + random(0, test.size()))); +} + +template void clause11_21_4_7_2_c2(String & test) { + const auto& cTest = test; + String str = cTest.substr( + random(0, test.size()), + random(0, test.size())); + Num2String(test, test.find(str.c_str(), + random(0, test.size()))); +} + template void clause11_21_4_7_2_d(String & test) { Num2String(test, test.find( random('a', 'z'), @@ -838,6 +889,30 @@ template void clause11_21_4_8_1_a(String & test) { } template void clause11_21_4_8_1_b(String & test) { + String s1; + randomString(&s1, maxString); + String s2; + randomString(&s2, maxString); + test = move(s1) + s2; +} + +template void clause11_21_4_8_1_c(String & test) { + String s1; + randomString(&s1, maxString); + String s2; + randomString(&s2, maxString); + test = s1 + move(s2); +} + +template void clause11_21_4_8_1_d(String & test) { + String s1; + randomString(&s1, maxString); + String s2; + randomString(&s2, maxString); + test = move(s1) + move(s2); +} + +template void clause11_21_4_8_1_e(String & test) { String s; randomString(&s, maxString); String s1; @@ -845,13 +920,27 @@ template void clause11_21_4_8_1_b(String & test) { test = s.c_str() + s1; } -template void clause11_21_4_8_1_c(String & test) { +template void clause11_21_4_8_1_f(String & test) { + String s; + randomString(&s, maxString); + String s1; + randomString(&s1, maxString); + test = s.c_str() + move(s1); +} + +template void clause11_21_4_8_1_g(String & test) { String s; randomString(&s, maxString); test = typename String::value_type(random('a', 'z')) + s; } -template void clause11_21_4_8_1_d(String & test) { +template void clause11_21_4_8_1_h(String & test) { + String s; + randomString(&s, maxString); + test = typename String::value_type(random('a', 'z')) + move(s); +} + +template void clause11_21_4_8_1_i(String & test) { String s; randomString(&s, maxString); String s1; @@ -859,20 +948,28 @@ template void clause11_21_4_8_1_d(String & test) { test = s + s1.c_str(); } -template void clause11_21_4_8_1_e(String & test) { +template void clause11_21_4_8_1_j(String & test) { String s; randomString(&s, maxString); String s1; randomString(&s1, maxString); - test = s + s1.c_str(); + test = move(s) + s1.c_str(); } -template void clause11_21_4_8_1_f(String & test) { +template void clause11_21_4_8_1_k(String & test) { String s; randomString(&s, maxString); test = s + typename String::value_type(random('a', 'z')); } +template void clause11_21_4_8_1_l(String & test) { + String s; + randomString(&s, maxString); + String s1; + randomString(&s1, maxString); + test = move(s) + s1.c_str(); +} + // Numbering here is from C++11 template void clause11_21_4_8_9_a(String & test) { basic_stringstream stst(test.c_str()); @@ -969,8 +1066,14 @@ TEST(FBString, testAllClauses) { TEST_CLAUSE(21_4_7_1); TEST_CLAUSE(21_4_7_2_a); + TEST_CLAUSE(21_4_7_2_a1); + TEST_CLAUSE(21_4_7_2_a2); TEST_CLAUSE(21_4_7_2_b); + TEST_CLAUSE(21_4_7_2_b1); + TEST_CLAUSE(21_4_7_2_b2); TEST_CLAUSE(21_4_7_2_c); + TEST_CLAUSE(21_4_7_2_c1); + TEST_CLAUSE(21_4_7_2_c2); TEST_CLAUSE(21_4_7_2_d); TEST_CLAUSE(21_4_7_3_a); TEST_CLAUSE(21_4_7_3_b); @@ -1004,6 +1107,12 @@ TEST(FBString, testAllClauses) { TEST_CLAUSE(21_4_8_1_d); TEST_CLAUSE(21_4_8_1_e); TEST_CLAUSE(21_4_8_1_f); + TEST_CLAUSE(21_4_8_1_g); + TEST_CLAUSE(21_4_8_1_h); + TEST_CLAUSE(21_4_8_1_i); + TEST_CLAUSE(21_4_8_1_j); + TEST_CLAUSE(21_4_8_1_k); + TEST_CLAUSE(21_4_8_1_l); TEST_CLAUSE(21_4_8_9_a); } -- 2.34.1