ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-3.0/src/openbabel/zipstreamimpl.hpp
Revision: 2486
Committed: Mon Dec 5 21:45:27 2005 UTC (18 years, 7 months ago) by chuckv
File size: 23031 byte(s)
Log Message:
Fixed build bug in openbabel.

File Contents

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