xref: /aosp_15_r20/external/marisa-trie/lib/marisa/grimoire/io/reader.cc (revision ab8db090fce404b23716c4c9194221ee27efe31c)
1*ab8db090SAndroid Build Coastguard Worker #include <stdio.h>
2*ab8db090SAndroid Build Coastguard Worker 
3*ab8db090SAndroid Build Coastguard Worker #ifdef _WIN32
4*ab8db090SAndroid Build Coastguard Worker  #include <io.h>
5*ab8db090SAndroid Build Coastguard Worker #else  // _WIN32
6*ab8db090SAndroid Build Coastguard Worker  #include <unistd.h>
7*ab8db090SAndroid Build Coastguard Worker #endif  // _WIN32
8*ab8db090SAndroid Build Coastguard Worker 
9*ab8db090SAndroid Build Coastguard Worker #include <limits>
10*ab8db090SAndroid Build Coastguard Worker 
11*ab8db090SAndroid Build Coastguard Worker #include "marisa/grimoire/io/reader.h"
12*ab8db090SAndroid Build Coastguard Worker 
13*ab8db090SAndroid Build Coastguard Worker namespace marisa {
14*ab8db090SAndroid Build Coastguard Worker namespace grimoire {
15*ab8db090SAndroid Build Coastguard Worker namespace io {
16*ab8db090SAndroid Build Coastguard Worker 
Reader()17*ab8db090SAndroid Build Coastguard Worker Reader::Reader()
18*ab8db090SAndroid Build Coastguard Worker     : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {}
19*ab8db090SAndroid Build Coastguard Worker 
~Reader()20*ab8db090SAndroid Build Coastguard Worker Reader::~Reader() {
21*ab8db090SAndroid Build Coastguard Worker   if (needs_fclose_) {
22*ab8db090SAndroid Build Coastguard Worker     ::fclose(file_);
23*ab8db090SAndroid Build Coastguard Worker   }
24*ab8db090SAndroid Build Coastguard Worker }
25*ab8db090SAndroid Build Coastguard Worker 
open(const char * filename)26*ab8db090SAndroid Build Coastguard Worker void Reader::open(const char *filename) {
27*ab8db090SAndroid Build Coastguard Worker   MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
28*ab8db090SAndroid Build Coastguard Worker 
29*ab8db090SAndroid Build Coastguard Worker   Reader temp;
30*ab8db090SAndroid Build Coastguard Worker   temp.open_(filename);
31*ab8db090SAndroid Build Coastguard Worker   swap(temp);
32*ab8db090SAndroid Build Coastguard Worker }
33*ab8db090SAndroid Build Coastguard Worker 
open(std::FILE * file)34*ab8db090SAndroid Build Coastguard Worker void Reader::open(std::FILE *file) {
35*ab8db090SAndroid Build Coastguard Worker   MARISA_THROW_IF(file == NULL, MARISA_NULL_ERROR);
36*ab8db090SAndroid Build Coastguard Worker 
37*ab8db090SAndroid Build Coastguard Worker   Reader temp;
38*ab8db090SAndroid Build Coastguard Worker   temp.open_(file);
39*ab8db090SAndroid Build Coastguard Worker   swap(temp);
40*ab8db090SAndroid Build Coastguard Worker }
41*ab8db090SAndroid Build Coastguard Worker 
open(int fd)42*ab8db090SAndroid Build Coastguard Worker void Reader::open(int fd) {
43*ab8db090SAndroid Build Coastguard Worker   MARISA_THROW_IF(fd == -1, MARISA_CODE_ERROR);
44*ab8db090SAndroid Build Coastguard Worker 
45*ab8db090SAndroid Build Coastguard Worker   Reader temp;
46*ab8db090SAndroid Build Coastguard Worker   temp.open_(fd);
47*ab8db090SAndroid Build Coastguard Worker   swap(temp);
48*ab8db090SAndroid Build Coastguard Worker }
49*ab8db090SAndroid Build Coastguard Worker 
open(std::istream & stream)50*ab8db090SAndroid Build Coastguard Worker void Reader::open(std::istream &stream) {
51*ab8db090SAndroid Build Coastguard Worker   Reader temp;
52*ab8db090SAndroid Build Coastguard Worker   temp.open_(stream);
53*ab8db090SAndroid Build Coastguard Worker   swap(temp);
54*ab8db090SAndroid Build Coastguard Worker }
55*ab8db090SAndroid Build Coastguard Worker 
clear()56*ab8db090SAndroid Build Coastguard Worker void Reader::clear() {
57*ab8db090SAndroid Build Coastguard Worker   Reader().swap(*this);
58*ab8db090SAndroid Build Coastguard Worker }
59*ab8db090SAndroid Build Coastguard Worker 
swap(Reader & rhs)60*ab8db090SAndroid Build Coastguard Worker void Reader::swap(Reader &rhs) {
61*ab8db090SAndroid Build Coastguard Worker   marisa::swap(file_, rhs.file_);
62*ab8db090SAndroid Build Coastguard Worker   marisa::swap(fd_, rhs.fd_);
63*ab8db090SAndroid Build Coastguard Worker   marisa::swap(stream_, rhs.stream_);
64*ab8db090SAndroid Build Coastguard Worker   marisa::swap(needs_fclose_, rhs.needs_fclose_);
65*ab8db090SAndroid Build Coastguard Worker }
66*ab8db090SAndroid Build Coastguard Worker 
seek(std::size_t size)67*ab8db090SAndroid Build Coastguard Worker void Reader::seek(std::size_t size) {
68*ab8db090SAndroid Build Coastguard Worker   MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
69*ab8db090SAndroid Build Coastguard Worker   if (size == 0) {
70*ab8db090SAndroid Build Coastguard Worker     return;
71*ab8db090SAndroid Build Coastguard Worker   } else if (size <= 16) {
72*ab8db090SAndroid Build Coastguard Worker     char buf[16];
73*ab8db090SAndroid Build Coastguard Worker     read_data(buf, size);
74*ab8db090SAndroid Build Coastguard Worker   } else {
75*ab8db090SAndroid Build Coastguard Worker     char buf[1024];
76*ab8db090SAndroid Build Coastguard Worker     while (size != 0) {
77*ab8db090SAndroid Build Coastguard Worker       const std::size_t count = (size < sizeof(buf)) ? size : sizeof(buf);
78*ab8db090SAndroid Build Coastguard Worker       read_data(buf, count);
79*ab8db090SAndroid Build Coastguard Worker       size -= count;
80*ab8db090SAndroid Build Coastguard Worker     }
81*ab8db090SAndroid Build Coastguard Worker   }
82*ab8db090SAndroid Build Coastguard Worker }
83*ab8db090SAndroid Build Coastguard Worker 
is_open() const84*ab8db090SAndroid Build Coastguard Worker bool Reader::is_open() const {
85*ab8db090SAndroid Build Coastguard Worker   return (file_ != NULL) || (fd_ != -1) || (stream_ != NULL);
86*ab8db090SAndroid Build Coastguard Worker }
87*ab8db090SAndroid Build Coastguard Worker 
open_(const char * filename)88*ab8db090SAndroid Build Coastguard Worker void Reader::open_(const char *filename) {
89*ab8db090SAndroid Build Coastguard Worker   std::FILE *file = NULL;
90*ab8db090SAndroid Build Coastguard Worker #ifdef _MSC_VER
91*ab8db090SAndroid Build Coastguard Worker   MARISA_THROW_IF(::fopen_s(&file, filename, "rb") != 0, MARISA_IO_ERROR);
92*ab8db090SAndroid Build Coastguard Worker #else  // _MSC_VER
93*ab8db090SAndroid Build Coastguard Worker   file = ::fopen(filename, "rb");
94*ab8db090SAndroid Build Coastguard Worker   MARISA_THROW_IF(file == NULL, MARISA_IO_ERROR);
95*ab8db090SAndroid Build Coastguard Worker #endif  // _MSC_VER
96*ab8db090SAndroid Build Coastguard Worker   file_ = file;
97*ab8db090SAndroid Build Coastguard Worker   needs_fclose_ = true;
98*ab8db090SAndroid Build Coastguard Worker }
99*ab8db090SAndroid Build Coastguard Worker 
open_(std::FILE * file)100*ab8db090SAndroid Build Coastguard Worker void Reader::open_(std::FILE *file) {
101*ab8db090SAndroid Build Coastguard Worker   file_ = file;
102*ab8db090SAndroid Build Coastguard Worker }
103*ab8db090SAndroid Build Coastguard Worker 
open_(int fd)104*ab8db090SAndroid Build Coastguard Worker void Reader::open_(int fd) {
105*ab8db090SAndroid Build Coastguard Worker   fd_ = fd;
106*ab8db090SAndroid Build Coastguard Worker }
107*ab8db090SAndroid Build Coastguard Worker 
open_(std::istream & stream)108*ab8db090SAndroid Build Coastguard Worker void Reader::open_(std::istream &stream) {
109*ab8db090SAndroid Build Coastguard Worker   stream_ = &stream;
110*ab8db090SAndroid Build Coastguard Worker }
111*ab8db090SAndroid Build Coastguard Worker 
read_data(void * buf,std::size_t size)112*ab8db090SAndroid Build Coastguard Worker void Reader::read_data(void *buf, std::size_t size) {
113*ab8db090SAndroid Build Coastguard Worker   MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
114*ab8db090SAndroid Build Coastguard Worker   if (size == 0) {
115*ab8db090SAndroid Build Coastguard Worker     return;
116*ab8db090SAndroid Build Coastguard Worker   } else if (fd_ != -1) {
117*ab8db090SAndroid Build Coastguard Worker     while (size != 0) {
118*ab8db090SAndroid Build Coastguard Worker #ifdef _WIN32
119*ab8db090SAndroid Build Coastguard Worker       static const std::size_t CHUNK_SIZE =
120*ab8db090SAndroid Build Coastguard Worker           std::numeric_limits<int>::max();
121*ab8db090SAndroid Build Coastguard Worker       const unsigned int count = (size < CHUNK_SIZE) ? size : CHUNK_SIZE;
122*ab8db090SAndroid Build Coastguard Worker       const int size_read = ::_read(fd_, buf, count);
123*ab8db090SAndroid Build Coastguard Worker #else  // _WIN32
124*ab8db090SAndroid Build Coastguard Worker       static const std::size_t CHUNK_SIZE =
125*ab8db090SAndroid Build Coastguard Worker           std::numeric_limits< ::ssize_t>::max();
126*ab8db090SAndroid Build Coastguard Worker       const ::size_t count = (size < CHUNK_SIZE) ? size : CHUNK_SIZE;
127*ab8db090SAndroid Build Coastguard Worker       const ::ssize_t size_read = ::read(fd_, buf, count);
128*ab8db090SAndroid Build Coastguard Worker #endif  // _WIN32
129*ab8db090SAndroid Build Coastguard Worker       MARISA_THROW_IF(size_read <= 0, MARISA_IO_ERROR);
130*ab8db090SAndroid Build Coastguard Worker       buf = static_cast<char *>(buf) + size_read;
131*ab8db090SAndroid Build Coastguard Worker       size -= static_cast<std::size_t>(size_read);
132*ab8db090SAndroid Build Coastguard Worker     }
133*ab8db090SAndroid Build Coastguard Worker   } else if (file_ != NULL) {
134*ab8db090SAndroid Build Coastguard Worker     MARISA_THROW_IF(::fread(buf, 1, size, file_) != size, MARISA_IO_ERROR);
135*ab8db090SAndroid Build Coastguard Worker   } else if (stream_ != NULL) {
136*ab8db090SAndroid Build Coastguard Worker     try {
137*ab8db090SAndroid Build Coastguard Worker       MARISA_THROW_IF(!stream_->read(static_cast<char *>(buf),
138*ab8db090SAndroid Build Coastguard Worker           static_cast<std::streamsize>(size)), MARISA_IO_ERROR);
139*ab8db090SAndroid Build Coastguard Worker     } catch (const std::ios_base::failure &) {
140*ab8db090SAndroid Build Coastguard Worker       MARISA_THROW(MARISA_IO_ERROR, "std::ios_base::failure");
141*ab8db090SAndroid Build Coastguard Worker     }
142*ab8db090SAndroid Build Coastguard Worker   }
143*ab8db090SAndroid Build Coastguard Worker }
144*ab8db090SAndroid Build Coastguard Worker 
145*ab8db090SAndroid Build Coastguard Worker }  // namespace io
146*ab8db090SAndroid Build Coastguard Worker }  // namespace grimoire
147*ab8db090SAndroid Build Coastguard Worker }  // namespace marisa
148