You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
1.7 KiB
83 lines
1.7 KiB
#pragma once |
|
|
|
#include <cerrno> |
|
#include <cstdio> |
|
#include <cstring> |
|
#include <string> |
|
|
|
#include "utils/file_util.h" |
|
#include "utils/log.hpp" |
|
#include "utils/stdcompat/optional.hpp" |
|
|
|
namespace devilution { |
|
|
|
// A wrapper around `FILE *` that logs errors. |
|
struct LoggedFStream { |
|
public: |
|
bool Open(const char *path, const char *mode) |
|
{ |
|
s_ = OpenFile(path, mode); |
|
return CheckError("fopen(\"{}\", \"{}\")", path, mode); |
|
} |
|
|
|
void Close() |
|
{ |
|
if (s_ != nullptr) { |
|
std::fclose(s_); |
|
s_ = nullptr; |
|
} |
|
} |
|
|
|
[[nodiscard]] bool IsOpen() const |
|
{ |
|
return s_ != nullptr; |
|
} |
|
|
|
bool Seekp(long pos, int dir = SEEK_SET) |
|
{ |
|
return CheckError(std::fseek(s_, pos, dir) == 0, |
|
"fseek({}, {})", pos, DirToString(dir)); |
|
} |
|
|
|
bool Tellp(long *result) |
|
{ |
|
*result = std::ftell(s_); |
|
return CheckError(*result != -1L, |
|
"ftell() = {}", *result); |
|
} |
|
|
|
bool Write(const char *data, size_t size) |
|
{ |
|
return CheckError(std::fwrite(data, size, 1, s_) == 1, |
|
"fwrite(data, {})", size); |
|
} |
|
|
|
bool Read(char *out, size_t size) |
|
{ |
|
return CheckError(std::fread(out, size, 1, s_) == 1, |
|
"fread(out, {})", size); |
|
} |
|
|
|
private: |
|
static const char *DirToString(int dir); |
|
|
|
template <typename... PrintFArgs> |
|
bool CheckError(bool ok, const char *fmt, PrintFArgs... args) |
|
{ |
|
if (!ok) { |
|
std::string fmtWithError = fmt; |
|
fmtWithError.append(": failed with \"{}\""); |
|
const char *errorMessage = std::strerror(errno); |
|
if (errorMessage == nullptr) |
|
errorMessage = ""; |
|
LogError(LogCategory::System, fmtWithError.c_str(), args..., errorMessage); |
|
} else { |
|
LogVerbose(LogCategory::System, fmt, args...); |
|
} |
|
return ok; |
|
} |
|
|
|
FILE *s_ = nullptr; |
|
}; |
|
|
|
} // namespace devilution
|
|
|