Skip to content

Commit

Permalink
Add trimAtMost functions
Browse files Browse the repository at this point in the history
Summary:
Add trimAtMost start and trimAtMost end.
These are useful functions to have if you
don't care about trimming an exact amount.

Reviewed By: yfeldblum

Differential Revision: D4658087

fbshipit-source-id: f7dd62c0f4837503e59cdec75fdad433be20306c
  • Loading branch information
siyengar authored and facebook-github-bot committed Apr 5, 2017
1 parent 2d2d3d3 commit 120cc11
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 4 deletions.
28 changes: 24 additions & 4 deletions folly/io/IOBufQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,31 +216,50 @@ unique_ptr<IOBuf> IOBufQueue::split(size_t n, bool throwOnUnderflow) {
}

void IOBufQueue::trimStart(size_t amount) {
auto trimmed = trimStartAtMost(amount);
if (trimmed != amount) {
throw std::underflow_error(
"Attempt to trim more bytes than are present in IOBufQueue");
}
}

size_t IOBufQueue::trimStartAtMost(size_t amount) {
auto original = amount;
while (amount > 0) {
if (!head_) {
throw std::underflow_error(
"Attempt to trim more bytes than are present in IOBufQueue");
break;
}
if (head_->length() > amount) {
head_->trimStart(amount);
chainLength_ -= amount;
amount = 0;
break;
}
amount -= head_->length();
chainLength_ -= head_->length();
head_ = head_->pop();
}
return original - amount;
}

void IOBufQueue::trimEnd(size_t amount) {
auto trimmed = trimEndAtMost(amount);
if (trimmed != amount) {
throw std::underflow_error(
"Attempt to trim more bytes than are present in IOBufQueue");
}
}

size_t IOBufQueue::trimEndAtMost(size_t amount) {
auto original = amount;
while (amount > 0) {
if (!head_) {
throw std::underflow_error(
"Attempt to trim more bytes than are present in IOBufQueue");
break;
}
if (head_->prev()->length() > amount) {
head_->prev()->trimEnd(amount);
chainLength_ -= amount;
amount = 0;
break;
}
amount -= head_->prev()->length();
Expand All @@ -252,6 +271,7 @@ void IOBufQueue::trimEnd(size_t amount) {
head_.reset();
}
}
return original - amount;
}

std::unique_ptr<folly::IOBuf> IOBufQueue::pop_front() {
Expand Down
12 changes: 12 additions & 0 deletions folly/io/IOBufQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,24 @@ class IOBufQueue {
*/
void trimStart(size_t amount);

/**
* Similar to trimStart, but will trim at most amount bytes and returns
* the number of bytes trimmed.
*/
size_t trimStartAtMost(size_t amount);

/**
* Similar to IOBuf::trimEnd, but works on the whole queue. Will
* pop off buffers that have been completely trimmed.
*/
void trimEnd(size_t amount);

/**
* Similar to trimEnd, but will trim at most amount bytes and returns
* the number of bytes trimmed.
*/
size_t trimEndAtMost(size_t amount);

/**
* Transfer ownership of the queue's entire IOBuf chain to the caller.
*/
Expand Down
70 changes: 70 additions & 0 deletions folly/io/test/IOBufQueueTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,76 @@ TEST(IOBufQueue, Trim) {
checkConsistency(queue);
}

TEST(IOBufQueue, TrimStartAtMost) {
IOBufQueue queue(clOptions);
unique_ptr<IOBuf> a = IOBuf::create(4);
a->append(4);
queue.append(std::move(a));
checkConsistency(queue);
a = IOBuf::create(6);
a->append(6);
queue.append(std::move(a));
checkConsistency(queue);
a = IOBuf::create(8);
a->append(8);
queue.append(std::move(a));
checkConsistency(queue);
a = IOBuf::create(10);
a->append(10);
queue.append(std::move(a));
checkConsistency(queue);

EXPECT_EQ(4, queue.front()->countChainElements());
EXPECT_EQ(28, queue.front()->computeChainDataLength());
EXPECT_EQ(4, queue.front()->length());

queue.trimStartAtMost(1);
checkConsistency(queue);
EXPECT_EQ(4, queue.front()->countChainElements());
EXPECT_EQ(27, queue.front()->computeChainDataLength());
EXPECT_EQ(3, queue.front()->length());

queue.trimStartAtMost(50);
checkConsistency(queue);
EXPECT_EQ(nullptr, queue.front());
EXPECT_EQ(0, queue.chainLength());
}

TEST(IOBufQueue, TrimEndAtMost) {
IOBufQueue queue(clOptions);
unique_ptr<IOBuf> a = IOBuf::create(4);
a->append(4);
queue.append(std::move(a));
checkConsistency(queue);
a = IOBuf::create(6);
a->append(6);
queue.append(std::move(a));
checkConsistency(queue);
a = IOBuf::create(8);
a->append(8);
queue.append(std::move(a));
checkConsistency(queue);
a = IOBuf::create(10);
a->append(10);
queue.append(std::move(a));
checkConsistency(queue);

EXPECT_EQ(4, queue.front()->countChainElements());
EXPECT_EQ(28, queue.front()->computeChainDataLength());
EXPECT_EQ(4, queue.front()->length());

queue.trimEndAtMost(1);
checkConsistency(queue);
EXPECT_EQ(4, queue.front()->countChainElements());
EXPECT_EQ(27, queue.front()->computeChainDataLength());
EXPECT_EQ(4, queue.front()->length());

queue.trimEndAtMost(50);
checkConsistency(queue);
EXPECT_EQ(nullptr, queue.front());
EXPECT_EQ(0, queue.chainLength());
}

TEST(IOBufQueue, TrimPack) {
IOBufQueue queue(clOptions);
unique_ptr<IOBuf> a = IOBuf::create(64);
Expand Down

0 comments on commit 120cc11

Please sign in to comment.