1 #include <limits.h>
2 #include <stdio.h>
3
4 #ifdef _MSC_VER
5 #include <io.h>
6 #else // _MSC_VER
7 #include <unistd.h>
8 #endif // _MSC_VER
9
10 #include "writer.h"
11
12 namespace marisa {
13
Writer()14 Writer::Writer()
15 : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {}
16
Writer(std::FILE * file)17 Writer::Writer(std::FILE *file)
18 : file_(file), fd_(-1), stream_(NULL), needs_fclose_(false) {}
19
Writer(int fd)20 Writer::Writer(int fd)
21 : file_(NULL), fd_(fd), stream_(NULL), needs_fclose_(false) {}
22
Writer(std::ostream * stream)23 Writer::Writer(std::ostream *stream)
24 : file_(NULL), fd_(-1), stream_(stream), needs_fclose_(false) {}
25
~Writer()26 Writer::~Writer() {
27 if (needs_fclose_) {
28 ::fclose(file_);
29 }
30 }
31
open(const char * filename,bool trunc_flag,long offset,int whence)32 void Writer::open(const char *filename, bool trunc_flag,
33 long offset, int whence) {
34 MARISA_THROW_IF(is_open(), MARISA_STATE_ERROR);
35 MARISA_THROW_IF(filename == NULL, MARISA_PARAM_ERROR);
36 #ifdef _MSC_VER
37 std::FILE *file = NULL;
38 if (!trunc_flag) {
39 ::fopen_s(&file, filename, "rb+");
40 }
41 if (file == NULL) {
42 if (::fopen_s(&file, filename, "wb") != 0) {
43 MARISA_THROW(MARISA_IO_ERROR);
44 }
45 }
46 #else // _MSC_VER
47 std::FILE *file = NULL;
48 if (!trunc_flag) {
49 file = ::fopen(filename, "rb+");
50 }
51 if (file == NULL) {
52 file = ::fopen(filename, "wb");
53 MARISA_THROW_IF(file == NULL, MARISA_IO_ERROR);
54 }
55 #endif // _MSC_VER
56 if (::fseek(file, offset, whence) != 0) {
57 ::fclose(file);
58 MARISA_THROW(MARISA_IO_ERROR);
59 }
60 file_ = file;
61 needs_fclose_ = true;
62 }
63
clear()64 void Writer::clear() {
65 Writer().swap(this);
66 }
67
swap(Writer * rhs)68 void Writer::swap(Writer *rhs) {
69 MARISA_THROW_IF(rhs == NULL, MARISA_PARAM_ERROR);
70 Swap(&file_, &rhs->file_);
71 Swap(&fd_, &rhs->fd_);
72 Swap(&stream_, &rhs->stream_);
73 Swap(&needs_fclose_, &rhs->needs_fclose_);
74 }
75
write_data(const void * data,std::size_t size)76 void Writer::write_data(const void *data, std::size_t size) {
77 if (fd_ != -1) {
78 while (size != 0) {
79 #ifdef _MSC_VER
80 const unsigned int count = (size < INT_MAX) ? size : INT_MAX;
81 const int size_written = _write(fd_, data, count);
82 #else // _MSC_VER
83 const ::size_t count = (size < SSIZE_MAX) ? size : SSIZE_MAX;
84 const ::ssize_t size_written = ::write(fd_, data, count);
85 #endif // _MSC_VER
86 MARISA_THROW_IF(size_written <= 0, MARISA_IO_ERROR);
87 data = static_cast<const char *>(data) + size_written;
88 size -= size_written;
89 }
90 } else if (file_ != NULL) {
91 if ((::fwrite(data, 1, size, file_) != size) || (::fflush(file_) != 0)) {
92 MARISA_THROW(MARISA_IO_ERROR);
93 }
94 } else if (stream_ != NULL) {
95 if (!stream_->write(static_cast<const char *>(data), size)) {
96 MARISA_THROW(MARISA_IO_ERROR);
97 }
98 } else {
99 MARISA_THROW(MARISA_STATE_ERROR);
100 }
101 }
102
103 } // namespace marisa
104