#include "common/serializer/buffered_file.h"
#include <cstring>
#include "common/assert.h"
#include "common/exception/runtime.h"
#include "common/file_system/file_info.h"
#include "common/system_config.h"
#include <format>
namespace lbug {
namespace common {
static constexpr uint64_t BUFFER_SIZE = LBUG_PAGE_SIZE;
BufferedFileWriter::BufferedFileWriter(FileInfo& fileInfo)
: buffer(std::make_unique<uint8_t[]>(BUFFER_SIZE)), fileOffset(0), bufferOffset(0),
fileInfo(fileInfo) {}
BufferedFileWriter::~BufferedFileWriter() {
flush();
}
void BufferedFileWriter::write(const uint8_t* data, uint64_t size) {
if (size > BUFFER_SIZE) {
flush();
fileInfo.writeFile(data, size, fileOffset);
fileOffset += size;
return;
}
DASSERT(size <= BUFFER_SIZE);
if (bufferOffset + size <= BUFFER_SIZE) {
memcpy(&buffer[bufferOffset], data, size);
bufferOffset += size;
} else {
auto toCopy = BUFFER_SIZE - bufferOffset;
memcpy(&buffer[bufferOffset], data, toCopy);
bufferOffset += toCopy;
flush();
auto remaining = size - toCopy;
memcpy(buffer.get(), data + toCopy, remaining);
bufferOffset += remaining;
}
}
void BufferedFileWriter::clear() {
fileInfo.truncate(0);
resetOffsets();
}
void BufferedFileWriter::flush() {
if (bufferOffset == 0) {
return;
}
fileInfo.writeFile(buffer.get(), bufferOffset, fileOffset);
fileOffset += bufferOffset;
bufferOffset = 0;
memset(buffer.get(), 0, BUFFER_SIZE);
}
void BufferedFileWriter::sync() {
fileInfo.syncFile();
}
uint64_t BufferedFileWriter::getSize() const {
return fileInfo.getFileSize() + bufferOffset;
}
BufferedFileReader::BufferedFileReader(FileInfo& fileInfo)
: buffer(std::make_unique<uint8_t[]>(BUFFER_SIZE)), fileOffset(0), bufferOffset(0),
fileInfo(fileInfo), bufferSize{0} {
fileSize = this->fileInfo.getFileSize();
readNextPage();
}
void BufferedFileReader::read(uint8_t* data, uint64_t size) {
if (size > BUFFER_SIZE) {
fileOffset -= bufferSize;
fileOffset += bufferOffset;
fileInfo.readFromFile(data, size, fileOffset);
fileOffset += size;
bufferOffset = bufferSize;
} else if (bufferOffset + size <= bufferSize) {
memcpy(data, &buffer[bufferOffset], size);
bufferOffset += size;
} else {
auto toCopy = bufferSize - bufferOffset;
memcpy(data, &buffer[bufferOffset], toCopy);
bufferOffset += toCopy;
readNextPage();
auto remaining = size - toCopy;
memcpy(data + toCopy, buffer.get(), remaining);
bufferOffset += remaining;
}
}
bool BufferedFileReader::finished() {
return bufferOffset >= bufferSize && fileSize <= fileOffset;
}
void BufferedFileReader::readNextPage() {
if (fileSize <= fileOffset) {
throw RuntimeException(
std::format("Reading past the end of the file {} with size {} at offset {}",
fileInfo.path, fileSize, fileOffset));
}
bufferSize = std::min(fileSize - fileOffset, BUFFER_SIZE);
fileInfo.readFromFile(buffer.get(), bufferSize, fileOffset);
fileOffset += bufferSize;
bufferOffset = 0;
}
} }