From 305453b52d03d83fc1973c04de928b2fd023051e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 22 Nov 2024 10:13:41 +0100 Subject: [PATCH] Buffer: Optimize scanning for the next crlf --- Common/Buffer.cpp | 10 +++++----- Common/Data/Collections/CharQueue.h | 21 +++++++++++++++++++++ Common/Net/NetBuffer.cpp | 4 ++++ unittest/UnitTest.cpp | 4 ++++ 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Common/Buffer.cpp b/Common/Buffer.cpp index eb56a490a6..e667020579 100644 --- a/Common/Buffer.cpp +++ b/Common/Buffer.cpp @@ -95,12 +95,12 @@ int Buffer::SkipLineCRLF() { // This relies on having buffered data! int Buffer::OffsetToAfterNextCRLF() { - for (int i = 0; i < (int)data_.size() - 1; i++) { - if (data_.peek(i) == '\r' && data_.peek(i + 1) == '\n') { - return i + 2; - } + int offset = data_.next_crlf_offset(); + if (offset >= 0) { + return offset + 2; + } else { + return -1; } - return -1; } void Buffer::Printf(const char *fmt, ...) { diff --git a/Common/Data/Collections/CharQueue.h b/Common/Data/Collections/CharQueue.h index 2be72d35b1..9d570b99e8 100644 --- a/Common/Data/Collections/CharQueue.h +++ b/Common/Data/Collections/CharQueue.h @@ -186,6 +186,27 @@ public: head_ = b; } + // If return value is negative, one wasn't found. + int next_crlf_offset() { + int offset = 0; + Block *b = head_; + do { + int remain = b->tail - b->head; + for (int i = 0; i < remain; i++) { + if (b->data[b->head + i] == '\r') { + // Use peek to avoid handling edge cases. + if (peek(offset + i + 1) == '\n') { + return offset + i; + } + } + } + offset += remain; + b = b->next; + } while (b); + // Ran out of data. + return -1; + } + private: struct Block { ~Block() { diff --git a/Common/Net/NetBuffer.cpp b/Common/Net/NetBuffer.cpp index eccc12a3fa..00886bd95d 100644 --- a/Common/Net/NetBuffer.cpp +++ b/Common/Net/NetBuffer.cpp @@ -15,6 +15,10 @@ #define MSG_NOSIGNAL 0x00 #endif +#if _MSC_VER +#pragma warning(disable:4267) +#endif + #include "Common/File/FileDescriptor.h" #include "Common/Log.h" #include "Common/Net/NetBuffer.h" diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index f800437934..3aed4a6991 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -1076,6 +1076,10 @@ bool TestCharQueue() { queue.pop_front_bulk(dest, 4); EXPECT_EQ_MEM(dest, "opqr", 4); EXPECT_TRUE(queue.empty()); + queue.push_back("asdf"); + EXPECT_EQ_INT(queue.next_crlf_offset(), -1); + queue.push_back("\r\r\n"); + EXPECT_EQ_INT(queue.next_crlf_offset(), 5); return true; }