namespace {
-std::pair<const uint8_t*, size_t> queueFront(const IOBufQueue& queue) {
+ByteRange queueFront(const IOBufQueue& queue) {
auto* p = queue.front();
- if (!p) return std::make_pair(nullptr, 0);
- return io::Cursor(p).peek();
+ if (!p) {
+ return ByteRange{};
+ }
+ return io::Cursor(p).peekBytes();
}
// fd write
bool handleWrite(int fd, IOBufQueue& queue) {
for (;;) {
- auto p = queueFront(queue);
- if (p.second == 0) {
+ auto b = queueFront(queue);
+ if (b.empty()) {
return true; // EOF
}
- ssize_t n = writeNoInt(fd, p.first, p.second);
+ ssize_t n = writeNoInt(fd, b.data(), b.size());
if (n == -1 && errno == EAGAIN) {
return false;
}
dynamic obj = dynamic::object;
for (auto& name : names) {
- auto pair = curs.peek();
- if ((BserType)pair.first[0] == BserType::Skip) {
+ auto bytes = curs.peekBytes();
+ if ((BserType)bytes.at(0) == BserType::Skip) {
obj[name.getString()] = nullptr;
curs.skipAtMost(1);
continue;
throw std::runtime_error("invalid BSER magic header");
}
- auto enc = (BserType)curs.peek().first[0];
+ auto enc = (BserType)curs.peekBytes().at(0);
size_t int_size;
switch (enc) {
case BserType::Int8:
}
}
- auto p = cursor.peek();
+ auto sp = StringPiece{cursor.peekBytes()};
auto out = IOBuf::create(actualUncompressedLength);
- int n = LZ4_decompress_safe(reinterpret_cast<const char*>(p.first),
- reinterpret_cast<char*>(out->writableTail()),
- p.second,
- actualUncompressedLength);
+ int n = LZ4_decompress_safe(
+ sp.data(),
+ reinterpret_cast<char*>(out->writableTail()),
+ sp.size(),
+ actualUncompressedLength);
if (n < 0 || uint64_t(n) != actualUncompressedLength) {
throw std::runtime_error(to<std::string>(
}
const char* IOBufSnappySource::Peek(size_t* len) {
- auto p = cursor_.peek();
- *len = p.second;
- return reinterpret_cast<const char*>(p.first);
+ auto sp = StringPiece{cursor_.peekBytes()};
+ *len = sp.size();
+ return sp.data();
}
void IOBufSnappySource::Skip(size_t n) {
defaultBufferLength));
bool streamEnd = false;
- auto buf = cursor.peek();
- while (buf.second != 0) {
- stream.next_in = const_cast<uint8_t*>(buf.first);
- stream.avail_in = buf.second;
+ auto buf = cursor.peekBytes();
+ while (!buf.empty()) {
+ stream.next_in = const_cast<uint8_t*>(buf.data());
+ stream.avail_in = buf.size();
while (stream.avail_in != 0) {
if (streamEnd) {
streamEnd = doInflate(&stream, out.get(), defaultBufferLength);
}
- cursor.skip(buf.second);
- buf = cursor.peek();
+ cursor.skip(buf.size());
+ buf = cursor.peekBytes();
}
while (!streamEnd) {
/**
* Return the remaining space available in the current IOBuf.
*
- * May return 0 if the cursor is at the end of an IOBuf. Use peek() instead
- * if you want to avoid this. peek() will advance to the next non-empty
- * IOBuf (up to the end of the chain) if the cursor is currently pointing at
- * the end of a buffer.
+ * May return 0 if the cursor is at the end of an IOBuf. Use peekBytes()
+ * instead if you want to avoid this. peekBytes() will advance to the next
+ * non-empty IOBuf (up to the end of the chain) if the cursor is currently
+ * pointing at the end of a buffer.
*/
size_t length() const {
return crtBuf_->length() - offset_;
/**
* Return the available data in the current buffer.
* If you want to gather more data from the chain into a contiguous region
- * (for hopefully zero-copy access), use gather() before peek().
+ * (for hopefully zero-copy access), use gather() before peekBytes().
*/
- std::pair<const uint8_t*, size_t> peek() {
+ ByteRange peekBytes() {
// Ensure that we're pointing to valid data
size_t available = length();
while (UNLIKELY(available == 0 && tryAdvanceBuffer())) {
available = length();
}
- return std::make_pair(data(), available);
+ return ByteRange{data(), available};
+ }
+
+ /**
+ * Alternate version of peekBytes() that returns a std::pair
+ * instead of a ByteRange. (This method pre-dates ByteRange.)
+ *
+ * This function will eventually be deprecated.
+ */
+ std::pair<const uint8_t*, size_t> peek() {
+ auto bytes = peekBytes();
+ return std::make_pair(bytes.data(), bytes.size());
}
void clone(std::unique_ptr<folly::IOBuf>& buf, size_t len) {
size_t pushAtMost(Cursor cursor, size_t len) {
size_t written = 0;
for(;;) {
- auto currentBuffer = cursor.peek();
- const uint8_t* crtData = currentBuffer.first;
- size_t available = currentBuffer.second;
+ auto currentBuffer = cursor.peekBytes();
+ const uint8_t* crtData = currentBuffer.data();
+ size_t available = currentBuffer.size();
if (available == 0) {
// end of buffer chain
return written;
hasher.Init(0, 0);
io::Cursor cursor(&buf);
for (;;) {
- auto p = cursor.peek();
- if (p.second == 0) {
+ auto b = cursor.peekBytes();
+ if (b.empty()) {
break;
}
- hasher.Update(p.first, p.second);
- cursor.skip(p.second);
+ hasher.Update(b.data(), b.size());
+ cursor.skip(b.size());
}
uint64_t h1;
uint64_t h2;
io::Cursor ca(&a);
io::Cursor cb(&b);
for (;;) {
- auto pa = ca.peek();
- auto pb = cb.peek();
- if (pa.second == 0 && pb.second == 0) {
+ auto ba = ca.peekBytes();
+ auto bb = cb.peekBytes();
+ if (ba.empty() && bb.empty()) {
return true;
- } else if (pa.second == 0 || pb.second == 0) {
+ } else if (ba.empty() || bb.empty()) {
return false;
}
- size_t n = std::min(pa.second, pb.second);
+ size_t n = std::min(ba.size(), bb.size());
DCHECK_GT(n, 0);
- if (memcmp(pa.first, pb.first, n)) {
+ if (memcmp(ba.data(), bb.data(), n)) {
return false;
}
ca.skip(n);
while (iters--) {
Cursor c(iobuf_read_benchmark.get());
for (int i = 0; i < benchmark_size; i++) {
- c.peek();
+ c.peekBytes();
c.skip(1);
}
}
std::string toString(const IOBuf& buf) {
std::string str;
Cursor cursor(&buf);
- std::pair<const uint8_t*, size_t> p;
- while ((p = cursor.peek()).second) {
- str.append(reinterpret_cast<const char*>(p.first), p.second);
- cursor.skip(p.second);
+ ByteRange b;
+ while (!(b = cursor.peekBytes()).empty()) {
+ str.append(reinterpret_cast<const char*>(b.data()), b.size());
+ cursor.skip(b.size());
}
return str;
}
{
RWPrivateCursor cursor(iobuf1.get());
- auto p = cursor.peek();
- EXPECT_EQ("he", std::string(reinterpret_cast<const char*>(p.first),
- p.second));
- cursor.skip(p.second);
- p = cursor.peek();
- EXPECT_EQ("llo ", std::string(reinterpret_cast<const char*>(p.first),
- p.second));
- cursor.skip(p.second);
- p = cursor.peek();
- EXPECT_EQ("world", std::string(reinterpret_cast<const char*>(p.first),
- p.second));
- cursor.skip(p.second);
+ auto b = cursor.peekBytes();
+ EXPECT_EQ("he", StringPiece(b));
+ cursor.skip(b.size());
+ b = cursor.peekBytes();
+ EXPECT_EQ("llo ", StringPiece(b));
+ cursor.skip(b.size());
+ b = cursor.peekBytes();
+ EXPECT_EQ("world", StringPiece(b));
+ cursor.skip(b.size());
EXPECT_EQ(3, iobuf1->countChainElements());
EXPECT_EQ(11, iobuf1->computeChainDataLength());
}
{
RWPrivateCursor cursor(iobuf1.get());
cursor.gather(11);
- auto p = cursor.peek();
- EXPECT_EQ("hello world", std::string(reinterpret_cast<const
- char*>(p.first), p.second));
+ auto b = cursor.peekBytes();
+ EXPECT_EQ("hello world", StringPiece(b));
EXPECT_EQ(1, iobuf1->countChainElements());
EXPECT_EQ(11, iobuf1->computeChainDataLength());
}
EXPECT_EQ(7, iobuf1->countChainElements());
EXPECT_EQ(14, iobuf1->computeChainDataLength());
// Check that nextBuf got set correctly to the buffer with 1 byte left
- EXPECT_EQ(1, cursor.peek().second);
+ EXPECT_EQ(1, cursor.peekBytes().size());
cursor.read<uint8_t>();
}