Home | History | Annotate | Download | only in marisa_alpha
      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_alpha {
     13 
     14 Writer::Writer()
     15     : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {}
     16 
     17 Writer::Writer(std::FILE *file)
     18     : file_(file), fd_(-1), stream_(NULL), needs_fclose_(false) {}
     19 
     20 Writer::Writer(int fd)
     21     : file_(NULL), fd_(fd), stream_(NULL), needs_fclose_(false) {}
     22 
     23 Writer::Writer(std::ostream *stream)
     24     : file_(NULL), fd_(-1), stream_(stream), needs_fclose_(false) {}
     25 
     26 Writer::~Writer() {
     27   if (needs_fclose_) {
     28     ::fclose(file_);
     29   }
     30 }
     31 
     32 void Writer::open(const char *filename, bool trunc_flag,
     33     long offset, int whence) {
     34   MARISA_ALPHA_THROW_IF(is_open(), MARISA_ALPHA_STATE_ERROR);
     35   MARISA_ALPHA_THROW_IF(filename == NULL, MARISA_ALPHA_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_ALPHA_THROW(MARISA_ALPHA_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_ALPHA_THROW_IF(file == NULL, MARISA_ALPHA_IO_ERROR);
     54   }
     55 #endif  // _MSC_VER
     56   if (::fseek(file, offset, whence) != 0) {
     57     ::fclose(file);
     58     MARISA_ALPHA_THROW(MARISA_ALPHA_IO_ERROR);
     59   }
     60   file_ = file;
     61   needs_fclose_ = true;
     62 }
     63 
     64 void Writer::clear() {
     65   Writer().swap(this);
     66 }
     67 
     68 void Writer::swap(Writer *rhs) {
     69   MARISA_ALPHA_THROW_IF(rhs == NULL, MARISA_ALPHA_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 
     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_ALPHA_THROW_IF(size_written <= 0, MARISA_ALPHA_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_ALPHA_THROW(MARISA_ALPHA_IO_ERROR);
     93     }
     94   } else if (stream_ != NULL) {
     95     try {
     96       if (!stream_->write(static_cast<const char *>(data), size)) {
     97         MARISA_ALPHA_THROW(MARISA_ALPHA_IO_ERROR);
     98       }
     99     } catch (const std::ios_base::failure &) {
    100       MARISA_ALPHA_THROW(MARISA_ALPHA_IO_ERROR);
    101     }
    102   } else {
    103     MARISA_ALPHA_THROW(MARISA_ALPHA_STATE_ERROR);
    104   }
    105 }
    106 
    107 }  // namespace marisa_alpha
    108