2021-09-08 15:18:24 +02:00
|
|
|
#include <hex/helpers/file.hpp>
|
2022-06-27 14:58:40 +02:00
|
|
|
|
2022-08-16 00:29:53 +02:00
|
|
|
#include <hex/helpers/utils.hpp>
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2022-03-04 11:36:37 +01:00
|
|
|
namespace hex::fs {
|
2021-09-08 15:18:24 +02:00
|
|
|
|
2022-03-04 11:36:37 +01:00
|
|
|
File::File(const std::fs::path &path, Mode mode) noexcept : m_path(path) {
|
2022-06-30 14:57:05 +02:00
|
|
|
#if defined(OS_WINDOWS)
|
|
|
|
if (mode == File::Mode::Read)
|
|
|
|
this->m_file = _wfopen(path.c_str(), L"rb");
|
|
|
|
else if (mode == File::Mode::Write)
|
|
|
|
this->m_file = _wfopen(path.c_str(), L"r+b");
|
2021-09-08 15:18:24 +02:00
|
|
|
|
2022-06-30 14:57:05 +02:00
|
|
|
if (mode == File::Mode::Create || (mode == File::Mode::Write && this->m_file == nullptr))
|
|
|
|
this->m_file = _wfopen(path.c_str(), L"w+b");
|
|
|
|
#else
|
|
|
|
if (mode == File::Mode::Read)
|
2022-10-04 09:10:58 +02:00
|
|
|
this->m_file = fopen64(hex::toUTF8String(path).c_str(), "rb");
|
2022-06-30 14:57:05 +02:00
|
|
|
else if (mode == File::Mode::Write)
|
2022-10-04 09:10:58 +02:00
|
|
|
this->m_file = fopen64(hex::toUTF8String(path).c_str(), "r+b");
|
2022-06-30 14:57:05 +02:00
|
|
|
|
|
|
|
if (mode == File::Mode::Create || (mode == File::Mode::Write && this->m_file == nullptr))
|
2022-10-04 09:10:58 +02:00
|
|
|
this->m_file = fopen64(hex::toUTF8String(path).c_str(), "w+b");
|
2022-06-30 14:57:05 +02:00
|
|
|
#endif
|
2021-09-08 15:18:24 +02:00
|
|
|
}
|
|
|
|
|
2022-01-17 20:06:00 +01:00
|
|
|
File::File() noexcept {
|
2021-09-11 14:41:18 +02:00
|
|
|
this->m_file = nullptr;
|
|
|
|
}
|
|
|
|
|
2021-09-12 20:26:39 +02:00
|
|
|
File::File(File &&other) noexcept {
|
|
|
|
this->m_file = other.m_file;
|
|
|
|
other.m_file = nullptr;
|
|
|
|
}
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
File::~File() {
|
2021-09-22 17:56:06 +02:00
|
|
|
this->close();
|
2021-09-08 15:18:24 +02:00
|
|
|
}
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
File &File::operator=(File &&other) noexcept {
|
2022-01-17 20:06:00 +01:00
|
|
|
this->m_file = other.m_file;
|
|
|
|
other.m_file = nullptr;
|
|
|
|
|
|
|
|
this->m_path = std::move(other.m_path);
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
void File::seek(u64 offset) {
|
|
|
|
fseeko64(this->m_file, offset, SEEK_SET);
|
|
|
|
}
|
|
|
|
|
2021-09-22 17:56:06 +02:00
|
|
|
void File::close() {
|
|
|
|
if (isValid()) {
|
2022-03-01 00:03:28 +01:00
|
|
|
std::fclose(this->m_file);
|
2021-09-22 17:56:06 +02:00
|
|
|
this->m_file = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-11 14:41:18 +02:00
|
|
|
size_t File::readBuffer(u8 *buffer, size_t size) {
|
|
|
|
if (!isValid()) return 0;
|
|
|
|
|
|
|
|
return fread(buffer, size, 1, this->m_file);
|
|
|
|
}
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
std::vector<u8> File::readBytes(size_t numBytes) {
|
2022-01-24 20:53:17 +01:00
|
|
|
if (!isValid()) return {};
|
2021-09-11 14:41:18 +02:00
|
|
|
|
2023-01-04 14:03:09 +01:00
|
|
|
auto size = numBytes == 0 ? getSize() : numBytes;
|
2022-02-26 16:43:38 +01:00
|
|
|
if (size == 0) return {};
|
|
|
|
|
2022-02-12 15:39:47 +01:00
|
|
|
std::vector<u8> bytes(size);
|
2022-01-24 20:53:17 +01:00
|
|
|
auto bytesRead = fread(bytes.data(), 1, bytes.size(), this->m_file);
|
2021-09-08 15:18:24 +02:00
|
|
|
|
|
|
|
bytes.resize(bytesRead);
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string File::readString(size_t numBytes) {
|
2022-01-24 20:53:17 +01:00
|
|
|
if (!isValid()) return {};
|
2021-09-11 14:41:18 +02:00
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
if (getSize() == 0) return {};
|
2021-10-05 18:46:57 +02:00
|
|
|
|
2021-10-07 14:49:49 +02:00
|
|
|
auto bytes = readBytes(numBytes);
|
|
|
|
|
2022-02-26 16:43:38 +01:00
|
|
|
if (bytes.empty())
|
|
|
|
return "";
|
|
|
|
|
2022-07-02 10:05:25 +02:00
|
|
|
auto cString = reinterpret_cast<const char *>(bytes.data());
|
2022-08-16 00:29:53 +02:00
|
|
|
return { cString, hex::strnlen(cString, bytes.size()) };
|
2021-09-08 15:18:24 +02:00
|
|
|
}
|
|
|
|
|
2022-07-02 10:05:25 +02:00
|
|
|
std::u8string File::readU8String(size_t numBytes) {
|
|
|
|
if (!isValid()) return {};
|
|
|
|
|
|
|
|
if (getSize() == 0) return {};
|
|
|
|
|
|
|
|
auto bytes = readBytes(numBytes);
|
|
|
|
|
|
|
|
if (bytes.empty())
|
|
|
|
return u8"";
|
|
|
|
|
|
|
|
auto cString = reinterpret_cast<const char8_t *>(bytes.data());
|
2022-08-16 00:39:56 +02:00
|
|
|
return { cString, hex::strnlen(reinterpret_cast<const char*>(bytes.data()), bytes.size()) };
|
2022-07-02 10:05:25 +02:00
|
|
|
}
|
|
|
|
|
2021-09-11 14:41:18 +02:00
|
|
|
void File::write(const u8 *buffer, size_t size) {
|
|
|
|
if (!isValid()) return;
|
|
|
|
|
2022-03-01 00:03:28 +01:00
|
|
|
std::fwrite(buffer, size, 1, this->m_file);
|
2021-09-11 14:41:18 +02:00
|
|
|
}
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
void File::write(const std::vector<u8> &bytes) {
|
2021-09-11 14:41:18 +02:00
|
|
|
if (!isValid()) return;
|
|
|
|
|
2022-03-01 00:03:28 +01:00
|
|
|
std::fwrite(bytes.data(), 1, bytes.size(), this->m_file);
|
2021-09-08 15:18:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void File::write(const std::string &string) {
|
2021-09-11 14:41:18 +02:00
|
|
|
if (!isValid()) return;
|
|
|
|
|
2022-03-01 00:03:28 +01:00
|
|
|
std::fwrite(string.data(), string.size(), 1, this->m_file);
|
2021-09-08 15:18:24 +02:00
|
|
|
}
|
|
|
|
|
2022-07-02 10:05:25 +02:00
|
|
|
void File::write(const std::u8string &string) {
|
|
|
|
if (!isValid()) return;
|
|
|
|
|
|
|
|
std::fwrite(string.data(), string.size(), 1, this->m_file);
|
|
|
|
}
|
|
|
|
|
2021-09-21 02:48:41 +02:00
|
|
|
size_t File::getSize() const {
|
2021-09-11 14:41:18 +02:00
|
|
|
if (!isValid()) return 0;
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
auto startPos = ftello64(this->m_file);
|
|
|
|
fseeko64(this->m_file, 0, SEEK_END);
|
2022-02-26 17:15:35 +01:00
|
|
|
auto size = ftello64(this->m_file);
|
2021-09-08 15:18:24 +02:00
|
|
|
fseeko64(this->m_file, startPos, SEEK_SET);
|
|
|
|
|
2022-02-26 17:15:35 +01:00
|
|
|
if (size < 0)
|
|
|
|
return 0;
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void File::setSize(u64 size) {
|
2021-09-11 14:41:18 +02:00
|
|
|
if (!isValid()) return;
|
|
|
|
|
2022-03-27 00:01:28 +01:00
|
|
|
auto result = ftruncate64(fileno(this->m_file), size);
|
|
|
|
hex::unused(result);
|
2021-09-08 15:18:24 +02:00
|
|
|
}
|
|
|
|
|
2021-09-22 17:56:06 +02:00
|
|
|
void File::flush() {
|
2022-03-01 00:03:28 +01:00
|
|
|
std::fflush(this->m_file);
|
2021-09-22 17:56:06 +02:00
|
|
|
}
|
|
|
|
|
2022-02-28 23:10:04 +01:00
|
|
|
bool File::remove() {
|
2021-09-22 17:56:06 +02:00
|
|
|
this->close();
|
2022-10-04 09:10:58 +02:00
|
|
|
return std::remove(hex::toUTF8String(this->m_path).c_str()) == 0;
|
2021-09-22 17:56:06 +02:00
|
|
|
}
|
|
|
|
|
2022-03-01 00:03:28 +01:00
|
|
|
void File::disableBuffering() {
|
|
|
|
if (!isValid()) return;
|
|
|
|
|
|
|
|
std::setvbuf(this->m_file, nullptr, _IONBF, 0);
|
|
|
|
}
|
|
|
|
|
2023-02-17 10:26:09 +01:00
|
|
|
std::optional<struct stat> File::getFileInfo() {
|
|
|
|
struct stat fileInfo = { };
|
|
|
|
|
|
|
|
#if defined(OS_WINDOWS)
|
|
|
|
if (wstat(this->m_path.c_str(), &fileInfo) != 0)
|
|
|
|
return std::nullopt;
|
|
|
|
#else
|
|
|
|
if (stat(hex::toUTF8String(this->m_path).c_str(), &fileInfo) != 0)
|
|
|
|
return std::nullopt;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return fileInfo;
|
|
|
|
}
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
}
|