From c84a6adfa129a50fc4d16df8a290a613ed548e82 Mon Sep 17 00:00:00 2001 From: Tudor Bosman Date: Thu, 19 Dec 2013 08:31:40 -0800 Subject: [PATCH] Add startsWith, endsWith, removePrefix, removeSuffix to folly::Range Summary: Yes, I know about boost::starts_with, but I think the convenience is worth it. Also, I've written then equivalent of removePrefix / removeSuffix way too many times. Test Plan: test added Reviewed By: andrei.alexandrescu@fb.com FB internal diff: D1106425 --- folly/Range.h | 42 ++++++++++++++ folly/test/RangeTest.cpp | 121 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) diff --git a/folly/Range.h b/folly/Range.h index 2041d29b..5466c6d6 100644 --- a/folly/Range.h +++ b/folly/Range.h @@ -455,6 +455,48 @@ public: std::swap(e_, rhs.e_); } + /** + * Does this Range start with another range? + */ + bool startsWith(const Range& other) const { + return size() >= other.size() && subpiece(0, other.size()) == other; + } + bool startsWith(value_type c) const { + return !empty() && front() == c; + } + + /** + * Does this Range end with another range? + */ + bool endsWith(const Range& other) const { + return size() >= other.size() && subpiece(size() - other.size()) == other; + } + bool endsWith(value_type c) const { + return !empty() && back() == c; + } + + /** + * Remove the given prefix and return true if the range starts with the given + * prefix; return false otherwise. + */ + bool removePrefix(const Range& prefix) { + return startsWith(prefix) && (b_ += prefix.size(), true); + } + bool removePrefix(value_type prefix) { + return startsWith(prefix) && (++b_, true); + } + + /** + * Remove the given suffix and return true if the range ends with the given + * suffix; return false otherwise. + */ + bool removeSuffix(const Range& suffix) { + return endsWith(suffix) && (e_ -= suffix.size(), true); + } + bool removeSuffix(value_type suffix) { + return endsWith(suffix) && (--e_, true); + } + private: Iter b_, e_; }; diff --git a/folly/test/RangeTest.cpp b/folly/test/RangeTest.cpp index 79698893..7859b6b8 100644 --- a/folly/test/RangeTest.cpp +++ b/folly/test/RangeTest.cpp @@ -302,6 +302,126 @@ TEST(StringPiece, Constexpr) { } #endif +TEST(StringPiece, Prefix) { + StringPiece a("hello"); + EXPECT_TRUE(a.startsWith("")); + EXPECT_TRUE(a.startsWith("h")); + EXPECT_TRUE(a.startsWith('h')); + EXPECT_TRUE(a.startsWith("hello")); + EXPECT_FALSE(a.startsWith("hellox")); + EXPECT_FALSE(a.startsWith('x')); + EXPECT_FALSE(a.startsWith("x")); + + { + auto b = a; + EXPECT_TRUE(b.removePrefix("")); + EXPECT_EQ("hello", b); + } + { + auto b = a; + EXPECT_TRUE(b.removePrefix("h")); + EXPECT_EQ("ello", b); + } + { + auto b = a; + EXPECT_TRUE(b.removePrefix('h')); + EXPECT_EQ("ello", b); + } + { + auto b = a; + EXPECT_TRUE(b.removePrefix("hello")); + EXPECT_EQ("", b); + } + { + auto b = a; + EXPECT_FALSE(b.removePrefix("hellox")); + EXPECT_EQ("hello", b); + } + { + auto b = a; + EXPECT_FALSE(b.removePrefix("x")); + EXPECT_EQ("hello", b); + } + { + auto b = a; + EXPECT_FALSE(b.removePrefix('x')); + EXPECT_EQ("hello", b); + } +} + +TEST(StringPiece, Suffix) { + StringPiece a("hello"); + EXPECT_TRUE(a.endsWith("")); + EXPECT_TRUE(a.endsWith("o")); + EXPECT_TRUE(a.endsWith('o')); + EXPECT_TRUE(a.endsWith("hello")); + EXPECT_FALSE(a.endsWith("xhello")); + EXPECT_FALSE(a.endsWith("x")); + EXPECT_FALSE(a.endsWith('x')); + + { + auto b = a; + EXPECT_TRUE(b.removeSuffix("")); + EXPECT_EQ("hello", b); + } + { + auto b = a; + EXPECT_TRUE(b.removeSuffix("o")); + EXPECT_EQ("hell", b); + } + { + auto b = a; + EXPECT_TRUE(b.removeSuffix('o')); + EXPECT_EQ("hell", b); + } + { + auto b = a; + EXPECT_TRUE(b.removeSuffix("hello")); + EXPECT_EQ("", b); + } + { + auto b = a; + EXPECT_FALSE(b.removeSuffix("xhello")); + EXPECT_EQ("hello", b); + } + { + auto b = a; + EXPECT_FALSE(b.removeSuffix("x")); + EXPECT_EQ("hello", b); + } + { + auto b = a; + EXPECT_FALSE(b.removeSuffix('x')); + EXPECT_EQ("hello", b); + } +} + +TEST(StringPiece, PrefixEmpty) { + StringPiece a; + EXPECT_TRUE(a.startsWith("")); + EXPECT_FALSE(a.startsWith("a")); + EXPECT_FALSE(a.startsWith('a')); + EXPECT_TRUE(a.removePrefix("")); + EXPECT_EQ("", a); + EXPECT_FALSE(a.removePrefix("a")); + EXPECT_EQ("", a); + EXPECT_FALSE(a.removePrefix('a')); + EXPECT_EQ("", a); +} + +TEST(StringPiece, SuffixEmpty) { + StringPiece a; + EXPECT_TRUE(a.endsWith("")); + EXPECT_FALSE(a.endsWith("a")); + EXPECT_FALSE(a.endsWith('a')); + EXPECT_TRUE(a.removeSuffix("")); + EXPECT_EQ("", a); + EXPECT_FALSE(a.removeSuffix("a")); + EXPECT_EQ("", a); + EXPECT_FALSE(a.removeSuffix('a')); + EXPECT_EQ("", a); +} + TEST(qfind, UInt32_Ranges) { vector a({1, 2, 3, 260, 5}); vector b({2, 3, 4}); @@ -494,3 +614,4 @@ TYPED_TEST(NeedleFinderTest, NoSegFault) { } } } + -- 2.34.1