add GapBuffer::insert()

This commit is contained in:
Josh Holtrop 2016-11-27 17:24:59 -05:00
parent 8631a94a2b
commit 915d62ceef
3 changed files with 71 additions and 0 deletions

View File

@ -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);

View File

@ -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()
{

View File

@ -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