LCOV - code coverage report
Current view: top level - toolkit/components/protobuf/src/google/protobuf/io - gzip_stream.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 189 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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@google.com (Brian Olson)
      32             : //
      33             : // This file contains the implementation of classes GzipInputStream and
      34             : // GzipOutputStream.
      35             : 
      36             : 
      37             : #if HAVE_ZLIB
      38             : #include <google/protobuf/io/gzip_stream.h>
      39             : 
      40             : #include <google/protobuf/stubs/common.h>
      41             : 
      42             : namespace google {
      43             : namespace protobuf {
      44             : namespace io {
      45             : 
      46             : static const int kDefaultBufferSize = 65536;
      47             : 
      48           0 : GzipInputStream::GzipInputStream(
      49           0 :     ZeroCopyInputStream* sub_stream, Format format, int buffer_size)
      50           0 :     : format_(format), sub_stream_(sub_stream), zerror_(Z_OK) {
      51           0 :   zcontext_.zalloc = Z_NULL;
      52           0 :   zcontext_.zfree = Z_NULL;
      53           0 :   zcontext_.opaque = Z_NULL;
      54           0 :   zcontext_.total_out = 0;
      55           0 :   zcontext_.next_in = NULL;
      56           0 :   zcontext_.avail_in = 0;
      57           0 :   zcontext_.total_in = 0;
      58           0 :   zcontext_.msg = NULL;
      59           0 :   if (buffer_size == -1) {
      60           0 :     output_buffer_length_ = kDefaultBufferSize;
      61             :   } else {
      62           0 :     output_buffer_length_ = buffer_size;
      63             :   }
      64           0 :   output_buffer_ = operator new(output_buffer_length_);
      65           0 :   GOOGLE_CHECK(output_buffer_ != NULL);
      66           0 :   zcontext_.next_out = static_cast<Bytef*>(output_buffer_);
      67           0 :   zcontext_.avail_out = output_buffer_length_;
      68           0 :   output_position_ = output_buffer_;
      69           0 : }
      70           0 : GzipInputStream::~GzipInputStream() {
      71           0 :   operator delete(output_buffer_);
      72           0 :   zerror_ = inflateEnd(&zcontext_);
      73           0 : }
      74             : 
      75           0 : static inline int internalInflateInit2(
      76             :     z_stream* zcontext, GzipInputStream::Format format) {
      77           0 :   int windowBitsFormat = 0;
      78           0 :   switch (format) {
      79           0 :     case GzipInputStream::GZIP: windowBitsFormat = 16; break;
      80           0 :     case GzipInputStream::AUTO: windowBitsFormat = 32; break;
      81           0 :     case GzipInputStream::ZLIB: windowBitsFormat = 0; break;
      82             :   }
      83           0 :   return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat);
      84             : }
      85             : 
      86           0 : int GzipInputStream::Inflate(int flush) {
      87           0 :   if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) {
      88             :     // previous inflate filled output buffer. don't change input params yet.
      89           0 :   } else if (zcontext_.avail_in == 0) {
      90             :     const void* in;
      91             :     int in_size;
      92           0 :     bool first = zcontext_.next_in == NULL;
      93           0 :     bool ok = sub_stream_->Next(&in, &in_size);
      94           0 :     if (!ok) {
      95           0 :       zcontext_.next_out = NULL;
      96           0 :       zcontext_.avail_out = 0;
      97           0 :       return Z_STREAM_END;
      98             :     }
      99           0 :     zcontext_.next_in = static_cast<Bytef*>(const_cast<void*>(in));
     100           0 :     zcontext_.avail_in = in_size;
     101           0 :     if (first) {
     102           0 :       int error = internalInflateInit2(&zcontext_, format_);
     103           0 :       if (error != Z_OK) {
     104           0 :         return error;
     105             :       }
     106             :     }
     107             :   }
     108           0 :   zcontext_.next_out = static_cast<Bytef*>(output_buffer_);
     109           0 :   zcontext_.avail_out = output_buffer_length_;
     110           0 :   output_position_ = output_buffer_;
     111           0 :   int error = inflate(&zcontext_, flush);
     112           0 :   return error;
     113             : }
     114             : 
     115           0 : void GzipInputStream::DoNextOutput(const void** data, int* size) {
     116           0 :   *data = output_position_;
     117           0 :   *size = ((uintptr_t)zcontext_.next_out) - ((uintptr_t)output_position_);
     118           0 :   output_position_ = zcontext_.next_out;
     119           0 : }
     120             : 
     121             : // implements ZeroCopyInputStream ----------------------------------
     122           0 : bool GzipInputStream::Next(const void** data, int* size) {
     123           0 :   bool ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END)
     124           0 :       || (zerror_ == Z_BUF_ERROR);
     125           0 :   if ((!ok) || (zcontext_.next_out == NULL)) {
     126           0 :     return false;
     127             :   }
     128           0 :   if (zcontext_.next_out != output_position_) {
     129           0 :     DoNextOutput(data, size);
     130           0 :     return true;
     131             :   }
     132           0 :   if (zerror_ == Z_STREAM_END) {
     133           0 :     if (zcontext_.next_out != NULL) {
     134             :       // sub_stream_ may have concatenated streams to follow
     135           0 :       zerror_ = inflateEnd(&zcontext_);
     136           0 :       if (zerror_ != Z_OK) {
     137           0 :         return false;
     138             :       }
     139           0 :       zerror_ = internalInflateInit2(&zcontext_, format_);
     140           0 :       if (zerror_ != Z_OK) {
     141           0 :         return false;
     142             :       }
     143             :     } else {
     144           0 :       *data = NULL;
     145           0 :       *size = 0;
     146           0 :       return false;
     147             :     }
     148             :   }
     149           0 :   zerror_ = Inflate(Z_NO_FLUSH);
     150           0 :   if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) {
     151             :     // The underlying stream's Next returned false inside Inflate.
     152           0 :     return false;
     153             :   }
     154           0 :   ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END)
     155           0 :       || (zerror_ == Z_BUF_ERROR);
     156           0 :   if (!ok) {
     157           0 :     return false;
     158             :   }
     159           0 :   DoNextOutput(data, size);
     160           0 :   return true;
     161             : }
     162           0 : void GzipInputStream::BackUp(int count) {
     163           0 :   output_position_ = reinterpret_cast<void*>(
     164           0 :       reinterpret_cast<uintptr_t>(output_position_) - count);
     165           0 : }
     166           0 : bool GzipInputStream::Skip(int count) {
     167             :   const void* data;
     168             :   int size;
     169           0 :   bool ok = Next(&data, &size);
     170           0 :   while (ok && (size < count)) {
     171           0 :     count -= size;
     172           0 :     ok = Next(&data, &size);
     173             :   }
     174           0 :   if (size > count) {
     175           0 :     BackUp(size - count);
     176             :   }
     177           0 :   return ok;
     178             : }
     179           0 : int64 GzipInputStream::ByteCount() const {
     180           0 :   return zcontext_.total_out +
     181           0 :     (((uintptr_t)zcontext_.next_out) - ((uintptr_t)output_position_));
     182             : }
     183             : 
     184             : // =========================================================================
     185             : 
     186           0 : GzipOutputStream::Options::Options()
     187             :     : format(GZIP),
     188             :       buffer_size(kDefaultBufferSize),
     189             :       compression_level(Z_DEFAULT_COMPRESSION),
     190           0 :       compression_strategy(Z_DEFAULT_STRATEGY) {}
     191             : 
     192           0 : GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream) {
     193           0 :   Init(sub_stream, Options());
     194           0 : }
     195             : 
     196           0 : GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream,
     197           0 :                                    const Options& options) {
     198           0 :   Init(sub_stream, options);
     199           0 : }
     200             : 
     201           0 : void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream,
     202             :                             const Options& options) {
     203           0 :   sub_stream_ = sub_stream;
     204           0 :   sub_data_ = NULL;
     205           0 :   sub_data_size_ = 0;
     206             : 
     207           0 :   input_buffer_length_ = options.buffer_size;
     208           0 :   input_buffer_ = operator new(input_buffer_length_);
     209           0 :   GOOGLE_CHECK(input_buffer_ != NULL);
     210             : 
     211           0 :   zcontext_.zalloc = Z_NULL;
     212           0 :   zcontext_.zfree = Z_NULL;
     213           0 :   zcontext_.opaque = Z_NULL;
     214           0 :   zcontext_.next_out = NULL;
     215           0 :   zcontext_.avail_out = 0;
     216           0 :   zcontext_.total_out = 0;
     217           0 :   zcontext_.next_in = NULL;
     218           0 :   zcontext_.avail_in = 0;
     219           0 :   zcontext_.total_in = 0;
     220           0 :   zcontext_.msg = NULL;
     221             :   // default to GZIP format
     222           0 :   int windowBitsFormat = 16;
     223           0 :   if (options.format == ZLIB) {
     224           0 :     windowBitsFormat = 0;
     225             :   }
     226           0 :   zerror_ = deflateInit2(
     227             :       &zcontext_,
     228             :       options.compression_level,
     229             :       Z_DEFLATED,
     230             :       /* windowBits */15 | windowBitsFormat,
     231             :       /* memLevel (default) */8,
     232             :       options.compression_strategy);
     233           0 : }
     234             : 
     235           0 : GzipOutputStream::~GzipOutputStream() {
     236           0 :   Close();
     237           0 :   if (input_buffer_ != NULL) {
     238           0 :     operator delete(input_buffer_);
     239             :   }
     240           0 : }
     241             : 
     242             : // private
     243           0 : int GzipOutputStream::Deflate(int flush) {
     244           0 :   int error = Z_OK;
     245           0 :   do {
     246           0 :     if ((sub_data_ == NULL) || (zcontext_.avail_out == 0)) {
     247           0 :       bool ok = sub_stream_->Next(&sub_data_, &sub_data_size_);
     248           0 :       if (!ok) {
     249           0 :         sub_data_ = NULL;
     250           0 :         sub_data_size_ = 0;
     251           0 :         return Z_BUF_ERROR;
     252             :       }
     253           0 :       GOOGLE_CHECK_GT(sub_data_size_, 0);
     254           0 :       zcontext_.next_out = static_cast<Bytef*>(sub_data_);
     255           0 :       zcontext_.avail_out = sub_data_size_;
     256             :     }
     257           0 :     error = deflate(&zcontext_, flush);
     258           0 :   } while (error == Z_OK && zcontext_.avail_out == 0);
     259           0 :   if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) {
     260             :     // Notify lower layer of data.
     261           0 :     sub_stream_->BackUp(zcontext_.avail_out);
     262             :     // We don't own the buffer anymore.
     263           0 :     sub_data_ = NULL;
     264           0 :     sub_data_size_ = 0;
     265             :   }
     266           0 :   return error;
     267             : }
     268             : 
     269             : // implements ZeroCopyOutputStream ---------------------------------
     270           0 : bool GzipOutputStream::Next(void** data, int* size) {
     271           0 :   if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) {
     272           0 :     return false;
     273             :   }
     274           0 :   if (zcontext_.avail_in != 0) {
     275           0 :     zerror_ = Deflate(Z_NO_FLUSH);
     276           0 :     if (zerror_ != Z_OK) {
     277           0 :       return false;
     278             :     }
     279             :   }
     280           0 :   if (zcontext_.avail_in == 0) {
     281             :     // all input was consumed. reset the buffer.
     282           0 :     zcontext_.next_in = static_cast<Bytef*>(input_buffer_);
     283           0 :     zcontext_.avail_in = input_buffer_length_;
     284           0 :     *data = input_buffer_;
     285           0 :     *size = input_buffer_length_;
     286             :   } else {
     287             :     // The loop in Deflate should consume all avail_in
     288           0 :     GOOGLE_LOG(DFATAL) << "Deflate left bytes unconsumed";
     289             :   }
     290           0 :   return true;
     291             : }
     292           0 : void GzipOutputStream::BackUp(int count) {
     293           0 :   GOOGLE_CHECK_GE(zcontext_.avail_in, count);
     294           0 :   zcontext_.avail_in -= count;
     295           0 : }
     296           0 : int64 GzipOutputStream::ByteCount() const {
     297           0 :   return zcontext_.total_in + zcontext_.avail_in;
     298             : }
     299             : 
     300           0 : bool GzipOutputStream::Flush() {
     301           0 :   zerror_ = Deflate(Z_FULL_FLUSH);
     302             :   // Return true if the flush succeeded or if it was a no-op.
     303           0 :   return  (zerror_ == Z_OK) ||
     304           0 :       (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 &&
     305           0 :        zcontext_.avail_out != 0);
     306             : }
     307             : 
     308           0 : bool GzipOutputStream::Close() {
     309           0 :   if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) {
     310           0 :     return false;
     311             :   }
     312           0 :   do {
     313           0 :     zerror_ = Deflate(Z_FINISH);
     314           0 :   } while (zerror_ == Z_OK);
     315           0 :   zerror_ = deflateEnd(&zcontext_);
     316           0 :   bool ok = zerror_ == Z_OK;
     317           0 :   zerror_ = Z_STREAM_END;
     318           0 :   return ok;
     319             : }
     320             : 
     321             : }  // namespace io
     322             : }  // namespace protobuf
     323             : }  // namespace google
     324             : 
     325             : #endif  // HAVE_ZLIB

Generated by: LCOV version 1.13