#include "base/include/buffer.h"
#include <cstdio>
namespace lynx {
namespace base {
using FileUniquePtr = std::unique_ptr<FILE, decltype(&fclose)>;
bool Buffer::WriteToFile(const std::string& path) const {
const size_t length = size();
const uint8_t* bytes = data();
if (bytes == nullptr && length != 0) {
return false;
}
FILE* file = fopen(path.c_str(), "wb");
if (file == nullptr) {
return false;
}
const bool success = length == 0 || fwrite(bytes, 1, length, file) == length;
const int close_result = fclose(file);
return success && close_result == 0;
}
std::unique_ptr<Buffer> Buffer::ReadFromFile(const std::string& path,
size_t max_size) {
auto file = FileUniquePtr(fopen(path.c_str(), "rb"), &fclose);
if (!file) {
return nullptr;
}
if (fseek(file.get(), 0, SEEK_END) != 0) {
return nullptr;
}
const long file_size = ftell(file.get());
if (file_size < 0 || static_cast<size_t>(file_size) > max_size ||
fseek(file.get(), 0, SEEK_SET) != 0) {
return nullptr;
}
auto buffer = std::make_unique<StringBuffer>(std::string{});
auto& content = buffer->GetString();
const size_t size = static_cast<size_t>(file_size);
if (size > content.max_size()) {
return nullptr;
}
content.resize(size);
if ((size != 0 && fread(content.data(), 1, size, file.get()) != size) ||
ferror(file.get())) {
return nullptr;
}
if (fclose(file.release()) != 0) {
return nullptr;
}
return buffer;
}
}
}