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