Skip to content

Commit

Permalink
Add startsWith, endsWith, removePrefix, removeSuffix to folly::Range
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tudor authored and jdelong committed Dec 20, 2013
1 parent 1ceb5ed commit c84a6ad
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 0 deletions.
42 changes: 42 additions & 0 deletions folly/Range.h
Expand Up @@ -455,6 +455,48 @@ class Range : private boost::totally_ordered<Range<Iter> > {
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_;
};
Expand Down
121 changes: 121 additions & 0 deletions folly/test/RangeTest.cpp
Expand Up @@ -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<uint32_t> a({1, 2, 3, 260, 5});
vector<uint32_t> b({2, 3, 4});
Expand Down Expand Up @@ -494,3 +614,4 @@ TYPED_TEST(NeedleFinderTest, NoSegFault) {
}
}
}

0 comments on commit c84a6ad

Please sign in to comment.