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