Load into the piece table's original store; save and copy without materializing

A loaded file's bytes are adopted as the piece table's original storage
instead of being appended to the add buffer: the first keystroke no
longer reallocates and copies the whole file (140 ms at 200 MB), and the
read buffer is not copied again.

Save writes the pieces in order instead of materializing the buffer (a
second full copy that then stayed resident). Buffer::Bytes() assembles a
copy from the pieces and replaces four hand-rolled copies (swap
snapshots, recovery comparison, Command.cc's per-row join, the tests'
accessor). A single-piece table (an unedited file) is viewed in place;
GetLineView serves a line from its piece when it lies within one, so it
no longer copies the whole buffer after every edit. Code that needed the
whole text contiguous says so with ContentView().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
This commit is contained in:
Claude
2026-09-24 12:19:59 -07:00
committed by Kyle Isom
parent 306a337516
commit 7dae9cc305
7 changed files with 156 additions and 129 deletions
+18 -3
View File
@@ -29,7 +29,7 @@
*
* 4. Content access:
* - Rows(): Materialized line cache (legacy, being phased out)
* - GetLineView(): Zero-copy line access via string_view (preferred)
* - GetLineView(): line access via string_view (zero-copy within a piece)
* - Direct PieceTable access for new editing operations
*/
#pragma once
@@ -311,10 +311,25 @@ public:
}
// Zero-copy view of a line. Points into the materialized backing store; becomes
// invalid after subsequent edits. Use immediately.
// View of a line's raw bytes, including its trailing '\n' if any. No copy
// when the line lies within one piece (an unedited stretch); a line that
// straddles an edit materializes the whole buffer, so per-row loops over
// an edited buffer should prefer GetLineString(). Invalid after the next
// edit; views of different lines need not be contiguous.
[[nodiscard]] std::string_view GetLineView(std::size_t row) const;
// The whole text as one contiguous view (materializes an edited buffer).
// Invalid after the next edit.
[[nodiscard]] std::string_view ContentView() const
{
return content_.ContentView();
}
// A copy of the whole text, assembled from the pieces (no materialized
// copy is kept).
[[nodiscard]] std::string Bytes() const;
[[nodiscard]] const std::string &Filename() const
{