summaryrefslogtreecommitdiffstats
path: root/third_party/jpeg-xl/lib/extras/mmap.cc
blob: 9f5bba97edae54ad94f0f54f3f38df5c02bb10e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "mmap.h"

#include <cstdint>
#include <memory>

#include "lib/jxl/base/common.h"

#if defined(__unix__) || defined(__unix) || \
    defined(__APPLE__) && defined(__MACH__)
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

namespace jxl {

struct MemoryMappedFileImpl {
  static StatusOr<std::unique_ptr<MemoryMappedFileImpl>> Init(
      const char* path) {
    auto f = make_unique<MemoryMappedFileImpl>();
    f->fd = open(path, O_RDONLY);
    if (f->fd == -1) {
      return JXL_FAILURE("Cannot open file %s", path);
    }
    f->mmap_len = lseek(f->fd, 0, SEEK_END);
    lseek(f->fd, 0, SEEK_SET);

    f->ptr = mmap(nullptr, f->mmap_len, PROT_READ, MAP_SHARED, f->fd, 0);
    if (f->ptr == MAP_FAILED) {
      return JXL_FAILURE("mmap failure");
    }
    return f;
  }

  const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(ptr); }
  size_t size() const { return mmap_len; }

  ~MemoryMappedFileImpl() {
    if (fd != -1) {
      close(fd);
    }
    if (ptr != nullptr) {
      munmap(ptr, mmap_len);
    }
  }

  int fd = -1;
  size_t mmap_len = 0;
  void* ptr = nullptr;
};

}  // namespace jxl

#elif defined(_WIN32)
#include <string.h>
#include <windows.h>

namespace {

struct HandleDeleter {
  void operator()(const HANDLE handle) const {
    if (handle != INVALID_HANDLE_VALUE) {
      CloseHandle(handle);
    }
  }
};
using HandleUniquePtr =
    std::unique_ptr<std::remove_pointer<HANDLE>::type, HandleDeleter>;

}  // namespace

namespace jxl {

struct MemoryMappedFileImpl {
  static StatusOr<std::unique_ptr<MemoryMappedFileImpl>> Init(
      const char* path) {
    auto f = make_unique<MemoryMappedFileImpl>();
    std::wstring stemp = std::wstring(path, path + strlen(path));
    f->handle.reset(CreateFileW(stemp.c_str(), GENERIC_READ, FILE_SHARE_READ,
                                nullptr, OPEN_EXISTING,
                                FILE_FLAG_SEQUENTIAL_SCAN, nullptr));
    if (f->handle.get() == INVALID_HANDLE_VALUE) {
      return JXL_FAILURE("Cannot open file %s", path);
    }
    if (!GetFileSizeEx(f->handle.get(), &f->fsize)) {
      return JXL_FAILURE("Cannot get file size (%s)", path);
    }
    f->handle_mapping.reset(CreateFileMappingW(f->handle.get(), nullptr,
                                               PAGE_READONLY, 0, 0, nullptr));
    if (f->handle_mapping == nullptr) {
      return JXL_FAILURE("Cannot create memory mapping (%s)", path);
    }
    f->ptr = MapViewOfFile(f->handle_mapping.get(), FILE_MAP_READ, 0, 0, 0);
    return f;
  }

  ~MemoryMappedFileImpl() { UnmapViewOfFile(ptr); }

  const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(ptr); }
  size_t size() const { return fsize.QuadPart; }

  HandleUniquePtr handle;
  HandleUniquePtr handle_mapping;
  LARGE_INTEGER fsize;
  void* ptr = nullptr;
};

}  // namespace jxl

#else

namespace jxl {

struct MemoryMappedFileImpl {
  static StatusOr<std::unique_ptr<MemoryMappedFileImpl>> Init(
      const char* path) {
    return JXL_FAILURE("Memory mapping not supported on this system");
  }

  const uint8_t* data() const { return nullptr; }
  size_t size() const { return 0; }
};

}  // namespace jxl

#endif

namespace jxl {

StatusOr<MemoryMappedFile> MemoryMappedFile::Init(const char* path) {
  JXL_ASSIGN_OR_RETURN(auto mmf, MemoryMappedFileImpl::Init(path));
  MemoryMappedFile ret;
  ret.impl_ = std::move(mmf);
  return ret;
}

MemoryMappedFile::MemoryMappedFile() = default;
MemoryMappedFile::~MemoryMappedFile() = default;
MemoryMappedFile::MemoryMappedFile(MemoryMappedFile&&) noexcept = default;
MemoryMappedFile& MemoryMappedFile::operator=(MemoryMappedFile&&) noexcept =
    default;

const uint8_t* MemoryMappedFile::data() const { return impl_->data(); }
size_t MemoryMappedFile::size() const { return impl_->size(); }
}  // namespace jxl