jes/src/core/Buffer.cc

118 lines
2.8 KiB
C++

#include "Buffer.h"
#include <stdio.h>
#include "System.h"
#include "File.h"
#include "TextLoader.h"
#include <cassert>
Buffer::Buffer()
{
piece_table = std::make_shared<PieceTable>();
m_file_buffer = nullptr;
m_file_buffer_size = 0u;
m_eol_at_eof = true;
m_line_endings = LineEndings::LF;
m_encoding = Encoding::UTF_8;
piece_table->encoding = m_encoding;
}
Buffer::~Buffer()
{
if (m_file_buffer != nullptr)
{
free_file_buffer();
}
}
bool Buffer::load_from_file(const char * filename)
{
File file;
if (!file.open(filename))
{
return false;
}
size_t file_size = file.get_size();
if (file_size < 0)
{
return false;
}
m_file_buffer_size = ((unsigned long)file_size + System::page_size) & System::page_base_mask;
m_file_buffer = (uint8_t *)System::alloc_pages(m_file_buffer_size >> System::page_size_log);
if (m_file_buffer == NULL)
{
return false;
}
if (!file.read(m_file_buffer, file_size))
{
free_file_buffer();
return false;
}
TextLoader text_loader;
text_loader.load_buffer(m_file_buffer, file_size);
piece_table = std::make_shared<PieceTable>();
for (auto it = text_loader.begin(); it != text_loader.end(); it++)
{
auto next = it;
next++;
bool eol = next != text_loader.end();
it->start[it->length] = PieceTable::INTERNAL_EOL;
piece_table->append_initial_line_piece(it->start, it->length + 1u, eol);
}
m_eol_at_eof = text_loader.get_eol_at_eof();
m_line_endings = text_loader.get_line_endings();
m_encoding = text_loader.get_encoding();
piece_table->encoding = m_encoding;
return true;
}
bool Buffer::write_to_file(const char * filename)
{
File file;
if (!file.open(filename, true))
{
return false;
}
uint32_t bytes_written = 0u;
for (auto piece = piece_table->start_piece->next;
piece != piece_table->end_piece;
piece = piece->next)
{
uint32_t length = piece->length;
if (piece->eol())
{
length--;
}
if (!file.write(piece->start, length))
{
return false;
}
bytes_written += length;
if (((piece->next != piece_table->end_piece) && piece->eol()) ||
(m_eol_at_eof && bytes_written > 0u))
{
if (!file.write(LineEndings::spans[m_line_endings]))
{
return false;
}
bytes_written += LineEndings::spans[m_line_endings].length;
}
}
return true;
}
void Buffer::free_file_buffer()
{
System::free_pages(m_file_buffer, m_file_buffer_size >> System::page_size_log);
m_file_buffer = nullptr;
m_file_buffer_size = 0u;
}