Codebase list libhpptools / 3fc7555
pull in changes from zstr Matei David 7 years ago
2 changed file(s) with 67 addition(s) and 49 deletion(s). Raw diff Collapse all Expand all
0 /// @author Matei David, Ontario Institute for Cancer Research
1 /// @version 1.0
2 /// @date 2015
3 /// @copyright MIT Public License
4 ///
5 /// Strict fstream objects.
6 ///
7 /// This namespace defines wrappers for std::ifstream, std::ofstream, and
8 /// std::fstream objects. The wrappers perform the following steps:
9 /// - check the open modes make sense
10 /// - check that the call to open() is successful
11 /// - (for input streams) check that the opened file is peek-able
12 /// - turn on the badbit in the exception mask
13
140 #ifndef __STRICT_FSTREAM_HPP
151 #define __STRICT_FSTREAM_HPP
162
195 #include <cstring>
206 #include <string>
217
8 /**
9 * This namespace defines wrappers for std::ifstream, std::ofstream, and
10 * std::fstream objects. The wrappers perform the following steps:
11 * - check the open modes make sense
12 * - check that the call to open() is successful
13 * - (for input streams) check that the opened file is peek-able
14 * - turn on the badbit in the exception mask
15 */
2216 namespace strict_fstream
2317 {
18
19 /// Overload of error-reporting function, to enable use with VS.
20 /// Ref: http://stackoverflow.com/a/901316/717706
21 static std::string strerror()
22 {
23 std::string buff(80, '\0');
24 #ifdef _WIN32
25 if (strerror_s(&buff[0], buff.size(), errno) != 0)
26 {
27 buff = "Unknown error";
28 }
29 #elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
30 // XSI-compliant strerror_r()
31 if (strerror_r(errno, &buff[0], buff.size()) != 0)
32 {
33 buff = "Unknown error";
34 }
35 #else
36 // GNU-specific strerror_r()
37 auto p = strerror_r(errno, &buff[0], buff.size());
38 std::string tmp(p, std::strlen(p));
39 std::swap(buff, tmp);
40 #endif
41 buff.resize(buff.find('\0'));
42 return buff;
43 }
2444
2545 /// Exception class thrown by failed operations.
2646 class Exception
6181 "binary"
6282 };
6383 std::string res;
64 for (size_t i = 0; i < n_modes; ++i)
84 for (int i = 0; i < n_modes; ++i)
6585 {
6686 if (mode & mode_val_v[i])
6787 {
68 res += (not res.empty()? "|" : "");
88 res += (! res.empty()? "|" : "");
6989 res += mode_name_v[i];
7090 }
7191 }
7494 }
7595 static void check_mode(const std::string& filename, std::ios_base::openmode mode)
7696 {
77 if ((mode & std::ios_base::trunc) and not (mode & std::ios_base::out))
97 if ((mode & std::ios_base::trunc) && ! (mode & std::ios_base::out))
7898 {
7999 throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and not out");
80100 }
81 else if ((mode & std::ios_base::app) and not (mode & std::ios_base::out))
101 else if ((mode & std::ios_base::app) && ! (mode & std::ios_base::out))
82102 {
83103 throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: app and not out");
84104 }
85 else if ((mode & std::ios_base::trunc) and (mode & std::ios_base::app))
105 else if ((mode & std::ios_base::trunc) && (mode & std::ios_base::app))
86106 {
87107 throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and app");
88108 }
93113 {
94114 throw Exception(std::string("strict_fstream: open('")
95115 + filename + "'," + mode_to_string(mode) + "): open failed: "
96 + std::strerror(errno));
116 + strerror());
97117 }
98118 }
99119 static void check_peek(std::istream * is_p, const std::string& filename, std::ios_base::openmode mode)
109129 {
110130 throw Exception(std::string("strict_fstream: open('")
111131 + filename + "'," + mode_to_string(mode) + "): peek failed: "
112 + std::strerror(errno));
132 + strerror());
113133 }
114134 is_p->clear();
115135 }
167187 }
168188 void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
169189 {
170 if (not (mode & std::ios_base::out)) mode |= std::ios_base::in;
190 if (! (mode & std::ios_base::out)) mode |= std::ios_base::in;
171191 exceptions(std::ios_base::badbit);
172192 detail::static_method_holder::check_mode(filename, mode);
173193 std::fstream::open(filename, mode);
0 /// @author Matei David, Ontario Institute for Cancer Research
1 /// @version 1.0
2 /// @date 2015
3 /// @copyright MIT Public License
4 ///
5 /// C++ libz wrapper.
6 ///
7 /// Reference:
8 /// http://stackoverflow.com/questions/14086417/how-to-write-custom-input-stream-in-c
0 //---------------------------------------------------------
1 // Copyright 2015 Ontario Institute for Cancer Research
2 // Written by Matei David (matei@cs.toronto.edu)
3 //---------------------------------------------------------
4
5 // Reference:
6 // http://stackoverflow.com/questions/14086417/how-to-write-custom-input-stream-in-c
97
108 #ifndef __ZSTR_HPP
119 #define __ZSTR_HPP
106104 {
107105 public:
108106 istreambuf(std::streambuf * _sbuf_p,
109 std::streamsize _buff_size = default_buff_size, bool _auto_detect = true)
107 std::size_t _buff_size = default_buff_size, bool _auto_detect = true)
110108 : sbuf_p(_sbuf_p),
111109 zstrm_p(nullptr),
112110 buff_size(_buff_size),
152150 if (in_buff_end == in_buff_start) break; // end of input
153151 }
154152 // auto detect if the stream contains text or deflate data
155 if (auto_detect and not auto_detect_run)
153 if (auto_detect && ! auto_detect_run)
156154 {
157155 auto_detect_run = true;
158156 unsigned char b0 = *reinterpret_cast< unsigned char * >(in_buff_start);
160158 // Ref:
161159 // http://en.wikipedia.org/wiki/Gzip
162160 // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like
163 is_text = not (in_buff_start + 2 <= in_buff_end
164 and ((b0 == 0x1F and b1 == 0x8B) // gzip header
165 or (b0 == 0x78 and (b1 == 0x01 // zlib header
166 or b1 == 0x9C
167 or b1 == 0xDA))));
161 is_text = ! (in_buff_start + 2 <= in_buff_end
162 && ((b0 == 0x1F && b1 == 0x8B) // gzip header
163 || (b0 == 0x78 && (b1 == 0x01 // zlib header
164 || b1 == 0x9C
165 || b1 == 0xDA))));
168166 }
169167 if (is_text)
170168 {
178176 else
179177 {
180178 // run inflate() on input
181 if (not zstrm_p) zstrm_p = new detail::z_stream_wrapper(true);
179 if (! zstrm_p) zstrm_p = new detail::z_stream_wrapper(true);
182180 zstrm_p->next_in = reinterpret_cast< decltype(zstrm_p->next_in) >(in_buff_start);
183181 zstrm_p->avail_in = in_buff_end - in_buff_start;
184182 zstrm_p->next_out = reinterpret_cast< decltype(zstrm_p->next_out) >(out_buff_free_start);
185183 zstrm_p->avail_out = (out_buff + buff_size) - out_buff_free_start;
186184 int ret = inflate(zstrm_p, Z_NO_FLUSH);
187185 // process return code
188 if (ret != Z_OK and ret != Z_STREAM_END) throw Exception(zstrm_p, ret);
186 if (ret != Z_OK && ret != Z_STREAM_END) throw Exception(zstrm_p, ret);
189187 // update in&out pointers following inflate()
190188 in_buff_start = reinterpret_cast< decltype(in_buff_start) >(zstrm_p->next_in);
191189 in_buff_end = in_buff_start + zstrm_p->avail_in;
215213 char * in_buff_end;
216214 char * out_buff;
217215 detail::z_stream_wrapper * zstrm_p;
218 std::streamsize buff_size;
216 std::size_t buff_size;
219217 bool auto_detect;
220218 bool auto_detect_run;
221219 bool is_text;
222220
223 static const std::streamsize default_buff_size = 1 << 20;
221 static const std::size_t default_buff_size = (std::size_t)1 << 20;
224222 }; // class istreambuf
225223
226224 class ostreambuf
228226 {
229227 public:
230228 ostreambuf(std::streambuf * _sbuf_p,
231 std::streamsize _buff_size = default_buff_size, int _level = Z_DEFAULT_COMPRESSION)
229 std::size_t _buff_size = default_buff_size, int _level = Z_DEFAULT_COMPRESSION)
232230 : sbuf_p(_sbuf_p),
233231 zstrm_p(new detail::z_stream_wrapper(false, _level)),
234232 buff_size(_buff_size)
251249 zstrm_p->next_out = reinterpret_cast< decltype(zstrm_p->next_out) >(out_buff);
252250 zstrm_p->avail_out = buff_size;
253251 int ret = deflate(zstrm_p, flush);
254 if (ret != Z_OK and ret != Z_STREAM_END and ret != Z_BUF_ERROR) throw Exception(zstrm_p, ret);
252 if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) throw Exception(zstrm_p, ret);
255253 std::streamsize sz = sbuf_p->sputn(out_buff, reinterpret_cast< decltype(out_buff) >(zstrm_p->next_out) - out_buff);
256254 if (sz != reinterpret_cast< decltype(out_buff) >(zstrm_p->next_out) - out_buff)
257255 {
258256 // there was an error in the sink stream
259257 return -1;
260258 }
261 if (ret == Z_STREAM_END or ret == Z_BUF_ERROR or sz == 0)
259 if (ret == Z_STREAM_END || ret == Z_BUF_ERROR || sz == 0)
262260 {
263261 break;
264262 }
301299 {
302300 // first, call overflow to clear in_buff
303301 overflow();
304 if (not pptr()) return -1;
302 if (! pptr()) return -1;
305303 // then, call deflate asking to finish the zlib stream
306304 zstrm_p->next_in = nullptr;
307305 zstrm_p->avail_in = 0;
314312 char * in_buff;
315313 char * out_buff;
316314 detail::z_stream_wrapper * zstrm_p;
317 std::streamsize buff_size;
318
319 static const std::streamsize default_buff_size = 1 << 20;
315 std::size_t buff_size;
316
317 static const std::size_t default_buff_size = (std::size_t)1 << 20;
320318 }; // class ostreambuf
321319
322320 class istream