Commit cb6fb8cd authored by Adam Simpkins's avatar Adam Simpkins Committed by Facebook GitHub Bot

allow explicit construction of ByteRange from std::string_view

Summary:
This enables explicit construction of ByteRange from both `std::string_view`
and `std::string`.

We have allowed implicit construction of `ByteRange` from `StringPiece` ever
since D518666.  `std::string_piece` is pretty equivalent to `StringPiece`, so
this helps bring the behavior for the two closer to parity.

Reviewed By: voznesenskym

Differential Revision: D32633008

fbshipit-source-id: fabba94b62bf471f1f8de5c35f844820993f0b0b
parent 3618ae79
...@@ -133,6 +133,20 @@ struct IsCharPointer<const char*> { ...@@ -133,6 +133,20 @@ struct IsCharPointer<const char*> {
using type = int; using type = int;
}; };
template <class T>
struct IsUnsignedCharPointer {};
template <>
struct IsUnsignedCharPointer<unsigned char*> {
using type = int;
};
template <>
struct IsUnsignedCharPointer<const unsigned char*> {
using const_type = int;
using type = int;
};
} // namespace detail } // namespace detail
/** /**
...@@ -298,6 +312,26 @@ class Range { ...@@ -298,6 +312,26 @@ class Range {
} }
} }
// Allow explicit construction of ByteRange from std::string_view or
// std::string. Given that we allow implicit construction of ByteRange from
// StringPiece, it makes sense to allow this explicit construction, and avoids
// callers having to say ByteRange{StringPiece{str}} when they want a
// ByteRange pointing to data in a std::string.
template <
class Container,
class T = Iter,
typename detail::IsUnsignedCharPointer<T>::const_type = 0,
class = typename std::enable_if<
std::is_same<typename Container::const_pointer, const char*>::value
>::type,
class = decltype(
Iter(std::declval<Container const&>().data()),
Iter(
std::declval<Container const&>().data() +
std::declval<Container const&>().size()))>
explicit Range(const Container& str)
: b_(reinterpret_cast<Iter>(str.data())), e_(b_ + str.size()) {}
// Allow implicit conversion from Range<const char*> (aka StringPiece) to // Allow implicit conversion from Range<const char*> (aka StringPiece) to
// Range<const unsigned char*> (aka ByteRange), as they're both frequently // Range<const unsigned char*> (aka ByteRange), as they're both frequently
// used to represent ranges of bytes. Allow explicit conversion in the other // used to represent ranges of bytes. Allow explicit conversion in the other
......
...@@ -303,6 +303,22 @@ TEST(StringPiece, ToByteRange) { ...@@ -303,6 +303,22 @@ TEST(StringPiece, ToByteRange) {
EXPECT_EQ(a.end(), c.end()); EXPECT_EQ(a.end(), c.end());
} }
TEST(ByteRange, FromString) {
std::string s("hello");
ByteRange b(s);
EXPECT_EQ(
static_cast<const void*>(s.data()), static_cast<const void*>(b.begin()));
EXPECT_EQ(s.size(), b.size());
#if FOLLY_HAS_STRING_VIEW
std::string_view sv(s);
ByteRange b2(sv);
EXPECT_EQ(
static_cast<const void*>(s.data()), static_cast<const void*>(b2.begin()));
EXPECT_EQ(s.size(), b2.size());
#endif
}
TEST(StringPiece, InvalidRange) { TEST(StringPiece, InvalidRange) {
StringPiece a("hello"); StringPiece a("hello");
EXPECT_EQ(a, a.subpiece(0, 10)); EXPECT_EQ(a, a.subpiece(0, 10));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment