• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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