| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "hwy/detect_compiler_arch.h" |
| |
| |
| #if HWY_OS_WIN |
|
|
| #include <stddef.h> |
| #include <stdint.h> |
|
|
| #include "compression/io.h" |
| #include "hwy/base.h" |
| #ifndef WIN32_LEAN_AND_MEAN |
| #define WIN32_LEAN_AND_MEAN |
| #endif |
| #ifndef VC_EXTRALEAN |
| #define VC_EXTRALEAN |
| #endif |
| #include <Windows.h> |
|
|
| namespace gcpp { |
|
|
| class FileWin : public File { |
| HANDLE hFile_ = INVALID_HANDLE_VALUE; |
|
|
| public: |
| FileWin(HANDLE hFile) : hFile_(hFile) { |
| HWY_ASSERT(hFile != INVALID_HANDLE_VALUE); |
| } |
| ~FileWin() override { |
| if (hFile_ != INVALID_HANDLE_VALUE) { |
| HWY_ASSERT(CloseHandle(hFile_) != 0); |
| } |
| } |
|
|
| uint64_t FileSize() const override { |
| DWORD hi; |
| const DWORD lo = GetFileSize(hFile_, &hi); |
| if (lo == INVALID_FILE_SIZE) return 0; |
| return (static_cast<uint64_t>(hi) << 32) | lo; |
| } |
|
|
| bool Read(uint64_t offset, uint64_t size, void* to) const override { |
| uint8_t* bytes = reinterpret_cast<uint8_t*>(to); |
| OVERLAPPED overlapped = {0}; |
| |
| while (size != 0) { |
| overlapped.Offset = offset & 0xFFFFFFFF; |
| overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; |
| const DWORD want = |
| static_cast<DWORD>(HWY_MIN(size, uint64_t{0xFFFFFFFF})); |
| DWORD got; |
| if (!ReadFile(hFile_, bytes, want, &got, &overlapped)) { |
| if (GetLastError() != ERROR_HANDLE_EOF) { |
| return false; |
| } |
| } |
| offset += got; |
| bytes += got; |
| size -= got; |
| } |
| return true; |
| } |
|
|
| bool Write(const void* from, uint64_t size, uint64_t offset) override { |
| const uint8_t* bytes = reinterpret_cast<const uint8_t*>(from); |
| OVERLAPPED overlapped = {0}; |
| |
| while (size != 0) { |
| overlapped.Offset = offset & 0xFFFFFFFF; |
| overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; |
| const DWORD want = |
| static_cast<DWORD>(HWY_MIN(size, uint64_t{0xFFFFFFFF})); |
| DWORD got; |
| if (!WriteFile(hFile_, bytes, want, &got, &overlapped)) { |
| if (GetLastError() != ERROR_HANDLE_EOF) { |
| return false; |
| } |
| } |
| offset += got; |
| bytes += got; |
| size -= got; |
| } |
| return true; |
| } |
| }; |
|
|
| std::unique_ptr<File> OpenFileOrNull(const Path& filename, const char* mode) { |
| const bool is_read = mode[0] != 'w'; |
| const DWORD flags = |
| FILE_ATTRIBUTE_NORMAL | (is_read ? FILE_FLAG_SEQUENTIAL_SCAN : 0); |
| const DWORD access = is_read ? GENERIC_READ : GENERIC_WRITE; |
| const DWORD share = is_read ? FILE_SHARE_READ : 0; |
| const DWORD create = is_read ? OPEN_EXISTING : CREATE_ALWAYS; |
| const HANDLE hFile = CreateFileA(filename.path.c_str(), access, share, |
| nullptr, create, flags, nullptr); |
| if (hFile == INVALID_HANDLE_VALUE) return std::unique_ptr<File>(); |
| return std::make_unique<FileWin>(hFile); |
| } |
|
|
| } |
| #endif |
|
|