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 "mapper.h"
14
15 namespace marisa_alpha {
16
17 #if defined _WIN32 || defined _WIN64
Mapper()18 Mapper::Mapper()
19 : ptr_(NULL), origin_(NULL), avail_(0), size_(0),
20 file_(NULL), map_(NULL) {}
21
Mapper(const void * ptr,std::size_t size)22 Mapper::Mapper(const void *ptr, std::size_t size)
23 : ptr_(ptr), origin_(NULL), avail_(size), size_(0),
24 file_(NULL), map_(NULL) {
25 MARISA_ALPHA_THROW_IF((ptr == NULL) && (size != 0),
26 MARISA_ALPHA_PARAM_ERROR);
27 }
28 #else // defined _WIN32 || defined _WIN64
29 Mapper::Mapper()
30 : ptr_(NULL), origin_(MAP_FAILED), avail_(0), size_(0), fd_(-1) {}
31
32 Mapper::Mapper(const void *ptr, std::size_t size)
33 : ptr_(ptr), origin_(MAP_FAILED), avail_(size), size_(0), fd_(-1) {
34 MARISA_ALPHA_THROW_IF((ptr == NULL) && (size != 0),
35 MARISA_ALPHA_PARAM_ERROR);
36 }
37 #endif // defined _WIN32 || defined _WIN64
38
39 #if defined _WIN32 || defined _WIN64
~Mapper()40 Mapper::~Mapper() {
41 if (origin_ != NULL) {
42 ::UnmapViewOfFile(origin_);
43 }
44
45 if (map_ != NULL) {
46 ::CloseHandle(map_);
47 }
48
49 if (file_ != NULL) {
50 ::CloseHandle(file_);
51 }
52 }
53 #else // defined _WIN32 || defined _WIN64
~Mapper()54 Mapper::~Mapper() {
55 if (origin_ != MAP_FAILED) {
56 ::munmap(origin_, size_);
57 }
58
59 if (fd_ != -1) {
60 ::close(fd_);
61 }
62 }
63 #endif // defined _WIN32 || defined _WIN64
64
65 #if defined _WIN32 || defined _WIN64
open(const char * filename,long offset,int whence)66 void Mapper::open(const char *filename, long offset, int whence) {
67 MARISA_ALPHA_THROW_IF(is_open(), MARISA_ALPHA_STATE_ERROR);
68 MARISA_ALPHA_THROW_IF(filename == NULL, MARISA_ALPHA_PARAM_ERROR);
69
70 struct __stat64 st;
71 if (::_stat64(filename, &st) != 0) {
72 MARISA_ALPHA_THROW(MARISA_ALPHA_IO_ERROR);
73 }
74 const UInt64 file_size = st.st_size;
75 MARISA_ALPHA_THROW_IF(file_size > MARISA_ALPHA_UINT32_MAX,
76 MARISA_ALPHA_SIZE_ERROR);
77
78 Mapper temp;
79 temp.size_ = (std::size_t)file_size;
80
81 temp.file_ = ::CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ,
82 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
83 MARISA_ALPHA_THROW_IF(temp.file_ == NULL, MARISA_ALPHA_IO_ERROR);
84
85 temp.map_ = ::CreateFileMapping(temp.file_, NULL, PAGE_READONLY, 0, 0, NULL);
86 MARISA_ALPHA_THROW_IF(temp.map_ == NULL, MARISA_ALPHA_IO_ERROR);
87
88 temp.origin_ = ::MapViewOfFile(temp.map_, FILE_MAP_READ, 0, 0, 0);
89 MARISA_ALPHA_THROW_IF(temp.origin_ == NULL, MARISA_ALPHA_IO_ERROR);
90
91 temp.seek(offset, whence);
92 temp.swap(this);
93 }
94 #else // defined _WIN32 || defined _WIN64
open(const char * filename,long offset,int whence)95 void Mapper::open(const char *filename, long offset, int whence) {
96 MARISA_ALPHA_THROW_IF(is_open(), MARISA_ALPHA_STATE_ERROR);
97 MARISA_ALPHA_THROW_IF(filename == NULL, MARISA_ALPHA_PARAM_ERROR);
98
99 struct stat st;
100 if (::stat(filename, &st) != 0) {
101 MARISA_ALPHA_THROW(MARISA_ALPHA_IO_ERROR);
102 }
103 UInt64 file_size = st.st_size;
104 MARISA_ALPHA_THROW_IF(file_size > MARISA_ALPHA_UINT32_MAX,
105 MARISA_ALPHA_SIZE_ERROR);
106
107 Mapper temp;
108 temp.size_ = (std::size_t)file_size;
109
110 temp.fd_ = ::open(filename, O_RDONLY);
111 MARISA_ALPHA_THROW_IF(temp.fd_ == -1, MARISA_ALPHA_IO_ERROR);
112
113 temp.origin_ = ::mmap(NULL, temp.size_, PROT_READ, MAP_SHARED, temp.fd_, 0);
114 MARISA_ALPHA_THROW_IF(temp.origin_ == MAP_FAILED, MARISA_ALPHA_IO_ERROR);
115
116 temp.seek(offset, whence);
117 temp.swap(this);
118 }
119 #endif // defined _WIN32 || defined _WIN64
120
clear()121 void Mapper::clear() {
122 Mapper().swap(this);
123 }
124
swap(Mapper * rhs)125 void Mapper::swap(Mapper *rhs) {
126 MARISA_ALPHA_THROW_IF(rhs == NULL, MARISA_ALPHA_PARAM_ERROR);
127 Swap(&ptr_, &rhs->ptr_);
128 Swap(&avail_, &rhs->avail_);
129 Swap(&origin_, &rhs->origin_);
130 Swap(&size_, &rhs->size_);
131 #if defined _WIN32 || defined _WIN64
132 Swap(&file_, &rhs->file_);
133 Swap(&map_, &rhs->map_);
134 #else // defined _WIN32 || defined _WIN64
135 Swap(&fd_, &rhs->fd_);
136 #endif // defined _WIN32 || defined _WIN64
137 }
138
seek(long offset,int whence)139 void Mapper::seek(long offset, int whence) {
140 switch (whence) {
141 case SEEK_SET:
142 case SEEK_CUR: {
143 MARISA_ALPHA_THROW_IF((offset < 0) || ((unsigned long)offset > size_),
144 MARISA_ALPHA_IO_ERROR);
145 ptr_ = static_cast<const UInt8 *>(origin_) + offset;
146 avail_ = (std::size_t)(size_ - offset);
147 return;
148 }
149 case SEEK_END: {
150 MARISA_ALPHA_THROW_IF((offset > 0) || ((unsigned long)-offset > size_),
151 MARISA_ALPHA_IO_ERROR);
152 ptr_ = static_cast<const UInt8 *>(origin_) + size_ + offset;
153 avail_ = (std::size_t)-offset;
154 return;
155 }
156 default: {
157 MARISA_ALPHA_THROW(MARISA_ALPHA_PARAM_ERROR);
158 }
159 }
160 }
161
map_data(std::size_t size)162 const void *Mapper::map_data(std::size_t size) {
163 MARISA_ALPHA_THROW_IF(!is_open(), MARISA_ALPHA_STATE_ERROR);
164 MARISA_ALPHA_THROW_IF(size > avail_, MARISA_ALPHA_IO_ERROR);
165 ptr_ = static_cast<const UInt8 *>(ptr_) + size;
166 avail_ -= size;
167 return static_cast<const UInt8 *>(ptr_) - size;
168 }
169
170 } // namespace marisa_alpha
171