xref: /aosp_15_r20/external/marisa-trie/lib/marisa/grimoire/io/writer.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/writer.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 
Writer()17*ab8db090SAndroid Build Coastguard Worker Writer::Writer()
18*ab8db090SAndroid Build Coastguard Worker     : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {}
19*ab8db090SAndroid Build Coastguard Worker 
~Writer()20*ab8db090SAndroid Build Coastguard Worker Writer::~Writer() {
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 Writer::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   Writer 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 Writer::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   Writer 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 Writer::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   Writer 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::ostream & stream)50*ab8db090SAndroid Build Coastguard Worker void Writer::open(std::ostream &stream) {
51*ab8db090SAndroid Build Coastguard Worker   Writer 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 Writer::clear() {
57*ab8db090SAndroid Build Coastguard Worker   Writer().swap(*this);
58*ab8db090SAndroid Build Coastguard Worker }
59*ab8db090SAndroid Build Coastguard Worker 
swap(Writer & rhs)60*ab8db090SAndroid Build Coastguard Worker void Writer::swap(Writer &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 Writer::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     const char buf[16] = {};
73*ab8db090SAndroid Build Coastguard Worker     write_data(buf, size);
74*ab8db090SAndroid Build Coastguard Worker   } else {
75*ab8db090SAndroid Build Coastguard Worker     const char buf[1024] = {};
76*ab8db090SAndroid Build Coastguard Worker     do {
77*ab8db090SAndroid Build Coastguard Worker       const std::size_t count = (size < sizeof(buf)) ? size : sizeof(buf);
78*ab8db090SAndroid Build Coastguard Worker       write_data(buf, count);
79*ab8db090SAndroid Build Coastguard Worker       size -= count;
80*ab8db090SAndroid Build Coastguard Worker     } while (size != 0);
81*ab8db090SAndroid Build Coastguard Worker   }
82*ab8db090SAndroid Build Coastguard Worker }
83*ab8db090SAndroid Build Coastguard Worker 
is_open() const84*ab8db090SAndroid Build Coastguard Worker bool Writer::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 Writer::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, "wb") != 0, MARISA_IO_ERROR);
92*ab8db090SAndroid Build Coastguard Worker #else  // _MSC_VER
93*ab8db090SAndroid Build Coastguard Worker   file = ::fopen(filename, "wb");
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 Writer::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 Writer::open_(int fd) {
105*ab8db090SAndroid Build Coastguard Worker   fd_ = fd;
106*ab8db090SAndroid Build Coastguard Worker }
107*ab8db090SAndroid Build Coastguard Worker 
open_(std::ostream & stream)108*ab8db090SAndroid Build Coastguard Worker void Writer::open_(std::ostream &stream) {
109*ab8db090SAndroid Build Coastguard Worker   stream_ = &stream;
110*ab8db090SAndroid Build Coastguard Worker }
111*ab8db090SAndroid Build Coastguard Worker 
write_data(const void * data,std::size_t size)112*ab8db090SAndroid Build Coastguard Worker void Writer::write_data(const void *data, 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_written = ::_write(fd_, data, 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_written = ::write(fd_, data, count);
128*ab8db090SAndroid Build Coastguard Worker #endif  // _WIN32
129*ab8db090SAndroid Build Coastguard Worker       MARISA_THROW_IF(size_written <= 0, MARISA_IO_ERROR);
130*ab8db090SAndroid Build Coastguard Worker       data = static_cast<const char *>(data) + size_written;
131*ab8db090SAndroid Build Coastguard Worker       size -= static_cast<std::size_t>(size_written);
132*ab8db090SAndroid Build Coastguard Worker     }
133*ab8db090SAndroid Build Coastguard Worker   } else if (file_ != NULL) {
134*ab8db090SAndroid Build Coastguard Worker     MARISA_THROW_IF(::fwrite(data, 1, size, file_) != size, MARISA_IO_ERROR);
135*ab8db090SAndroid Build Coastguard Worker     MARISA_THROW_IF(::fflush(file_) != 0, MARISA_IO_ERROR);
136*ab8db090SAndroid Build Coastguard Worker   } else if (stream_ != NULL) {
137*ab8db090SAndroid Build Coastguard Worker     try {
138*ab8db090SAndroid Build Coastguard Worker       MARISA_THROW_IF(!stream_->write(static_cast<const char *>(data),
139*ab8db090SAndroid Build Coastguard Worker           static_cast<std::streamsize>(size)), MARISA_IO_ERROR);
140*ab8db090SAndroid Build Coastguard Worker     } catch (const std::ios_base::failure &) {
141*ab8db090SAndroid Build Coastguard Worker       MARISA_THROW(MARISA_IO_ERROR, "std::ios_base::failure");
142*ab8db090SAndroid Build Coastguard Worker     }
143*ab8db090SAndroid Build Coastguard Worker   }
144*ab8db090SAndroid Build Coastguard Worker }
145*ab8db090SAndroid Build Coastguard Worker 
146*ab8db090SAndroid Build Coastguard Worker }  // namespace io
147*ab8db090SAndroid Build Coastguard Worker }  // namespace grimoire
148*ab8db090SAndroid Build Coastguard Worker }  // namespace marisa
149