Home | History | Annotate | Download | only in io
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 // Author: brianolson (at) google.com (Brian Olson)
     32 //
     33 // This file contains the definition for classes GzipInputStream and
     34 // GzipOutputStream.
     35 //
     36 // GzipInputStream decompresses data from an underlying
     37 // ZeroCopyInputStream and provides the decompressed data as a
     38 // ZeroCopyInputStream.
     39 //
     40 // GzipOutputStream is an ZeroCopyOutputStream that compresses data to
     41 // an underlying ZeroCopyOutputStream.
     42 
     43 #ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
     44 #define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
     45 
     46 #include <google/protobuf/stubs/common.h>
     47 #include <google/protobuf/io/zero_copy_stream.h>
     48 #include <zlib.h>
     49 
     50 namespace google {
     51 namespace protobuf {
     52 namespace io {
     53 
     54 // A ZeroCopyInputStream that reads compressed data through zlib
     55 class LIBPROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream {
     56  public:
     57   // Format key for constructor
     58   enum Format {
     59     // zlib will autodetect gzip header or deflate stream
     60     AUTO = 0,
     61 
     62     // GZIP streams have some extra header data for file attributes.
     63     GZIP = 1,
     64 
     65     // Simpler zlib stream format.
     66     ZLIB = 2,
     67   };
     68 
     69   // buffer_size and format may be -1 for default of 64kB and GZIP format
     70   explicit GzipInputStream(
     71       ZeroCopyInputStream* sub_stream,
     72       Format format = AUTO,
     73       int buffer_size = -1);
     74   virtual ~GzipInputStream();
     75 
     76   // Return last error message or NULL if no error.
     77   inline const char* ZlibErrorMessage() const {
     78     return zcontext_.msg;
     79   }
     80   inline int ZlibErrorCode() const {
     81     return zerror_;
     82   }
     83 
     84   // implements ZeroCopyInputStream ----------------------------------
     85   bool Next(const void** data, int* size);
     86   void BackUp(int count);
     87   bool Skip(int count);
     88   int64 ByteCount() const;
     89 
     90  private:
     91   Format format_;
     92 
     93   ZeroCopyInputStream* sub_stream_;
     94 
     95   z_stream zcontext_;
     96   int zerror_;
     97 
     98   void* output_buffer_;
     99   void* output_position_;
    100   size_t output_buffer_length_;
    101   int64 byte_count_;
    102 
    103   int Inflate(int flush);
    104   void DoNextOutput(const void** data, int* size);
    105 
    106   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream);
    107 };
    108 
    109 
    110 class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream {
    111  public:
    112   // Format key for constructor
    113   enum Format {
    114     // GZIP streams have some extra header data for file attributes.
    115     GZIP = 1,
    116 
    117     // Simpler zlib stream format.
    118     ZLIB = 2,
    119   };
    120 
    121   struct Options {
    122     // Defaults to GZIP.
    123     Format format;
    124 
    125     // What size buffer to use internally.  Defaults to 64kB.
    126     int buffer_size;
    127 
    128     // A number between 0 and 9, where 0 is no compression and 9 is best
    129     // compression.  Defaults to Z_DEFAULT_COMPRESSION (see zlib.h).
    130     int compression_level;
    131 
    132     // Defaults to Z_DEFAULT_STRATEGY.  Can also be set to Z_FILTERED,
    133     // Z_HUFFMAN_ONLY, or Z_RLE.  See the documentation for deflateInit2 in
    134     // zlib.h for definitions of these constants.
    135     int compression_strategy;
    136 
    137     Options();  // Initializes with default values.
    138   };
    139 
    140   // Create a GzipOutputStream with default options.
    141   explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream);
    142 
    143   // Create a GzipOutputStream with the given options.
    144   GzipOutputStream(
    145       ZeroCopyOutputStream* sub_stream,
    146       const Options& options);
    147 
    148   virtual ~GzipOutputStream();
    149 
    150   // Return last error message or NULL if no error.
    151   inline const char* ZlibErrorMessage() const {
    152     return zcontext_.msg;
    153   }
    154   inline int ZlibErrorCode() const {
    155     return zerror_;
    156   }
    157 
    158   // Flushes data written so far to zipped data in the underlying stream.
    159   // It is the caller's responsibility to flush the underlying stream if
    160   // necessary.
    161   // Compression may be less efficient stopping and starting around flushes.
    162   // Returns true if no error.
    163   //
    164   // Please ensure that block size is > 6. Here is an excerpt from the zlib
    165   // doc that explains why:
    166   //
    167   // In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out
    168   // is greater than six to avoid repeated flush markers due to
    169   // avail_out == 0 on return.
    170   bool Flush();
    171 
    172   // Writes out all data and closes the gzip stream.
    173   // It is the caller's responsibility to close the underlying stream if
    174   // necessary.
    175   // Returns true if no error.
    176   bool Close();
    177 
    178   // implements ZeroCopyOutputStream ---------------------------------
    179   bool Next(void** data, int* size);
    180   void BackUp(int count);
    181   int64 ByteCount() const;
    182 
    183  private:
    184   ZeroCopyOutputStream* sub_stream_;
    185   // Result from calling Next() on sub_stream_
    186   void* sub_data_;
    187   int sub_data_size_;
    188 
    189   z_stream zcontext_;
    190   int zerror_;
    191   void* input_buffer_;
    192   size_t input_buffer_length_;
    193 
    194   // Shared constructor code.
    195   void Init(ZeroCopyOutputStream* sub_stream, const Options& options);
    196 
    197   // Do some compression.
    198   // Takes zlib flush mode.
    199   // Returns zlib error code.
    200   int Deflate(int flush);
    201 
    202   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipOutputStream);
    203 };
    204 
    205 }  // namespace io
    206 }  // namespace protobuf
    207 
    208 }  // namespace google
    209 #endif  // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
    210