Coverage Report

Created: 2025-12-31 07:22

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