implement windows version of nf7::NativeFile

This commit is contained in:
falsycat 2022-08-16 08:02:01 -07:00
parent 2baca5e917
commit 3c40cb9eef
4 changed files with 127 additions and 5 deletions

View File

@ -106,6 +106,7 @@ target_sources(nf7
common/yas_std_variant.hh
$<$<PLATFORM_ID:Linux>:common/native_file_unix.cc>
$<$<PLATFORM_ID:Windows>:common/native_file_win.cc>
file/audio_context.cc
file/audio_device.cc

View File

@ -18,7 +18,6 @@ class NativeFile final : public nf7::Buffer, public nf7::Context {
enum Flag : uint8_t {
kCreateIf = 1 << 0,
kExclusive = 1 << 1,
kTrunc = 1 << 2,
};
using Flags = uint8_t;
@ -56,7 +55,7 @@ class NativeFile final : public nf7::Buffer, public nf7::Context {
const Buffer::Flags flags_;
const NativeFile::Flags nflags_;
std::optional<uint64_t> handle_;
std::optional<uintptr_t> handle_;
};
} // namespace nf7

View File

@ -8,8 +8,6 @@ extern "C" {
#include <unistd.h>
}
#include <thread>
namespace nf7 {
@ -27,7 +25,6 @@ void NativeFile::Lock() {
flags |= O_WRONLY;
}
if (nflags_ & kCreateIf) flags |= O_CREAT;
if (nflags_ & kTrunc) flags |= O_TRUNC;
int fd = open(path_.string().c_str(), flags, 0600);
if (fd < 0) {

125
common/native_file_win.cc Normal file
View File

@ -0,0 +1,125 @@
#include "common/native_file.hh"
extern "C" {
#include <windows.h>
}
namespace nf7 {
void NativeFile::Lock() {
if (handle_) {
throw nf7::Buffer::IOException("already locked");
}
DWORD acc = 0;
if (flags_ & nf7::Buffer::kRead) {
acc |= GENERIC_READ;
}
if (flags_ & nf7::Buffer::kWrite) {
acc |= GENERIC_WRITE;
}
DWORD flags = 0;
if (nflags_ & kCreateIf) {
flags |= OPEN_ALWAYS;
} else {
flags |= OPEN_EXISTING;
}
HANDLE h = CreateFileA(
path_.string().c_str(),
acc, 0, nullptr, flags, FILE_ATTRIBUTE_NORMAL, nullptr);
if (h == INVALID_HANDLE_VALUE) {
throw IOException {"open failure"};
}
handle_ = reinterpret_cast<uintptr_t>(h);
}
void NativeFile::Unlock() {
if (!handle_) {
throw nf7::Buffer::IOException("not locked yet");
}
auto h = reinterpret_cast<HANDLE>(*handle_);
if (!CloseHandle(h)) {
throw nf7::Buffer::IOException("close failure");
}
handle_ = std::nullopt;
}
size_t NativeFile::Read(size_t offset, uint8_t* buf, size_t size) {
if (!handle_) {
throw nf7::Buffer::IOException("not locked yet");
}
const auto h = reinterpret_cast<HANDLE>(*handle_);
LONG off_low = offset & 0xFFFFFFFF;
LONG off_high = offset >> 32;
if (INVALID_SET_FILE_POINTER == SetFilePointer(h, off_low, &off_high, FILE_BEGIN)) {
throw nf7::Buffer::IOException("failed to set file pointer");
}
DWORD ret;
if (!ReadFile(h, buf, static_cast<DWORD>(size), &ret, nullptr)) {
throw nf7::Buffer::IOException("read failure");
}
return static_cast<size_t>(ret);
}
size_t NativeFile::Write(size_t offset, const uint8_t* buf, size_t size) {
if (!handle_) {
throw nf7::Buffer::IOException("not locked yet");
}
const auto h = reinterpret_cast<HANDLE>(*handle_);
LONG off_low = offset & 0xFFFFFFFF;
LONG off_high = offset >> 32;
if (INVALID_SET_FILE_POINTER == SetFilePointer(h, off_low, &off_high, FILE_BEGIN)) {
throw nf7::Buffer::IOException("failed to set file pointer");
}
DWORD ret;
if (!WriteFile(h, buf, static_cast<DWORD>(size), &ret, nullptr)) {
throw nf7::Buffer::IOException("read failure");
}
return static_cast<size_t>(ret);
}
size_t NativeFile::Truncate(size_t size) {
if (!handle_) {
throw nf7::Buffer::IOException("not locked yet");
}
const auto h = reinterpret_cast<HANDLE>(*handle_);
LONG off_low = size & 0xFFFFFFFF;
LONG off_high = size >> 32;
if (INVALID_SET_FILE_POINTER == SetFilePointer(h, off_low, &off_high, FILE_BEGIN)) {
throw nf7::Buffer::IOException("failed to set file pointer");
}
if (!SetEndOfFile(h)) {
throw nf7::Buffer::IOException("SetEndOfFile failure");
}
return size;
}
size_t NativeFile::size() const {
if (!handle_) {
throw nf7::Buffer::IOException("not locked yet");
}
const auto h = reinterpret_cast<HANDLE>(*handle_);
DWORD high;
DWORD low = GetFileSize(h, &high);
if (low == INVALID_FILE_SIZE) {
throw nf7::Buffer::IOException("GetFileSize failure");
}
return (static_cast<size_t>(high) << 32) | low;
}
void NativeFile::CleanUp() noexcept {
}
void NativeFile::Abort() noexcept {
}
size_t NativeFile::GetMemoryUsage() const noexcept {
return 0;
}
std::string NativeFile::GetDescription() const noexcept {
return path_.string() + (handle_? " (active)": " (inactive)");
}
} // namespace nf7