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