diff --git a/src/content_stream.cpp b/src/content_stream.cpp index e7c6628..05d7f47 100644 --- a/src/content_stream.cpp +++ b/src/content_stream.cpp @@ -44,13 +44,17 @@ void ContentReader::close() { } std::string ContentReader::read() { + matched_idx = 0; + // Find Content-Length header prefix if (!scan("Content-Length:")) { return ""; } + // Skip whitespace and tabs while (matchAny(" \t")) { } + // Parse length size_t len = 0; while (true) { @@ -68,10 +72,16 @@ std::string ContentReader::read() { if (!match("\r\n\r\n")) { return ""; } + // Read message - if (!buffer(len)) { + if (!buffer(len + matched_idx)) { return ""; } + + for (size_t i = 0; i < matched_idx; i++) { + buf.pop_front(); + } + std::string out; out.reserve(len); for (size_t i = 0; i < len; i++) { @@ -97,18 +107,17 @@ bool ContentReader::scan(const char* str) { } bool ContentReader::match(const uint8_t* seq, size_t len) { - if (!buffer(len)) { + if (!buffer(len + matched_idx)) { return false; } - auto it = buf.begin(); + auto it = matched_idx; for (size_t i = 0; i < len; i++, it++) { - if (*it != seq[i]) { + if (buf[it] != seq[i]) { return false; } } - for (size_t i = 0; i < len; i++) { - buf.pop_front(); - } + + matched_idx += len; return true; } @@ -118,12 +127,12 @@ bool ContentReader::match(const char* str) { } char ContentReader::matchAny(const char* chars) { - if (!buffer(1)) { + if (!buffer(1 + matched_idx)) { return false; } - int c = buf.front(); + int c = buf[matched_idx]; if (auto p = strchr(chars, c)) { - buf.pop_front(); + matched_idx++; return *p; } return 0; @@ -177,4 +186,4 @@ bool ContentWriter::write(const std::string& msg) const { writer->write(msg.data(), msg.size()); } -} // namespace dap \ No newline at end of file +} // namespace dap diff --git a/src/content_stream.h b/src/content_stream.h index f01fef7..1fd0849 100644 --- a/src/content_stream.h +++ b/src/content_stream.h @@ -47,6 +47,7 @@ class ContentReader { std::shared_ptr reader; std::deque buf; + uint32_t matched_idx = 0; }; class ContentWriter { diff --git a/src/content_stream_test.cpp b/src/content_stream_test.cpp index 8742333..80939a8 100644 --- a/src/content_stream_test.cpp +++ b/src/content_stream_test.cpp @@ -81,3 +81,19 @@ TEST(ContentStreamTest, ShortRead) { ASSERT_EQ(cs.read(), "Content payload number three"); ASSERT_EQ(cs.read(), ""); } + +TEST(ContentStreamTest, PartialReadAndParse) { + auto sb = std::make_shared(); + dap::ContentReader cs(sb); + sb->write("Content"); + ASSERT_EQ(cs.read(), ""); + sb->write("-Length: "); + ASSERT_EQ(cs.read(), ""); + sb->write("26"); + ASSERT_EQ(cs.read(), ""); + sb->write("\r\n\r\n"); + ASSERT_EQ(cs.read(), ""); + sb->write("Content payload number one"); + ASSERT_EQ(cs.read(), "Content payload number one"); + ASSERT_EQ(cs.read(), ""); +}