Use std::equal<> as qfind default comparator
authorJosh Metzler <joshm@fb.com>
Tue, 30 Jul 2013 17:36:58 +0000 (10:36 -0700)
committerSara Golemon <sgolemon@fb.com>
Wed, 28 Aug 2013 21:30:11 +0000 (14:30 -0700)
Summary:
qfind(haystack, needle) is templated, but used a non-templated
default comparator that cast everything to char.  This works find for
8-bit types, but not for others such as the uint32_t Ranges we are
using.  Replace the default comparator with std::equal<> to use a
working comparator for whatever type is being searched.

Test Plan:
Compiles, unit tests (including a new one that fails with the
old code) pass.  Not sure how to test other users of this, or measure
performance impact. :(

Reviewed By: andrei.alexandrescu@fb.com

FB internal diff: D906311

folly/Range.h
folly/test/RangeTest.cpp

index a1cce77f4a995deea7e0dcfb1ceee93a7b8632ab..b0834b8b956e615c6a1a620dc9322b4a4972c6e7 100644 (file)
@@ -49,9 +49,10 @@ template <class T> class Range;
  * as Boyer-Moore. On the upside, it does not do any upfront
  * preprocessing and does not allocate memory.
  */
-template <class T>
+template <class T, class Comp = std::equal_to<typename Range<T>::value_type>>
 inline size_t qfind(const Range<T> & haystack,
-                    const Range<T> & needle);
+                    const Range<T> & needle,
+                    Comp eq = Comp());
 
 /**
  * Finds the first occurrence of needle in haystack. The result is the
@@ -566,10 +567,10 @@ struct StringPieceHash {
 /**
  * Finds substrings faster than brute force by borrowing from Boyer-Moore
  */
-template <class T, class Comp>
+template <class T, class Comp = std::equal_to<typename Range<T>::value_type>>
 size_t qfind(const Range<T>& haystack,
              const Range<T>& needle,
-             Comp eq) {
+             Comp eq = Comp()) {
   // Don't use std::search, use a Boyer-Moore-like trick by comparing
   // the last characters first
   auto const nsize = needle.size();
@@ -673,12 +674,6 @@ struct AsciiCaseInsensitive {
 extern const AsciiCaseSensitive asciiCaseSensitive;
 extern const AsciiCaseInsensitive asciiCaseInsensitive;
 
-template <class T>
-size_t qfind(const Range<T>& haystack,
-             const Range<T>& needle) {
-  return qfind(haystack, needle, asciiCaseSensitive);
-}
-
 template <class T>
 size_t qfind(const Range<T>& haystack,
              const typename Range<T>::value_type& needle) {
index 1c2b1f369cde9e074cf7da29518f493e20353b49..1ed678c85bb9689aebb800e1c2eef41baf0e3d13 100644 (file)
@@ -290,6 +290,19 @@ TEST(StringPiece, InvalidRange) {
   EXPECT_THROW(a.subpiece(6), std::out_of_range);
 }
 
+TEST(qfind, UInt32_Ranges) {
+  vector<uint32_t> a({1, 2, 3, 260, 5});
+  vector<uint32_t> b({2, 3, 4});
+
+  auto a_range = folly::Range<const uint32_t*>(&a[0], a.size());
+  auto b_range = folly::Range<const uint32_t*>(&b[0], b.size());
+
+  EXPECT_EQ(qfind(a_range, b_range), string::npos);
+
+  a[3] = 4;
+  EXPECT_EQ(qfind(a_range, b_range), 1);
+}
+
 template <typename NeedleFinder>
 class NeedleFinderTest : public ::testing::Test {
  public: