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 14 Reader::Reader() 15 : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {} 16 17 Reader::Reader(std::FILE *file) 18 : file_(file), fd_(-1), stream_(NULL), needs_fclose_(false) {} 19 20 Reader::Reader(int fd) 21 : file_(NULL), fd_(fd), stream_(NULL), needs_fclose_(false) {} 22 23 Reader::Reader(std::istream *stream) 24 : file_(NULL), fd_(-1), stream_(stream), needs_fclose_(false) {} 25 26 Reader::~Reader() { 27 if (needs_fclose_) { 28 ::fclose(file_); 29 } 30 } 31 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 52 void Reader::clear() { 53 Reader().swap(this); 54 } 55 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 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