ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/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

# 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 chuckv 2486 this->setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]));
76 tim 2440 }
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     }