~ubuntu-branches/ubuntu/feisty/openbabel/feisty

« back to all changes in this revision

Viewing changes to src/zipstreamimpl.h

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2006-05-14 19:46:01 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060514194601-h3j1wovvc42cigxl
Tags: 2.0.1-1
* New upstream release. (Closes: #341628)
* debian/patches/04_zipstream_fix.diff: Removed, applied upstream.
* debian/rules (DEB_MAKE_CHECK_TARGET): Readded.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
zipstream Library License:
 
3
--------------------------
 
4
 
 
5
The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux.
 
6
 
 
7
This software is provided 'as-is', without any express or implied warranty. In
 
8
no event will the authors be held liable for any damages arising from the use
 
9
of this software.
 
10
 
 
11
Permission is granted to anyone to use this software for any purpose,
 
12
including commercial applications, and to alter it and redistribute it freely,
 
13
subject to the following restrictions:
 
14
 
 
15
1. The origin of this software must not be misrepresented; you must not claim
 
16
   that you wrote the original software. If you use this software in a
 
17
   product, an acknowledgment in the product documentation would be
 
18
   appreciated but is not required.
 
19
 
 
20
2. Altered source versions must be plainly marked as such, and must not be
 
21
   misrepresented as being the original software.
 
22
 
 
23
3. This notice may not be removed or altered from any source distribution
 
24
 
 
25
Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003
 
26
 
 
27
Altered by: Andreas Zieringer 2003 for OpenSG project
 
28
            made it platform independent, gzip conform, fixed gzip footer
 
29
 
 
30
Altered by: Geoffrey Hutchison 2005 for Open Babel project
 
31
            minor namespace modifications, VC++ compatibility
 
32
*/
 
33
 
 
34
//*****************************************************************************
 
35
//  template class basic_zip_streambuf
 
36
//*****************************************************************************
 
37
 
 
38
//-----------------------------------------------------------------------------
 
39
// PUBLIC
 
40
//-----------------------------------------------------------------------------
 
41
 
 
42
/** Construct a zip stream
 
43
 * More info on the following parameters can be found in the zlib documentation.
 
44
 */
 
45
 
 
46
template <class charT, class traits>
 
47
basic_zip_streambuf<charT, traits>::basic_zip_streambuf(ostream_reference ostream,
 
48
                                                        int level,
 
49
                                                        EStrategy strategy,
 
50
                                                        int window_size,
 
51
                                                        int memory_level,
 
52
                                                        size_t buffer_size)
 
53
    : _ostream(ostream),
 
54
      _output_buffer(buffer_size, 0),
 
55
      _buffer(buffer_size, 0),
 
56
      _crc(0)
 
57
{
 
58
    _zip_stream.zalloc = (alloc_func) 0;
 
59
    _zip_stream.zfree = (free_func) 0;
 
60
 
 
61
    _zip_stream.next_in = NULL;
 
62
    _zip_stream.avail_in = 0;
 
63
    _zip_stream.avail_out = 0;
 
64
    _zip_stream.next_out = NULL;
 
65
 
 
66
    if(level > 9)
 
67
        level = 9;
 
68
        
 
69
    if(memory_level > 9)
 
70
        memory_level = 9;
 
71
        
 
72
    _err=deflateInit2(&_zip_stream, level, Z_DEFLATED,
 
73
                      window_size, memory_level,
 
74
                      static_cast<int>(strategy));
 
75
 
 
76
    this->setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]));
 
77
}
 
78
 
 
79
/** Destructor
 
80
 */
 
81
template <class charT, class traits>
 
82
basic_zip_streambuf<charT, traits>::~basic_zip_streambuf(void)
 
83
{
 
84
    flush();
 
85
 //   _ostream.flush(); CM already done in flush()
 
86
    _err=deflateEnd(&_zip_stream);
 
87
}
 
88
 
 
89
/** Do the synchronization
 
90
 * @todo
 
91
 * document correctly!
 
92
 */
 
93
template <class charT, class traits>
 
94
int basic_zip_streambuf<charT, traits>::sync(void)
 
95
 
96
    if(this->pptr() && this->pptr() > this->pbase()) 
 
97
    {
 
98
        /*int c =*/ overflow(EOF);
 
99
 
 
100
        // ACHTUNG wenn das drin ist hoert er nach dem ersten endl auf!
 
101
        /*
 
102
          if ( c == EOF)
 
103
          return -1;
 
104
        */
 
105
    }
 
