ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/zipstreamimpl.hpp
Revision: 2440
Committed: Wed Nov 16 19:42:11 2005 UTC (18 years, 8 months ago) by tim
File size: 23026 byte(s)
Log Message:
adding openbabel

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