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