add GapBuffer::insert()
This commit is contained in:
parent
8631a94a2b
commit
915d62ceef
@ -13,6 +13,11 @@ public:
|
||||
CP_1252,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_CODE_POINT_SIZE = 8,
|
||||
};
|
||||
|
||||
static Type detect_encoding(const uint8_t * buffer, size_t length);
|
||||
static uint8_t num_bytes_in_code_point(Type type, const uint8_t * encoded);
|
||||
static const uint8_t * beginning_of_code_point(Type type, const uint8_t * encoded);
|
||||
|
@ -43,6 +43,68 @@ void GapBuffer::compact()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert code_point into the gap buffer at position position.
|
||||
*
|
||||
* @param position Position in the gap buffer to insert the code point at.
|
||||
* Must be <= size.
|
||||
* @param code_point The code point to insert.
|
||||
*/
|
||||
void GapBuffer::insert(size_t position, uint32_t code_point)
|
||||
{
|
||||
if (position > m_size)
|
||||
return;
|
||||
check_grow();
|
||||
move_gap(position);
|
||||
size_t size = Encoding::encode(code_point, m_encoding, &m_buffer[m_gap_position]);
|
||||
m_gap_position += size;
|
||||
m_size += size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that there is enough free space in the gap, and if not, grow the gap
|
||||
* and move data.
|
||||
*/
|
||||
void GapBuffer::check_grow()
|
||||
{
|
||||
if (gap_size() < Encoding::MAX_CODE_POINT_SIZE)
|
||||
{
|
||||
/* We're out of space. Allocate more and move. */
|
||||
size_t new_size = (m_buffer_size + (128u * 1024u)) & System::page_base_mask;
|
||||
size_t new_num_pages = new_size >> System::page_size_log;
|
||||
uint8_t * new_buffer = (uint8_t *)System::alloc_pages(new_num_pages);
|
||||
memcpy(new_buffer, m_buffer, m_gap_position);
|
||||
memcpy(&new_buffer[m_gap_position], &m_buffer[m_gap_position + gap_size()], m_size - m_gap_position);
|
||||
|
||||
/* Free the old buffer */
|
||||
System::free_pages(m_buffer, m_buffer_size >> System::page_size_log);
|
||||
|
||||
m_buffer = new_buffer;
|
||||
m_buffer_size = new_size;
|
||||
m_gap_position = m_size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the gap buffer gap position to the requested position.
|
||||
*
|
||||
* @param position New gap position. Must be <= m_size.
|
||||
*/
|
||||
void GapBuffer::move_gap(size_t position)
|
||||
{
|
||||
if (position != m_gap_position)
|
||||
{
|
||||
if (position < m_gap_position)
|
||||
{
|
||||
memmove(&m_buffer[position + gap_size()], &m_buffer[position], m_gap_position - position);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(&m_buffer[m_gap_position], &m_buffer[m_gap_position + gap_size()], position - m_gap_position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GapBuffer::Iterator::go_forward()
|
||||
{
|
||||
|
@ -110,6 +110,7 @@ public:
|
||||
}
|
||||
size_t gap_size() const { return m_buffer_size - m_size; }
|
||||
void compact();
|
||||
void insert(size_t position, uint32_t code_point);
|
||||
|
||||
protected:
|
||||
uint8_t * m_buffer;
|
||||
@ -118,6 +119,9 @@ protected:
|
||||
size_t m_gap_position;
|
||||
Encoding::Type m_encoding;
|
||||
std::list<std::shared_ptr<Cursor>> m_cursors;
|
||||
|
||||
void check_grow();
|
||||
void move_gap(size_t position);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user