fxos/lib/util/Buffer.cpp

93 lines
2.8 KiB
C++

//---------------------------------------------------------------------------//
// 1100101 |_ mov #0, r4 __ //
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
// |_ base# + offset |_| /_\_\___/__/ //
//---------------------------------------------------------------------------//
#include <fxos/util/Buffer.h>
#include <fxos/util/format.h>
#include <stdexcept>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <filesystem>
namespace fs = std::filesystem;
Buffer::Buffer(): size {0}, data {nullptr}, path {"(none)"}
{
}
/* Empty buffer initialized with given byte */
Buffer::Buffer(size_t bufsize, int fill)
{
this->size = bufsize;
this->data = std::make_unique<char[]>(bufsize);
memset(this->data.get(), fill, bufsize);
this->path = "(anonymous)";
}
/* Buffer initialized from file */
void Buffer::loadFromFile(
std::string const &filepath, ssize_t bufsize, int fill)
{
char const *path = filepath.c_str();
int fd = open(path, O_RDONLY);
if(!fd)
throw std::runtime_error(format("cannot open '%s'", path));
struct stat statbuf;
if(fstat(fd, &statbuf) < 0) {
close(fd);
throw std::runtime_error(format("cannot stat '%s'", path));
}
this->size = (bufsize < 0) ? statbuf.st_size : bufsize;
size_t size_to_read = std::min(size, (size_t)statbuf.st_size);
/* Read buffer and fill whatever is left */
this->data = std::make_unique<char[]>(this->size);
memset(this->data.get(), fill, this->size);
ssize_t x = read(fd, this->data.get(), size_to_read);
close(fd);
if(x != (ssize_t)size_to_read)
throw std::runtime_error(format("error while reading '%s'", path));
this->path = filepath;
}
/* Buffer initialized from file */
Buffer::Buffer(std::string const &filepath, ssize_t bufsize, int fill): Buffer()
{
this->loadFromFile(filepath, bufsize, fill);
}
Buffer::Buffer(std::string filepath, std::vector<std::string> const &folders,
ssize_t size, int fill):
Buffer()
{
for(auto const &f: folders) {
fs::path p = fs::path(f) / fs::path(filepath);
if(fs::exists(p)) {
this->loadFromFile(p, size, fill);
return;
}
}
char const *path = filepath.c_str();
throw std::runtime_error(format("cannot find '%s' in library", path));
}
/* Create a buffer by copying and resizing another buffer */
Buffer::Buffer(Buffer const &other, size_t new_size, int fill):
Buffer(new_size, fill)
{
memcpy(this->data.get(), other.data.get(), std::min(new_size, other.size));
this->path = other.path;
}