]> git.mxchange.org Git - simgear.git/blob - simgear/misc/zfstream.cxx
Modified Files:
[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     : streambuf(),
42       file(NULL),
43 #if defined( __MWERKS__ ) || __GNUC__ > 2
44       mode(ios_openmode(0)),
45 #else
46       mode(0),
47 #endif
48       own_file_descriptor(false),
49       ibuf_size(0),
50       ibuffer(0)
51 {
52 //     try {
53     ibuf_size = page_size / sizeof(char);
54     ibuffer = new char [ibuf_size];
55 //     } catch (...) {
56 //      delete [] ibuffer;
57 //     }
58
59     // Null get and set pointers.
60     this->setg(0,0,0);
61     this->setp(0,0);
62 }
63
64 gzfilebuf::~gzfilebuf()
65 {
66     sync();
67     if ( own_file_descriptor )
68         this->close();
69     delete [] ibuffer;
70 }
71
72 void
73 gzfilebuf::cvt_iomode( char* p, ios_openmode io_mode )
74 {
75 //     memset( char_mode, '\0', 10 );
76 //     char* p = char_mode;
77
78     if ( io_mode & ios_in )
79     {
80         mode = ios_in;
81         *p++ = 'r';
82     }
83     else if ( io_mode & ios_app )
84     {
85         mode = ios_app;
86         *p++ = 'a';
87     }
88     else
89     {
90         mode = ios_out;
91         *p++ = 'w';
92     }
93
94     if ( io_mode & ios_binary )
95     {
96         mode |= ios_binary;
97         *p++ = 'b';
98     }
99
100     // Hard code the compression level
101     if ( io_mode & (ios_out | ios_app) )
102     {
103         *p++ = '9';
104     }
105
106     *p = '\0';
107 }
108
109 gzfilebuf*
110 gzfilebuf::open( const char *name, ios_openmode io_mode )
111 {
112     if ( is_open() )
113         return NULL;
114
115     char char_mode[10];
116     cvt_iomode( char_mode, io_mode );
117     if ( (file = gzopen(name, char_mode)) == NULL ) {
118         // perror( "gzfilebuf::open(): " );
119         errno = 0;
120         return NULL;
121     }
122
123     own_file_descriptor = true;
124
125     return this;
126 }
127
128 gzfilebuf*
129 gzfilebuf::attach( int file_descriptor, ios_openmode io_mode )
130 {
131     if ( is_open() )
132         return NULL;
133
134     char char_mode[10];
135     cvt_iomode( char_mode, io_mode );
136     if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) {
137         perror( "gzfilebuf::attach(): " );
138         errno = 0;
139         return NULL;
140     }
141
142     own_file_descriptor = false;
143
144     return this;
145 }
146
147 gzfilebuf*
148 gzfilebuf::close()
149 {
150     // cout << "closing ..." ;
151     if ( is_open() )
152     {
153         sync();
154         gzclose( file );
155         file = NULL;
156         // cout << "done" << endl;
157     } else {
158         // cout << "error" << endl;
159     }
160
161     return this;
162 }
163
164 // int
165 // gzfilebuf::setcompressionlevel( int comp_level )
166 // {
167 //     return gzsetparams(file, comp_level, -2);
168 // }
169
170 // int
171 // gzfilebuf::setcompressionstrategy( int comp_strategy )
172 // {
173 //     return gzsetparams(file, -2, comp_strategy);
174 // }
175
176
177 streampos
178 gzfilebuf::seekoff( streamoff, ios_seekdir, int )
179 {
180     return streampos(EOF);
181 }
182
183 gzfilebuf::int_type
184 gzfilebuf::overflow( int_type )
185 {
186 #if 0
187     if ( !is_open() || !(mode & ios::out) )
188         return EOF;
189
190     if ( !base() )
191     {
192         if ( allocate() == EOF )
193             return EOF;
194         setg(0,0,0);
195     }
196     else
197     {
198         if (in_avail())
199         {
200             return EOF;
201         }
202
203         if (out_waiting())
204         {
205             if (flushbuf() == EOF)
206                 return EOF;
207         }
208     }
209
210     int bl = blen();
211     setp( base(), base() + bl);
212
213     if ( c != EOF )
214     {
215         *pptr() = c;
216         pbump(1);
217     }
218 #endif
219     return 0;
220 }
221
222 int
223 gzfilebuf::sync()
224 {
225     if ( !is_open() )
226         return EOF;
227
228     if ( pptr() != 0 && pptr() > pbase() )
229         return flushbuf();
230
231     return 0;
232 }
233
234 gzfilebuf::int_type
235 gzfilebuf::flushbuf()
236 {
237     char* q = pbase();
238     int n = pptr() - q;
239
240     if ( gzwrite( file, q, n) < n )
241         return traits_type::eof();
242
243     setp(0,0);
244
245     return 0;
246 }
247
248 gzfilebuf::int_type
249 gzfilebuf::underflow()
250 {
251 //     cerr << "gzfilebuf::underflow(): gptr()=" << (void*)gptr() << endl;
252     // Error if the file not open for reading.
253     if ( !is_open() || !(mode & ios_in) )
254         return traits_type::eof();
255
256     // If the input buffer is empty then try to fill it.
257     if ( gptr() != 0 && gptr() < egptr() )
258     {
259         return int_type(*gptr());
260     }
261     else
262     {
263         return fillbuf() == EOF ? traits_type::eof() : int_type(*gptr());
264     }
265 }
266
267 //
268 // Load the input buffer from the underlying gz file.
269 // Returns number of characters read, or EOF.
270 //
271 int
272 gzfilebuf::fillbuf()
273 {
274     int t = gzread( file, ibuffer, ibuf_size );
275     if ( t <= 0)
276     {
277         // disable get area
278         setg(0,0,0);
279         return EOF;
280     }
281
282     // Set the input (get) pointers
283     setg( ibuffer, ibuffer, ibuffer+t );
284
285 //     cerr << "gzfilebuf::fillbuf():"
286 //       << " t=" << t
287 //       << ", ibuffer=" << (void*)ibuffer
288 //       << ", ibuffer+t=" << (void*)(ibuffer+t) << endl;
289
290     return t;
291 }
292
293 #if 0
294 gzifstream::gzifstream()
295     : istream(&buffer), buffer()
296 {
297     clear( ios_badbit );
298 }
299
300 gzifstream::gzifstream( const char *name, ios_openmode io_mode )
301     : istream(&buffer), buffer()
302 {
303     this->open( name, io_mode );
304 }
305
306 gzifstream::gzifstream( int fd, ios_openmode io_mode )
307     : istream(&buffer), buffer()
308 {
309     buffer.attach( fd, io_mode );
310 }
311
312 gzifstream::~gzifstream()
313 {
314 }
315
316 void
317 gzifstream::open( const char *name, ios_openmode io_mode )
318 {
319     if ( !buffer.open( name, io_mode ) )
320         clear( ios_failbit | ios_badbit );
321     else
322         clear();
323 }
324
325 void
326 gzifstream::close()
327 {
328     if ( !buffer.close() )
329         clear( ios_failbit | ios_badbit );
330 }
331 #endif
332