106
 
 
107
    return 0;
 
108
}
 
109
 
 
110
/** <unknown purpose>
 
111
 * @todo
 
112
 * document correctly!
 
113
 */
 
114
template <class charT, class traits>
 
115
typename basic_zip_streambuf<charT, traits>::int_type
 
116
basic_zip_streambuf<charT, traits>::overflow(int_type c)
 
117
 
118
    int w = static_cast<int>(this->pptr() - this->pbase());
 
119
    if (c != EOF)
 
120
    {
 
121
        *this->pptr() = c;
 
122
        ++w;
 
123
    }
 
124
    if (zip_to_stream(this->pbase(), w))
 
125
    {
 
126
        this->setp(this->pbase(), this->epptr() - 1);
 
127
        return c;
 
128
    }
 
129
    else
 
130
    {
 
131
        return EOF;
 
132
    }
 
133
}
 
134
 
 
135
/** flushes the zip buffer and output buffer.
 
136
 *
 
137
 *    This method should be called at the end of the compression. Calling flush
 
138
 *    multiple times, will lower the compression ratio.
 
139
 */
 
140
template <class charT, class traits>
 
141
std::streamsize basic_zip_streambuf<charT, traits>::flush(void)
 
142
{
 
143
    std::streamsize written_byte_size = 0, total_written_byte_size = 0;
 
144
 
 
145
    size_t remainder = 0;
 
146
 
 
147
    // updating crc
 
148
    _crc = crc32(_crc,  _zip_stream.next_in,
 
149
                 _zip_stream.avail_in);        
 
150
 
 
151
    do
 
152
    {
 
153
        _err = deflate(&_zip_stream, Z_FINISH);
 
154
        if(_err == Z_OK || _err == Z_STREAM_END)
 
155
        {
 
156
            written_byte_size = static_cast<std::streamsize>(_output_buffer.size()) - _zip_stream.avail_out;
 
157
            total_written_byte_size += written_byte_size;
 
158
            // ouput buffer is full, dumping to ostream
 
159
            _ostream.write( (const char_type*) &(_output_buffer[0]), 
 
160
                            static_cast<std::streamsize>(written_byte_size/sizeof(char_type)*sizeof(char)));
 
161
            
 
162
            // checking if some bytes were not written.
 
163
            if((remainder = written_byte_size%sizeof(char_type)) != 0)
 
164
            {
 
165
                // copy to the beginning of the stream
 
166
                memcpy(&(_output_buffer[0]), 
 
167
                       &(_output_buffer[written_byte_size-remainder]), remainder);
 
168
                    
 
169
            }
 
170
                
 
171
            _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size() - remainder);
 
172
            _zip_stream.next_out = &_output_buffer[remainder];
 
173
        }
 
174
    }
 
175
    while(_err == Z_OK);
 
176
 
 
177
    if(&_ostream)
 
178
                        _ostream.flush();
 
179
 
 
180
    return total_written_byte_size;
 
181
}
 
182
 
 
183
/** returns a reference to the output stream
 
184
 */
 
185
template <class charT, class traits> inline 
 
186
typename basic_zip_streambuf<charT, traits>::ostream_reference
 
187
basic_zip_streambuf<charT, traits>::get_ostream(void) const
 
188
{
 
189
    return _ostream;
 
190
}
 
191
 
 
192
/** returns the latest zlib error status
 
193
 */
 
194
template <class charT, class traits> inline
 
195
int basic_zip_streambuf<charT, traits>::get_zerr(void) const
 
196
{
 
197
    return _err;
 
198
}
 
199
 
 
200
/** returns the crc of the input data compressed so far.
 
201
 */
 
202
template <class charT, class traits> inline
 
203
unsigned long
 
204
basic_zip_streambuf<charT, traits>:: get_crc(void) const
 
205
{
 
206
    return _crc;
 
207
}
 
208
 
 
209
/**  returns the size (bytes) of the input data compressed so far.
 
210
 */
 
211
template <class charT, class traits> inline
 
212
unsigned long
 
213
basic_zip_streambuf<charT, traits>::get_in_size(void) const
 
214
{
 
215
    return _zip_stream.total_in;
 
216
}
 
217
 
 
218
/**  returns the size (bytes) of the compressed data so far.
 
219
 */
 
