aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/UndoHistory.cxx
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2024-02-01 12:38:58 +1100
committerNeil <nyamatongwe@gmail.com>2024-02-01 12:38:58 +1100
commitfa3f060e142243c7848284f16561d4af9f9ee935 (patch)
tree55975d3c9f1b13b38686424b4dc2c4daf314a052 /src/UndoHistory.cxx
parent252cb0fe25a8cbbce19944033e311203e0fb07dc (diff)
downloadscintilla-mirror-fa3f060e142243c7848284f16561d4af9f9ee935.tar.gz
Store undo text in ScrapStack, a single allocation instead of one allocation per
step. This saves about 50% for a long sequence of single byte actions.
Diffstat (limited to 'src/UndoHistory.cxx')
-rw-r--r--src/UndoHistory.cxx72
1 files changed, 57 insertions, 15 deletions
diff --git a/src/UndoHistory.cxx b/src/UndoHistory.cxx
index d667c9b4d..bc1a4d36a 100644
--- a/src/UndoHistory.cxx
+++ b/src/UndoHistory.cxx
@@ -38,23 +38,50 @@ namespace Scintilla::Internal {
UndoAction::UndoAction() noexcept = default;
-void UndoAction::Create(ActionType at_, Sci::Position position_, const char *data_, Sci::Position lenData_, bool mayCoalesce_) {
+void UndoAction::Create(ActionType at_, Sci::Position position_, Sci::Position lenData_, bool mayCoalesce_) noexcept {
position = position_;
at = at_;
mayCoalesce = mayCoalesce_;
lenData = lenData_;
- data = nullptr;
- if (lenData_) {
- data = std::make_unique<char[]>(lenData_);
- memcpy(&data[0], data_, lenData_);
- }
}
void UndoAction::Clear() noexcept {
- data = nullptr;
lenData = 0;
}
+const char *ScrapStack::Push(const char *text, size_t length) {
+ if (current < stack.length()) {
+ stack.resize(current);
+ }
+ stack.append(text, length);
+ current = stack.length();
+ return stack.data() + current - length;
+}
+
+void ScrapStack::SetCurrent(size_t position) noexcept {
+ current = position;
+}
+
+void ScrapStack::MoveForward(size_t length) noexcept {
+ if ((current + length) <= stack.length()) {
+ current += length;
+ }
+}
+
+void ScrapStack::MoveBack(size_t length) noexcept {
+ if (current >= length) {
+ current -= length;
+ }
+}
+
+const char *ScrapStack::CurrentText() const noexcept {
+ return stack.data() + current;
+}
+
+const char *ScrapStack::TextAt(size_t position) const noexcept {
+ return stack.data() + position;
+}
+
// The undo history stores a sequence of user operations that represent the user's view of the
// commands executed on the text.
// Each user operation contains a sequence of text insertion and text deletion actions.
@@ -81,10 +108,13 @@ UndoHistory::UndoHistory() {
undoSequenceDepth = 0;
savePoint = 0;
tentativePoint = -1;
+ scraps = std::make_unique<ScrapStack>();
actions[currentAction].Create(ActionType::start);
}
+UndoHistory::~UndoHistory() noexcept = default;
+
void UndoHistory::EnsureUndoRoom() {
// Have to test that there is room for 2 more actions in the array
// as two actions may be created by the calling function
@@ -163,12 +193,12 @@ const char *UndoHistory::AppendAction(ActionType at, Sci::Position position, con
currentAction++;
}
startSequence = oldCurrentAction != currentAction;
- const int actionWithData = currentAction;
- actions[currentAction].Create(at, position, data, lengthData, mayCoalesce);
+ const char *dataNew = lengthData ? scraps->Push(data, lengthData) : nullptr;
+ actions[currentAction].Create(at, position, lengthData, mayCoalesce);
currentAction++;
actions[currentAction].Create(ActionType::start);
maxAction = currentAction;
- return actions[actionWithData].data.get();
+ return dataNew;
}
void UndoHistory::BeginUndoAction() {
@@ -202,7 +232,7 @@ void UndoHistory::DropUndoSequence() noexcept {
undoSequenceDepth = 0;
}
-void UndoHistory::DeleteUndoHistory() {
+void UndoHistory::DeleteUndoHistory() noexcept {
for (int i = 1; i < maxAction; i++)
actions[i].Clear();
maxAction = 0;
@@ -278,11 +308,17 @@ int UndoHistory::StartUndo() noexcept {
return currentAction - act;
}
-const UndoAction &UndoHistory::GetUndoStep() const noexcept {
- return actions[currentAction];
+Action UndoHistory::GetUndoStep() const noexcept {
+ const UndoAction &step = actions[currentAction];
+ Action acta {step.at, step.mayCoalesce, step.position, nullptr, step.lenData};
+ if (step.lenData) {
+ acta.data = scraps->CurrentText() - step.lenData;
+ }
+ return acta;
}
void UndoHistory::CompletedUndoStep() noexcept {
+ scraps->MoveBack(actions[currentAction].lenData);
currentAction--;
}
@@ -303,11 +339,17 @@ int UndoHistory::StartRedo() noexcept {
return act - currentAction;
}
-const UndoAction &UndoHistory::GetRedoStep() const noexcept {
- return actions[currentAction];
+Action UndoHistory::GetRedoStep() const noexcept {
+ const UndoAction &step = actions[currentAction];
+ Action acta {step.at, step.mayCoalesce, step.position, nullptr, step.lenData};
+ if (step.lenData) {
+ acta.data = scraps->CurrentText();
+ }
+ return acta;
}
void UndoHistory::CompletedRedoStep() noexcept {
+ scraps->MoveForward(actions[currentAction].lenData);
currentAction++;
}