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