From 7307387f6496dca6a939fcbee1937ffd06788c95 Mon Sep 17 00:00:00 2001 From: Syed Daanish Date: Fri, 19 Dec 2025 20:46:52 +0000 Subject: [PATCH] Optimize line iterator --- README.md | 2 - include/knot.h | 2 + src/editor.cc | 14 ++--- src/editor_ctrl.cc | 128 +++++++++++++++++++++++------------------- src/editor_events.cc | 20 +++---- src/editor_indents.cc | 4 +- src/editor_scroll.cc | 38 +++++++------ src/knot.cc | 58 +++++++++---------- 8 files changed, 136 insertions(+), 130 deletions(-) diff --git a/README.md b/README.md index 278f8ff..3a27f69 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ A TUI IDE. # TODO -- [ ] Overwrite empty space between line number and line. (in the renderer) -- [ ] Make iterator for next/prev line reuse same allocation buffer (so only free once with iterator). - [ ] Add tab/untab with [,<] and [.>] - [ ] Add something that works like `p` but doesnt move cursor. - [ ] Fix the fact that hooks arent updated when a line is deleted/added. diff --git a/include/knot.h b/include/knot.h index 13f7103..9d4845e 100644 --- a/include/knot.h +++ b/include/knot.h @@ -27,6 +27,8 @@ typedef struct LineIterator { uint8_t top; uint32_t offset; Knot *stack[64]; + char *buffer; + size_t capacity; } LineIterator; typedef struct LeafIterator { diff --git a/src/editor.cc b/src/editor.cc index 3fbae81..72270a6 100644 --- a/src/editor.cc +++ b/src/editor.cc @@ -92,12 +92,12 @@ void render_editor(Editor *editor) { case LINE: LineIterator *it = begin_l_iter(editor->root, editor->selection.row); char *line = next_line(it, &line_len); - free(it); if (!line) return; if (line_len > 0 && line[line_len - 1] == '\n') line_len--; - free(line); + free(it->buffer); + free(it); end = {editor->selection.row, line_len}; break; } @@ -122,7 +122,7 @@ void render_editor(Editor *editor) { update(editor->position.row + rendered_rows, editor->position.col, "", 0xAAAAAA, 0, 0); char buf[16]; - int len = snprintf(buf, sizeof(buf), "%*u", numlen - 3, fold->start + 1); + int len = snprintf(buf, sizeof(buf), "%*u ", numlen - 3, fold->start + 1); uint32_t num_color = editor->cursor.row == fold->start ? 0xFFFFFF : 0x555555; for (int i = 0; i < len; i++) @@ -148,7 +148,6 @@ void render_editor(Editor *editor) { if (line_len > 0 && line[line_len - 1] == '\n') global_byte_offset--; global_byte_offset++; - free(line); line_index++; } continue; @@ -179,7 +178,8 @@ void render_editor(Editor *editor) { update(editor->position.row + rendered_rows, editor->position.col, hook, 0xAAAAAA, 0, 0); char buf[16]; - int len = snprintf(buf, sizeof(buf), "%*u", numlen - 3, line_index + 1); + int len = + snprintf(buf, sizeof(buf), "%*u ", numlen - 3, line_index + 1); uint32_t num_color = editor->cursor.row == line_index ? 0xFFFFFF : 0x555555; for (int i = 0; i < len; i++) @@ -270,7 +270,7 @@ void render_editor(Editor *editor) { update(editor->position.row + rendered_rows, editor->position.col, hook, 0xAAAAAA, 0, 0); char buf[16]; - int len = snprintf(buf, sizeof(buf), "%*u", numlen - 3, line_index + 1); + int len = snprintf(buf, sizeof(buf), "%*u ", numlen - 3, line_index + 1); uint32_t num_color = editor->cursor.row == line_index ? 0xFFFFFF : 0x555555; for (int i = 0; i < len; i++) @@ -298,7 +298,6 @@ void render_editor(Editor *editor) { } global_byte_offset += line_len + 1; line_index++; - free(line); } if (cursor.row != UINT32_MAX && cursor.col != UINT32_MAX) { int type = 0; @@ -322,5 +321,6 @@ void render_editor(Editor *editor) { " ", 0xFFFFFF, 0, 0); rendered_rows++; } + free(it->buffer); free(it); } diff --git a/src/editor_ctrl.cc b/src/editor_ctrl.cc index db9391b..3731ee7 100644 --- a/src/editor_ctrl.cc +++ b/src/editor_ctrl.cc @@ -48,7 +48,6 @@ void word_boundaries_exclusive(Editor *editor, Coord coord, uint32_t *prev_col, return; uint32_t line_len; char *line = next_line(it, &line_len); - free(it); if (!line) return; if (line_len && line[line_len - 1] == '\n') @@ -62,7 +61,8 @@ void word_boundaries_exclusive(Editor *editor, Coord coord, uint32_t *prev_col, *prev_col = left; if (next_col) *next_col = right; - free(line); + free(it->buffer); + free(it); } uint32_t word_jump_right(const char *line, size_t len, uint32_t pos) { @@ -99,7 +99,6 @@ void word_boundaries(Editor *editor, Coord coord, uint32_t *prev_col, return; uint32_t line_len; char *line = next_line(it, &line_len); - free(it); if (!line) return; if (line_len && line[line_len - 1] == '\n') @@ -117,7 +116,8 @@ void word_boundaries(Editor *editor, Coord coord, uint32_t *prev_col, *prev_clusters = count_clusters(line, line_len, left, col); if (next_clusters) *next_clusters = count_clusters(line, line_len, col, right); - free(line); + free(it->buffer); + free(it); } Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) { @@ -140,6 +140,7 @@ Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) { const Fold *fold = fold_for_line(editor->folds, line_index); if (fold) { if (visual_row == target_visual_row) { + free(it->buffer); free(it); if (is_gutter_click) { remove_fold(editor, fold->start); @@ -152,7 +153,6 @@ Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) { char *l = next_line(it, nullptr); if (!l) break; - free(l); line_index++; } continue; @@ -177,7 +177,7 @@ Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) { if (col + w > render_width) break; if (visual_row == target_visual_row && x < col + w) { - free(line); + free(it->buffer); free(it); return {line_index, offset + advance}; } @@ -187,7 +187,7 @@ Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) { col += w; } if (visual_row == target_visual_row) { - free(line); + free(it->buffer); free(it); return {line_index, last_good_offset}; } @@ -200,9 +200,9 @@ Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) { if (line_len == 0) break; } - free(line); line_index++; } + free(it->buffer); free(it); return editor->scroll; } @@ -215,16 +215,18 @@ Coord move_right_pure(Editor *editor, Coord cursor, uint32_t number) { uint32_t col = result.col; uint32_t line_len = 0; LineIterator *it = begin_l_iter(editor->root, row); - char *line = next_line(it, &line_len); - free(it); - if (!line) + if (!it) return result; + char *line = next_line(it, &line_len); + if (!line) { + free(it->buffer); + free(it); + return result; + } if (line_len > 0 && line[line_len - 1] == '\n') --line_len; while (number > 0) { if (col >= line_len) { - free(line); - line = nullptr; uint32_t next_row = row + 1; if (next_row >= editor->root->line_count) { col = line_len; @@ -232,9 +234,7 @@ Coord move_right_pure(Editor *editor, Coord cursor, uint32_t number) { } row = next_row; col = 0; - it = begin_l_iter(editor->root, row); line = next_line(it, &line_len); - free(it); if (!line) break; if (line_len > 0 && line[line_len - 1] == '\n') @@ -248,8 +248,8 @@ Coord move_right_pure(Editor *editor, Coord cursor, uint32_t number) { } number--; } - if (line) - free(line); + free(it->buffer); + free(it); result.row = row; result.col = col; return result; @@ -265,6 +265,7 @@ Coord move_left_pure(Editor *editor, Coord cursor, uint32_t number) { LineIterator *it = begin_l_iter(editor->root, row); char *line = next_line(it, &len); if (!line) { + free(it->buffer); free(it); return result; } @@ -276,10 +277,9 @@ Coord move_left_pure(Editor *editor, Coord cursor, uint32_t number) { if (row == 0) break; if (iterator_ahead) { - free(prev_line(it, nullptr)); + prev_line(it, nullptr); iterator_ahead = false; } - free(line); line = nullptr; row--; line = prev_line(it, &len); @@ -301,8 +301,7 @@ Coord move_left_pure(Editor *editor, Coord cursor, uint32_t number) { } number--; } - if (line) - free(line); + free(it->buffer); free(it); result.row = row; result.col = col; @@ -317,41 +316,58 @@ Coord move_right(Editor *editor, Coord cursor, uint32_t number) { uint32_t col = result.col; uint32_t line_len = 0; LineIterator *it = begin_l_iter(editor->root, row); - char *line = next_line(it, &line_len); - free(it); - if (!line) + if (!it) return result; + uint32_t target_row = next_unfolded_row(editor, row); + while (row < target_row) { + if (!next_line(it, &line_len)) { + free(it->buffer); + free(it); + return result; + } + ++row; + } + char *line = next_line(it, &line_len); + if (!line) { + free(it->buffer); + free(it); + return result; + } if (line_len > 0 && line[line_len - 1] == '\n') --line_len; while (number > 0) { if (col >= line_len) { - free(line); - line = nullptr; uint32_t next_row = next_unfolded_row(editor, row + 1); if (next_row >= editor->root->line_count) { col = line_len; break; } - row = next_row; + while (row < next_row) { + line = next_line(it, &line_len); + if (!line) { + free(it->buffer); + free(it); + result.row = row; + result.col = col; + return result; + } + ++row; + } col = 0; - it = begin_l_iter(editor->root, row); - line = next_line(it, &line_len); - free(it); - if (!line) - break; if (line_len > 0 && line[line_len - 1] == '\n') --line_len; + continue; } else { uint32_t inc = grapheme_next_character_break_utf8(line + col, line_len - col); if (inc == 0) break; col += inc; + --number; } - number--; } - if (line) - free(line); + free(it->buffer); + free(it); result.row = row; result.col = col; return result; @@ -367,6 +383,7 @@ Coord move_left(Editor *editor, Coord cursor, uint32_t number) { LineIterator *it = begin_l_iter(editor->root, row); char *line = next_line(it, &len); if (!line) { + free(it->buffer); free(it); return result; } @@ -378,10 +395,9 @@ Coord move_left(Editor *editor, Coord cursor, uint32_t number) { if (row == 0) break; if (iterator_ahead) { - free(prev_line(it, nullptr)); + prev_line(it, nullptr); iterator_ahead = false; } - free(line); line = nullptr; while (row > 0) { row--; @@ -391,14 +407,10 @@ Coord move_left(Editor *editor, Coord cursor, uint32_t number) { const Fold *fold = fold_for_line(editor->folds, row); if (fold) { while (line && row > fold->start) { - free(line); line = prev_line(it, &len); row--; } - if (line) { - free(line); - line = nullptr; - } + line = nullptr; continue; } break; @@ -421,8 +433,7 @@ Coord move_left(Editor *editor, Coord cursor, uint32_t number) { } number--; } - if (line) - free(line); + free(it->buffer); free(it); result.row = row; result.col = col; @@ -435,14 +446,14 @@ void cursor_down(Editor *editor, uint32_t number) { uint32_t len; LineIterator *it = begin_l_iter(editor->root, editor->cursor.row); char *line_content = next_line(it, &len); - free(it); if (line_content == nullptr) return; if (editor->cursor_preffered == UINT32_MAX) editor->cursor_preffered = get_visual_col_from_bytes(line_content, len, editor->cursor.col); uint32_t visual_col = editor->cursor_preffered; - free(line_content); + free(it->buffer); + free(it); uint32_t target_row = editor->cursor.row; while (number > 0 && target_row < editor->root->line_count - 1) { target_row = next_unfolded_row(editor, target_row + 1); @@ -454,14 +465,14 @@ void cursor_down(Editor *editor, uint32_t number) { } it = begin_l_iter(editor->root, target_row); line_content = next_line(it, &len); - free(it); if (!line_content) return; if (len > 0 && line_content[len - 1] == '\n') --len; editor->cursor.row = target_row; editor->cursor.col = get_bytes_from_visual_col(line_content, len, visual_col); - free(line_content); + free(it->buffer); + free(it); } void cursor_up(Editor *editor, uint32_t number) { @@ -470,14 +481,14 @@ void cursor_up(Editor *editor, uint32_t number) { uint32_t len; LineIterator *it = begin_l_iter(editor->root, editor->cursor.row); char *line_content = next_line(it, &len); - free(it); if (!line_content) return; if (editor->cursor_preffered == UINT32_MAX) editor->cursor_preffered = get_visual_col_from_bytes(line_content, len, editor->cursor.col); uint32_t visual_col = editor->cursor_preffered; - free(line_content); + free(it->buffer); + free(it); uint32_t target_row = editor->cursor.row; while (number > 0 && target_row > 0) { target_row = prev_unfolded_row(editor, target_row - 1); @@ -489,18 +500,18 @@ void cursor_up(Editor *editor, uint32_t number) { } it = begin_l_iter(editor->root, target_row); line_content = next_line(it, &len); - free(it); if (line_content) { if (len > 0 && line_content[len - 1] == '\n') --len; editor->cursor.row = target_row; editor->cursor.col = get_bytes_from_visual_col(line_content, len, visual_col); - free(line_content); } else { editor->cursor.row = 0; editor->cursor.col = 0; } + free(it->buffer); + free(it); } void cursor_right(Editor *editor, uint32_t number) { @@ -525,7 +536,6 @@ void move_line_up(Editor *editor) { std::shared_lock lock(editor->knot_mtx); LineIterator *it = begin_l_iter(editor->root, editor->cursor.row); char *line = next_line(it, &line_len); - free(it); if (!line) { lock.unlock(); return; @@ -543,7 +553,8 @@ void move_line_up(Editor *editor) { edit_erase(editor, {cursor.row, 0}, -1); edit_insert(editor, {cursor.row - up_by, 0}, (char *)"\n", 1); edit_insert(editor, {cursor.row - up_by, 0}, line, line_len); - free(line); + free(it->buffer); + free(it); editor->cursor = {cursor.row - up_by, cursor.col}; } else if (mode == SELECT) { uint32_t start_row = MIN(editor->cursor.row, editor->selection.row); @@ -576,7 +587,6 @@ void move_line_down(Editor *editor) { std::shared_lock lock(editor->knot_mtx); LineIterator *it = begin_l_iter(editor->root, editor->cursor.row); char *line = next_line(it, &line_len); - free(it); if (!line) { lock.unlock(); return; @@ -601,7 +611,8 @@ void move_line_down(Editor *editor) { edit_erase(editor, {cursor.row, 0}, -1); edit_insert(editor, {cursor.row + down_by, 0}, (char *)"\n", 1); edit_insert(editor, {cursor.row + down_by, 0}, line, line_len); - free(line); + free(it->buffer); + free(it); editor->cursor = {cursor.row + down_by, cursor.col}; } else if (mode == SELECT) { if (editor->cursor.row >= editor->root->line_count - 1 || @@ -811,12 +822,13 @@ char *get_selection(Editor *editor, uint32_t *out_len) { case LINE: LineIterator *it = begin_l_iter(editor->root, editor->selection.row); char *line = next_line(it, &line_len); - free(it); if (!line) return nullptr; if (line_len > 0 && line[line_len - 1] == '\n') line_len--; end = {editor->selection.row, line_len}; + free(it->buffer); + free(it); break; } } @@ -877,13 +889,11 @@ bool add_fold(Editor *editor, uint32_t start, uint32_t end) { end = std::min(end, editor->root->line_count - 1); if (start == end) return false; - Fold new_fold{start, end}; auto &folds = editor->folds; auto it = std::lower_bound( folds.begin(), folds.end(), new_fold.start, [](const Fold &fold, uint32_t value) { return fold.start < value; }); - if (it != folds.begin()) { auto prev = std::prev(it); if (prev->end + 1 >= new_fold.start) { diff --git a/src/editor_events.cc b/src/editor_events.cc index abf6f3e..02c32fe 100644 --- a/src/editor_events.cc +++ b/src/editor_events.cc @@ -70,12 +70,12 @@ void handle_editor_event(Editor *editor, KeyEvent event) { uint32_t line_len; LineIterator *it = begin_l_iter(editor->root, p.row); char *line = next_line(it, &line_len); - free(it); if (!line) return; if (line_len > 0 && line[line_len - 1] == '\n') line_len--; - free(line); + free(it->buffer); + free(it); editor->cursor = {p.row, line_len}; } editor->cursor_preffered = UINT32_MAX; @@ -115,12 +115,12 @@ void handle_editor_event(Editor *editor, KeyEvent event) { } else { LineIterator *it = begin_l_iter(editor->root, p.row); char *line = next_line(it, &line_len); - free(it); if (!line) return; if (line_len > 0 && line[line_len - 1] == '\n') line_len--; - free(line); + free(it->buffer); + free(it); editor->cursor = {p.row, line_len}; } break; @@ -216,9 +216,9 @@ void handle_editor_event(Editor *editor, KeyEvent event) { break; if (line_len > 0 && line[line_len - 1] == '\n') line_len--; - free(it); line_len = count_clusters(line, line_len, 0, line_len); - free(line); + free(it->buffer); + free(it); editor->cursor.col = line_len; editor->cursor_preffered = UINT32_MAX; mode = SELECT; @@ -305,7 +305,6 @@ void handle_editor_event(Editor *editor, KeyEvent event) { uint32_t line_len = 0; LineIterator *it = begin_l_iter(editor->root, editor->cursor.row); char *line = next_line(it, &line_len); - free(it); bool closing = false; if (line && line_len > 0 && line[line_len - 1] == '\n') line_len--; @@ -314,8 +313,9 @@ void handle_editor_event(Editor *editor, KeyEvent event) { if (indent == 0) indent = leading_indent(line, line_len); closing = closing_after_cursor(line, line_len, editor->cursor.col); - free(line); } + free(it->buffer); + free(it); uint32_t closing_indent = indent >= INDENT_WIDTH ? indent - INDENT_WIDTH : 0; std::string insert_text("\n"); @@ -366,10 +366,10 @@ void handle_editor_event(Editor *editor, KeyEvent event) { if (!it) return; char *line = next_line(it, nullptr); - free(it); char prev_char = line[prev_pos.col]; char next_char = line[editor->cursor.col]; - free(line); + free(it->buffer); + free(it); bool is_pair = (prev_char == '{' && next_char == '}') || (prev_char == '(' && next_char == ')') || (prev_char == '[' && next_char == ']') || diff --git a/src/editor_indents.cc b/src/editor_indents.cc index a03acc2..7e1af77 100644 --- a/src/editor_indents.cc +++ b/src/editor_indents.cc @@ -23,10 +23,10 @@ uint32_t get_indent(Editor *editor, Coord cursor) { if (line_len == 0) continue; uint32_t indent = leading_indent(line, line_len); - free(line); - free(it); return indent; } + free(it->buffer); + free(it); return 0; } diff --git a/src/editor_scroll.cc b/src/editor_scroll.cc index e09a44b..e92c282 100644 --- a/src/editor_scroll.cc +++ b/src/editor_scroll.cc @@ -18,6 +18,7 @@ void scroll_up(Editor *editor, int32_t number) { uint32_t len; char *line = next_line(it, &len); if (!line) { + free(it->buffer); free(it); return; } @@ -45,24 +46,24 @@ void scroll_up(Editor *editor, int32_t number) { ++it_seg) { if (--number == 0) { editor->scroll = {line_index, *it_seg}; - free(line); + free(it->buffer); free(it); return; } } - free(line); line = prev_line(it, &len); if (!line) { editor->scroll = {0, 0}; + free(it->buffer); free(it); return; } - free(line); do { line_index--; line = prev_line(it, &len); if (!line) { editor->scroll = {0, 0}; + free(it->buffer); free(it); return; } @@ -74,19 +75,20 @@ void scroll_up(Editor *editor, int32_t number) { line_index--; if (!line) { editor->scroll = {0, 0}; + free(it->buffer); free(it); return; } } if (--number == 0) { editor->scroll = {fold->start, 0}; - free(line); + free(it->buffer); free(it); return; } - free(line); if (fold->start == 0) { editor->scroll = {0, 0}; + free(it->buffer); free(it); return; } @@ -94,6 +96,7 @@ void scroll_up(Editor *editor, int32_t number) { line = prev_line(it, &len); if (!line) { editor->scroll = {0, 0}; + free(it->buffer); free(it); return; } @@ -121,13 +124,13 @@ void scroll_up(Editor *editor, int32_t number) { ++it_seg) { if (--number == 0) { editor->scroll = {line_index, *it_seg}; - free(line); + free(it->buffer); free(it); return; } } - free(line); } while (number > 0); + free(it->buffer); free(it); } @@ -168,10 +171,10 @@ void scroll_down(Editor *editor, uint32_t number) { char *line = next_line(it, nullptr); if (!line) { free(scroll_queue); + free(it->buffer); free(it); return; } - free(line); line_index++; } continue; @@ -200,8 +203,8 @@ void scroll_down(Editor *editor, uint32_t number) { visual_seen++; if (visual_seen >= number + max_visual_lines) { editor->scroll = scroll_queue[q_head]; - free(line); free(scroll_queue); + free(it->buffer); free(it); return; } @@ -223,13 +226,13 @@ void scroll_down(Editor *editor, uint32_t number) { if (line_len == 0) break; } - free(line); line_index++; } if (q_size > 0) { uint32_t advance = (q_size > number) ? number : (q_size - 1); editor->scroll = scroll_queue[(q_head + advance) % max_visual_lines]; } + free(it->buffer); free(it); free(scroll_queue); } @@ -267,7 +270,6 @@ void ensure_cursor(Editor *editor) { char *line = next_line(it, nullptr); if (!line) break; - free(line); line_index++; } continue; @@ -302,7 +304,7 @@ void ensure_cursor(Editor *editor) { if (line_index == editor->cursor.row) { if (editor->cursor.col >= offset && editor->cursor.col <= offset + advance) { - free(line); + free(it->buffer); free(it); return; } @@ -313,7 +315,6 @@ void ensure_cursor(Editor *editor) { if (line_len == 0) break; } - free(line); line_index++; } uint32_t last_real_row = last_visible.row; @@ -325,6 +326,7 @@ void ensure_cursor(Editor *editor) { editor->cursor.row = last_visible.row; editor->cursor.col = last_visible.row == last_real_row ? last_visible.col : 0; editor->cursor_preffered = UINT32_MAX; + free(it->buffer); free(it); } @@ -340,6 +342,7 @@ void ensure_scroll(Editor *editor) { uint32_t len; char *line = next_line(it, &len); if (!line) { + free(it->buffer); free(it); return; } @@ -359,7 +362,7 @@ void ensure_scroll(Editor *editor) { if (editor->cursor.col > old_offset && editor->cursor.col <= offset) { editor->scroll.row = editor->cursor.row; editor->scroll.col = old_offset; - free(line); + free(it->buffer); free(it); return; } @@ -368,7 +371,7 @@ void ensure_scroll(Editor *editor) { cols += width; offset += inc; } - free(line); + free(it->buffer); free(it); editor->scroll.row = editor->cursor.row; editor->scroll.col = (editor->cursor.col == 0) ? 0 : old_offset; @@ -403,7 +406,6 @@ void ensure_scroll(Editor *editor) { char *line = next_line(it, nullptr); if (!line) break; - free(line); line_index++; } continue; @@ -453,8 +455,8 @@ void ensure_scroll(Editor *editor) { cursor_found = true; if (cursor_found) { editor->scroll = scroll_queue[q_head]; - free(line); free(scroll_queue); + free(it->buffer); free(it); return; } @@ -464,9 +466,9 @@ void ensure_scroll(Editor *editor) { break; } line_index++; - free(line); } free(scroll_queue); + free(it->buffer); free(it); } } diff --git a/src/knot.cc b/src/knot.cc index 452962c..921b9cc 100644 --- a/src/knot.cc +++ b/src/knot.cc @@ -471,6 +471,12 @@ LineIterator *begin_l_iter(Knot *root, uint32_t start_line) { return nullptr; it->top = 0; it->node = nullptr; + it->capacity = 128; + it->buffer = (char *)malloc(it->capacity); + if (!it->buffer) { + free(it); + return nullptr; + } if (start_line == 0) { it->offset = 0; while (root->left) { @@ -499,6 +505,7 @@ LineIterator *begin_l_iter(Knot *root, uint32_t start_line) { } } if (!it->node) { + free(it->buffer); free(it); return nullptr; } @@ -516,7 +523,7 @@ LineIterator *begin_l_iter(Knot *root, uint32_t start_line) { } } } - free(next_line(it, nullptr)); + next_line(it, nullptr); return it; } @@ -559,11 +566,7 @@ static void str_reverse(char *begin, char *end) { char *prev_line(LineIterator *it, uint32_t *out_len) { if (!it || !it->node) return nullptr; - size_t capacity = 128; size_t len = 0; - char *buffer = (char *)malloc(capacity); - if (!buffer) - return nullptr; while (it->node) { if (it->offset == 0) { iter_retreat_leaf(it); @@ -578,25 +581,22 @@ char *prev_line(LineIterator *it, uint32_t *out_len) { break; } } - if (len + 1 >= capacity) { - capacity *= 2; - char *new_buf = (char *)realloc(buffer, capacity); - if (!new_buf) { - free(buffer); + if (len + 1 >= it->capacity) { + it->capacity *= 2; + char *new_buf = (char *)realloc(it->buffer, it->capacity); + if (!new_buf) return nullptr; - } - buffer = new_buf; + it->buffer = new_buf; } - buffer[len++] = c; + it->buffer[len++] = c; } if (len > 0) { - buffer[len] = '\0'; - str_reverse(buffer, buffer + len - 1); + it->buffer[len] = '\0'; + str_reverse(it->buffer, it->buffer + len - 1); if (out_len) *out_len = len; - return buffer; + return it->buffer; } - free(buffer); return nullptr; } @@ -630,11 +630,7 @@ static inline void iter_advance_leaf(LineIterator *it) { char *next_line(LineIterator *it, uint32_t *out_len) { if (!it || !it->node) return nullptr; - size_t capacity = 128; size_t len = 0; - char *buffer = (char *)malloc(capacity); - if (!buffer) - return nullptr; while (it->node) { if (it->offset >= it->node->char_count) { iter_advance_leaf(it); @@ -652,32 +648,30 @@ char *next_line(LineIterator *it, uint32_t *out_len) { } else { chunk_len = end - start; } - if (len + chunk_len + 1 > capacity) { - capacity = (capacity * 2) + chunk_len; - char *new_buf = (char *)realloc(buffer, capacity); + if (len + chunk_len + 1 > it->capacity) { + it->capacity = (it->capacity * 2) + chunk_len; + char *new_buf = (char *)realloc(it->buffer, it->capacity); if (!new_buf) { - free(buffer); return nullptr; } - buffer = new_buf; + it->buffer = new_buf; } - memcpy(buffer + len, start, chunk_len); + memcpy(it->buffer + len, start, chunk_len); len += chunk_len; it->offset += chunk_len; if (found_newline) { - buffer[len] = '\0'; + it->buffer[len] = '\0'; if (out_len) *out_len = len; - return buffer; + return it->buffer; } } if (len > 0) { - buffer[len] = '\0'; + it->buffer[len] = '\0'; if (out_len) *out_len = len; - return buffer; + return it->buffer; } - free(buffer); return nullptr; }