TorchCraftAI
A bot for machine learning research on StarCraft: Brood War
zstdstream.h
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  *
7  * This source code is licensed under the BSD-style license found in the
8  * LICENSE file in the root directory of this source tree. An additional grant
9  * of patent rights can be found in the PATENTS file in the same directory.
10  *
11  * STL stream classes for Zstd compression and decompression.
12  * Partially inspired by https://github.com/mateidavid/zstr.
13  */
14 
15 #pragma once
16 
17 #include <cassert>
18 #include <fstream>
19 #include <stdexcept>
20 #include <vector>
21 
22 // Required to access ZSTD_isFrame()
23 #define ZSTD_STATIC_LINKING_ONLY
24 #include <zstd.h>
25 
26 #include "circularbuffer.h"
27 
28 namespace common {
29 namespace zstd {
30 
31 /**
32  * Custom exception for zstd error codes
33  */
34 class exception : public std::exception {
35  public:
36  explicit exception(int code);
37  const char* what() const throw();
38 
39  private:
40  std::string msg_;
41 };
42 
43 inline size_t check(size_t code) {
44  if (ZSTD_isError(code)) {
45  throw exception(code);
46  }
47  return code;
48 }
49 
50 /**
51  * Provides stream compression functionality
52  */
53 class cstream {
54  public:
55  static constexpr int defaultLevel = 5;
56 
57  cstream();
58  ~cstream();
59 
60  size_t init(int level = defaultLevel);
61  size_t compress(ZSTD_outBuffer* output, ZSTD_inBuffer* input);
62  size_t flush(ZSTD_outBuffer* output);
63  size_t end(ZSTD_outBuffer* output);
64 
65  private:
66  ZSTD_CStream* cstrm_;
67 };
68 
69 /**
70  * Provides stream decompression functionality
71  */
72 class dstream {
73  public:
74  dstream();
75  ~dstream();
76 
77  size_t decompress(ZSTD_outBuffer* output, ZSTD_inBuffer* input);
78 
79  private:
80  ZSTD_DStream* dstrm_;
81 };
82 
83 /**
84  * Zstd stream buffer for compression. Data is written in a single big frame.
85  */
86 class ostreambuf : public std::streambuf {
87  public:
88  explicit ostreambuf(std::streambuf* sbuf, int level = cstream::defaultLevel);
89  virtual ~ostreambuf();
90 
91  using int_type = typename std::streambuf::int_type;
92  virtual int_type overflow(int_type ch = traits_type::eof());
93  virtual int sync();
94 
95  private:
96  ssize_t compress(size_t pos);
97 
98  std::streambuf* sbuf_;
99  int clevel_;
100  cstream strm_;
101  std::vector<char> inbuf_;
102  std::vector<char> outbuf_;
103  size_t inhint_;
104  bool strInit_;
105 };
106 
107 /**
108  * Zstd stream buffer for decompression. If input data is not compressed, this
109  * stream will simply copy it.
110  */
111 class istreambuf : public std::streambuf {
112  public:
113  explicit istreambuf(std::streambuf* sbuf);
114 
115  virtual std::streambuf::int_type underflow();
116 
117  private:
118  std::streambuf* sbuf_;
119  dstream strm_;
120  std::vector<char> inbuf_;
121  std::vector<char> outbuf_; // only needed if actually compressed
122  size_t inhint_;
123  size_t inpos_ = 0;
124  size_t inavail_ = 0;
125  bool detected_ = false;
126  bool compressed_ = false;
127 };
128 
129 // Input stream for Zstd-compressed data
130 class istream : public std::istream {
131  public:
132  istream(std::streambuf* sbuf);
133 
134  virtual ~istream();
135 };
136 
137 /**
138  * Output stream for Zstd-compressed data
139  */
140 class ostream : public std::ostream {
141  public:
142  ostream(std::streambuf* sbuf);
143  virtual ~ostream();
144 };
145 
146 /**
147  * This class enables [io]fstream below to inherit from [io]stream (required for
148  * setting a custom streambuf) while still constructing a corresponding
149  * [io]fstream first (required for initializing the Zstd streambufs).
150  */
151 template <typename T>
152 class fsholder {
153  public:
154  explicit fsholder(
155  const std::string& path,
156  std::ios_base::openmode mode = std::ios_base::out)
157  : fs_(path, mode) {}
158 
159  protected:
160  T fs_;
161 };
162 
163 /**
164  * Output file stream that writes Zstd-compressed data
165  */
166 class ofstream : private fsholder<std::ofstream>, public std::ostream {
167  public:
168  explicit ofstream(
169  const std::string& path,
170  std::ios_base::openmode mode = std::ios_base::out);
171  virtual ~ofstream();
172 
173  virtual operator bool() const;
174  void close();
175 };
176 
177 /**
178  * Input file stream for Zstd-compressed data
179  */
180 class ifstream : private fsholder<std::ifstream>, public std::istream {
181  public:
182  explicit ifstream(
183  const std::string& path,
184  std::ios_base::openmode mode = std::ios_base::in);
185 
186  virtual ~ifstream();
187  operator bool() const;
188  void close();
189 };
190 
191 } // namespace zstd
192 } // namespace common
Input file stream for Zstd-compressed data.
Definition: zstdstream.h:180
Zstd stream buffer for decompression.
Definition: zstdstream.h:111
fsholder(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
Definition: zstdstream.h:154
typename std::streambuf::int_type int_type
Definition: zstdstream.h:91
const char * what() const
Definition: zstdstream.cpp:24
Zstd stream buffer for compression.
Definition: zstdstream.h:86
Output stream for Zstd-compressed data.
Definition: zstdstream.h:140
Output file stream that writes Zstd-compressed data.
Definition: zstdstream.h:166
static constexpr int defaultLevel
Definition: zstdstream.h:55
General utilities.
Definition: assert.cpp:7
size_t check(size_t code)
Definition: zstdstream.h:43
Provides stream compression functionality.
Definition: zstdstream.h:53
This class enables [io]fstream below to inherit from [io]stream (required for setting a custom stream...
Definition: zstdstream.h:152
exception(int code)
Definition: zstdstream.cpp:20
T fs_
Definition: zstdstream.h:160
Provides stream decompression functionality.
Definition: zstdstream.h:72
Custom exception for zstd error codes.
Definition: zstdstream.h:34
Definition: zstdstream.h:130