jes/src/core/Buffer.h

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