220
template <class charT, class traits> inline
 
221
long 
 
222
basic_zip_streambuf<charT, traits>::get_out_size(void) const
 
223
{
 
224
    return _zip_stream.total_out;
 
225
}
 
226
 
 
227
//-----------------------------------------------------------------------------
 
228
// PRIVATE
 
229
//-----------------------------------------------------------------------------
 
230
 
 
231
/** <undocumented>
 
232
 * @todo
 
233
 * document!
 
234
 */
 
235
template <class charT, class traits>
 
236
bool basic_zip_streambuf<charT, traits>::zip_to_stream(
 
237
    char_type *buffer,
 
238
    std::streamsize buffer_size)
 
239
{    
 
240
    std::streamsize written_byte_size = 0, total_written_byte_size = 0;
 
241
 
 
242
    _zip_stream.next_in = (byte_buffer_type) buffer;
 
243
    _zip_stream.avail_in = static_cast<uInt>(buffer_size * sizeof(char_type));
 
244
    _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size());
 
245
    _zip_stream.next_out = &_output_buffer[0];
 
246
    size_t remainder = 0;
 
247
 
 
248
    // updating crc
 
249
    _crc = crc32(_crc, _zip_stream.next_in,
 
250
                 _zip_stream.avail_in);        
 
251
 
 
252
    do
 
253
    {
 
254
        _err = deflate(&_zip_stream, 0);
 
255
    
 
256
        if (_err == Z_OK  || _err == Z_STREAM_END)
 
257
        {
 
258
            written_byte_size= static_cast<std::streamsize>(_output_buffer.size()) -
 
259
                _zip_stream.avail_out;
 
260
            total_written_byte_size += written_byte_size;
 
261
            // ouput buffer is full, dumping to ostream
 
262
 
 
263
            _ostream.write((const char_type*) &_output_buffer[0], 
 
264
                           static_cast<std::streamsize>(written_byte_size / sizeof(char_type)));
 
265
                                                
 
266
            // checking if some bytes were not written.
 
267
            if((remainder = written_byte_size % sizeof(char_type)) != 0)
 
268
            {
 
269
                // copy to the beginning of the stream
 
270
                memcpy(&_output_buffer[0], 
 
271
                       &_output_buffer[written_byte_size-remainder],
 
272
                       remainder);
 
273
            }
 
274
                
 
275
            _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size()-remainder);
 
276
            _zip_stream.next_out = &_output_buffer[remainder];
 
277
        }
 
278
    } 
 
279
    while(_zip_stream.avail_in != 0 && _err == Z_OK);
 
280
    
 
281
    return _err == Z_OK;
 
282
}
 
283
 
 
284
 
 
285
 
 
286
 
 
287
 
 
288
 
 
289
 
 
290
//*****************************************************************************
 
291
//  template class basic_unzip_streambuf
 
292
//*****************************************************************************
 
293
 
 
294
//-----------------------------------------------------------------------------
 
295
// PUBLIC
 
296
//-----------------------------------------------------------------------------
 
297
 
 
298
/** Constructor
 
299
 */
 
300
template <class charT, class traits>
 
301
basic_unzip_streambuf<charT, traits>::basic_unzip_streambuf(istream_reference istream,
 
302
                                                            int window_size,
 
303
                                                            size_t read_buffer_size,
 
304
                                                            size_t input_buffer_size)
 
305
    : _istream(istream),
 
306
      _input_buffer(input_buffer_size),
 
307
      _buffer(read_buffer_size),
 
308
      _crc(0)
 
309
{
 
310
    // setting zalloc, zfree and opaque
 
311
    _zip_stream.zalloc = (alloc_func) 0;
 
312
    _zip_stream.zfree = (free_func) 0;
 
313
 
 
314
    _zip_stream.next_in = NULL;
 
315
    _zip_stream.avail_in = 0;
 
316
    _zip_stream.avail_out = 0;
 
317
    _zip_stream.next_out = NULL;
 
318
 
 
319
    _err = inflateInit2(&_zip_stream, window_size);
 
320
        
 
321
    this->setg(&_buffer[0] + 4,     // beginning of putback area
 
322
               &_buffer[0] + 4,     // read position
 
323
               &_buffer[0] + 4);    // end position    
 
324
}
 
