Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/nall/filemap.hpp
2 views
1
#ifndef NALL_FILEMAP_HPP
2
#define NALL_FILEMAP_HPP
3
4
#include <nall/file.hpp>
5
#include <nall/stdint.hpp>
6
#include <nall/windows/utf8.hpp>
7
8
#include <stdio.h>
9
#include <stdlib.h>
10
#if defined(_WIN32)
11
#include <windows.h>
12
#else
13
#include <fcntl.h>
14
#include <unistd.h>
15
#include <sys/mman.h>
16
#include <sys/stat.h>
17
#include <sys/types.h>
18
#endif
19
20
namespace nall {
21
class filemap {
22
public:
23
enum class mode : unsigned { read, write, readwrite, writeread };
24
25
bool open() const { return p_open(); }
26
bool open(const char *filename, mode mode_) { return p_open(filename, mode_); }
27
void close() { return p_close(); }
28
unsigned size() const { return p_size; }
29
uint8_t* data() { return p_handle; }
30
const uint8_t* data() const { return p_handle; }
31
filemap() : p_size(0), p_handle(0) { p_ctor(); }
32
filemap(const char *filename, mode mode_) : p_size(0), p_handle(0) { p_ctor(); p_open(filename, mode_); }
33
~filemap() { p_dtor(); }
34
35
private:
36
unsigned p_size;
37
uint8_t *p_handle;
38
39
#if defined(_WIN32)
40
//=============
41
//MapViewOfFile
42
//=============
43
44
HANDLE p_filehandle, p_maphandle;
45
46
bool p_open() const {
47
return p_handle;
48
}
49
50
bool p_open(const char *filename, mode mode_) {
51
if(file::exists(filename) && file::size(filename) == 0) {
52
p_handle = 0;
53
p_size = 0;
54
return true;
55
}
56
57
int desired_access, creation_disposition, flprotect, map_access;
58
59
switch(mode_) {
60
default: return false;
61
case mode::read:
62
desired_access = GENERIC_READ;
63
creation_disposition = OPEN_EXISTING;
64
flprotect = PAGE_READONLY;
65
map_access = FILE_MAP_READ;
66
break;
67
case mode::write:
68
//write access requires read access
69
desired_access = GENERIC_WRITE;
70
creation_disposition = CREATE_ALWAYS;
71
flprotect = PAGE_READWRITE;
72
map_access = FILE_MAP_ALL_ACCESS;
73
break;
74
case mode::readwrite:
75
desired_access = GENERIC_READ | GENERIC_WRITE;
76
creation_disposition = OPEN_EXISTING;
77
flprotect = PAGE_READWRITE;
78
map_access = FILE_MAP_ALL_ACCESS;
79
break;
80
case mode::writeread:
81
desired_access = GENERIC_READ | GENERIC_WRITE;
82
creation_disposition = CREATE_NEW;
83
flprotect = PAGE_READWRITE;
84
map_access = FILE_MAP_ALL_ACCESS;
85
break;
86
}
87
88
p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, NULL,
89
creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL);
90
if(p_filehandle == INVALID_HANDLE_VALUE) return false;
91
92
p_size = GetFileSize(p_filehandle, NULL);
93
94
p_maphandle = CreateFileMapping(p_filehandle, NULL, flprotect, 0, p_size, NULL);
95
if(p_maphandle == INVALID_HANDLE_VALUE) {
96
CloseHandle(p_filehandle);
97
p_filehandle = INVALID_HANDLE_VALUE;
98
return false;
99
}
100
101
p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size);
102
return p_handle;
103
}
104
105
void p_close() {
106
if(p_handle) {
107
UnmapViewOfFile(p_handle);
108
p_handle = 0;
109
}
110
111
if(p_maphandle != INVALID_HANDLE_VALUE) {
112
CloseHandle(p_maphandle);
113
p_maphandle = INVALID_HANDLE_VALUE;
114
}
115
116
if(p_filehandle != INVALID_HANDLE_VALUE) {
117
CloseHandle(p_filehandle);
118
p_filehandle = INVALID_HANDLE_VALUE;
119
}
120
}
121
122
void p_ctor() {
123
p_filehandle = INVALID_HANDLE_VALUE;
124
p_maphandle = INVALID_HANDLE_VALUE;
125
}
126
127
void p_dtor() {
128
close();
129
}
130
131
#else
132
//====
133
//mmap
134
//====
135
136
int p_fd;
137
138
bool p_open() const {
139
return p_handle;
140
}
141
142
bool p_open(const char *filename, mode mode_) {
143
if(file::exists(filename) && file::size(filename) == 0) {
144
p_handle = 0;
145
p_size = 0;
146
return true;
147
}
148
149
int open_flags, mmap_flags;
150
151
switch(mode_) {
152
default: return false;
153
case mode::read:
154
open_flags = O_RDONLY;
155
mmap_flags = PROT_READ;
156
break;
157
case mode::write:
158
open_flags = O_RDWR | O_CREAT; //mmap() requires read access
159
mmap_flags = PROT_WRITE;
160
break;
161
case mode::readwrite:
162
open_flags = O_RDWR;
163
mmap_flags = PROT_READ | PROT_WRITE;
164
break;
165
case mode::writeread:
166
open_flags = O_RDWR | O_CREAT;
167
mmap_flags = PROT_READ | PROT_WRITE;
168
break;
169
}
170
171
p_fd = ::open(filename, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
172
if(p_fd < 0) return false;
173
174
struct stat p_stat;
175
fstat(p_fd, &p_stat);
176
p_size = p_stat.st_size;
177
178
p_handle = (uint8_t*)mmap(0, p_size, mmap_flags, MAP_SHARED, p_fd, 0);
179
if(p_handle == MAP_FAILED) {
180
p_handle = 0;
181
::close(p_fd);
182
p_fd = -1;
183
return false;
184
}
185
186
return p_handle;
187
}
188
189
void p_close() {
190
if(p_handle) {
191
munmap(p_handle, p_size);
192
p_handle = 0;
193
}
194
195
if(p_fd >= 0) {
196
::close(p_fd);
197
p_fd = -1;
198
}
199
}
200
201
void p_ctor() {
202
p_fd = -1;
203
}
204
205
void p_dtor() {
206
p_close();
207
}
208
209
#endif
210
};
211
}
212
213
#endif
214
215