66 lines
1.5 KiB
C
66 lines
1.5 KiB
C
|
#pragma once
|
||
|
|
||
|
#include <cstdio>
|
||
|
#include <string>
|
||
|
|
||
|
#include "misc.h"
|
||
|
|
||
|
static void try_close(FILE* file);
|
||
|
|
||
|
class File {
|
||
|
public:
|
||
|
// https://stackoverflow.com/a/2173764
|
||
|
File(const File&) = delete;
|
||
|
File& operator=(const File&) = delete;
|
||
|
|
||
|
inline constexpr File(File&& other) {
|
||
|
try_close(this->_file);
|
||
|
this->_file = other._file;
|
||
|
other._file = nullptr;
|
||
|
}
|
||
|
inline constexpr File& operator=(File&& other) {
|
||
|
if (this == &other) {
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
try_close(this->_file);
|
||
|
this->_file = other._file;
|
||
|
other._file = nullptr;
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
File(const char* __restrict path, const char* __restrict mode) {
|
||
|
using namespace std::string_literals;
|
||
|
|
||
|
this->_file = fopen(path, mode);
|
||
|
if (!this->_file) {
|
||
|
throw_system_error("fopen("s + quote(path) + ')');
|
||
|
}
|
||
|
}
|
||
|
~File() {
|
||
|
try_close(this->_file);
|
||
|
}
|
||
|
|
||
|
void write(const char* data, size_t length) {
|
||
|
if (fwrite(data, 1, length, this->_file) != length) {
|
||
|
throw_system_error("fwrite()");
|
||
|
}
|
||
|
}
|
||
|
inline constexpr void write(const std::string& str) {
|
||
|
this->write(str.data(), str.size());
|
||
|
}
|
||
|
inline constexpr FILE* get() const noexcept {
|
||
|
return this->_file;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
FILE* _file = nullptr;
|
||
|
};
|
||
|
|
||
|
static void try_close(FILE* file) {
|
||
|
if (file && fclose(file)) {
|
||
|
perror("Failed to close a file: fclose()");
|
||
|
}
|
||
|
}
|