From: Tom Jackson Date: Wed, 26 Jun 2013 23:53:58 +0000 (-0700) Subject: Range::rfind() X-Git-Tag: v0.22.0~938 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=1408e9d51430bb51b0a07a4bebb43325c2190f21;p=folly.git Range::rfind() Test Plan: Unit tests Reviewed By: andrei.alexandrescu@fb.com FB internal diff: D865951 --- diff --git a/folly/Range.h b/folly/Range.h index 188a534a..2c26db07 100644 --- a/folly/Range.h +++ b/folly/Range.h @@ -62,6 +62,15 @@ template size_t qfind(const Range & haystack, const typename Range::value_type& needle); +/** + * Finds the last occurrence of needle in haystack. The result is the + * offset reported to the beginning of haystack, or string::npos if + * needle wasn't found. + */ +template +size_t rfind(const Range & haystack, + const typename Range::value_type& needle); + /** * Finds the first occurrence of any element of needle in @@ -392,6 +401,10 @@ public: return qfind(*this, c); } + size_type rfind(value_type c) const { + return folly::rfind(*this, c); + } + size_type find(value_type c, size_t pos) const { if (pos > size()) return std::string::npos; size_type ret = qfind(subpiece(pos), c); @@ -673,6 +686,17 @@ size_t qfind(const Range& haystack, return pos == haystack.end() ? std::string::npos : pos - haystack.data(); } +template +size_t rfind(const Range& haystack, + const typename Range::value_type& needle) { + for (auto i = haystack.size(); i-- > 0; ) { + if (haystack[i] == needle) { + return i; + } + } + return std::string::npos; +} + // specialization for StringPiece template <> inline size_t qfind(const Range& haystack, const char& needle) { @@ -681,6 +705,13 @@ inline size_t qfind(const Range& haystack, const char& needle) { return pos == nullptr ? std::string::npos : pos - haystack.data(); } +template <> +inline size_t rfind(const Range& haystack, const char& needle) { + auto pos = static_cast( + ::memrchr(haystack.data(), needle, haystack.size())); + return pos == nullptr ? std::string::npos : pos - haystack.data(); +} + // specialization for ByteRange template <> inline size_t qfind(const Range& haystack, @@ -690,6 +721,14 @@ inline size_t qfind(const Range& haystack, return pos == nullptr ? std::string::npos : pos - haystack.data(); } +template <> +inline size_t rfind(const Range& haystack, + const unsigned char& needle) { + auto pos = static_cast( + ::memrchr(haystack.data(), needle, haystack.size())); + return pos == nullptr ? std::string::npos : pos - haystack.data(); +} + template size_t qfind_first_of(const Range& haystack, const Range& needles) { diff --git a/folly/test/RangeTest.cpp b/folly/test/RangeTest.cpp index b82ac85f..1c2b1f36 100644 --- a/folly/test/RangeTest.cpp +++ b/folly/test/RangeTest.cpp @@ -121,6 +121,16 @@ TEST(StringPiece, All) { EXPECT_EQ(s.find('\0'), std::string().find('\0')); EXPECT_EQ(s.find('\0'), StringPiece::npos); + // single char rfinds + EXPECT_EQ(s.rfind('b'), 6); + EXPECT_EQ(s.rfind('y'), StringPiece::npos); + EXPECT_EQ(s.str().rfind('y'), StringPiece::npos); + EXPECT_EQ(ByteRange(s).rfind('b'), 6); + EXPECT_EQ(ByteRange(s).rfind('y'), StringPiece::npos); + // null char + EXPECT_EQ(s.rfind('\0'), s.str().rfind('\0')); + EXPECT_EQ(s.rfind('\0'), StringPiece::npos); + // find_first_of s.reset(foobarbaz, strlen(foobarbaz)); EXPECT_EQ(s.find_first_of("bar"), 3);