Remove Buffer::Rows() and the Line wrapper
The row cache rebuilt a string for every line of the file after each edit and had one production caller left (filetype detection in the ImGui frontend, which needs only the first line). Removed with it: rows_, nrows_, the dirty flag set on every edit, ensure_rows_cache and a mutex guarding only that cache. Tests read lines with GetLineString, Nrows or, where they compare every line, a test-only LinesForTests(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
This commit is contained in:
+1
-1
@@ -94,7 +94,7 @@ public:
|
||||
[[nodiscard]] std::string
|
||||
Text() const
|
||||
{
|
||||
const auto &rows = Buf().Rows();
|
||||
const auto &rows = Buf().LinesForTests();
|
||||
std::string out;
|
||||
for (std::size_t i = 0; i < rows.size(); ++i) {
|
||||
out += static_cast<std::string>(rows[i]);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Benchmarks cover:
|
||||
* - PieceTable operations (insert, delete, GetLine, GetLineRange)
|
||||
* - Buffer operations (Nrows, GetLineString, GetLineView)
|
||||
* - Iteration patterns (comparing old Rows() vs new GetLineString/GetLineView)
|
||||
* - Iteration patterns (GetLineString vs GetLineView)
|
||||
* - Syntax highlighting on large files
|
||||
*
|
||||
* Each benchmark reports execution time in milliseconds.
|
||||
@@ -240,26 +240,6 @@ TEST (Benchmark_Buffer_GetLineView_Sequential)
|
||||
}
|
||||
|
||||
|
||||
TEST (Benchmark_Buffer_Rows_Materialization)
|
||||
{
|
||||
std::cout << "\n=== Buffer Rows() Materialization Benchmark ===\n";
|
||||
Buffer buf;
|
||||
std::string data = generate_large_file(10000, 80);
|
||||
buf.insert_text(0, 0, data);
|
||||
|
||||
std::size_t total_chars = 0;
|
||||
{
|
||||
BenchmarkTimer timer("Rows() materialization + iteration on 10K lines");
|
||||
const auto &rows = buf.Rows();
|
||||
for (std::size_t i = 0; i < rows.size(); ++i) {
|
||||
total_chars += rows[i].size();
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(total_chars > 0);
|
||||
}
|
||||
|
||||
|
||||
TEST (Benchmark_Buffer_Iteration_Comparison)
|
||||
{
|
||||
std::cout << "\n=== Buffer Iteration Pattern Comparison ===\n";
|
||||
@@ -267,16 +247,8 @@ TEST (Benchmark_Buffer_Iteration_Comparison)
|
||||
std::string data = generate_large_file(5000, 80);
|
||||
buf.insert_text(0, 0, data);
|
||||
|
||||
std::size_t sum1 = 0, sum2 = 0, sum3 = 0;
|
||||
|
||||
// Pattern 1: Old style with Rows()
|
||||
{
|
||||
BenchmarkTimer timer("Pattern 1: Rows() + iteration");
|
||||
const auto &rows = buf.Rows();
|
||||
for (std::size_t i = 0; i < rows.size(); ++i) {
|
||||
sum1 += rows[i].size();
|
||||
}
|
||||
}
|
||||
std::size_t sum2 = 0, sum3 = 0;
|
||||
std::size_t newlines = 0;
|
||||
|
||||
// Pattern 2: New style with GetLineString
|
||||
{
|
||||
@@ -290,14 +262,15 @@ TEST (Benchmark_Buffer_Iteration_Comparison)
|
||||
{
|
||||
BenchmarkTimer timer("Pattern 3: Nrows() + GetLineView (zero-copy)");
|
||||
for (std::size_t i = 0; i < buf.Nrows(); ++i) {
|
||||
sum3 += buf.GetLineView(i).size();
|
||||
const auto v = buf.GetLineView(i);
|
||||
sum3 += v.size();
|
||||
newlines += !v.empty() && v.back() == '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// sum1 and sum2 should match (both strip newlines)
|
||||
ASSERT_EQ(sum1, sum2);
|
||||
// sum3 includes newlines, so it will be larger
|
||||
EXPECT_TRUE(sum3 > sum2);
|
||||
// GetLineView includes the newlines GetLineString strips.
|
||||
ASSERT_EQ(sum3, sum2 + newlines);
|
||||
EXPECT_TRUE(newlines > 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ static void
|
||||
check_buffer_matches_model(const Buffer &b, const std::string &model)
|
||||
{
|
||||
auto expected_lines = split_lines_preserve_trailing_empty(model);
|
||||
const auto &rows = b.Rows();
|
||||
const auto &rows = b.LinesForTests();
|
||||
ASSERT_EQ(rows.size(), expected_lines.size());
|
||||
ASSERT_EQ(b.Nrows(), rows.size());
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ read_file_bytes(const std::string &path)
|
||||
static std::string
|
||||
buffer_bytes_via_views(const Buffer &b)
|
||||
{
|
||||
const auto &rows = b.Rows();
|
||||
const auto &rows = b.LinesForTests();
|
||||
std::string out;
|
||||
for (std::size_t i = 0; i < rows.size(); i++) {
|
||||
auto v = b.GetLineView(i);
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
* test_migration_coverage.cc - Edge case tests for Buffer::Line migration
|
||||
*
|
||||
* This file provides comprehensive test coverage for the migration from
|
||||
* Buffer::Rows() to direct PieceTable operations using Nrows(), GetLineString(),
|
||||
* the removed Buffer::Rows() to direct PieceTable operations using Nrows(), GetLineString(),
|
||||
* and GetLineView().
|
||||
*
|
||||
* Tests cover:
|
||||
* - Edge cases: empty buffers, single lines, very long lines
|
||||
* - Boundary conditions: first line, last line, out-of-bounds
|
||||
* - Consistency: GetLineString vs GetLineView vs Rows()
|
||||
* - Consistency: GetLineString vs GetLineView vs LinesForTests()
|
||||
* - Performance: large files, many small operations
|
||||
* - Correctness: special characters, newlines, unicode
|
||||
*/
|
||||
@@ -117,7 +117,7 @@ TEST (Migration_ManyEmptyLines)
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Consistency Tests: GetLineString vs GetLineView vs Rows()
|
||||
// Consistency Tests: GetLineString vs GetLineView vs LinesForTests()
|
||||
// ============================================================================
|
||||
|
||||
TEST (Migration_Consistency_AllMethods)
|
||||
@@ -125,13 +125,13 @@ TEST (Migration_Consistency_AllMethods)
|
||||
Buffer buf;
|
||||
buf.insert_text(0, 0, std::string("abc\n123\nxyz"));
|
||||
|
||||
const auto &rows = buf.Rows();
|
||||
const auto &rows = buf.LinesForTests();
|
||||
ASSERT_EQ(buf.Nrows(), rows.size());
|
||||
|
||||
for (std::size_t i = 0; i < buf.Nrows(); ++i) {
|
||||
std::string via_string = buf.GetLineString(i);
|
||||
std::string via_rows = std::string(rows[i]);
|
||||
// GetLineString and Rows() both strip newlines
|
||||
// GetLineString and LinesForTests() both strip newlines
|
||||
ASSERT_EQ(via_string, via_rows);
|
||||
// GetLineView includes the raw range (with newlines if present)
|
||||
// Just verify it's accessible
|
||||
@@ -148,18 +148,18 @@ TEST (Migration_Consistency_AfterEdits)
|
||||
// Edit: insert in middle
|
||||
buf.insert_text(1, 2, std::string("XX"));
|
||||
|
||||
const auto &rows = buf.Rows();
|
||||
const auto &rows = buf.LinesForTests();
|
||||
ASSERT_EQ(buf.Nrows(), rows.size());
|
||||
|
||||
for (std::size_t i = 0; i < buf.Nrows(); ++i) {
|
||||
// GetLineString and Rows() both strip newlines
|
||||
// GetLineString and LinesForTests() both strip newlines
|
||||
ASSERT_EQ(buf.GetLineString(i), std::string(rows[i]));
|
||||
}
|
||||
|
||||
// Edit: delete line
|
||||
buf.delete_row(1);
|
||||
|
||||
const auto &rows2 = buf.Rows();
|
||||
const auto &rows2 = buf.LinesForTests();
|
||||
ASSERT_EQ(buf.Nrows(), rows2.size());
|
||||
|
||||
for (std::size_t i = 0; i < buf.Nrows(); ++i) {
|
||||
@@ -332,7 +332,7 @@ TEST (Migration_Stress_ManySmallInserts)
|
||||
ASSERT_EQ(buf.GetLineString(1).size(), (std::size_t) 100);
|
||||
|
||||
// Verify consistency
|
||||
const auto &rows = buf.Rows();
|
||||
const auto &rows = buf.LinesForTests();
|
||||
ASSERT_EQ(buf.GetLineString(1), std::string(rows[1]));
|
||||
}
|
||||
|
||||
@@ -367,11 +367,11 @@ TEST (Migration_Stress_AlternatingInsertDelete)
|
||||
}
|
||||
|
||||
// Verify consistency after many operations
|
||||
const auto &rows = buf.Rows();
|
||||
const auto &rows = buf.LinesForTests();
|
||||
ASSERT_EQ(buf.Nrows(), rows.size());
|
||||
|
||||
for (std::size_t i = 0; i < buf.Nrows(); ++i) {
|
||||
// GetLineString and Rows() both strip newlines
|
||||
// GetLineString and LinesForTests() both strip newlines
|
||||
ASSERT_EQ(buf.GetLineString(i), std::string(rows[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ static std::string
|
||||
to_string_rows(const Buffer &buf)
|
||||
{
|
||||
std::string out;
|
||||
for (const auto &r: buf.Rows()) {
|
||||
for (const auto &r: buf.LinesForTests()) {
|
||||
out += static_cast<std::string>(r);
|
||||
out.push_back('\n');
|
||||
}
|
||||
@@ -45,7 +45,7 @@ TEST(ReflowParagraph_IndentedBullets_PreserveStructure)
|
||||
const int width = 80;
|
||||
ASSERT_TRUE(Execute(ed, std::string("reflow-paragraph"), std::string(), width));
|
||||
|
||||
const auto &rows = buf->Rows();
|
||||
const auto &rows = buf->LinesForTests();
|
||||
const std::string result = to_string_rows(*buf);
|
||||
|
||||
// We should have 3 lines (plus possibly a trailing empty line)
|
||||
|
||||
@@ -12,7 +12,7 @@ static std::string
|
||||
to_string_rows(const Buffer &buf)
|
||||
{
|
||||
std::string out;
|
||||
for (const auto &r: buf.Rows()) {
|
||||
for (const auto &r: buf.LinesForTests()) {
|
||||
out += static_cast<std::string>(r);
|
||||
out.push_back('\n');
|
||||
}
|
||||
@@ -46,7 +46,7 @@ TEST(ReflowParagraph_NumberedList_HangingIndent)
|
||||
const int width = 25;
|
||||
ASSERT_TRUE(Execute(ed, std::string("reflow-paragraph"), std::string(), width));
|
||||
|
||||
const auto &rows = buf->Rows();
|
||||
const auto &rows = buf->LinesForTests();
|
||||
ASSERT_TRUE(!rows.empty());
|
||||
const std::string dump = to_string_rows(*buf);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ static std::string
|
||||
to_string_rows(const Buffer &buf)
|
||||
{
|
||||
std::string out;
|
||||
for (const auto &r: buf.Rows()) {
|
||||
for (const auto &r: buf.LinesForTests()) {
|
||||
out += static_cast<std::string>(r);
|
||||
out.push_back('\n');
|
||||
}
|
||||
@@ -50,7 +50,7 @@ TEST (ReflowUndo)
|
||||
|
||||
const std::string reflowed_dump = to_string_rows(*buf);
|
||||
ASSERT_TRUE(reflowed_dump != original_dump);
|
||||
ASSERT_TRUE(buf->Rows().size() > 1);
|
||||
ASSERT_TRUE(buf->Nrows() > 1);
|
||||
|
||||
// Undo reflow
|
||||
ASSERT_TRUE(Execute(ed, "undo", "", 1));
|
||||
|
||||
@@ -127,7 +127,7 @@ TEST(SearchFlow_SearchReplace_EmptyWith_ReplacesAdjacentOverlappingMatches)
|
||||
ASSERT_TRUE(h.Exec(CommandId::Newline));
|
||||
|
||||
ASSERT_TRUE(!ed.PromptActive());
|
||||
ASSERT_EQ(std::string(b.Rows()[0]), std::string(""));
|
||||
ASSERT_EQ(b.GetLineString(0), std::string(""));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ read_file_bytes(const std::string &path)
|
||||
static std::string
|
||||
buffer_bytes_via_views(const Buffer &b)
|
||||
{
|
||||
const auto &rows = b.Rows();
|
||||
const auto &rows = b.LinesForTests();
|
||||
std::string out;
|
||||
for (std::size_t i = 0; i < rows.size(); i++) {
|
||||
auto v = b.GetLineView(i);
|
||||
|
||||
@@ -32,7 +32,7 @@ read_file_bytes(const std::string &path)
|
||||
static std::string
|
||||
buffer_bytes_via_views(const Buffer &b)
|
||||
{
|
||||
const auto &rows = b.Rows();
|
||||
const auto &rows = b.LinesForTests();
|
||||
std::string out;
|
||||
for (std::size_t i = 0; i < rows.size(); i++) {
|
||||
auto v = b.GetLineView(i);
|
||||
|
||||
+210
-210
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ static std::string
|
||||
dump_buf(const Buffer &buf)
|
||||
{
|
||||
std::string out;
|
||||
for (const auto &r: buf.Rows()) {
|
||||
for (const auto &r: buf.LinesForTests()) {
|
||||
out += static_cast<std::string>(r);
|
||||
out.push_back('\n');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user