325
 
 
326
/**
 
327
 * @todo document!
 
328
 */
 
329
template <class charT, class traits>
 
330
basic_unzip_streambuf<charT, traits>::~basic_unzip_streambuf(void)
 
331
{
 
332
    inflateEnd(&_zip_stream);
 
333
}
 
334
 
 
335
 
 
336
/**
 
337
 * @todo document!
 
338
 */
 
339
template <class charT, class traits>
 
340
typename basic_unzip_streambuf<charT, traits>::int_type
 
341
basic_unzip_streambuf<charT, traits>::underflow(void)
 
342
 
343
    if(this->gptr() && ( this->gptr() < this->egptr()))
 
344
        return * reinterpret_cast<unsigned char *>(this->gptr());
 
345
     
 
346
    int n_putback = static_cast<int>(this->gptr() - this->eback());
 
347
    if(n_putback > 4)
 
348
        n_putback = 4;
 
349
       
 
350
    memcpy(&_buffer[0] + (4 - n_putback),
 
351
           this->gptr() - n_putback,
 
352
           n_putback * sizeof(char_type));
 
353
  
 
354
    int num = 
 
355
        unzip_from_stream(&_buffer[0] + 4, 
 
356
                          static_cast<std::streamsize>((_buffer.size() - 4) *
 
357
                                                       sizeof(char_type)));
 
358
        
 
359
    if(num <= 0) // ERROR or EOF
 
360
        return EOF;
 
361
    
 
362
    // reset buffer pointers
 
363
    this->setg(&_buffer[0] + (4 - n_putback),   // beginning of putback area
 
364
               &_buffer[0] + 4,                 // read position
 
365
               &_buffer[0] + 4 + num);          // end of buffer
 
366
    
 
367
    // return next character
 
368
    return * reinterpret_cast<unsigned char *>(this->gptr());    
 
369
}
 
370
 
 
371
/** returns the compressed input istream
 
372
 */
 
373
template <class charT, class traits> inline
 
374
typename basic_unzip_streambuf<charT, traits>::istream_reference
 
375
basic_unzip_streambuf<charT, traits>::get_istream(void)
 
376
{
 
377
    return _istream;
 
378
}
 
379
 
 
380
/** returns the zlib stream structure
 
381
 */
 
382
template <class charT, class traits> inline
 
383
z_stream &
 
384
basic_unzip_streambuf<charT, traits>::get_zip_stream(void)
 
385
{
 
386
    return _zip_stream;
 
387
}
 
388
 
 
389
/** returns the latest zlib error state
 
390
 */
 
391
template <class charT, class traits> inline
 
392
int
 
393
basic_unzip_streambuf<charT, traits>::get_zerr(void) const
 
394
{
 
395
    return _err;
 
396
}
 
397
 
 
398
/** returns the crc of the uncompressed data so far
 
399
 */
 
400
template <class charT, class traits> inline
 
401
unsigned long
 
402
basic_unzip_streambuf<charT, traits>::get_crc(void) const
 
403
{
 
404
    return _crc;
 
405
}
 
406
 
 
407
/** returns the number of uncompressed bytes
 
408
 */
 
409
template <class charT, class traits> inline
 
410
long
 
411
basic_unzip_streambuf<charT, traits>::get_out_size(void) const
 
412
{
 
413
    return _zip_stream.total_out;
 
414
}
 
415
 
 
416
/** returns the number of read compressed bytes
 
417
 */
 
418
template <class charT, class traits> inline
 
419
long
 
420
basic_unzip_streambuf<charT, traits>::get_in_size(void) const
 
421
{
 
422
    return _zip_stream.total_in;
 
423
}
 
424
 
 
425
 
 
426
//-----------------------------------------------------------------------------
 
427
// PRIVATE
 
428
//-----------------------------------------------------------------------------
 
429
 
 
430
/** 
 
431
 */
 
432
template <class charT, class traits> inline
 
433
void
 
434
basic_unzip_streambuf<charT, traits>::put_back_from_zip_stream(void)
 
435
{
 
436
    if(_zip_stream.avail_in == 0)
 
437
        return;
 
438
 
 
439
    _istream.clear(std::ios::goodbit);
 
440
    _istream.seekg(-intf(_zip_stream.avail_in),
 
441
                   std::ios_base::cur);
 
442
 
 
443
    _zip_stream.avail_in = 0;
 
444
}
 
