]> git.mxchange.org Git - simgear.git/blob - simgear/misc/zfstream.cxx
HTTP: Rename urlretrieve/urlload to save/load.
[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 #include <cerrno>
27 #include <memory.h>
28 #include <stdio.h>
29
30 #include "zfstream.hxx"
31
32 //
33 // Construct a gzfilebuf object.
34 // Allocate memory for 'get' buffer and zero all buffer pointers.
35 //
36 gzfilebuf::gzfilebuf()
37     : std::streambuf(),
38       file(NULL),
39       mode(ios_openmode(0)),
40       own_file_descriptor(false),
41       ibuf_size(0),
42       ibuffer(0),
43       obuf_size(0),
44       obuffer(0)
45 {
46 //     try {
47     ibuf_size = page_size / sizeof(char);
48     ibuffer = new char [ibuf_size];
49 //     } catch (...) {
50 //         delete [] ibuffer;
51 //     }
52
53     // Null get and set pointers.
54     this->setg(0,0,0);
55     this->setp(0,0);
56 }
57
58 gzfilebuf::~gzfilebuf()
59 {
60     sync();
61     if ( own_file_descriptor )
62         this->close();
63     delete [] ibuffer;
64     if (obuffer)
65         delete [] obuffer;
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, ios_openmode )
175 {
176     return std::streampos(EOF);
177 }
178
179 gzfilebuf::int_type
180 gzfilebuf::overflow( int_type c )
181 {
182     if ( !is_open() || !(mode & ios_out) )
183         return EOF;
184
185     if ( !base() )
186     {
187         if ( allocate() == EOF )
188             return EOF;
189         setg(0,0,0);
190     }
191     else
192     {
193         if (in_avail())
194         {
195             return EOF;
196         }
197
198         if (out_waiting())
199         {
200             if (flushbuf() == EOF)
201                 return EOF;
202         }
203     }
204
205     int bl = blen();
206     setp( base(), base() + bl);
207
208     if ( c != EOF )
209     {
210         *pptr() = c;
211         pbump(1);
212     }
213     return 0;
214 }
215
216 int
217 gzfilebuf::sync()
218 {
219     if ( !is_open() )
220         return EOF;
221
222     if ( pptr() != 0 && pptr() > pbase() )
223         return flushbuf();
224
225     return 0;
226 }
227
228 bool
229 gzfilebuf::out_waiting()
230 {
231     char* q = pbase();
232     int n = pptr() - q;
233     return n>0;
234 }
235
236 char
237 gzfilebuf::allocate()
238 {
239     obuf_size = page_size / sizeof(char);
240     obuffer = new char [obuf_size];
241     return 0;
242 }
243
244 gzfilebuf::int_type
245 gzfilebuf::flushbuf()
246 {
247     char* q = pbase();
248     int n = pptr() - q;
249
250     if ( gzwrite( file, q, n) < n )
251         return traits_type::eof();
252
253     setp(0,0);
254
255     return 0;
256 }
257
258 gzfilebuf::int_type
259 gzfilebuf::underflow()
260 {
261 //     cerr << "gzfilebuf::underflow(): gptr()=" << (void*)gptr() << endl;
262     // Error if the file not open for reading.
263     if ( !is_open() || !(mode & ios_in) )
264         return traits_type::eof();
265
266     // If the input buffer is empty then try to fill it.
267     if ( gptr() != 0 && gptr() < egptr() )
268     {
269         return int_type(*gptr());
270     }
271     else
272     {
273         return fillbuf() == EOF ? traits_type::eof() : (unsigned char) (*gptr());
274     }
275 }
276
277 //
278 // Load the input buffer from the underlying gz file.
279 // Returns number of characters read, or EOF.
280 //
281 int
282 gzfilebuf::fillbuf()
283 {
284     int t = gzread( file, ibuffer, ibuf_size );
285     if ( t <= 0)
286     {
287         // disable get area
288         setg(0,0,0);
289         return EOF;
290     }
291
292     // Set the input (get) pointers
293     setg( ibuffer, ibuffer, ibuffer+t );
294
295 //     cerr << "gzfilebuf::fillbuf():"
296 //          << " t=" << t
297 //          << ", ibuffer=" << (void*)ibuffer
298 //          << ", ibuffer+t=" << (void*)(ibuffer+t) << endl;
299
300     return t;
301 }
302
303 #if 0
304 gzifstream::gzifstream()
305     : istream(&buffer), buffer()
306 {
307     clear( ios_badbit );
308 }
309
310 gzifstream::gzifstream( const char *name, ios_openmode io_mode )
311     : istream(&buffer), buffer()
312 {
313     this->open( name, io_mode );
314 }
315
316 gzifstream::gzifstream( int fd, ios_openmode io_mode )
317     : istream(&buffer), buffer()
318 {
319     buffer.attach( fd, io_mode );
320 }
321
322 gzifstream::~gzifstream()
323 {
324 }
325
326 void
327 gzifstream::open( const char *name, ios_openmode io_mode )
328 {
329     if ( !buffer.open( name, io_mode ) )
330         clear( ios_failbit | ios_badbit );
331     else
332         clear();
333 }
334
335 void
336 gzifstream::close()
337 {
338     if ( !buffer.close() )
339         clear( ios_failbit | ios_badbit );
340 }
341 #endif
342