mmap.cc (4010B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #include "mmap.h" 7 8 #include <cstdint> 9 #include <memory> 10 11 #include "lib/jxl/base/common.h" 12 13 #if defined(__unix__) || defined(__unix) || \ 14 defined(__APPLE__) && defined(__MACH__) 15 #include <fcntl.h> 16 #include <sys/mman.h> 17 #include <unistd.h> 18 19 namespace jxl { 20 21 struct MemoryMappedFileImpl { 22 static StatusOr<std::unique_ptr<MemoryMappedFileImpl>> Init( 23 const char* path) { 24 auto f = make_unique<MemoryMappedFileImpl>(); 25 f->fd = open(path, O_RDONLY); 26 if (f->fd == -1) { 27 return JXL_FAILURE("Cannot open file %s", path); 28 } 29 f->mmap_len = lseek(f->fd, 0, SEEK_END); 30 lseek(f->fd, 0, SEEK_SET); 31 32 f->ptr = mmap(nullptr, f->mmap_len, PROT_READ, MAP_SHARED, f->fd, 0); 33 if (f->ptr == MAP_FAILED) { 34 return JXL_FAILURE("mmap failure"); 35 } 36 return f; 37 } 38 39 const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(ptr); } 40 size_t size() const { return mmap_len; } 41 42 ~MemoryMappedFileImpl() { 43 if (fd != -1) { 44 close(fd); 45 } 46 if (ptr != nullptr) { 47 munmap(ptr, mmap_len); 48 } 49 } 50 51 int fd = -1; 52 size_t mmap_len = 0; 53 void* ptr = nullptr; 54 }; 55 56 } // namespace jxl 57 58 #elif defined(_WIN32) 59 #include <string.h> 60 #include <windows.h> 61 62 namespace { 63 64 struct HandleDeleter { 65 void operator()(const HANDLE handle) const { 66 if (handle != INVALID_HANDLE_VALUE) { 67 CloseHandle(handle); 68 } 69 } 70 }; 71 using HandleUniquePtr = 72 std::unique_ptr<std::remove_pointer<HANDLE>::type, HandleDeleter>; 73 74 } // namespace 75 76 namespace jxl { 77 78 struct MemoryMappedFileImpl { 79 static StatusOr<std::unique_ptr<MemoryMappedFileImpl>> Init( 80 const char* path) { 81 auto f = make_unique<MemoryMappedFileImpl>(); 82 std::wstring stemp = std::wstring(path, path + strlen(path)); 83 f->handle.reset(CreateFileW(stemp.c_str(), GENERIC_READ, FILE_SHARE_READ, 84 nullptr, OPEN_EXISTING, 85 FILE_FLAG_SEQUENTIAL_SCAN, nullptr)); 86 if (f->handle.get() == INVALID_HANDLE_VALUE) { 87 return JXL_FAILURE("Cannot open file %s", path); 88 } 89 if (!GetFileSizeEx(f->handle.get(), &f->fsize)) { 90 return JXL_FAILURE("Cannot get file size (%s)", path); 91 } 92 f->handle_mapping.reset(CreateFileMappingW(f->handle.get(), nullptr, 93 PAGE_READONLY, 0, 0, nullptr)); 94 if (f->handle_mapping == nullptr) { 95 return JXL_FAILURE("Cannot create memory mapping (%s)", path); 96 } 97 f->ptr = MapViewOfFile(f->handle_mapping.get(), FILE_MAP_READ, 0, 0, 0); 98 return f; 99 } 100 101 ~MemoryMappedFileImpl() { UnmapViewOfFile(ptr); } 102 103 const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(ptr); } 104 size_t size() const { return fsize.QuadPart; } 105 106 HandleUniquePtr handle; 107 HandleUniquePtr handle_mapping; 108 LARGE_INTEGER fsize; 109 void* ptr = nullptr; 110 }; 111 112 } // namespace jxl 113 114 #else 115 116 namespace jxl { 117 118 struct MemoryMappedFileImpl { 119 static StatusOr<std::unique_ptr<MemoryMappedFileImpl>> Init( 120 const char* path) { 121 return JXL_FAILURE("Memory mapping not supported on this system"); 122 } 123 124 const uint8_t* data() const { return nullptr; } 125 size_t size() const { return 0; } 126 }; 127 128 } // namespace jxl 129 130 #endif 131 132 namespace jxl { 133 134 StatusOr<MemoryMappedFile> MemoryMappedFile::Init(const char* path) { 135 JXL_ASSIGN_OR_RETURN(auto mmf, MemoryMappedFileImpl::Init(path)); 136 MemoryMappedFile ret; 137 ret.impl_ = std::move(mmf); 138 return ret; 139 } 140 141 MemoryMappedFile::MemoryMappedFile() = default; 142 MemoryMappedFile::~MemoryMappedFile() = default; 143 MemoryMappedFile::MemoryMappedFile(MemoryMappedFile&&) noexcept = default; 144 MemoryMappedFile& MemoryMappedFile::operator=(MemoryMappedFile&&) noexcept = 145 default; 146 147 const uint8_t* MemoryMappedFile::data() const { return impl_->data(); } 148 size_t MemoryMappedFile::size() const { return impl_->size(); } 149 } // namespace jxl