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