refactor Buffer insert and delete operations

add Buffer functions to insert/erase data chunks
This commit is contained in:
Josh Holtrop 2017-01-09 21:34:16 -05:00
parent 66aa9c5235
commit f3753be4eb
2 changed files with 79 additions and 28 deletions

View File

@ -171,49 +171,61 @@ void Buffer::exit_insert_mode()
void Buffer::insert_code_point(const Buffer::Iterator & position, uint32_t code_point) void Buffer::insert_code_point(const Buffer::Iterator & position, uint32_t code_point)
{ {
push_operation(); push_operation();
Buffer::Iterator local_position = position; uint8_t encoded[Encoding::MAX_CODE_POINT_SIZE * 2];
if ((code_point != '\n') && (size() == 0u))
{
insert_code_point(position, '\n');
}
uint8_t encoded[Encoding::MAX_CODE_POINT_SIZE];
uint8_t bytes = Encoding::encode(code_point, m_encoding, encoded); uint8_t bytes = Encoding::encode(code_point, m_encoding, encoded);
m_gap_buffer->insert(local_position.offset(), encoded, bytes); if ((size() == 0u) && (code_point != '\n'))
record_change(encoded, bytes, local_position.offset(), true); {
ssize_t lines = (code_point == '\n') ? 1 : 0; bytes += Encoding::encode('\n', m_encoding, &encoded[bytes]);
warp_iterators(local_position.offset(), bytes, lines, true); }
insert_data(position.offset(), encoded, bytes);
pop_operation(); 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) void Buffer::erase_code_point(const Buffer::Iterator & position)
{ {
if (position.valid()) if (position.valid())
{ {
push_operation(); push_operation();
Buffer::Iterator local_position = position; erase_data(position.offset(), Encoding::num_bytes_in_code_point(m_encoding, position.address()));
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);
pop_operation(); 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. */
offset++; record_change(m_gap_buffer->address(offset), length, offset, false);
m_gap_buffer->erase(offset, length);
post_warp_cursors();
} }
for (auto iterator : m_iterators)
size_t Buffer::lines_in_data(size_t offset, size_t length)
{ {
if (iterator->offset() >= offset) size_t lines = 0u;
for (size_t i = 0u; i < length; )
{ {
iterator->warp(offset_adjustment, lines_adjustment); uint8_t bytes;
uint32_t c = Encoding::decode(m_encoding, m_gap_buffer->address(offset), &bytes);
if (c == '\n')
{
lines++;
} }
i += bytes;
} }
return lines;
}
void Buffer::post_warp_cursors()
{
for (auto cursor : m_cursors) for (auto cursor : m_cursors)
{ {
if ((*cursor == *m_eof_iterator) && (size() > 0u)) 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() void Buffer::pop_operation()
{ {
if (m_operation_level > 0) 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) if (!m_current_change_operation)
{ {

View File

@ -152,9 +152,14 @@ 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(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 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 #endif