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 "reader.h"
11
12 namespace marisa {
13
Reader()14 Reader::Reader()
15 : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {}
16
Reader(std::FILE * file)17 Reader::Reader(std::FILE *file)
18 : file_(file), fd_(-1), stream_(NULL), needs_fclose_(false) {}
19
Reader(int fd)20 Reader::Reader(int fd)
21 : file_(NULL), fd_(fd), stream_(NULL), needs_fclose_(false) {}
22
Reader(std::istream * stream)23 Reader::Reader(std::istream *stream)
24 : file_(NULL), fd_(-1), stream_(stream), needs_fclose_(false) {}
25
~Reader()26 Reader::~Reader() {
27 if (needs_fclose_) {
28 ::fclose(file_);
29 }
30 }
31
open(const char * filename,long offset,int whence)32 void Reader::open(const char *filename, long offset, int whence) {
33 MARISA_THROW_IF(is_open(), MARISA_STATE_ERROR);
34 MARISA_THROW_IF(filename == NULL, MARISA_PARAM_ERROR);
35 #ifdef _MSC_VER
36 std::FILE *file = NULL;
37 if (::fopen_s(&file, filename, "rb") != 0) {
38 MARISA_THROW(MARISA_IO_ERROR);
39 }
40 #else // _MSC_VER
41 std::FILE * const file = ::fopen(filename, "rb");
42 MARISA_THROW_IF(file == NULL, MARISA_IO_ERROR);
43 #endif // _MSC_VER
44 if (::fseek(file, offset, whence) != 0) {
45 ::fclose(file);
46 MARISA_THROW(MARISA_IO_ERROR);
47 }
48 file_ = file;
49 needs_fclose_ = true;
50 }
51
clear()52 void Reader::clear() {
53 Reader().swap(this);
54 }
55
swap(Reader * rhs)56 void Reader::swap(Reader *rhs) {
57 MARISA_THROW_IF(rhs == NULL, MARISA_PARAM_ERROR);
58 Swap(&file_, &rhs->file_);
59 Swap(&fd_, &rhs->fd_);
60 Swap(&stream_, &rhs->stream_);
61 Swap(&needs_fclose_, &rhs->needs_fclose_);
62 }
63
read_data(void * buf,std::size_t size)64 void Reader::read_data(void *buf, std::size_t size) {
65 if (fd_ != -1) {
66 while (size != 0) {
67 #ifdef _MSC_VER
68 const unsigned int count = (size < INT_MAX) ? size : INT_MAX;
69 const int size_read = _read(fd_, buf, count);
70 #else // _MSC_VER
71 const ::size_t count = (size < SSIZE_MAX) ? size : SSIZE_MAX;
72 const ::ssize_t size_read = ::read(fd_, buf, count);
73 #endif // _MSC_VER
74 MARISA_THROW_IF(size_read <= 0, MARISA_IO_ERROR);
75 buf = static_cast<char *>(buf) + size_read;
76 size -= size_read;
77 }
78 } else if (file_ != NULL) {
79 if (::fread(buf, 1, size, file_) != size) {
80 MARISA_THROW(MARISA_IO_ERROR);
81 }
82 } else if (stream_ != NULL) {
83 if (!stream_->read(static_cast<char *>(buf), size)) {
84 MARISA_THROW(MARISA_IO_ERROR);
85 }
86 } else {
87 MARISA_THROW(MARISA_STATE_ERROR);
88 }
89 }
90
91 } // namespace marisa
92