pw_stream: Allow staging data to MemoryWriter end
Changes the memory writer to use std::memmove to allow data to be staged
to the unused portion of a MemoryWriter's buffer before it is written.
This is useful for operations that require direct access to a buffer to
build data before it is flushed to a MemoryWriter.
No-Docs-Update-Reason: Optimization that shouldn't be advertised
Change-Id: I3728e50e30031d7f87db43981827ef799fbce217
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/40244
Reviewed-by: David Rogers <davidrogers@google.com>
Commit-Queue: Armando Montanez <amontanez@google.com>
diff --git a/pw_stream/CMakeLists.txt b/pw_stream/CMakeLists.txt
index 55a9f96..c414144 100644
--- a/pw_stream/CMakeLists.txt
+++ b/pw_stream/CMakeLists.txt
@@ -37,3 +37,13 @@
pw_stream
pw_sys_io
)
+
+pw_add_test(pw_stream.memory_stream_test
+ SOURCES
+ memory_stream_test.cc
+ DEPS
+ pw_stream
+ GROUPS
+ modules
+ pw_stream
+)
diff --git a/pw_stream/memory_stream.cc b/pw_stream/memory_stream.cc
index 0a44810..2faa510 100644
--- a/pw_stream/memory_stream.cc
+++ b/pw_stream/memory_stream.cc
@@ -30,7 +30,7 @@
}
size_t bytes_to_write = data.size_bytes();
- std::memcpy(dest_.data() + bytes_written_, data.data(), bytes_to_write);
+ std::memmove(dest_.data() + bytes_written_, data.data(), bytes_to_write);
bytes_written_ += bytes_to_write;
return OkStatus();
diff --git a/pw_stream/memory_stream_test.cc b/pw_stream/memory_stream_test.cc
index b4a1395..4b47b2c 100644
--- a/pw_stream/memory_stream_test.cc
+++ b/pw_stream/memory_stream_test.cc
@@ -131,6 +131,21 @@
EXPECT_EQ(memory_writer.data()[1], std::byte{0x7E});
}
+TEST(MemoryWriter, OverlappingBuffer) {
+ constexpr std::string_view kTestString("This is staged into the same buffer");
+ // Write at a five-byte offset from the start of the destination buffer.
+ constexpr std::byte* kOverlappingStart = memory_buffer.data() + 5;
+ std::memcpy(kOverlappingStart, kTestString.data(), kTestString.size());
+ MemoryWriter memory_writer(memory_buffer);
+ EXPECT_TRUE(memory_writer.Write(kOverlappingStart, kTestString.size()).ok());
+ EXPECT_TRUE(memory_writer.Write(std::byte(0)).ok());
+ EXPECT_EQ(memory_writer.bytes_written(), kTestString.size() + 1);
+
+ EXPECT_STREQ(
+ reinterpret_cast<const char*>(memory_writer.WrittenData().data()),
+ kTestString.data());
+}
+
#define TESTING_CHECK_FAILURES_IS_SUPPORTED 0
#if TESTING_CHECK_FAILURES_IS_SUPPORTED