176 lines
5.4 KiB
C++
176 lines
5.4 KiB
C++
#ifndef BUFFER_H
|
|
#define BUFFER_H
|
|
|
|
#include <list>
|
|
#include <memory>
|
|
#include "LineEndings.h"
|
|
#include "Encoding.h"
|
|
#include "GapBuffer.h"
|
|
#include <string>
|
|
#include "ChangeOperation.h"
|
|
#include <vector>
|
|
|
|
class Buffer
|
|
{
|
|
public:
|
|
enum : uint32_t
|
|
{
|
|
INVALID_CHANGE_OPERATION_INDEX = 0xFFFFFFFFu,
|
|
};
|
|
|
|
class Iterator
|
|
{
|
|
public:
|
|
enum : uint32_t
|
|
{
|
|
INVALID_CODE_POINT = 0xFFFFFFFFu,
|
|
};
|
|
|
|
Iterator(const Buffer * buffer)
|
|
{
|
|
m_buffer = buffer;
|
|
m_offset = 0u;
|
|
m_line = 0u;
|
|
}
|
|
bool valid() const
|
|
{
|
|
return m_offset < m_buffer->size();
|
|
}
|
|
bool is_start_of_line();
|
|
bool is_end_of_line(bool eol_only);
|
|
bool go_back();
|
|
bool go_forward();
|
|
bool go_start_of_line();
|
|
bool go_end_of_line(bool allow_eol);
|
|
bool go_left_in_line();
|
|
bool go_right_in_line(bool allow_eol);
|
|
bool go_previous_line();
|
|
bool go_next_line();
|
|
Iterator prev();
|
|
Iterator next();
|
|
void warp(ssize_t offset_offset, ssize_t line_offset)
|
|
{
|
|
m_offset += offset_offset;
|
|
m_line += line_offset;
|
|
}
|
|
void warp_to_offset(size_t offset);
|
|
uint8_t * address() const
|
|
{
|
|
return m_buffer->address(m_offset);
|
|
}
|
|
uint32_t operator*() const
|
|
{
|
|
if (valid())
|
|
{
|
|
return Encoding::decode(m_buffer->encoding(), address());
|
|
}
|
|
else
|
|
{
|
|
return INVALID_CODE_POINT;
|
|
}
|
|
}
|
|
bool operator==(const Iterator & other) const
|
|
{
|
|
return m_offset == other.m_offset;
|
|
}
|
|
bool operator!=(const Iterator & other) const
|
|
{
|
|
return m_offset != other.m_offset;
|
|
}
|
|
bool operator<(const Iterator & other) const
|
|
{
|
|
return m_offset < other.m_offset;
|
|
}
|
|
bool operator<=(const Iterator & other) const
|
|
{
|
|
return m_offset <= other.m_offset;
|
|
}
|
|
bool operator>(const Iterator & other) const
|
|
{
|
|
return m_offset > other.m_offset;
|
|
}
|
|
bool operator>=(const Iterator & other) const
|
|
{
|
|
return m_offset >= other.m_offset;
|
|
}
|
|
size_t line() const { return m_line; }
|
|
size_t offset() const { return m_offset; }
|
|
|
|
protected:
|
|
const Buffer * m_buffer;
|
|
size_t m_offset;
|
|
size_t m_line;
|
|
};
|
|
|
|
Buffer();
|
|
Buffer(const char * filename);
|
|
Buffer(const uint8_t * data, size_t data_length);
|
|
bool write_to_file(const char * filename);
|
|
|
|
std::shared_ptr<Iterator> add_iterator()
|
|
{
|
|
std::shared_ptr<Iterator> iterator = std::make_shared<Iterator>(this);
|
|
m_iterators.push_back(iterator);
|
|
return iterator;
|
|
}
|
|
std::shared_ptr<Iterator> add_cursor()
|
|
{
|
|
auto iterator = add_iterator();
|
|
m_cursors.push_back(iterator);
|
|
return iterator;
|
|
}
|
|
auto get_string() { return m_gap_buffer->get_string(); }
|
|
size_t size() const { return m_gap_buffer->size(); }
|
|
uint8_t * address(size_t offset) const { return m_gap_buffer->address(offset); }
|
|
Encoding::Type encoding() const { return m_encoding; }
|
|
uint8_t tabstop() const { return m_tabstop; }
|
|
void enter_insert_mode();
|
|
void exit_insert_mode();
|
|
bool insert_mode() const { return m_insert_mode; }
|
|
void insert_code_point(const Buffer::Iterator & position, uint32_t code_point);
|
|
void erase_code_point(const Buffer::Iterator & position);
|
|
std::string filename() const { return m_filename; }
|
|
Iterator begin() const { return Iterator(this); }
|
|
Iterator end() const { return *m_eof_iterator; }
|
|
void push_operation() { m_operation_level++; }
|
|
void pop_operation();
|
|
void undo();
|
|
void redo();
|
|
|
|
protected:
|
|
bool m_eol_at_eof;
|
|
LineEndings::Type m_line_endings;
|
|
std::shared_ptr<GapBuffer> m_gap_buffer;
|
|
std::shared_ptr<GapBuffer> m_change_buffer;
|
|
Encoding::Type m_encoding;
|
|
uint8_t m_tabstop;
|
|
bool m_insert_mode;
|
|
std::list<std::shared_ptr<Iterator>> m_iterators;
|
|
std::list<std::shared_ptr<Iterator>> m_cursors;
|
|
std::shared_ptr<Iterator> m_eof_iterator;
|
|
std::string m_filename;
|
|
std::shared_ptr<ChangeOperation> m_current_change_operation;
|
|
int m_operation_level;
|
|
size_t m_current_change_operation_index;
|
|
std::vector<std::shared_ptr<ChangeOperation>> m_change_operations;
|
|
|
|
void common_pre_load_initialization();
|
|
void common_post_load_initialization();
|
|
bool load_from_file(const char * filename);
|
|
void load_empty_buffer();
|
|
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 record_change(size_t offset, size_t length, bool insert);
|
|
void save_current_operation();
|
|
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();
|
|
void apply_change_operation(const ChangeOperation & change_operation, bool forward);
|
|
void apply_change_unit(const ChangeUnit & change_unit, bool forward);
|
|
};
|
|
|
|
#endif
|