From c8354588c9af6a9d5064ec4e9665b1eea6c4eb77 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 2 Jun 2014 15:17:56 +0100 Subject: [PATCH] Remove undo group optimizer --- src/buffer.cc | 188 -------------------------------------------------- 1 file changed, 188 deletions(-) diff --git a/src/buffer.cc b/src/buffer.cc index 91f143c8..884ae270 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -181,200 +181,12 @@ struct Buffer::Modification } }; -class UndoGroupOptimizer -{ - static constexpr auto Insert = Buffer::Modification::Type::Insert; - static constexpr auto Erase = Buffer::Modification::Type::Erase; - - static ByteCoord advance(ByteCoord coord, const String& str) - { - for (auto c : str) - { - if (c == '\n') - { - ++coord.line; - coord.column = 0; - } - else - ++coord.column; - } - return coord; - } - - static ByteCount count_byte_to(ByteCoord pos, ByteCoord endpos, const String& str) - { - ByteCount count = 0; - for (auto it = str.begin(); it != str.end() and pos != endpos; ++it) - { - if (*it == '\n') - { - ++pos.line; - pos.column = 0; - } - else - ++pos.column; - ++count; - } - kak_assert(pos == endpos); - return count; - } - - static const ByteCount overlaps(const String& lhs, const String& rhs) - { - if (lhs.empty() or rhs.empty()) - return -1; - - char c = rhs.front(); - ByteCount pos = 0; - while ((pos = (int)lhs.find_first_of(c, (int)pos)) != -1) - { - ByteCount i = pos, j = 0; - while (i != lhs.length() and j != rhs.length() and lhs[i] == rhs[j]) - ++i, ++j; - if (i == lhs.length()) - break; - ++pos; - } - return pos; - } - - static bool merge_contiguous(Buffer::UndoGroup& undo_group) - { - bool progress = false; - auto it = undo_group.begin(); - auto it_next = it+1; - while (it_next != undo_group.end()) - { - ByteCount pos; - auto& coord = it->coord; - auto& next_coord = it_next->coord; - - // reorders modification doing a kind of custom bubble sort - // so we have a O(n²) worst case complexity of the undo group optimization - if (next_coord < coord) - { - ByteCoord next_end = advance(next_coord, it_next->content); - if (it_next->type == Insert) - { - if (coord.line == next_coord.line) - coord.column += next_end.column - next_coord.column; - coord.line += next_end.line - next_coord.line; - } - else if (it->type == Insert and next_end > coord) - { - ByteCount start = count_byte_to(next_coord, coord, it_next->content); - ByteCount len = std::min(it->content.length(), it_next->content.length() - start); - kak_assert(it_next->content.substr(start, len) == it->content.substr(0, len)); - it->coord = it_next->coord; - it->content = it->content.substr(len); - it_next->content = it_next->content.substr(0,start) + it_next->content.substr(start + len); - } - else if (it->type == Erase and next_end >= coord) - { - ByteCount start = count_byte_to(next_coord, coord, it_next->content); - it_next->content = it_next->content.substr(0, start) + it->content + it_next->content.substr(start); - it->coord = it_next->coord; - it->content.clear(); - } - else - { - if (next_end.line == coord.line) - { - coord.line = next_coord.line; - coord.column = next_coord.column + coord.column - next_end.column; - } - else - coord.line -= next_end.line - next_coord.line; - } - std::swap(*it, *it_next); - progress = true; - } - - kak_assert(coord <= next_coord); - if (it->type == Erase and it_next->type == Erase and coord == next_coord) - { - it->content += it_next->content; - it_next = undo_group.erase(it_next); - progress = true; - } - else if (it->type == Insert and it_next->type == Insert and - is_in_range(next_coord, coord, advance(coord, it->content))) - { - ByteCount prefix_len = count_byte_to(coord, next_coord, it->content); - it->content = it->content.substr(0, prefix_len) + it_next->content - + it->content.substr(prefix_len); - it_next = undo_group.erase(it_next); - progress = true; - } - else if (it->type == Insert and it_next->type == Erase and - next_coord < advance(coord, it->content)) - { - ByteCount insert_len = it->content.length(); - ByteCount erase_len = it_next->content.length(); - ByteCount prefix_len = count_byte_to(coord, next_coord, it->content); - - ByteCount suffix_len = insert_len - prefix_len; - if (suffix_len >= erase_len) - { - it->content = it->content.substr(0, prefix_len) + it->content.substr(prefix_len + erase_len); - it_next = undo_group.erase(it_next); - } - else - { - it->content = it->content.substr(0, prefix_len); - it_next->content = it_next->content.substr(suffix_len); - ++it, ++it_next; - } - progress = true; - } - else if (it->type == Erase and it_next->type == Insert and coord == next_coord and - (pos = overlaps(it->content, it_next->content)) != -1) - { - ByteCount overlaps_len = it->content.length() - pos; - it->content = it->content.substr(0, pos); - it_next->coord = advance(it_next->coord, it_next->content.substr(0, overlaps_len)); - it_next->content = it_next->content.substr(overlaps_len); - ++it, ++it_next; - progress = true; - } - else - ++it, ++it_next; - } - return progress; - } - - static bool erase_empty(Buffer::UndoGroup& undo_group) - { - auto it = std::remove_if(begin(undo_group), end(undo_group), - [](Buffer::Modification& m) { return m.content.empty(); }); - if (it != end(undo_group)) - { - undo_group.erase(it, end(undo_group)); - return true; - } - return false; - } -public: - static void optimize(Buffer::UndoGroup& undo_group) - { - while (undo_group.size() > 1) - { - bool progress = false; - progress |= merge_contiguous(undo_group); - progress |= erase_empty(undo_group); - if (not progress) - break; - } - } -}; void Buffer::commit_undo_group() { if (m_flags & Flags::NoUndo) return; - UndoGroupOptimizer::optimize(m_current_undo_group); - if (m_current_undo_group.empty()) return;