98 lines
2.5 KiB
C++
98 lines
2.5 KiB
C++
#ifndef PIECETABLE_H
|
|
#define PIECETABLE_H
|
|
|
|
#include <stdint.h>
|
|
#include "PagedBuffer.h"
|
|
#include <utility>
|
|
|
|
#define PIECE_DESCRIPTOR_INDEX_START 0u
|
|
#define PIECE_DESCRIPTOR_INDEX_END 1u
|
|
|
|
#define PIECE_DESCRIPTOR_N_CHARS_EOL_FLAG_MASK 0x80000000u
|
|
|
|
class PieceTable
|
|
{
|
|
public:
|
|
struct PieceDescriptor
|
|
{
|
|
/** The previous piece descriptor in the chain. */
|
|
PieceDescriptor * prev;
|
|
|
|
/** The next piece descriptor in the chain. */
|
|
PieceDescriptor * next;
|
|
|
|
/** Text that the piece describes. */
|
|
uint8_t * start;
|
|
|
|
/** Length of the text (in bytes). */
|
|
uint32_t length;
|
|
|
|
/**
|
|
* Number of characters in the text.
|
|
* Also, the highest bit is the eol flag.
|
|
*/
|
|
uint32_t n_chars;
|
|
|
|
/** Get the number of characters pointed to by this descriptor. */
|
|
uint32_t get_n_chars() { return n_chars & (~PIECE_DESCRIPTOR_N_CHARS_EOL_FLAG_MASK); }
|
|
|
|
/** Get whether this descriptor is the end of a line. */
|
|
bool eol() { return (n_chars & PIECE_DESCRIPTOR_N_CHARS_EOL_FLAG_MASK) != 0u; }
|
|
|
|
/** Toggle whether this descriptor is the end of a line. */
|
|
void toggle_eol() { n_chars ^= PIECE_DESCRIPTOR_N_CHARS_EOL_FLAG_MASK; }
|
|
};
|
|
|
|
struct Position
|
|
{
|
|
/** The piece. */
|
|
PieceDescriptor * pd;
|
|
|
|
/** Byte offset within the piece. */
|
|
uint32_t offset;
|
|
};
|
|
|
|
struct ChangeDescriptor
|
|
{
|
|
uint32_t piece_descriptor_index;
|
|
uint32_t from_val;
|
|
uint32_t to_val;
|
|
uint8_t attr_idx;
|
|
};
|
|
|
|
PieceTable(const uint8_t * file_buffer, unsigned long file_buffer_size);
|
|
|
|
PieceDescriptor * add_piece_descriptor()
|
|
{
|
|
return &m_piece_descriptors[m_piece_descriptor_index++];
|
|
}
|
|
|
|
PieceDescriptor & operator[](uint32_t index)
|
|
{
|
|
return m_piece_descriptors[index];
|
|
}
|
|
|
|
uint32_t get_num_lines() { return m_num_lines; }
|
|
|
|
PieceDescriptor * start_descriptor;
|
|
PieceDescriptor * end_descriptor;
|
|
|
|
Position cursor_position;
|
|
|
|
void append_initial_line_piece(uint8_t * start, uint32_t length, uint32_t n_chars, bool eol);
|
|
|
|
protected:
|
|
const uint8_t * m_file_buffer;
|
|
unsigned long m_file_buffer_size;
|
|
uint32_t m_num_lines;
|
|
|
|
/** Next available piece descriptor index. */
|
|
uint32_t m_piece_descriptor_index;
|
|
|
|
PagedBuffer<uint8_t> m_append_buffer;
|
|
PagedBuffer<PieceDescriptor> m_piece_descriptors;
|
|
PagedBuffer<ChangeDescriptor> m_change_descriptors;
|
|
};
|
|
|
|
#endif
|