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