445
 
 
446
/** 
 
447
 */
 
448
template <class charT, class traits> inline
 
449
std::streamsize
 
450
basic_unzip_streambuf<charT, traits>::unzip_from_stream(char_type* buffer,
 
451
                                                        std::streamsize buffer_size)
 
452
{
 
453
    _zip_stream.next_out  = 
 
454
        (byte_buffer_type) buffer;
 
455
    _zip_stream.avail_out = 
 
456
        static_cast<uInt>(buffer_size * sizeof(char_type));
 
457
    size_t count = _zip_stream.avail_in;
 
458
 
 
459
    do
 
460
    {
 
461
        if(_zip_stream.avail_in == 0)
 
462
            count=fill_input_buffer();
 
463
 
 
464
        if(_zip_stream.avail_in)
 
465
        {
 
466
            _err = inflate(&_zip_stream,  Z_SYNC_FLUSH);
 
467
        }
 
468
    }
 
469
    while(_err==Z_OK && _zip_stream.avail_out != 0 && count != 0);
 
470
 
 
471
    // updating crc
 
472
    _crc = crc32(_crc, (byte_buffer_type) buffer,
 
473
                 buffer_size - _zip_stream.avail_out / sizeof(char_type));
 
474
        
 
475
    std::streamsize n_read = 
 
476
        buffer_size - _zip_stream.avail_out / sizeof(char_type);
 
477
        
 
478
    // check if it is the end
 
479
    if (_err == Z_STREAM_END)
 
480
        put_back_from_zip_stream();                
 
481
        
 
482
    return n_read;
 
483
}
 
484
 
 
485
 
 
486
/** 
 
487
 */
 
488
template <class charT, class traits> inline
 
489
size_t
 
490
basic_unzip_streambuf<charT, traits>::fill_input_buffer(void)
 
491
{
 
492
    _zip_stream.next_in = &_input_buffer[0];
 
493
    _istream.read((char_type*) &_input_buffer[0], 
 
494
                  static_cast<std::streamsize>(_input_buffer.size() /
 
495
                                               sizeof(char_type)));
 
496
        
 
497
    return _zip_stream.avail_in = _istream.gcount()*sizeof(char_type);
 
498
}
 
499
 
 
500
 
 
501
 
 
502
 
 
503
 
 
504
 
 
505
 
 
506
//*****************************************************************************
 
507
//  template class basic_zip_ostream
 
508
//*****************************************************************************
 
509
 
 
510
//-----------------------------------------------------------------------------
 
511
// PUBLIC
 
512
//-----------------------------------------------------------------------------
 
513
 
 
514
/**
 
515
 */
 
516
template <class charT, class traits> inline
 
517
basic_zip_ostream<charT, traits>::basic_zip_ostream(ostream_reference ostream,
 
518
                                                    bool is_gzip,
 
519
                                                    int level,
 
520
                                                    EStrategy strategy,
 
521
                                                    int window_size,
 
522
                                                    int memory_level,
 
523
                                                    size_t buffer_size) :
 
524
    basic_zip_streambuf<charT, traits>(ostream, level, strategy, window_size,
 
525
                                       memory_level, buffer_size),
 
526
    std::basic_ostream<charT, traits>(this),
 
527
    _is_gzip(is_gzip),
 
528
    _added_footer(false)
 
529
{
 
530
                if(_is_gzip)
 
531
        add_header();
 
532
}
 
533
 
 
534
/** Destructor
 
535
 */
 
536
template <class charT, class traits>
 
537
basic_zip_ostream<charT, traits>::~basic_zip_ostream(void)
 
538
{
 
539
    if(_is_gzip)
 
540
        add_footer();
 
541
}
 
542
 
 
543
/** returns true if it is a gzip
 
544
 */
 
545
template <class charT, class traits> inline
 
546
bool basic_zip_ostream<charT, traits>::is_gzip(void) const
 
547
{
 
548
    return _is_gzip;
 
549
}
 
550
 
 
551
/** flush inner buffer and zipper buffer
 
552
 */
 
553
 
 
554
template <class charT, class traits> inline
 
555
basic_zip_ostream<charT, traits>& basic_zip_ostream<charT, traits>::zflush(void)
 
556
{
 
557
    static_cast<std::basic_ostream<charT, traits> *>(this)->flush();
 
558
    static_cast<basic_zip_streambuf<charT, traits> *>(this)->flush();
 
559
    return *this;
 
560
}
 
