- Added branching model for undo/redo, enabling multiple redo paths and branch selection. - Updated `UndoNode` to include `parent` and refined hierarchical navigation. - Extended `UndoSystem` with branching logic for redo operations, supporting sibling branch selection. - Overhauled tests to validate branching behavior and tree invariants. - Refined editor command logic for undo/redo with repeat counts and branch selection. - Enabled test-only introspection hooks for undo tree validation. - Updated CMake to include test definitions (`KTE_TESTS` flag).
63 lines
1.5 KiB
C++
63 lines
1.5 KiB
C++
#pragma once
|
|
#include <stack>
|
|
#include <vector>
|
|
#include <memory>
|
|
#include "UndoNode.h"
|
|
|
|
// Pool allocator for UndoNode to eliminate frequent malloc/free.
|
|
// Uses fixed-size blocks to keep node addresses stable.
|
|
class UndoNodePool {
|
|
public:
|
|
explicit UndoNodePool(std::size_t block_size = 64)
|
|
: block_size_(block_size) {}
|
|
|
|
|
|
UndoNode *acquire()
|
|
{
|
|
if (available_.empty())
|
|
allocate_block();
|
|
auto *node = available_.top();
|
|
available_.pop();
|
|
// Node comes zeroed; ensure links are reset
|
|
node->text.clear();
|
|
node->parent = nullptr;
|
|
node->child = nullptr;
|
|
node->next = nullptr;
|
|
node->row = node->col = 0;
|
|
node->type = UndoType{};
|
|
return node;
|
|
}
|
|
|
|
|
|
void release(UndoNode *node)
|
|
{
|
|
if (!node)
|
|
return;
|
|
// Clear heavy fields to free memory held by strings
|
|
node->text.clear();
|
|
node->parent = nullptr;
|
|
node->child = nullptr;
|
|
node->next = nullptr;
|
|
node->row = node->col = 0;
|
|
node->type = UndoType{};
|
|
available_.push(node);
|
|
}
|
|
|
|
private:
|
|
void allocate_block()
|
|
{
|
|
// allocate a new block; keep ownership so memory stays valid
|
|
std::unique_ptr<UndoNode[]> block(new UndoNode[block_size_]);
|
|
UndoNode *base = block.get();
|
|
blocks_.push_back(std::move(block));
|
|
for (std::size_t i = 0; i < block_size_; ++i) {
|
|
// ensure the node is reset; rely on default constructor/zero init
|
|
available_.push(&base[i]);
|
|
}
|
|
}
|
|
|
|
|
|
std::size_t block_size_;
|
|
std::vector<std::unique_ptr<UndoNode[]> > blocks_;
|
|
std::stack<UndoNode *> available_;
|
|
}; |