/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <folly/Portability.h>
#include <folly/FBString.h>
+#include <folly/SpookyHashV2.h>
+
#include <algorithm>
#include <boost/operators.hpp>
+#include <climits>
+#include <cstddef>
#include <cstring>
#include <glog/logging.h>
#include <iosfwd>
-#include <limits.h>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <folly/CpuId.h>
#include <folly/Traits.h>
#include <folly/Likely.h>
+#include <folly/detail/RangeCommon.h>
+#include <folly/detail/RangeSse42.h>
// Ignore shadowing warnings within this file, so includers can use -Wshadow.
#pragma GCC diagnostic push
constexpr Range() : b_(), e_() {
}
+ constexpr Range(const Range&) = default;
+ constexpr Range(Range&&) = default;
+
public:
// Works for all iterators
constexpr Range(Iter start, Iter end) : b_(start), e_(end) {
constexpr Range(Iter start, size_t size)
: b_(start), e_(start + size) { }
-#if FOLLY_HAVE_CONSTEXPR_STRLEN
+# if !__clang__ || __CLANG_PREREQ(3, 7) // Clang 3.6 crashes on this line
+ /* implicit */ Range(std::nullptr_t) = delete;
+# endif
+
template <class T = Iter, typename detail::IsCharPointer<T>::type = 0>
constexpr /* implicit */ Range(Iter str)
- : b_(str), e_(str + strlen(str)) {}
-#else
- template <class T = Iter, typename detail::IsCharPointer<T>::type = 0>
- /* implicit */ Range(Iter str)
- : b_(str), e_(str + strlen(str)) {}
-#endif
+ : b_(str), e_(str + constexpr_strlen(str)) {}
+
template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
/* implicit */ Range(const std::string& str)
: b_(str.data()), e_(b_ + str.size()) {}
e_(other.end()) {
}
+ Range& operator=(const Range& rhs) & = default;
+ Range& operator=(Range&& rhs) & = default;
+
void clear() {
b_ = Iter();
e_ = Iter();
return e_ - b_;
}
size_type walk_size() const {
- assert(b_ <= e_);
return std::distance(b_, e_);
}
bool empty() const { return b_ == e_; }
return b_[i];
}
+ // Do NOT use this function, which was left behind for backwards
+ // compatibility. Use SpookyHashV2 instead -- it is faster, and produces
+ // a 64-bit hash, which means dramatically fewer collisions in large maps.
+ // (The above advice does not apply if you are targeting a 32-bit system.)
+ //
// Works only for Range<const char*> and Range<char*>
uint32_t hash() const {
// Taken from fbi/nstring.h:
typedef Range<const unsigned char*> ByteRange;
typedef Range<unsigned char*> MutableByteRange;
-std::ostream& operator<<(std::ostream& os, const StringPiece piece);
-std::ostream& operator<<(std::ostream& os, const MutableStringPiece piece);
+inline std::ostream& operator<<(std::ostream& os,
+ const StringPiece piece) {
+ os.write(piece.start(), piece.size());
+ return os;
+}
+
+inline std::ostream& operator<<(std::ostream& os,
+ const MutableStringPiece piece) {
+ os.write(piece.start(), piece.size());
+ return os;
+}
/**
* Templated comparison operators
return StringPiece(lhs) >= StringPiece(rhs);
}
+// Do NOT use this, use SpookyHashV2 instead, see commment on hash() above.
struct StringPieceHash {
std::size_t operator()(const StringPiece str) const {
return static_cast<std::size_t>(str.hash());
namespace detail {
-size_t qfind_first_byte_of_nosse(const StringPiece haystack,
- const StringPiece needles);
-
-#if FOLLY_HAVE_EMMINTRIN_H && __GNUC_PREREQ(4, 6)
-size_t qfind_first_byte_of_sse42(const StringPiece haystack,
- const StringPiece needles);
-
inline size_t qfind_first_byte_of(const StringPiece haystack,
const StringPiece needles) {
static auto const qfind_first_byte_of_fn =
return qfind_first_byte_of_fn(haystack, needles);
}
-#else
-inline size_t qfind_first_byte_of(const StringPiece haystack,
- const StringPiece needles) {
- return qfind_first_byte_of_nosse(haystack, needles);
-}
-#endif // FOLLY_HAVE_EMMINTRIN_H
-
} // namespace detail
template <class T, class Comp>
}
};
-extern const AsciiCaseSensitive asciiCaseSensitive;
-extern const AsciiCaseInsensitive asciiCaseInsensitive;
-
template <class T>
size_t qfind(const Range<T>& haystack,
const typename Range<T>::value_type& needle) {
template <class T>
size_t qfind_first_of(const Range<T>& haystack,
const Range<T>& needles) {
- return qfind_first_of(haystack, needles, asciiCaseSensitive);
+ return qfind_first_of(haystack, needles, AsciiCaseSensitive());
}
// specialization for StringPiece
return detail::qfind_first_byte_of(StringPiece(haystack),
StringPiece(needles));
}
+
+template<class Key, class Enable>
+struct hasher;
+
+template <class T>
+struct hasher<folly::Range<T*>,
+ typename std::enable_if<std::is_pod<T>::value, void>::type> {
+ size_t operator()(folly::Range<T*> r) const {
+ return hash::SpookyHashV2::Hash64(r.begin(), r.size() * sizeof(T), 0);
+ }
+};
+
} // !namespace folly
#pragma GCC diagnostic pop