summaryrefslogtreecommitdiff
path: root/src/buffer.cc
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2012-02-22 21:54:25 +0000
committerMaxime Coste <frrrwww@gmail.com>2012-02-22 21:54:25 +0000
commita386315bde576cc77c22ca7677de51f86f97755c (patch)
treeb6c3c3cf3c76fcf6b593cb2a255b8cc0ebdb0544 /src/buffer.cc
parent030450838a532ad052b54449222f08f80ca78604 (diff)
Buffer: optimize line updating when applying a modification
Diffstat (limited to 'src/buffer.cc')
-rw-r--r--src/buffer.cc65
1 files changed, 54 insertions, 11 deletions
diff --git a/src/buffer.cc b/src/buffer.cc
index bbd8c762..409ee4e0 100644
--- a/src/buffer.cc
+++ b/src/buffer.cc
@@ -103,16 +103,6 @@ BufferIterator Buffer::iterator_at_line_end(const BufferIterator& iterator) cons
return line < m_lines.size() ? BufferIterator(*this, m_lines[line]) : end();
}
-void Buffer::compute_lines()
-{
- m_lines.clear();
- m_lines.push_back(0);
- for (BufferPos i = 0; i + 1 < m_content.size(); ++i)
- {
- if (m_content[i] == '\n')
- m_lines.push_back(i + 1);
- }
-}
BufferIterator Buffer::begin() const
{
@@ -197,6 +187,59 @@ bool Buffer::redo()
++m_history_cursor;
}
+void Buffer::compute_lines()
+{
+ m_lines.clear();
+ m_lines.push_back(0);
+ for (BufferPos i = 0; i + 1 < m_content.size(); ++i)
+ {
+ if (m_content[i] == '\n')
+ m_lines.push_back(i + 1);
+ }
+}
+
+void Buffer::update_lines(const Modification& modification)
+{
+ const BufferString& content = modification.content;
+ size_t length = content.length();
+
+ if (modification.type == Modification::Insert)
+ {
+ auto line_it = m_lines.begin() + line_at(modification.position) + 1;
+ for (auto it = line_it; it != m_lines.end(); ++it)
+ *it += length;
+
+ BufferPos pos = modification.position.m_position + 1;
+ std::vector<BufferPos> new_lines;
+ for (BufferPos i = 0; i < length; ++i)
+ {
+ if (content[i] == '\n')
+ new_lines.push_back(pos);
+ ++pos;
+ }
+ m_lines.insert(line_it, new_lines.begin(), new_lines.end());
+ }
+ else if (modification.type == Modification::Erase)
+ {
+ BufferPos line = line_at(modification.position) + 1;
+
+ auto begin = m_lines.begin() + line;
+ auto end = begin;
+ BufferPos pos = modification.position.m_position;
+ while (end != m_lines.end() and *end <= pos + length)
+ ++end;
+ m_lines.erase(begin, end);
+
+ for (BufferPos i = line; i != m_lines.size(); ++i)
+ {
+ m_lines[i] -= length;
+ assert(m_content[m_lines[i]-1] == '\n');
+ }
+ }
+ else
+ assert(false);
+}
+
void Buffer::apply_modification(const Modification& modification)
{
switch (modification.type)
@@ -216,7 +259,7 @@ void Buffer::apply_modification(const Modification& modification)
default:
assert(false);
}
- compute_lines();
+ update_lines(modification);
for (auto listener : m_modification_listeners)
listener->on_modification(modification);
}