FST  openfst-1.7.2
OpenFst Library
gzfile.h
Go to the documentation of this file.
1 // See www.openfst.org for extensive documentation on this weighted
2 // finite-state transducer library.
3 //
4 // Resource handles for gzip files written to or read from stringstreams. These
5 // are necessary to provide the compression routines with streams reading from
6 // or writing to compressed files (or the UNIX standard streams), and are not
7 // intended for general use.
8 
9 #ifndef FST_EXTENSIONS_COMPRESS_GZFILE_H_
10 #define FST_EXTENSIONS_COMPRESS_GZFILE_H_
11 
12 #include <cstddef>
13 #include <memory>
14 #include <sstream>
15 #include <string>
16 
17 #include <fst/compat.h>
18 #include <fst/log.h>
19 #include <fst/fst.h>
20 #include <zlib.h>
21 
22 using std::stringstream;
23 using std::unique_ptr;
24 
25 namespace fst {
26 
27 // Gives the zlib gzFile type an OO-like interface. String inputs are all
28 // C-style strings. The caller is responsible to get the file modes appropriate
29 // for the IO methods being called, and for opening the file descriptors
30 // if that constructor is used. The ! operator can be used to check for errors
31 // after construction or read/writing.
32 class GzFile {
33  public:
34  GzFile(const char *filename, const char *mode)
35  : gzfile_(gzopen(filename, mode)), error_(check_handle()) {
36  }
37 
38  // The caller is responsible to ensure the corresponding FD is open and has
39  // the needed modes ("r" for reading, "w" or "a" for writing).
40  explicit GzFile(const int fd, const char *mode)
41  : gzfile_(gzdopen(fd, mode)), error_(check_handle()), close_me_(false) {
42  }
43 
44  // If the instance was constructed from an FD, flush the buffer; otherwise,
45  // close the file, which flushes the buffer as a side-effect.
46  ~GzFile() { close_me_ ? gzclose(gzfile_) : gzflush(gzfile_, Z_FINISH); }
47 
48  inline bool operator!() const { return error_; }
49 
50  // Returns false on EOF and sets error if short read does not reach an EOF.
51  int read(void *buf, unsigned int size) {
52  int bytes_read = gzread(gzfile_, buf, size);
53  if ((bytes_read < size) && !gzeof(gzfile_)) error_ = true;
54  return bytes_read;
55  }
56 
57  // Sets error on short writes.
58  void write(const char *buf, unsigned int size) {
59  if (gzwrite(gzfile_, buf, size) != size) error_ = true;
60  }
61 
62  private:
63  // gzopen and gzdopen signal failure by returning null.
64  bool check_handle() { return gzfile_ == nullptr; }
65 
66  gzFile gzfile_ = nullptr;
67  bool error_ = false;
68  bool close_me_ = false;
69 };
70 
71 // Resource handle for writing stringstream to GzFile.
72 class OGzFile {
73  public:
74  explicit OGzFile(const string &filename) : OGzFile(filename.c_str()) {}
75 
76  explicit OGzFile(const char *filename) : gz_(GzFile(filename, mode_)) {}
77 
78  explicit OGzFile(const int fd) : gz_(GzFile(fd, mode_)) {}
79 
80  inline bool operator!() const { return !gz_; }
81 
82  void write(const std::stringstream &ssbuf) {
83  string sbuf = ssbuf.str();
84  gz_.write(sbuf.data(), sbuf.size());
85  }
86 
87  private:
88  GzFile gz_;
89  static constexpr auto &mode_ = "wb";
90 };
91 
92 // Resource handle for reading stringstream from GzFile.
93 class IGzFile {
94  public:
95  explicit IGzFile(const string &filename) : IGzFile(filename.c_str()) {}
96 
97  explicit IGzFile(const char *filename) : gz_(GzFile(filename, mode_)) {}
98 
99  explicit IGzFile(const int fd) : gz_(GzFile(fd, mode_)) {}
100 
101  inline bool operator!() const { return !gz_; }
102 
103  // This is a great case for "move", but GCC 4 is missing the C+11 standard
104  // move constructor for stringstream, so a unique_ptr is the next best thing.
105  std::unique_ptr<std::stringstream> read() {
106  char buf[bufsize_];
107  std::unique_ptr<std::stringstream> sstrm(new std::stringstream);
108  // We always read at least once, and the result of the last read is always
109  // pushed onto the stringstream. We use the "write" member because << onto
110  // a stringstream stops at the null byte, which might be data!
111  int bytes_read;
112  while ((bytes_read = gz_.read(buf, bufsize_)) == bufsize_)
113  sstrm->write(buf, bufsize_);
114  sstrm->write(buf, bytes_read);
115  return sstrm;
116  }
117 
118  private:
119  GzFile gz_;
120  static constexpr auto &mode_ = "rb";
121  // This is the same size as the default internal buffer for zlib.
122  static const size_t bufsize_ = 8192;
123 };
124 
125 } // namespace fst
126 
127 #endif // FST_EXTENSIONS_COMPRESS_GZFILE_H_
GzFile(const char *filename, const char *mode)
Definition: gzfile.h:34
OGzFile(const char *filename)
Definition: gzfile.h:76
int read(void *buf, unsigned int size)
Definition: gzfile.h:51
bool operator!() const
Definition: gzfile.h:80
OGzFile(const int fd)
Definition: gzfile.h:78
IGzFile(const string &filename)
Definition: gzfile.h:95
bool operator!() const
Definition: gzfile.h:48
bool operator!() const
Definition: gzfile.h:101
GzFile(const int fd, const char *mode)
Definition: gzfile.h:40
void write(const std::stringstream &ssbuf)
Definition: gzfile.h:82
IGzFile(const char *filename)
Definition: gzfile.h:97
void write(const char *buf, unsigned int size)
Definition: gzfile.h:58
std::unique_ptr< std::stringstream > read()
Definition: gzfile.h:105
OGzFile(const string &filename)
Definition: gzfile.h:74
~GzFile()
Definition: gzfile.h:46
IGzFile(const int fd)
Definition: gzfile.h:99