From f3753be4eb2857e4b0ba5f98fc0120724f4d8be9 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 9 Jan 2017 21:34:16 -0500 Subject: [PATCH] refactor Buffer insert and delete operations add Buffer functions to insert/erase data chunks --- src/core/Buffer.cc | 98 ++++++++++++++++++++++++++++++++++------------ src/core/Buffer.h | 9 ++++- 2 files changed, 79 insertions(+), 28 deletions(-) diff --git a/src/core/Buffer.cc b/src/core/Buffer.cc index 0d17d47..b7c3314 100644 --- a/src/core/Buffer.cc +++ b/src/core/Buffer.cc @@ -171,49 +171,61 @@ void Buffer::exit_insert_mode() void Buffer::insert_code_point(const Buffer::Iterator & position, uint32_t code_point) { push_operation(); - Buffer::Iterator local_position = position; - if ((code_point != '\n') && (size() == 0u)) - { - insert_code_point(position, '\n'); - } - uint8_t encoded[Encoding::MAX_CODE_POINT_SIZE]; + uint8_t encoded[Encoding::MAX_CODE_POINT_SIZE * 2]; uint8_t bytes = Encoding::encode(code_point, m_encoding, encoded); - m_gap_buffer->insert(local_position.offset(), encoded, bytes); - record_change(encoded, bytes, local_position.offset(), true); - ssize_t lines = (code_point == '\n') ? 1 : 0; - warp_iterators(local_position.offset(), bytes, lines, true); + if ((size() == 0u) && (code_point != '\n')) + { + bytes += Encoding::encode('\n', m_encoding, &encoded[bytes]); + } + insert_data(position.offset(), encoded, bytes); pop_operation(); } +void Buffer::insert_data(size_t offset, const uint8_t data[], size_t length) +{ + m_gap_buffer->insert(offset, data, length); + record_change(data, length, offset, true); + warp_iterators_after_insert(offset, length); + post_warp_cursors(); +} + void Buffer::erase_code_point(const Buffer::Iterator & position) { if (position.valid()) { push_operation(); - Buffer::Iterator local_position = position; - uint8_t bytes = 0u; - uint32_t code_point = Encoding::decode(m_encoding, local_position.address(), &bytes); - record_change(local_position.address(), bytes, local_position.offset(), false); - m_gap_buffer->erase(local_position.offset(), bytes); - ssize_t lines = (code_point == '\n') ? -1 : 0; - warp_iterators(local_position.offset(), -(ssize_t)bytes, lines, false); + erase_data(position.offset(), Encoding::num_bytes_in_code_point(m_encoding, position.address())); pop_operation(); } } -void Buffer::warp_iterators(size_t offset, ssize_t offset_adjustment, ssize_t lines_adjustment, bool include_equal) +void Buffer::erase_data(size_t offset, size_t length) { - if (!include_equal) + warp_iterators_before_delete(offset, length); + /* FIXME: erased data may not be contiguous in gap buffer. */ + record_change(m_gap_buffer->address(offset), length, offset, false); + m_gap_buffer->erase(offset, length); + post_warp_cursors(); +} + +size_t Buffer::lines_in_data(size_t offset, size_t length) +{ + size_t lines = 0u; + for (size_t i = 0u; i < length; ) { - offset++; - } - for (auto iterator : m_iterators) - { - if (iterator->offset() >= offset) + uint8_t bytes; + uint32_t c = Encoding::decode(m_encoding, m_gap_buffer->address(offset), &bytes); + if (c == '\n') { - iterator->warp(offset_adjustment, lines_adjustment); + lines++; } + i += bytes; } + return lines; +} + +void Buffer::post_warp_cursors() +{ for (auto cursor : m_cursors) { if ((*cursor == *m_eof_iterator) && (size() > 0u)) @@ -223,6 +235,40 @@ void Buffer::warp_iterators(size_t offset, ssize_t offset_adjustment, ssize_t li } } +void Buffer::warp_iterators_after_insert(size_t offset, size_t length) +{ + size_t lines = lines_in_data(offset, length); + for (auto iterator : m_iterators) + { + if (iterator->offset() >= offset) + { + iterator->warp(length, lines); + } + } +} + +void Buffer::warp_iterators_before_delete(size_t offset, size_t length) +{ + size_t lines = lines_in_data(offset, length); + for (auto iterator : m_iterators) + { + /* Move any iterators within the chunk to be deleted to after it. */ + while ((iterator->offset() >= offset) && + (iterator->offset() < (offset + length))) + { + iterator->go_forward(); + if (!iterator->valid()) + { + break; + } + } + if (iterator->offset() >= offset) + { + iterator->warp(-(ssize_t)length, -(ssize_t)lines); + } + } +} + void Buffer::pop_operation() { if (m_operation_level > 0) @@ -235,7 +281,7 @@ void Buffer::pop_operation() } } -void Buffer::record_change(uint8_t data[], size_t length, size_t buffer_position, bool insert) +void Buffer::record_change(const uint8_t data[], size_t length, size_t buffer_position, bool insert) { if (!m_current_change_operation) { diff --git a/src/core/Buffer.h b/src/core/Buffer.h index 3fe2602..38b0733 100644 --- a/src/core/Buffer.h +++ b/src/core/Buffer.h @@ -152,9 +152,14 @@ protected: void load_empty_buffer(); bool load_from_memory(const uint8_t * data, size_t data_length); void load_text_in_buffer(uint8_t * buffer, size_t buffer_size, size_t data_length); - void record_change(uint8_t data[], size_t length, size_t buffer_position, bool insert); + void record_change(const uint8_t data[], size_t length, size_t buffer_position, bool insert); void save_current_operation(); - void warp_iterators(size_t offset, ssize_t offset_adjustment, ssize_t lines_adjustments, bool include_equal); + void warp_iterators_after_insert(size_t offset, size_t length); + void warp_iterators_before_delete(size_t offset, size_t length); + void insert_data(size_t offset, const uint8_t data[], size_t length); + void erase_data(size_t offset, size_t length); + size_t lines_in_data(size_t offset, size_t length); + void post_warp_cursors(); }; #endif