Mercurial > hg > octave-nkf
annotate src/zfstream.h @ 11118:d517388b1c41
Added tag ss-3-3-53 for changeset 6c69a7c39039
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 19 Oct 2010 02:25:45 -0400 |
parents | 42d098307c30 |
children | fd0a3ac60b0e |
rev | line source |
---|---|
5269 | 1 /* |
2 | |
8920 | 3 Copyright (C) 2005, 2007, 2008 Ludwig Schwardt, Kevin Ruland |
5269 | 4 |
5 This file is part of Octave. | |
6 | |
7 Octave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
7016 | 9 Free Software Foundation; either version 3 of the License, or (at your |
10 option) any later version. | |
5269 | 11 |
12 Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
7016 | 18 along with Octave; see the file COPYING. If not, see |
19 <http://www.gnu.org/licenses/>. | |
5269 | 20 |
21 */ | |
22 | |
23 /* | |
24 | |
25 This file is adapted from the zlib 1.2.2 contrib/iostream3 code, | |
26 written by | |
27 | |
28 Ludwig Schwardt <schwardt@sun.ac.za> | |
29 original version by Kevin Ruland <kevin@rodin.wustl.edu> | |
30 | |
31 */ | |
32 | |
33 #ifndef ZFSTREAM_H | |
34 #define ZFSTREAM_H | |
35 | |
36 #ifdef HAVE_ZLIB | |
37 | |
8950
d865363208d6
include <iosfwd> instead of <iostream> in header files
John W. Eaton <jwe@octave.org>
parents:
8920
diff
changeset
|
38 #include <iosfwd> |
d865363208d6
include <iosfwd> instead of <iostream> in header files
John W. Eaton <jwe@octave.org>
parents:
8920
diff
changeset
|
39 |
5269 | 40 #include "zlib.h" |
41 | |
42 /*****************************************************************************/ | |
43 | |
44 /** | |
45 * @brief Gzipped file stream buffer class. | |
46 * | |
47 * This class implements basic_filebuf for gzipped files. It doesn't yet support | |
48 * seeking (allowed by zlib but slow/limited), putback and read/write access | |
49 * (tricky). Otherwise, it attempts to be a drop-in replacement for the standard | |
50 * file streambuf. | |
51 */ | |
52 class gzfilebuf : public std::streambuf | |
53 { | |
54 public: | |
55 // Default constructor. | |
56 gzfilebuf(); | |
57 | |
58 // Destructor. | |
59 virtual | |
60 ~gzfilebuf(); | |
61 | |
62 /** | |
63 * @brief Set compression level and strategy on the fly. | |
64 * @param comp_level Compression level (see zlib.h for allowed values) | |
65 * @param comp_strategy Compression strategy (see zlib.h for allowed values) | |
66 * @return Z_OK on success, Z_STREAM_ERROR otherwise. | |
67 * | |
68 * Unfortunately, these parameters cannot be modified separately, as the | |
69 * previous zfstream version assumed. Since the strategy is seldom changed, | |
70 * it can default and setcompression(level) then becomes like the old | |
71 * setcompressionlevel(level). | |
72 */ | |
73 int | |
74 setcompression(int comp_level, | |
75 int comp_strategy = Z_DEFAULT_STRATEGY); | |
76 | |
77 /** | |
78 * @brief Check if file is open. | |
79 * @return True if file is open. | |
80 */ | |
81 bool | |
7520 | 82 is_open() const { return (file != 0); } |
5269 | 83 |
84 /** | |
85 * @brief Open gzipped file. | |
86 * @param name File name. | |
87 * @param mode Open mode flags. | |
88 * @return @c this on success, NULL on failure. | |
89 */ | |
90 gzfilebuf* | |
91 open(const char* name, | |
92 std::ios_base::openmode mode); | |
93 | |
94 /** | |
95 * @brief Attach to already open gzipped file. | |
96 * @param fd File descriptor. | |
97 * @param mode Open mode flags. | |
98 * @return @c this on success, NULL on failure. | |
99 */ | |
100 gzfilebuf* | |
101 attach(int fd, | |
102 std::ios_base::openmode mode); | |
103 | |
104 /** | |
105 * @brief Close gzipped file. | |
106 * @return @c this on success, NULL on failure. | |
107 */ | |
108 gzfilebuf* | |
109 close(); | |
110 | |
111 protected: | |
112 /** | |
113 * @brief Convert ios open mode int to mode string used by zlib. | |
114 * @return True if valid mode flag combination. | |
115 */ | |
116 bool | |
117 open_mode(std::ios_base::openmode mode, | |
118 char* c_mode) const; | |
119 | |
120 /** | |
121 * @brief Number of characters available in stream buffer. | |
122 * @return Number of characters. | |
123 * | |
124 * This indicates number of characters in get area of stream buffer. | |
125 * These characters can be read without accessing the gzipped file. | |
126 */ | |
127 virtual std::streamsize | |
128 showmanyc(); | |
129 | |
130 /** | |
131 * @brief Fill get area from gzipped file. | |
132 * @return First character in get area on success, EOF on error. | |
133 * | |
134 * This actually reads characters from gzipped file to stream | |
135 * buffer. Always buffered. | |
136 */ | |
137 virtual int_type | |
138 underflow(); | |
139 | |
140 /** | |
141 * @brief Write put area to gzipped file. | |
142 * @param c Extra character to add to buffer contents. | |
143 * @return Non-EOF on success, EOF on error. | |
144 * | |
145 * This actually writes characters in stream buffer to | |
146 * gzipped file. With unbuffered output this is done one | |
147 * character at a time. | |
148 */ | |
149 virtual int_type | |
150 overflow(int_type c = traits_type::eof()); | |
151 | |
152 /** | |
153 * @brief Installs external stream buffer. | |
154 * @param p Pointer to char buffer. | |
155 * @param n Size of external buffer. | |
156 * @return @c this on success, NULL on failure. | |
157 * | |
158 * Call setbuf(0,0) to enable unbuffered output. | |
159 */ | |
160 virtual std::streambuf* | |
161 setbuf(char_type* p, | |
162 std::streamsize n); | |
163 | |
164 /** | |
165 * @brief Flush stream buffer to file. | |
166 * @return 0 on success, -1 on error. | |
167 * | |
168 * This calls underflow(EOF) to do the job. | |
169 */ | |
170 virtual int | |
171 sync(); | |
172 | |
173 /** | |
174 * @brief Alters the stream positions. | |
175 * | |
176 * Each derived class provides its own appropriate behavior. | |
177 */ | |
178 virtual pos_type | |
179 seekoff(off_type off, std::ios_base::seekdir way, | |
10317
42d098307c30
untabify additional source files
John W. Eaton <jwe@octave.org>
parents:
10160
diff
changeset
|
180 std::ios_base::openmode mode = |
42d098307c30
untabify additional source files
John W. Eaton <jwe@octave.org>
parents:
10160
diff
changeset
|
181 std::ios_base::in|std::ios_base::out); |
5269 | 182 |
183 /** | |
184 * @brief Alters the stream positions. | |
185 * | |
186 * Each derived class provides its own appropriate behavior. | |
187 */ | |
188 virtual pos_type | |
189 seekpos(pos_type sp, std::ios_base::openmode mode = | |
10317
42d098307c30
untabify additional source files
John W. Eaton <jwe@octave.org>
parents:
10160
diff
changeset
|
190 std::ios_base::in|std::ios_base::out); |
5269 | 191 |
6777 | 192 virtual int_type |
193 pbackfail (int_type c = traits_type::eof()); | |
194 | |
5269 | 195 // |
196 // Some future enhancements | |
197 // | |
198 // virtual int_type uflow(); | |
199 // virtual int_type pbackfail(int_type c = traits_type::eof()); | |
200 | |
201 private: | |
202 /** | |
203 * @brief Allocate internal buffer. | |
204 * | |
205 * This function is safe to call multiple times. It will ensure | |
206 * that a proper internal buffer exists if it is required. If the | |
207 * buffer already exists or is external, the buffer pointers will be | |
208 * reset to their original state. | |
209 */ | |
210 void | |
211 enable_buffer(); | |
212 | |
213 /** | |
214 * @brief Destroy internal buffer. | |
215 * | |
216 * This function is safe to call multiple times. It will ensure | |
217 * that the internal buffer is deallocated if it exists. In any | |
218 * case, it will also reset the buffer pointers. | |
219 */ | |
220 void | |
221 disable_buffer(); | |
222 | |
223 /** | |
224 * Underlying file pointer. | |
225 */ | |
226 gzFile file; | |
227 | |
228 /** | |
229 * Mode in which file was opened. | |
230 */ | |
231 std::ios_base::openmode io_mode; | |
232 | |
233 /** | |
234 * @brief True if this object owns file descriptor. | |
235 * | |
236 * This makes the class responsible for closing the file | |
237 * upon destruction. | |
238 */ | |
239 bool own_fd; | |
240 | |
241 /** | |
242 * @brief Stream buffer. | |
243 * | |
244 * For simplicity this remains allocated on the free store for the | |
245 * entire life span of the gzfilebuf object, unless replaced by setbuf. | |
246 */ | |
247 char_type* buffer; | |
248 | |
249 /** | |
250 * @brief Stream buffer size. | |
251 * | |
252 * Defaults to system default buffer size (typically 8192 bytes). | |
253 * Modified by setbuf. | |
254 */ | |
255 std::streamsize buffer_size; | |
256 | |
257 /** | |
258 * @brief True if this object owns stream buffer. | |
259 * | |
260 * This makes the class responsible for deleting the buffer | |
261 * upon destruction. | |
262 */ | |
263 bool own_buffer; | |
264 }; | |
265 | |
266 /*****************************************************************************/ | |
267 | |
268 /** | |
269 * @brief Gzipped file input stream class. | |
270 * | |
271 * This class implements ifstream for gzipped files. Seeking and putback | |
272 * is not supported yet. | |
273 */ | |
274 class gzifstream : public std::istream | |
275 { | |
276 public: | |
277 // Default constructor | |
278 gzifstream(); | |
279 | |
280 /** | |
281 * @brief Construct stream on gzipped file to be opened. | |
282 * @param name File name. | |
283 * @param mode Open mode flags (forced to contain ios::in). | |
284 */ | |
285 explicit | |
286 gzifstream(const char* name, | |
287 std::ios_base::openmode mode = std::ios_base::in); | |
288 | |
289 /** | |
290 * @brief Construct stream on already open gzipped file. | |
291 * @param fd File descriptor. | |
292 * @param mode Open mode flags (forced to contain ios::in). | |
293 */ | |
294 explicit | |
295 gzifstream(int fd, | |
296 std::ios_base::openmode mode = std::ios_base::in); | |
297 | |
298 /** | |
299 * Obtain underlying stream buffer. | |
300 */ | |
301 gzfilebuf* | |
302 rdbuf() const | |
303 { return const_cast<gzfilebuf*>(&sb); } | |
304 | |
305 /** | |
306 * @brief Check if file is open. | |
307 * @return True if file is open. | |
308 */ | |
309 bool | |
310 is_open() { return sb.is_open(); } | |
311 | |
312 /** | |
313 * @brief Open gzipped file. | |
314 * @param name File name. | |
315 * @param mode Open mode flags (forced to contain ios::in). | |
316 * | |
317 * Stream will be in state good() if file opens successfully; | |
318 * otherwise in state fail(). This differs from the behavior of | |
319 * ifstream, which never sets the state to good() and therefore | |
320 * won't allow you to reuse the stream for a second file unless | |
321 * you manually clear() the state. The choice is a matter of | |
322 * convenience. | |
323 */ | |
324 void | |
325 open(const char* name, | |
326 std::ios_base::openmode mode = std::ios_base::in); | |
327 | |
328 /** | |
329 * @brief Attach to already open gzipped file. | |
330 * @param fd File descriptor. | |
331 * @param mode Open mode flags (forced to contain ios::in). | |
332 * | |
333 * Stream will be in state good() if attach succeeded; otherwise | |
334 * in state fail(). | |
335 */ | |
336 void | |
337 attach(int fd, | |
338 std::ios_base::openmode mode = std::ios_base::in); | |
339 | |
340 /** | |
341 * @brief Close gzipped file. | |
342 * | |
343 * Stream will be in state fail() if close failed. | |
344 */ | |
345 void | |
346 close(); | |
347 | |
348 private: | |
349 /** | |
350 * Underlying stream buffer. | |
351 */ | |
352 gzfilebuf sb; | |
353 }; | |
354 | |
355 /*****************************************************************************/ | |
356 | |
357 /** | |
358 * @brief Gzipped file output stream class. | |
359 * | |
360 * This class implements ofstream for gzipped files. Seeking and putback | |
361 * is not supported yet. | |
362 */ | |
363 class gzofstream : public std::ostream | |
364 { | |
365 public: | |
366 // Default constructor | |
367 gzofstream(); | |
368 | |
369 /** | |
370 * @brief Construct stream on gzipped file to be opened. | |
371 * @param name File name. | |
372 * @param mode Open mode flags (forced to contain ios::out). | |
373 */ | |
374 explicit | |
375 gzofstream(const char* name, | |
376 std::ios_base::openmode mode = std::ios_base::out); | |
377 | |
378 /** | |
379 * @brief Construct stream on already open gzipped file. | |
380 * @param fd File descriptor. | |
381 * @param mode Open mode flags (forced to contain ios::out). | |
382 */ | |
383 explicit | |
384 gzofstream(int fd, | |
385 std::ios_base::openmode mode = std::ios_base::out); | |
386 | |
387 /** | |
388 * Obtain underlying stream buffer. | |
389 */ | |
390 gzfilebuf* | |
391 rdbuf() const | |
392 { return const_cast<gzfilebuf*>(&sb); } | |
393 | |
394 /** | |
395 * @brief Check if file is open. | |
396 * @return True if file is open. | |
397 */ | |
398 bool | |
399 is_open() { return sb.is_open(); } | |
400 | |
401 /** | |
402 * @brief Open gzipped file. | |
403 * @param name File name. | |
404 * @param mode Open mode flags (forced to contain ios::out). | |
405 * | |
406 * Stream will be in state good() if file opens successfully; | |
407 * otherwise in state fail(). This differs from the behavior of | |
408 * ofstream, which never sets the state to good() and therefore | |
409 * won't allow you to reuse the stream for a second file unless | |
410 * you manually clear() the state. The choice is a matter of | |
411 * convenience. | |
412 */ | |
413 void | |
414 open(const char* name, | |
415 std::ios_base::openmode mode = std::ios_base::out); | |
416 | |
417 /** | |
418 * @brief Attach to already open gzipped file. | |
419 * @param fd File descriptor. | |
420 * @param mode Open mode flags (forced to contain ios::out). | |
421 * | |
422 * Stream will be in state good() if attach succeeded; otherwise | |
423 * in state fail(). | |
424 */ | |
425 void | |
426 attach(int fd, | |
427 std::ios_base::openmode mode = std::ios_base::out); | |
428 | |
429 /** | |
430 * @brief Close gzipped file. | |
431 * | |
432 * Stream will be in state fail() if close failed. | |
433 */ | |
434 void | |
435 close(); | |
436 | |
437 private: | |
438 /** | |
439 * Underlying stream buffer. | |
440 */ | |
441 gzfilebuf sb; | |
442 }; | |
443 | |
444 /*****************************************************************************/ | |
445 | |
446 /** | |
447 * @brief Gzipped file output stream manipulator class. | |
448 * | |
449 * This class defines a two-argument manipulator for gzofstream. It is used | |
450 * as base for the setcompression(int,int) manipulator. | |
451 */ | |
452 template<typename T1, typename T2> | |
453 class gzomanip2 | |
454 { | |
455 public: | |
456 // Allows insertor to peek at internals | |
457 template <typename Ta, typename Tb> | |
458 friend gzofstream& | |
459 operator<<(gzofstream&, | |
460 const gzomanip2<Ta,Tb>&); | |
461 | |
462 // Constructor | |
463 gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2), | |
464 T1 v1, | |
465 T2 v2); | |
466 private: | |
467 // Underlying manipulator function | |
468 gzofstream& | |
469 (*func)(gzofstream&, T1, T2); | |
470 | |
471 // Arguments for manipulator function | |
472 T1 val1; | |
473 T2 val2; | |
474 }; | |
475 | |
476 /*****************************************************************************/ | |
477 | |
478 // Manipulator function thunks through to stream buffer | |
479 inline gzofstream& | |
480 setcompression(gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY) | |
481 { | |
482 (gzs.rdbuf())->setcompression(l, s); | |
483 return gzs; | |
484 } | |
485 | |
486 // Manipulator constructor stores arguments | |
487 template<typename T1, typename T2> | |
488 inline | |
489 gzomanip2<T1,T2>::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2), | |
490 T1 v1, | |
491 T2 v2) | |
492 : func(f), val1(v1), val2(v2) | |
493 { } | |
494 | |
495 // Insertor applies underlying manipulator function to stream | |
496 template<typename T1, typename T2> | |
497 inline gzofstream& | |
498 operator<<(gzofstream& s, const gzomanip2<T1,T2>& m) | |
499 { return (*m.func)(s, m.val1, m.val2); } | |
500 | |
501 // Insert this onto stream to simplify setting of compression level | |
502 inline gzomanip2<int,int> | |
503 setcompression(int l, int s = Z_DEFAULT_STRATEGY) | |
504 { return gzomanip2<int,int>(&setcompression, l, s); } | |
505 | |
506 #endif // HAVE_ZLIB | |
507 | |
508 #endif // ZFSTREAM_H |