#include #include #include #include #include #include #include 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(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(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 &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); }