561
 
 
562
template <class charT, class traits> inline
 
563
void basic_zip_ostream<charT, traits>::finished(void)
 
564
{
 
565
    if(_is_gzip)
 
566
        add_footer();
 
567
    else
 
568
        zflush();
 
569
}
 
570
 
 
571
 
 
572
//-----------------------------------------------------------------------------
 
573
// PRIVATE
 
574
//-----------------------------------------------------------------------------
 
575
 
 
576
/**
 
577
 * @todo document!
 
578
 */
 
579
template <class charT, class traits>
 
580
basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_header(void)
 
581
{
 
582
    char_type zero = 0;
 
583
        
 
584
    this->get_ostream() << static_cast<char_type>(detail::gz_magic[0])
 
585
                        << static_cast<char_type>(detail::gz_magic[1])
 
586
                        << static_cast<char_type>(Z_DEFLATED)
 
587
                        << zero //flags
 
588
                        << zero<<zero<<zero<<zero // time
 
589
                        << zero //xflags
 
590
                        << static_cast<char_type>(OS_CODE);
 
591
        
 
592
    return *this;
 
593
}
 
594
 
 
595
/**
 
596
 * @todo document!
 
597
 */
 
598
template <class charT, class traits>
 
599
basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_footer(void)
 
600
{
 
601
    if(_added_footer)
 
602
        return *this;
 
603
 
 
604
    zflush();
 
605
 
 
606
    _added_footer = true;
 
607
 
 
608
    // Writes crc and length in LSB order to the stream.
 
609
    unsigned long crc = this->get_crc();
 
610
    for(int n=0;n<4;++n)
 
611
    {
 
612
        this->get_ostream().put((int)(crc & 0xff));
 
613
        crc >>= 8;
 
614
    }
 
615
 
 
616
    unsigned long length = this->get_in_size();
 
617
    for(int m=0;m<4;++m)
 
618
    {
 
619
        this->get_ostream().put((int)(length & 0xff));
 
620
        length >>= 8;
 
621
    }
 
622
 
 
623
    return *this;
 
624
}
 
625
 
 
626
 
 
627
 
 
628
 
 
629
 
 
630
 
 
631
//*****************************************************************************
 
632
//  template class basic_zip_istream
 
633
//*****************************************************************************
 
634
 
 
635
//-----------------------------------------------------------------------------
 
636
// PUBLIC
 
637
//-----------------------------------------------------------------------------
 
638
 
 
639
/** Constructor
 
640
 */
 
641
template <class charT, class traits>
 
642
basic_zip_istream<charT, traits>::basic_zip_istream(istream_reference istream,
 
643
                                                    int window_size,
 
644
                                                    size_t read_buffer_size,
 
645
                                                    size_t input_buffer_size)
 
646
    : basic_unzip_streambuf<charT, traits>(istream, window_size,
 
647
                                           read_buffer_size, input_buffer_size),
 
648
      std::basic_istream<charT, traits>(this),
 
649
      _is_gzip(false),
 
650
      _gzip_crc(0),
 
651
      _gzip_data_size(0)
 
652
{
 
653
    if(this->get_zerr() == Z_OK)
 
654
        check_header();
 
655
}
 
656
 
 
657
/** returns true if it is a gzip file
 
658
 */
 
659
template <class charT, class traits> inline
 
660
bool
 
661
basic_zip_istream<charT, traits>::is_gzip(void) const
 
662
{
 
663
    return _is_gzip;
 
664
}
 
665
 
 
666
/** return crc check result
 
667
 *
 
668
 * This must be called after the reading of compressed data is finished!  This
 
669
 * method compares it to the crc of the uncompressed data.
 
670
 *
 
671
 *    \return true if crc check is succesful
 
672
 */
 
673
template <class charT, class traits> inline
 
674
bool
 
675
basic_zip_istream<charT, traits>::check_crc(void)
 
676
{
 
677
    read_footer();
 
678
    return this->get_crc() == _gzip_crc;
 
679
}
 
680
 
 
681
/** return data size check
 
682
 */
 
683
template <class charT, class traits> inline
 
684
bool
 
685
basic_zip_istream<charT, traits>::check_data_size(void) const
 
