ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/openbabel/zipstreamimpl.hpp
Revision: 1081
Committed: Thu Oct 19 20:49:05 2006 UTC (18 years, 6 months ago) by gezelter
File size: 23055 byte(s)
Log Message:
updated OpenBabel to version 2.0.2

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
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 }