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 12namespace marisa_alpha { 13 14Reader::Reader() 15 : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {} 16 17Reader::Reader(std::FILE *file) 18 : file_(file), fd_(-1), stream_(NULL), needs_fclose_(false) {} 19 20Reader::Reader(int fd) 21 : file_(NULL), fd_(fd), stream_(NULL), needs_fclose_(false) {} 22 23Reader::Reader(std::istream *stream) 24 : file_(NULL), fd_(-1), stream_(stream), needs_fclose_(false) {} 25 26Reader::~Reader() { 27 if (needs_fclose_) { 28 ::fclose(file_); 29 } 30} 31 32void Reader::open(const char *filename, long offset, int whence) { 33 MARISA_ALPHA_THROW_IF(is_open(), MARISA_ALPHA_STATE_ERROR); 34 MARISA_ALPHA_THROW_IF(filename == NULL, MARISA_ALPHA_PARAM_ERROR); 35#ifdef _MSC_VER 36 std::FILE *file = NULL; 37 if (::fopen_s(&file, filename, "rb") != 0) { 38 MARISA_ALPHA_THROW(MARISA_ALPHA_IO_ERROR); 39 } 40#else // _MSC_VER 41 std::FILE * const file = ::fopen(filename, "rb"); 42 MARISA_ALPHA_THROW_IF(file == NULL, MARISA_ALPHA_IO_ERROR); 43#endif // _MSC_VER 44 if (::fseek(file, offset, whence) != 0) { 45 ::fclose(file); 46 MARISA_ALPHA_THROW(MARISA_ALPHA_IO_ERROR); 47 } 48 file_ = file; 49 needs_fclose_ = true; 50} 51 52void Reader::clear() { 53 Reader().swap(this); 54} 55 56void Reader::swap(Reader *rhs) { 57 MARISA_ALPHA_THROW_IF(rhs == NULL, MARISA_ALPHA_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 64void 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_ALPHA_THROW_IF(size_read <= 0, MARISA_ALPHA_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_ALPHA_THROW(MARISA_ALPHA_IO_ERROR); 81 } 82 } else if (stream_ != NULL) { 83 try { 84 if (!stream_->read(static_cast<char *>(buf), size)) { 85 MARISA_ALPHA_THROW(MARISA_ALPHA_IO_ERROR); 86 } 87 } catch (const std::ios_base::failure &) { 88 MARISA_ALPHA_THROW(MARISA_ALPHA_IO_ERROR); 89 } 90 } else { 91 MARISA_ALPHA_THROW(MARISA_ALPHA_STATE_ERROR); 92 } 93} 94 95} // namespace marisa_alpha 96