686
{
 
687
    return this->get_out_size() == _gzip_data_size;
 
688
}
 
689
 
 
690
/** return the crc value in the file
 
691
 */
 
692
template <class charT, class traits> inline
 
693
long
 
694
basic_zip_istream<charT, traits>::get_gzip_crc(void) const
 
695
{
 
696
    return _gzip_crc;
 
697
}
 
698
 
 
699
/** return the data size in the file
 
700
 */
 
701
template <class charT, class traits> inline
 
702
long
 
703
basic_zip_istream<charT, traits>::get_gzip_data_size(void) const
 
704
{
 
705
    return _gzip_data_size;
 
706
}
 
707
 
 
708
//-----------------------------------------------------------------------------
 
709
// PROTECTED
 
710
//-----------------------------------------------------------------------------
 
711
 
 
712
/**
 
713
 * @todo document!
 
714
 */
 
715
template <class charT, class traits>
 
716
int
 
717
basic_zip_istream<charT, traits>::check_header(void)
 
718
{
 
719
    int method; /* method byte */
 
720
    int flags;  /* flags byte */
 
721
    uInt len;
 
722
    int c;
 
723
    int err=0;
 
724
    z_stream &zip_stream = this->get_zip_stream();
 
725
 
 
726
    /* Check the gzip magic header */
 
727
    for(len = 0; len < 2; len++) 
 
728
    {
 
729
        c = (int)this->get_istream().get();
 
730
        if (c != detail::gz_magic[len]) 
 
731
        {
 
732
            if (len != 0) 
 
733
                this->get_istream().unget();
 
734
            if (c!= EOF) 
 
735
            {
 
736
                this->get_istream().unget();
 
737
            }
 
738
            
 
739
            err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
 
740
            _is_gzip = false;
 
741
            return err;
 
742
        }
 
743
    }
 
744
    
 
745
    _is_gzip = true;
 
746
    method = (int)this->get_istream().get();
 
747
    flags = (int)this->get_istream().get();
 
748
    if (method != Z_DEFLATED || (flags & detail::gz_reserved) != 0) 
 
749
    {
 
750
        err = Z_DATA_ERROR;
 
751
        return err;
 
752
    }
 
753
 
 
754
    /* Discard time, xflags and OS code: */
 
755
    for (len = 0; len < 6; len++) 
 
756
        this->get_istream().get();
 
757
    
 
758
    if ((flags & detail::gz_extra_field) != 0) 
 
759
    { 
 
760
        /* skip the extra field */
 
761
        len  =  (uInt)this->get_istream().get();
 
762
        len += ((uInt)this->get_istream().get())<<8;
 
763
        /* len is garbage if EOF but the loop below will quit anyway */
 
764
        while (len-- != 0 && this->get_istream().get() != EOF) ;
 
765
    }
 
766
    if ((flags & detail::gz_orig_name) != 0) 
 
767
    { 
 
768
        /* skip the original file name */
 
769
        while ((c = this->get_istream().get()) != 0 && c != EOF) ;
 
770
    }
 
771
    if ((flags & detail::gz_comment) != 0) 
 
772
    {   
 
773
        /* skip the .gz file comment */
 
774
        while ((c = this->get_istream().get()) != 0 && c != EOF) ;
 
775
    }
 
776
    if ((flags & detail::gz_head_crc) != 0) 
 
777
    {  /* skip the header crc */
 
778
        for (len = 0; len < 2; len++) 
 
779
            this->get_istream().get();
 
780
    }
 
781
    err = this->get_istream().eof() ? Z_DATA_ERROR : Z_OK;
 
782
 
 
783
    return err;
 
784
}
 
785
 
 
786
/**
 
787
 * @todo document!
 
788
 */
 
789
template <class charT, class traits>
 
790
void
 
791
basic_zip_istream<charT, traits>::read_footer(void)
 
792
{        
 
793
    if(_is_gzip)
 
794
    {
 
795
        _gzip_crc = 0;
 
796
        for(int n=0;n<4;++n)
 
797
            _gzip_crc += ((((int) this->get_istream().get()) & 0xff) << (8*n));
 
798
 
 
799
        _gzip_data_size = 0;
 
800
        for(int n=0;n<4;++n)
 
801
            _gzip_data_size += 
 
802
                ((((int) this->get_istream().get()) & 0xff) << (8*n));
 
803
    }
 
804
}