refactor Buffer insert and delete operations
add Buffer functions to insert/erase data chunks
This commit is contained in:
parent
66aa9c5235
commit
f3753be4eb
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user