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)
|
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. */
|
||||||
|
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++;
|
uint8_t bytes;
|
||||||
}
|
uint32_t c = Encoding::decode(m_encoding, m_gap_buffer->address(offset), &bytes);
|
||||||
for (auto iterator : m_iterators)
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
if (iterator->offset() >= offset)
|
lines++;
|
||||||
{
|
|
||||||
iterator->warp(offset_adjustment, lines_adjustment);
|
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user