fxos/lib/util.cpp

122 lines
2.4 KiB
C++

#include <fxos/util.h>
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
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)
{
size = bufsize;
data = static_cast<char *>(malloc(size));
if(!data) throw std::bad_alloc();
memset(data, fill, size);
path = "(anonymous)";
}
/* Move constructor */
Buffer::Buffer(Buffer &&other):
size {0}, data {nullptr}, path {}
{
*this = std::move(other);
}
/* Move assignment operator */
Buffer &Buffer::operator=(Buffer &&other)
{
if(this != &other)
{
free(data);
data = other.data;
size = other.size;
path = other.path;
other.data = nullptr;
other.size = 0;
other.path = "(moved)";
}
return *this;
}
/* Buffer initialized from file */
Buffer::Buffer(std::string 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;
ssize_t x = fstat(fd, &statbuf);
if(x < 0)
{
close(fd);
throw std::runtime_error(format("cannot stat '%s'", path));
}
size = (bufsize < 0) ? statbuf.st_size : bufsize;
size_t size_to_read = std::min(size, (size_t)statbuf.st_size);
data = static_cast<char *>(malloc(size));
if(!data) throw std::bad_alloc();
/* Read buffer and fill whatever is left */
memset(data, fill, size);
x = read(fd, data, 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::Buffer(std::string filepath, std::vector<std::string> &folders,
ssize_t size, int fill):
Buffer()
{
for(auto &f: folders)
{
fs::path p = fs::path(f) / fs::path(filepath);
if(fs::exists(p))
{
/* Hopefully this will use the move assignment */
*this = Buffer(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(data, other.data, std::min(new_size, other.size));
}
/* Free allocated data, obviously */
Buffer::~Buffer()
{
free(data);
}