#include <bits/c++config.h>
#include "folly/CpuId.h"
#include "folly/Traits.h"
+#include "folly/Likely.h"
namespace folly {
: b_(str.data()), e_(b_ + str.size()) {}
// Works only for Range<const char*>
Range(const std::string& str, std::string::size_type startFrom) {
- CHECK_LE(startFrom, str.size());
+ if (UNLIKELY(startFrom > str.size())) {
+ throw std::out_of_range("index out of range");
+ }
b_ = str.data() + startFrom;
e_ = str.data() + str.size();
}
Range(const std::string& str,
std::string::size_type startFrom,
std::string::size_type size) {
- CHECK_LE(startFrom + size, str.size());
+ if (UNLIKELY(startFrom > str.size())) {
+ throw std::out_of_range("index out of range");
+ }
b_ = str.data() + startFrom;
- e_ = b_ + size;
+ if (str.size() - startFrom < size) {
+ e_ = str.data() + str.size();
+ } else {
+ e_ = b_ + size;
+ }
}
Range(const Range<Iter>& str,
size_t startFrom,
size_t size) {
- CHECK_LE(startFrom + size, str.size());
+ if (UNLIKELY(startFrom > str.size())) {
+ throw std::out_of_range("index out of range");
+ }
b_ = str.b_ + startFrom;
- e_ = b_ + size;
+ if (str.size() - startFrom < size) {
+ e_ = str.e_;
+ } else {
+ e_ = b_ + size;
+ }
}
// Works only for Range<const char*>
/* implicit */ Range(const fbstring& str)
: b_(str.data()), e_(b_ + str.size()) { }
// Works only for Range<const char*>
Range(const fbstring& str, fbstring::size_type startFrom) {
- CHECK_LE(startFrom, str.size());
+ if (UNLIKELY(startFrom > str.size())) {
+ throw std::out_of_range("index out of range");
+ }
b_ = str.data() + startFrom;
e_ = str.data() + str.size();
}
// Works only for Range<const char*>
Range(const fbstring& str, fbstring::size_type startFrom,
fbstring::size_type size) {
- CHECK_LE(startFrom + size, str.size());
+ if (UNLIKELY(startFrom > str.size())) {
+ throw std::out_of_range("index out of range");
+ }
b_ = str.data() + startFrom;
- e_ = b_ + size;
+ if (str.size() - startFrom < size) {
+ e_ = str.data() + str.size();
+ } else {
+ e_ = b_ + size;
+ }
}
// Allow implicit conversion from Range<const char*> (aka StringPiece) to
}
void advance(size_type n) {
- CHECK_LE(n, size());
+ if (n > size()) {
+ throw std::out_of_range("index out of range");
+ }
b_ += n;
}
void subtract(size_type n) {
- CHECK_LE(n, size());
+ if (n > size()) {
+ throw std::out_of_range("index out of range");
+ }
e_ -= n;
}
Range subpiece(size_type first,
size_type length = std::string::npos) const {
- CHECK_LE(first, size());
+ if (first > size()) {
+ throw std::out_of_range("index out of range");
+ }
return Range(b_ + first,
std::min<std::string::size_type>(length, size() - first));
}
EXPECT_EQ(a.end(), c.end());
}
+TEST(StringPiece, InvalidRange) {
+ StringPiece a("hello");
+ EXPECT_EQ(a, a.subpiece(0, 10));
+ EXPECT_EQ(StringPiece("ello"), a.subpiece(1));
+ EXPECT_EQ(StringPiece("ello"), a.subpiece(1, std::string::npos));
+ EXPECT_EQ(StringPiece("ell"), a.subpiece(1, 3));
+ EXPECT_THROW(a.subpiece(6, 7), std::out_of_range);
+ EXPECT_THROW(a.subpiece(6), std::out_of_range);
+
+ std::string b("hello");
+ EXPECT_EQ(a, StringPiece(b, 0, 10));
+ EXPECT_EQ("ello", a.subpiece(1));
+ EXPECT_EQ("ello", a.subpiece(1, std::string::npos));
+ EXPECT_EQ("ell", a.subpiece(1, 3));
+ EXPECT_THROW(a.subpiece(6, 7), std::out_of_range);
+ EXPECT_THROW(a.subpiece(6), std::out_of_range);
+}
+
template <typename NeedleFinder>
class NeedleFinderTest : public ::testing::Test {
public: