]> git.mxchange.org Git - simgear.git/blob - simgear/misc/zfstream.cxx
0df3c81037fc6e4b3ef2f4a316332a44453c20af
[simgear.git] / simgear / misc / zfstream.cxx
1 //  A C++ I/O streams interface to the zlib gz* functions
2 //
3 // Written by Bernie Bright, 1998
4 // Based on zlib/contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
5 //
6 // Copyright (C) 1998  Bernie Bright - bbright@c031.aone.net.au
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // Library General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 // $Id$
23
24 #include <simgear/compiler.h>
25
26 #ifdef SG_HAVE_STD_INCLUDES
27 # include <cerrno>
28 #else
29 # include <errno.h>
30 #endif
31 #include <memory.h>
32 #include <stdio.h>
33
34 #include "zfstream.hxx"
35
36 //
37 // Construct a gzfilebuf object.
38 // Allocate memory for 'get' buffer and zero all buffer pointers.
39 //
40 gzfilebuf::gzfilebuf()
41     : std::streambuf(),
42       file(NULL),
43       mode(ios_openmode(0)),
44       own_file_descriptor(false),
45       ibuf_size(0),
46       ibuffer(0)
47 {
48 //     try {
49     ibuf_size = page_size / sizeof(char);
50     ibuffer = new char [ibuf_size];
51 //     } catch (...) {
52 //      delete [] ibuffer;
53 //     }
54
55     // Null get and set pointers.
56     this->setg(0,0,0);
57     this->setp(0,0);
58 }
59
60 gzfilebuf::~gzfilebuf()
61 {
62     sync();
63     if ( own_file_descriptor )
64         this->close();
65     delete [] ibuffer;
66 }
67
68 void
69 gzfilebuf::cvt_iomode( char* p, ios_openmode io_mode )
70 {
71 //     memset( char_mode, '\0', 10 );
72 //     char* p = char_mode;
73
74     if ( io_mode & ios_in )
75     {
76         mode = ios_in;
77         *p++ = 'r';
78     }
79     else if ( io_mode & ios_app )
80     {
81         mode = ios_app;
82         *p++ = 'a';
83     }
84     else
85     {
86         mode = ios_out;
87         *p++ = 'w';
88     }
89
90     if ( io_mode & ios_binary )
91     {
92         mode |= ios_binary;
93         *p++ = 'b';
94     }
95
96     // Hard code the compression level
97     if ( io_mode & (ios_out | ios_app) )
98     {
99         *p++ = '9';
100     }
101
102     *p = '\0';
103 }
104
105 gzfilebuf*
106 gzfilebuf::open( const char *name, ios_openmode io_mode )
107 {
108     if ( is_open() )
109         return NULL;
110
111     char char_mode[10];
112     cvt_iomode( char_mode, io_mode );
113     if ( (file = gzopen(name, char_mode)) == NULL ) {
114         // perror( "gzfilebuf::open(): " );
115         errno = 0;
116         return NULL;
117     }
118
119     own_file_descriptor = true;
120
121     return this;
122 }
123
124 gzfilebuf*
125 gzfilebuf::attach( int file_descriptor, ios_openmode io_mode )
126 {
127     if ( is_open() )
128         return NULL;
129
130     char char_mode[10];
131     cvt_iomode( char_mode, io_mode );
132     if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) {
133         perror( "gzfilebuf::attach(): " );
134         errno = 0;
135         return NULL;
136     }
137
138     own_file_descriptor = false;
139
140     return this;
141 }
142
143 gzfilebuf*
144 gzfilebuf::close()
145 {
146     // cout << "closing ..." ;
147     if ( is_open() )
148     {
149         sync();
150         gzclose( file );
151         file = NULL;
152         // cout << "done" << endl;
153     } else {
154         // cout << "error" << endl;
155     }
156
157     return this;
158 }
159
160 // int
161 // gzfilebuf::setcompressionlevel( int comp_level )
162 // {
163 //     return gzsetparams(file, comp_level, -2);
164 // }
165
166 // int
167 // gzfilebuf::setcompressionstrategy( int comp_strategy )
168 // {
169 //     return gzsetparams(file, -2, comp_strategy);
170 // }
171
172
173 std::streampos
174 gzfilebuf::seekoff( std::streamoff, ios_seekdir, int )
175 {
176     return std::streampos(EOF);
177 }
178
179 gzfilebuf::int_type
180 gzfilebuf::overflow( int_type )
181 {
182 #if 0
183     if ( !is_open() || !(mode & ios::out) )
184         return EOF;
185
186     if ( !base() )
187     {
188         if ( allocate() == EOF )
189             return EOF;
190         setg(0,0,0);
191     }
192     else
193     {
194         if (in_avail())
195         {
196             return EOF;
197         }
198
199         if (out_waiting())
200         {
201             if (flushbuf() == EOF)
202                 return EOF;
203         }
204     }
205
206     int bl = blen();
207     setp( base(), base() + bl);
208
209     if ( c != EOF )
210     {
211         *pptr() = c;
212         pbump(1);
213     }
214 #endif
215     return 0;
216 }
217
218 int
219 gzfilebuf::sync()
220 {
221     if ( !is_open() )
222         return EOF;
223
224     if ( pptr() != 0 && pptr() > pbase() )
225         return flushbuf();
226
227     return 0;
228 }
229
230 gzfilebuf::int_type
231 gzfilebuf::flushbuf()
232 {
233     char* q = pbase();
234     int n = pptr() - q;
235
236     if ( gzwrite( file, q, n) < n )
237         return traits_type::eof();
238
239     setp(0,0);
240
241     return 0;
242 }
243
244 gzfilebuf::int_type
245 gzfilebuf::underflow()
246 {
247 //     cerr << "gzfilebuf::underflow(): gptr()=" << (void*)gptr() << endl;
248     // Error if the file not open for reading.
249     if ( !is_open() || !(mode & ios_in) )
250         return traits_type::eof();
251
252     // If the input buffer is empty then try to fill it.
253     if ( gptr() != 0 && gptr() < egptr() )
254     {
255         return int_type(*gptr());
256     }
257     else
258     {
259         return fillbuf() == EOF ? traits_type::eof() : int_type(*gptr());
260     }
261 }
262
263 //
264 // Load the input buffer from the underlying gz file.
265 // Returns number of characters read, or EOF.
266 //
267 int
268 gzfilebuf::fillbuf()
269 {
270     int t = gzread( file, ibuffer, ibuf_size );
271     if ( t <= 0)
272     {
273         // disable get area
274         setg(0,0,0);
275         return EOF;
276     }
277
278     // Set the input (get) pointers
279     setg( ibuffer, ibuffer, ibuffer+t );
280
281 //     cerr << "gzfilebuf::fillbuf():"
282 //       << " t=" << t
283 //       << ", ibuffer=" << (void*)ibuffer
284 //       << ", ibuffer+t=" << (void*)(ibuffer+t) << endl;
285
286     return t;
287 }
288
289 #if 0
290 gzifstream::gzifstream()
291     : istream(&buffer), buffer()
292 {
293     clear( ios_badbit );
294 }
295
296 gzifstream::gzifstream( const char *name, ios_openmode io_mode )
297     : istream(&buffer), buffer()
298 {
299     this->open( name, io_mode );
300 }
301
302 gzifstream::gzifstream( int fd, ios_openmode io_mode )
303     : istream(&buffer), buffer()
304 {
305     buffer.attach( fd, io_mode );
306 }
307
308 gzifstream::~gzifstream()
309 {
310 }
311
312 void
313 gzifstream::open( const char *name, ios_openmode io_mode )
314 {
315     if ( !buffer.open( name, io_mode ) )
316         clear( ios_failbit | ios_badbit );
317     else
318         clear();
319 }
320
321 void
322 gzifstream::close()
323 {
324     if ( !buffer.close() )
325         clear( ios_failbit | ios_badbit );
326 }
327 #endif
328