fix problem of record_change() not receiving contiguous range by using GapBuffer::copy_to()

This commit is contained in:
Josh Holtrop 2017-01-09 22:11:08 -05:00
parent b9313ad606
commit fca838fcbf
2 changed files with 19 additions and 20 deletions

View File

@ -184,7 +184,7 @@ void Buffer::insert_code_point(const Buffer::Iterator & position, uint32_t code_
void Buffer::insert_data(size_t offset, const uint8_t data[], size_t length) void Buffer::insert_data(size_t offset, const uint8_t data[], size_t length)
{ {
m_gap_buffer->insert(offset, data, length); m_gap_buffer->insert(offset, data, length);
record_change(data, length, offset, true); record_change(offset, length, true);
warp_iterators_after_insert(offset, length); warp_iterators_after_insert(offset, length);
post_warp_cursors(); post_warp_cursors();
} }
@ -202,8 +202,7 @@ void Buffer::erase_code_point(const Buffer::Iterator & position)
void Buffer::erase_data(size_t offset, size_t length) void Buffer::erase_data(size_t offset, size_t length)
{ {
warp_iterators_before_delete(offset, length); warp_iterators_before_delete(offset, length);
/* FIXME: erased data may not be contiguous in gap buffer. */ record_change(offset, length, false);
record_change(m_gap_buffer->address(offset), length, offset, false);
m_gap_buffer->erase(offset, length); m_gap_buffer->erase(offset, length);
post_warp_cursors(); post_warp_cursors();
} }
@ -281,7 +280,7 @@ void Buffer::pop_operation()
} }
} }
void Buffer::record_change(const uint8_t data[], size_t length, size_t buffer_position, bool insert) void Buffer::record_change(size_t offset, size_t length, bool insert)
{ {
if (!m_current_change_operation) if (!m_current_change_operation)
{ {
@ -294,41 +293,41 @@ void Buffer::record_change(const uint8_t data[], size_t length, size_t buffer_po
* modified to encompass the new change. */ * modified to encompass the new change. */
ChangeUnit & cu = *m_current_change_operation->changes.rbegin(); ChangeUnit & cu = *m_current_change_operation->changes.rbegin();
if (insert && cu.insert && if (insert && cu.insert &&
((buffer_position + length) >= cu.buffer_position) && ((offset + length) >= cu.buffer_position) &&
(buffer_position <= (cu.buffer_position + cu.length))) (offset <= (cu.buffer_position + cu.length)))
{ {
/* The new insertion can extend the previous insertion change unit. */ /* The new insertion can extend the previous insertion change unit. */
size_t change_buffer_offset = cu.change_buffer_offset + buffer_position - cu.buffer_position; size_t change_buffer_offset = cu.change_buffer_offset + offset - cu.buffer_position;
m_change_buffer->insert(change_buffer_offset, data, length); m_gap_buffer->copy_to(offset, length, *m_change_buffer, change_buffer_offset);
cu.length += length; cu.length += length;
cu.change_buffer_offset = std::min(cu.change_buffer_offset, change_buffer_offset); cu.change_buffer_offset = std::min(cu.change_buffer_offset, change_buffer_offset);
cu.buffer_position = std::min(cu.buffer_position, buffer_position); cu.buffer_position = std::min(cu.buffer_position, offset);
return; return;
} }
else if ((!insert) && (!cu.insert) && else if ((!insert) && (!cu.insert) &&
((buffer_position == cu.buffer_position) || ((offset == cu.buffer_position) ||
((buffer_position + length) == cu.buffer_position))) ((offset + length) == cu.buffer_position)))
{ {
/* The new deletion can extend the previous deletion change unit. */ /* The new deletion can extend the previous deletion change unit. */
if (buffer_position == cu.buffer_position) if (offset == cu.buffer_position)
{ {
/* The new deletion immediately follows the previous. */ /* The new deletion immediately follows the previous. */
m_change_buffer->insert(cu.change_buffer_offset + cu.length, data, length); m_gap_buffer->copy_to(offset, length, *m_change_buffer, cu.change_buffer_offset + cu.length);
} }
else else
{ {
/* The new deletion immediately precedes the previous. */ /* The new deletion immediately precedes the previous. */
m_change_buffer->insert(cu.change_buffer_offset, data, length); m_gap_buffer->copy_to(offset, length, *m_change_buffer, cu.change_buffer_offset);
} }
cu.length += length; cu.length += length;
return; return;
} }
else if ((!insert) && cu.insert && else if ((!insert) && cu.insert &&
(buffer_position >= cu.buffer_position) && (offset >= cu.buffer_position) &&
((buffer_position + length) <= (cu.buffer_position + cu.length))) ((offset + length) <= (cu.buffer_position + cu.length)))
{ {
/* The deletion is removing from the previous insertion change unit. */ /* The deletion is removing from the previous insertion change unit. */
m_change_buffer->erase(cu.change_buffer_offset + (buffer_position - cu.buffer_position), length); m_change_buffer->erase(cu.change_buffer_offset + (offset - cu.buffer_position), length);
if (cu.length <= length) if (cu.length <= length)
{ {
m_current_change_operation->changes.erase(--m_current_change_operation->changes.end()); m_current_change_operation->changes.erase(--m_current_change_operation->changes.end());
@ -342,11 +341,11 @@ void Buffer::record_change(const uint8_t data[], size_t length, size_t buffer_po
} }
/* Start a new change unit. */ /* Start a new change unit. */
size_t change_buffer_offset = m_change_buffer->size(); size_t change_buffer_offset = m_change_buffer->size();
m_change_buffer->insert(change_buffer_offset, data, length); m_gap_buffer->copy_to(offset, length, *m_change_buffer, change_buffer_offset);
ChangeUnit cu; ChangeUnit cu;
cu.change_buffer_offset = change_buffer_offset; cu.change_buffer_offset = change_buffer_offset;
cu.length = length; cu.length = length;
cu.buffer_position = buffer_position; cu.buffer_position = offset;
cu.insert = insert; cu.insert = insert;
m_current_change_operation->changes.push_back(cu); m_current_change_operation->changes.push_back(cu);
} }

View File

@ -157,7 +157,7 @@ protected:
void load_empty_buffer(); void load_empty_buffer();
bool load_from_memory(const uint8_t * data, size_t data_length); 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 load_text_in_buffer(uint8_t * buffer, size_t buffer_size, size_t data_length);
void record_change(const uint8_t data[], size_t length, size_t buffer_position, bool insert); void record_change(size_t offset, size_t length, bool insert);
void save_current_operation(); void save_current_operation();
void warp_iterators_after_insert(size_t offset, size_t length); void warp_iterators_after_insert(size_t offset, size_t length);
void warp_iterators_before_delete(size_t offset, size_t length); void warp_iterators_before_delete(size_t offset, size_t length);