Commit c84a6adf authored by Tudor Bosman's avatar Tudor Bosman Committed by Jordan DeLong

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
parent 1ceb5edc
...@@ -455,6 +455,48 @@ public: ...@@ -455,6 +455,48 @@ public:
std::swap(e_, rhs.e_); 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: private:
Iter b_, e_; Iter b_, e_;
}; };
......
...@@ -302,6 +302,126 @@ TEST(StringPiece, Constexpr) { ...@@ -302,6 +302,126 @@ TEST(StringPiece, Constexpr) {
} }
#endif #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) { TEST(qfind, UInt32_Ranges) {
vector<uint32_t> a({1, 2, 3, 260, 5}); vector<uint32_t> a({1, 2, 3, 260, 5});
vector<uint32_t> b({2, 3, 4}); vector<uint32_t> b({2, 3, 4});
...@@ -494,3 +614,4 @@ TYPED_TEST(NeedleFinderTest, NoSegFault) { ...@@ -494,3 +614,4 @@ TYPED_TEST(NeedleFinderTest, NoSegFault) {
} }
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment