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