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

File Contents

# User Rev Content
1 tim 2440 /*
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 gezelter 3057
76 chuckv 2486 this->setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]));
77 tim 2440 }
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 gezelter 3057 this->setp(this->pbase(), this->epptr() - 1);
127 tim 2440 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 gezelter 3057 if(&_ostream)
178     _ostream.flush();
179 tim 2440
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     }