149 lines
3.3 KiB
C++
149 lines
3.3 KiB
C++
#include "Buffer.h"
|
|
#include <stdio.h>
|
|
#include "System.h"
|
|
#include "File.h"
|
|
#include "TextLoader.h"
|
|
#include <cassert>
|
|
#include <string.h>
|
|
|
|
Buffer::Buffer()
|
|
{
|
|
common_initialization();
|
|
load_empty_buffer();
|
|
}
|
|
|
|
Buffer::Buffer(const char * filename)
|
|
{
|
|
common_initialization();
|
|
if (!load_from_file(filename))
|
|
{
|
|
load_empty_buffer();
|
|
}
|
|
}
|
|
|
|
Buffer::Buffer(const uint8_t * data, size_t data_length)
|
|
{
|
|
common_initialization();
|
|
if (!load_from_memory(data, data_length))
|
|
{
|
|
load_empty_buffer();
|
|
}
|
|
}
|
|
|
|
void Buffer::common_initialization()
|
|
{
|
|
m_tabstop = 4u;
|
|
}
|
|
|
|
void Buffer::load_empty_buffer()
|
|
{
|
|
m_gap_buffer = std::make_shared<GapBuffer>();
|
|
m_eol_at_eof = true;
|
|
m_line_endings = LineEndings::LF;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
size_t buffer_size = ((unsigned long)file_size + System::page_size + (64u * 1024u)) & System::page_base_mask;
|
|
uint8_t * buffer = (uint8_t *)System::alloc_pages(buffer_size >> System::page_size_log);
|
|
if (buffer == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!file.read(buffer, file_size))
|
|
{
|
|
System::free_pages(buffer, buffer_size >> System::page_size_log);
|
|
return false;
|
|
}
|
|
|
|
load_text_in_buffer(buffer, buffer_size, file_size);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Buffer::load_from_memory(const uint8_t * data, size_t data_length)
|
|
{
|
|
size_t buffer_size = ((unsigned long)data_length + 2u * System::page_size) & System::page_base_mask;
|
|
uint8_t * buffer = (uint8_t *)System::alloc_pages(buffer_size >> System::page_size_log);
|
|
if (buffer == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
memcpy(buffer, data, data_length);
|
|
|
|
load_text_in_buffer(buffer, buffer_size, data_length);
|
|
|
|
return true;
|
|
}
|
|
|
|
void Buffer::load_text_in_buffer(uint8_t * buffer, size_t buffer_size, size_t data_length)
|
|
{
|
|
TextLoader text_loader;
|
|
size_t loaded_size;
|
|
text_loader.load_buffer(buffer, data_length, &loaded_size);
|
|
|
|
m_gap_buffer = std::make_shared<GapBuffer>(buffer, buffer_size, loaded_size);
|
|
m_encoding = text_loader.get_encoding();
|
|
m_eol_at_eof = text_loader.get_eol_at_eof();
|
|
m_line_endings = text_loader.get_line_endings();
|
|
}
|
|
|
|
bool Buffer::write_to_file(const char * filename)
|
|
{
|
|
File file;
|
|
if (!file.open(filename, true))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
m_gap_buffer->compact();
|
|
|
|
Iterator start_of_line(this);
|
|
size_t bytes_written = 0u;
|
|
|
|
while (start_of_line.valid())
|
|
{
|
|
Iterator iterator = start_of_line;
|
|
iterator.go_end_of_line(true);
|
|
size_t len = iterator.address() - start_of_line.address();
|
|
if (len > 0u)
|
|
{
|
|
if (!file.write(start_of_line.address(), len))
|
|
{
|
|
return false;
|
|
}
|
|
bytes_written += len;
|
|
}
|
|
bool moved_down = iterator.go_next_line();
|
|
if (moved_down || m_eol_at_eof)
|
|
{
|
|
if (!file.write(LineEndings::spans[m_line_endings]))
|
|
{
|
|
return false;
|
|
}
|
|
bytes_written += LineEndings::spans[m_line_endings].length;
|
|
}
|
|
if (!moved_down)
|
|
{
|
|
break;
|
|
}
|
|
start_of_line = iterator;
|
|
}
|
|
|
|
return true;
|
|
}
|