1*ab8db090SAndroid Build Coastguard Worker #if (defined _WIN32) || (defined _WIN64)
2*ab8db090SAndroid Build Coastguard Worker #include <sys/types.h>
3*ab8db090SAndroid Build Coastguard Worker #include <sys/stat.h>
4*ab8db090SAndroid Build Coastguard Worker #include <windows.h>
5*ab8db090SAndroid Build Coastguard Worker #else // (defined _WIN32) || (defined _WIN64)
6*ab8db090SAndroid Build Coastguard Worker #include <sys/mman.h>
7*ab8db090SAndroid Build Coastguard Worker #include <sys/stat.h>
8*ab8db090SAndroid Build Coastguard Worker #include <sys/types.h>
9*ab8db090SAndroid Build Coastguard Worker #include <fcntl.h>
10*ab8db090SAndroid Build Coastguard Worker #include <unistd.h>
11*ab8db090SAndroid Build Coastguard Worker #endif // (defined _WIN32) || (defined _WIN64)
12*ab8db090SAndroid Build Coastguard Worker
13*ab8db090SAndroid Build Coastguard Worker #include "marisa/grimoire/io/mapper.h"
14*ab8db090SAndroid Build Coastguard Worker
15*ab8db090SAndroid Build Coastguard Worker namespace marisa {
16*ab8db090SAndroid Build Coastguard Worker namespace grimoire {
17*ab8db090SAndroid Build Coastguard Worker namespace io {
18*ab8db090SAndroid Build Coastguard Worker
19*ab8db090SAndroid Build Coastguard Worker #if (defined _WIN32) || (defined _WIN64)
Mapper()20*ab8db090SAndroid Build Coastguard Worker Mapper::Mapper()
21*ab8db090SAndroid Build Coastguard Worker : ptr_(NULL), origin_(NULL), avail_(0), size_(0),
22*ab8db090SAndroid Build Coastguard Worker file_(NULL), map_(NULL) {}
23*ab8db090SAndroid Build Coastguard Worker #else // (defined _WIN32) || (defined _WIN64)
24*ab8db090SAndroid Build Coastguard Worker Mapper::Mapper()
25*ab8db090SAndroid Build Coastguard Worker : ptr_(NULL), origin_(MAP_FAILED), avail_(0), size_(0), fd_(-1) {}
26*ab8db090SAndroid Build Coastguard Worker #endif // (defined _WIN32) || (defined _WIN64)
27*ab8db090SAndroid Build Coastguard Worker
28*ab8db090SAndroid Build Coastguard Worker #if (defined _WIN32) || (defined _WIN64)
~Mapper()29*ab8db090SAndroid Build Coastguard Worker Mapper::~Mapper() {
30*ab8db090SAndroid Build Coastguard Worker if (origin_ != NULL) {
31*ab8db090SAndroid Build Coastguard Worker ::UnmapViewOfFile(origin_);
32*ab8db090SAndroid Build Coastguard Worker }
33*ab8db090SAndroid Build Coastguard Worker
34*ab8db090SAndroid Build Coastguard Worker if (map_ != NULL) {
35*ab8db090SAndroid Build Coastguard Worker ::CloseHandle(map_);
36*ab8db090SAndroid Build Coastguard Worker }
37*ab8db090SAndroid Build Coastguard Worker
38*ab8db090SAndroid Build Coastguard Worker if (file_ != NULL) {
39*ab8db090SAndroid Build Coastguard Worker ::CloseHandle(file_);
40*ab8db090SAndroid Build Coastguard Worker }
41*ab8db090SAndroid Build Coastguard Worker }
42*ab8db090SAndroid Build Coastguard Worker #else // (defined _WIN32) || (defined _WIN64)
~Mapper()43*ab8db090SAndroid Build Coastguard Worker Mapper::~Mapper() {
44*ab8db090SAndroid Build Coastguard Worker if (origin_ != MAP_FAILED) {
45*ab8db090SAndroid Build Coastguard Worker ::munmap(origin_, size_);
46*ab8db090SAndroid Build Coastguard Worker }
47*ab8db090SAndroid Build Coastguard Worker
48*ab8db090SAndroid Build Coastguard Worker if (fd_ != -1) {
49*ab8db090SAndroid Build Coastguard Worker ::close(fd_);
50*ab8db090SAndroid Build Coastguard Worker }
51*ab8db090SAndroid Build Coastguard Worker }
52*ab8db090SAndroid Build Coastguard Worker #endif // (defined _WIN32) || (defined _WIN64)
53*ab8db090SAndroid Build Coastguard Worker
open(const char * filename)54*ab8db090SAndroid Build Coastguard Worker void Mapper::open(const char *filename) {
55*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
56*ab8db090SAndroid Build Coastguard Worker
57*ab8db090SAndroid Build Coastguard Worker Mapper temp;
58*ab8db090SAndroid Build Coastguard Worker temp.open_(filename);
59*ab8db090SAndroid Build Coastguard Worker swap(temp);
60*ab8db090SAndroid Build Coastguard Worker }
61*ab8db090SAndroid Build Coastguard Worker
open(const void * ptr,std::size_t size)62*ab8db090SAndroid Build Coastguard Worker void Mapper::open(const void *ptr, std::size_t size) {
63*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF((ptr == NULL) && (size != 0), MARISA_NULL_ERROR);
64*ab8db090SAndroid Build Coastguard Worker
65*ab8db090SAndroid Build Coastguard Worker Mapper temp;
66*ab8db090SAndroid Build Coastguard Worker temp.open_(ptr, size);
67*ab8db090SAndroid Build Coastguard Worker swap(temp);
68*ab8db090SAndroid Build Coastguard Worker }
69*ab8db090SAndroid Build Coastguard Worker
seek(std::size_t size)70*ab8db090SAndroid Build Coastguard Worker void Mapper::seek(std::size_t size) {
71*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
72*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(size > avail_, MARISA_IO_ERROR);
73*ab8db090SAndroid Build Coastguard Worker
74*ab8db090SAndroid Build Coastguard Worker map_data(size);
75*ab8db090SAndroid Build Coastguard Worker }
76*ab8db090SAndroid Build Coastguard Worker
is_open() const77*ab8db090SAndroid Build Coastguard Worker bool Mapper::is_open() const {
78*ab8db090SAndroid Build Coastguard Worker return ptr_ != NULL;
79*ab8db090SAndroid Build Coastguard Worker }
80*ab8db090SAndroid Build Coastguard Worker
clear()81*ab8db090SAndroid Build Coastguard Worker void Mapper::clear() {
82*ab8db090SAndroid Build Coastguard Worker Mapper().swap(*this);
83*ab8db090SAndroid Build Coastguard Worker }
84*ab8db090SAndroid Build Coastguard Worker
swap(Mapper & rhs)85*ab8db090SAndroid Build Coastguard Worker void Mapper::swap(Mapper &rhs) {
86*ab8db090SAndroid Build Coastguard Worker marisa::swap(ptr_, rhs.ptr_);
87*ab8db090SAndroid Build Coastguard Worker marisa::swap(avail_, rhs.avail_);
88*ab8db090SAndroid Build Coastguard Worker marisa::swap(origin_, rhs.origin_);
89*ab8db090SAndroid Build Coastguard Worker marisa::swap(size_, rhs.size_);
90*ab8db090SAndroid Build Coastguard Worker #if (defined _WIN32) || (defined _WIN64)
91*ab8db090SAndroid Build Coastguard Worker marisa::swap(file_, rhs.file_);
92*ab8db090SAndroid Build Coastguard Worker marisa::swap(map_, rhs.map_);
93*ab8db090SAndroid Build Coastguard Worker #else // (defined _WIN32) || (defined _WIN64)
94*ab8db090SAndroid Build Coastguard Worker marisa::swap(fd_, rhs.fd_);
95*ab8db090SAndroid Build Coastguard Worker #endif // (defined _WIN32) || (defined _WIN64)
96*ab8db090SAndroid Build Coastguard Worker }
97*ab8db090SAndroid Build Coastguard Worker
map_data(std::size_t size)98*ab8db090SAndroid Build Coastguard Worker const void *Mapper::map_data(std::size_t size) {
99*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
100*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(size > avail_, MARISA_IO_ERROR);
101*ab8db090SAndroid Build Coastguard Worker
102*ab8db090SAndroid Build Coastguard Worker const char * const data = static_cast<const char *>(ptr_);
103*ab8db090SAndroid Build Coastguard Worker ptr_ = data + size;
104*ab8db090SAndroid Build Coastguard Worker avail_ -= size;
105*ab8db090SAndroid Build Coastguard Worker return data;
106*ab8db090SAndroid Build Coastguard Worker }
107*ab8db090SAndroid Build Coastguard Worker
108*ab8db090SAndroid Build Coastguard Worker #if (defined _WIN32) || (defined _WIN64)
109*ab8db090SAndroid Build Coastguard Worker #ifdef __MSVCRT_VERSION__
110*ab8db090SAndroid Build Coastguard Worker #if __MSVCRT_VERSION__ >= 0x0601
111*ab8db090SAndroid Build Coastguard Worker #define MARISA_HAS_STAT64
112*ab8db090SAndroid Build Coastguard Worker #endif // __MSVCRT_VERSION__ >= 0x0601
113*ab8db090SAndroid Build Coastguard Worker #endif // __MSVCRT_VERSION__
open_(const char * filename)114*ab8db090SAndroid Build Coastguard Worker void Mapper::open_(const char *filename) {
115*ab8db090SAndroid Build Coastguard Worker #ifdef MARISA_HAS_STAT64
116*ab8db090SAndroid Build Coastguard Worker struct __stat64 st;
117*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(::_stat64(filename, &st) != 0, MARISA_IO_ERROR);
118*ab8db090SAndroid Build Coastguard Worker #else // MARISA_HAS_STAT64
119*ab8db090SAndroid Build Coastguard Worker struct _stat st;
120*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(::_stat(filename, &st) != 0, MARISA_IO_ERROR);
121*ab8db090SAndroid Build Coastguard Worker #endif // MARISA_HAS_STAT64
122*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF((UInt64)st.st_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
123*ab8db090SAndroid Build Coastguard Worker size_ = (std::size_t)st.st_size;
124*ab8db090SAndroid Build Coastguard Worker
125*ab8db090SAndroid Build Coastguard Worker file_ = ::CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ,
126*ab8db090SAndroid Build Coastguard Worker NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
127*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(file_ == INVALID_HANDLE_VALUE, MARISA_IO_ERROR);
128*ab8db090SAndroid Build Coastguard Worker
129*ab8db090SAndroid Build Coastguard Worker map_ = ::CreateFileMapping(file_, NULL, PAGE_READONLY, 0, 0, NULL);
130*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(map_ == NULL, MARISA_IO_ERROR);
131*ab8db090SAndroid Build Coastguard Worker
132*ab8db090SAndroid Build Coastguard Worker origin_ = ::MapViewOfFile(map_, FILE_MAP_READ, 0, 0, 0);
133*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(origin_ == NULL, MARISA_IO_ERROR);
134*ab8db090SAndroid Build Coastguard Worker
135*ab8db090SAndroid Build Coastguard Worker ptr_ = static_cast<const char *>(origin_);
136*ab8db090SAndroid Build Coastguard Worker avail_ = size_;
137*ab8db090SAndroid Build Coastguard Worker }
138*ab8db090SAndroid Build Coastguard Worker #else // (defined _WIN32) || (defined _WIN64)
open_(const char * filename)139*ab8db090SAndroid Build Coastguard Worker void Mapper::open_(const char *filename) {
140*ab8db090SAndroid Build Coastguard Worker struct stat st;
141*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(::stat(filename, &st) != 0, MARISA_IO_ERROR);
142*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF((UInt64)st.st_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
143*ab8db090SAndroid Build Coastguard Worker size_ = (std::size_t)st.st_size;
144*ab8db090SAndroid Build Coastguard Worker
145*ab8db090SAndroid Build Coastguard Worker fd_ = ::open(filename, O_RDONLY);
146*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(fd_ == -1, MARISA_IO_ERROR);
147*ab8db090SAndroid Build Coastguard Worker
148*ab8db090SAndroid Build Coastguard Worker origin_ = ::mmap(NULL, size_, PROT_READ, MAP_SHARED, fd_, 0);
149*ab8db090SAndroid Build Coastguard Worker MARISA_THROW_IF(origin_ == MAP_FAILED, MARISA_IO_ERROR);
150*ab8db090SAndroid Build Coastguard Worker
151*ab8db090SAndroid Build Coastguard Worker ptr_ = static_cast<const char *>(origin_);
152*ab8db090SAndroid Build Coastguard Worker avail_ = size_;
153*ab8db090SAndroid Build Coastguard Worker }
154*ab8db090SAndroid Build Coastguard Worker #endif // (defined _WIN32) || (defined _WIN64)
155*ab8db090SAndroid Build Coastguard Worker
open_(const void * ptr,std::size_t size)156*ab8db090SAndroid Build Coastguard Worker void Mapper::open_(const void *ptr, std::size_t size) {
157*ab8db090SAndroid Build Coastguard Worker ptr_ = ptr;
158*ab8db090SAndroid Build Coastguard Worker avail_ = size;
159*ab8db090SAndroid Build Coastguard Worker }
160*ab8db090SAndroid Build Coastguard Worker
161*ab8db090SAndroid Build Coastguard Worker } // namespace io
162*ab8db090SAndroid Build Coastguard Worker } // namespace grimoire
163*ab8db090SAndroid Build Coastguard Worker } // namespace marisa
164