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