#ifndef GAPBUFFER_H #define GAPBUFFER_H #include #include #ifdef ENABLE_TESTING #include #endif class GapBuffer { public: /** * Create a new GapBuffer object. * * The GapBuffer will allocate its own memory. */ GapBuffer(); /** * Create a GapBuffer object that points to preallocated memory. * * The GapBuffer object will take over ownership of the allocated memory. * * @param buffer * Pointer to buffer allocated by System::alloc_pages(). * @param buffer_size * Size of the buffer allocated by System::alloc_pages(). * @param size * Size of the data in the buffer. */ GapBuffer(uint8_t * buffer, size_t buffer_size, size_t size); /** * Destroy the GapBuffer object and free its memory. */ ~GapBuffer(); /** * Insert data into the gap buffer at the given position. * * @param position * Position in the gap buffer to insert the code point at. * @param data * Pointer to the data to insert. * @param length * Length of the data to insert. */ void insert(size_t position, const uint8_t * data, size_t length); /** * Erase data from the gap buffer. * * @param position * Position in the gap buffer to erase data from. * @param length * Length of the data to erase. */ void erase(size_t position, size_t length); /** * Erase all data from the gap buffer. */ void clear(); /** * Get the size of the data stored within the buffer. */ size_t size() const { return m_size; } /** * Get the memory address of a buffer location. * * @param offset * The index into the gap buffer data. */ uint8_t * address(size_t offset) const { if (offset < m_gap_position) { return &m_buffer[offset]; } else { return &m_buffer[offset + gap_size()]; } } /** * Move buffer gap to the end of the buffer so the contents are congruent * at the beginning of the buffer. */ void compact() { move_gap(m_size); } /** * Copy a range of data from this GapBuffer to another. * * @param source_position * Position in the gap buffer containing the data to copy. * @param length * Length of the data to copy. * @param other * Destination GapBuffer to copy the data into. * @param destination_position * Position in the destination GapBuffer to copy the data to. */ void copy_to(size_t source_position, size_t length, GapBuffer & other, size_t destination_position); #ifdef ENABLE_TESTING /** * Get the contents of the gap buffer as a string. * * This makes a copy of the entire buffer in a std::string. This method is * intended for use by unit tests. */ std::string get_string(); /** * Replace the buffer contents with a string. */ void set_string(const std::string & s); #endif protected: /** Address of the allocated memory buffer. */ uint8_t * m_buffer; /** Size of the allocated memory buffer. */ size_t m_buffer_size; /** Size of the data stored in the buffer. */ size_t m_size; /** Index of the gap in the memory buffer. */ size_t m_gap_position; /** * Get the gap size. */ size_t gap_size() const { return m_buffer_size - m_size; } /** * Verify that there is enough free space in the gap, and if not, grow the * gap and move data. * * @param length * The number of bytes that must be free. */ void ensure_free(size_t length); /** * Move the gap buffer gap position to the requested position. * * @param position * New gap position. Must be <= m_size. */ void move_gap(size_t position); }; #endif