# zipstreamimpl.h

Go to the documentation of this file.

    00001 /*
    00002 zipstream Library License:
    00003 --------------------------
    00004
    00005 The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux.
    00006
    00007 This software is provided 'as-is', without any express or implied warranty. In
    00008 no event will the authors be held liable for any damages arising from the use
    00009 of this software.
    00010
    00011 Permission is granted to anyone to use this software for any purpose,
    00012 including commercial applications, and to alter it and redistribute it freely,
    00013 subject to the following restrictions:
    00014
    00015 1. The origin of this software must not be misrepresented; you must not claim
    00016    that you wrote the original software. If you use this software in a
    00017    product, an acknowledgment in the product documentation would be
    00018    appreciated but is not required.
    00019
    00020 2. Altered source versions must be plainly marked as such, and must not be
    00021    misrepresented as being the original software.
    00022
    00023 3. This notice may not be removed or altered from any source distribution
    00024
    00025 Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003
    00026
    00027 Altered by: Andreas Zieringer 2003 for OpenSG project
    00028             made it platform independent, gzip conform, fixed gzip footer
    00029
    00030 Altered by: Geoffrey Hutchison 2005 for Open Babel project
    00031             minor namespace modifications, VC++ compatibility
    00032
    00033 Altered by: Mathieu Malaterre 2008, for GDCM project
    00034             when reading deflate bit stream in DICOM special handling of \0 is needed
    00035             also when writing deflate back to disk, the add_footer must be called
    00036 */
    00037
    00038 /*
    00039 Code is from:
    00040
    00041 http://www.codeproject.com/KB/stl/zipstream.aspx
    00042
    00043  TODO:
    00044
    00045 zran.c
    00046     index a zlib or gzip stream and randomly access it
    00047     - illustrates the use of Z_BLOCK, inflatePrime(), and
    00048       inflateSetDictionary() to provide random access
    00049
    00050   So I might after all be able to implement seeking :)
    00051 */
    00052 #ifndef _ZIPSTREAM_H_
    00053 #define _ZIPSTREAM_H_
    00054
    00055 #include <vector>
    00056 #include <string>
    00057 #include <streambuf>
    00058 #include <sstream>
    00059 #include <iostream>
    00060 #include <algorithm>
    00061
    00062 #include <string.h> // memcpy
    00063 #include <stdio.h> // EOF
    00064
    00065 #include <gdcm_zlib.h>
    00066
    00067 #ifdef WIN32 /* Window 95 & Windows NT */
    00068 #  define OS_CODE  0x0b
    00069 #endif
    00070 #if defined(MACOS) || defined(TARGET_OS_MAC)
    00071 #  define OS_CODE  0x07
    00072 #endif
    00073 #ifndef OS_CODE
    00074 #  define OS_CODE  0x03  /* assume Unix */
    00075 #endif
    00076
    00077 namespace zlib_stream {
    00078
    00079 namespace detail
    00080 {
    00081     const int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
    00082
    00083     /* gzip flag byte */
    00084     const int gz_ascii_flag =  0x01; /* bit 0 set: file probably ascii text */
    00085     const int gz_head_crc    = 0x02; /* bit 1 set: header CRC present */
    00086     const int gz_extra_field = 0x04; /* bit 2 set: extra field present */
    00087     const int gz_orig_name  =  0x08; /* bit 3 set: original file name present */
    00088     const int gz_comment    =  0x10; /* bit 4 set: file comment present */
    00089     const int gz_reserved   =  0xE0; /* bits 5..7: reserved */
    00090 }
    00091
    00094 const size_t zstream_default_buffer_size = 4096;
    00095
    00097 enum EStrategy
    00098 {
    00099     StrategyFiltered = 1,
    00100     StrategyHuffmanOnly = 2,
    00101     DefaultStrategy = 0
    00102 };
    00103
    00104 //*****************************************************************************
    00105 //  template class basic_zip_streambuf
    00106 //*****************************************************************************
    00107
    00112 template <class charT,
    00113           class traits = std::char_traits<charT> >
    00114 class basic_zip_streambuf : public std::basic_streambuf<charT, traits>
    00115 {
    00116 public:
    00117     typedef std::basic_ostream<charT, traits>& ostream_reference;
    00118     typedef unsigned char byte_type;
    00119     typedef char          char_type;
    00120     typedef byte_type* byte_buffer_type;
    00121     typedef std::vector<byte_type> byte_vector_type;
    00122     typedef std::vector<char_type> char_vector_type;
    00123     typedef int int_type;
    00124
    00125     basic_zip_streambuf(ostream_reference ostream,
    00126                             int level,
    00127                             EStrategy strategy,
    00128                             int window_size,
    00129                             int memory_level,
    00130                             size_t buffer_size);
    00131
    00132     ~basic_zip_streambuf(void);
    00133
    00134     int               sync        (void);
    00135     int_type          overflow    (int_type c);
    00136     std::streamsize   flush       (void);
    00137     inline
    00138     ostream_reference get_ostream (void) const;
    00139     inline
    00140     int               get_zerr    (void) const;
    00141     inline
    00142     unsigned long     get_crc     (void) const;
    00143     inline
    00144     unsigned long     get_in_size (void) const;
    00145     inline
    00146     long              get_out_size(void) const;
    00147
    00148 private:
    00149
    00150     bool              zip_to_stream(char_type *buffer,
    00151                                     std::streamsize buffer_size);
    00152
    00153     ostream_reference   _ostream;
    00154     z_stream            _zip_stream;
    00155     int                 _err;
    00156     byte_vector_type    _output_buffer;
    00157     char_vector_type    _buffer;
    00158     unsigned long       _crc;
    00159 };
    00160
    00161
    00162 //*****************************************************************************
    00163 //  template class basic_unzip_streambuf
    00164 //*****************************************************************************
    00165
    00170 template <class charT,
    00171           class traits = std::char_traits<charT> >
    00172 class basic_unzip_streambuf :
    00173     public std::basic_streambuf<charT, traits>
    00174 {
    00175 public:
    00176     typedef std::basic_istream<charT,traits>& istream_reference;
    00177     typedef unsigned char byte_type;
    00178     typedef charT          char_type;
    00179     typedef byte_type* byte_buffer_type;
    00180     typedef std::vector<byte_type> byte_vector_type;
    00181     typedef std::vector<char_type> char_vector_type;
    00182     typedef int int_type;
    00183
    00187     basic_unzip_streambuf(istream_reference istream,
    00188                           int window_size,
    00189                           size_t read_buffer_size,
    00190                           size_t input_buffer_size);
    00191
    00192     ~basic_unzip_streambuf(void);
    00193
    00194     int_type underflow(void);
    00195
    00197     inline
    00198     istream_reference get_istream              (void);
    00199     inline
    00200     z_stream&         get_zip_stream           (void);
    00201     inline
    00202     int               get_zerr                 (void) const;
    00203     inline
    00204     unsigned long     get_crc                  (void) const;
    00205     inline
    00206     long              get_out_size             (void) const;
    00207     inline
    00208     long              get_in_size              (void) const;
    00209
    00210
    00211 private:
    00212
    00213     void              put_back_from_zip_stream (void);
    00214
    00215     std::streamsize   unzip_from_stream        (char_type* buffer,
    00216                                                 std::streamsize buffer_size);
    00217
    00218     size_t            fill_input_buffer        (void);
    00219
    00220     istream_reference   _istream;
    00221     z_stream            _zip_stream;
    00222     int                 _err;
    00223     byte_vector_type    _input_buffer;
    00224     char_vector_type    _buffer;
    00225     unsigned long       _crc;
    00226 };
    00227
    00228 //*****************************************************************************
    00229 //  template class basic_zip_ostream
    00230 //*****************************************************************************
    00231
    00232 template <class charT,
    00233           class traits = std::char_traits<charT> >
    00234 class basic_zip_ostream :
    00235     public basic_zip_streambuf<charT, traits>,
    00236     public std::basic_ostream<charT, traits>
    00237 {
    00238 public:
    00239
    00240     typedef char char_type;
    00241     typedef std::basic_ostream<charT, traits>& ostream_reference;
    00242     typedef std::basic_ostream<charT, traits> ostream_type;
    00243
    00244     inline
    00245     explicit basic_zip_ostream(ostream_reference ostream,
    00246                                bool is_gzip = false,
    00247                                int level = Z_DEFAULT_COMPRESSION,
    00248                                EStrategy strategy = DefaultStrategy,
    00249                                int window_size = -15 /*windowBits is passed < 0 to suppress zlib header */,
    00250                                int memory_level = 8,
    00251                                size_t buffer_size = zstream_default_buffer_size);
    00252
    00253     ~basic_zip_ostream(void);
    00254
    00255     inline
    00256     bool                              is_gzip   (void) const;
    00257     inline
    00258     basic_zip_ostream<charT, traits>& zflush    (void);
    00259     void                              finished  (void);
    00260
    00261 //    void                              make_gzip()
    00262 //       { add_header(); _is_gzip = true; }
    00263
    00264 private:
    00265
    00266     basic_zip_ostream<charT,traits>&  add_header(void);
    00267     basic_zip_ostream<charT,traits>&  add_footer(void);
    00268
    00269     bool _is_gzip;
    00270     bool _added_footer;
    00271 };
    00272
    00273 //*****************************************************************************
    00274 //  template class basic_zip_istream
    00275 //*****************************************************************************
    00276
    00277 template <class charT,
    00278           class traits = std::char_traits<charT> >
    00279 class basic_zip_istream :
    00280     public basic_unzip_streambuf<charT, traits>,
    00281     public std::basic_istream<charT, traits>
    00282 {
    00283 public:
    00284     typedef std::basic_istream<charT, traits>& istream_reference;
    00285     typedef std::basic_istream<charT, traits> istream_type;
    00286
    00287     explicit basic_zip_istream(istream_reference istream,
    00288                                int window_size = -15 /*windowBits is passed < 0 to suppress zlib header */,
    00289                                size_t read_buffer_size = zstream_default_buffer_size,
    00290                                size_t input_buffer_size = zstream_default_buffer_size);
    00291
    00292     inline
    00293     bool     is_gzip           (void) const;
    00294     inline
    00295     bool     check_crc         (void);
    00296     inline
    00297     bool     check_data_size   (void) const;
    00298     inline
    00299     long     get_gzip_crc      (void) const;
    00300     inline
    00301     long     get_gzip_data_size(void) const;
    00302
    00303 protected:
    00304
    00305     int      check_header      (void);
    00306     void     read_footer       (void);
    00307
    00308     bool _is_gzip;
    00309     long _gzip_crc;
    00310     long _gzip_data_size;
    00311 };
    00312
    00314 typedef basic_zip_ostream<char> zip_ostream;
    00316 typedef basic_zip_istream<char> zip_istream;
    00317
    00319 //typedef basic_zip_ostream<wchar_t> zip_wostream;
    00321 //typedef basic_zip_istream<wchar_t> zip_wistream;
    00322
    00324 inline bool isGZip(std::istream &is)
    00325 {
    00326     const int gz_magic[2] = {0x1f, 0x8b};
    00327
    00328     int c1 = (int) is.get();
    00329     if(c1 != gz_magic[0])
    00330     {
    00331         is.putback(c1);
    00332         return false;
    00333     }
    00334
    00335     int c2 = (int) is.get();
    00336     if(c2 != gz_magic[1])
    00337     {
    00338         is.putback(c2);
    00339         is.putback(c1);
    00340         return false;
    00341     }
    00342
    00343     is.putback(c2);
    00344     is.putback(c1);
    00345     return true;
    00346 }
    00347
    00348 #include "zipstreamimpl.hpp"
    00349
    00350 }
    00351
    00352 #endif // _ZIPSTREAM_H_
    00353