Coverage for /Syzygy/core/zstream.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
83.1%1081300.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/core/zstream.h"
  16    :  
  17    :  #include "syzygy/core/serialization.h"
  18    :  #include "third_party/zlib/zlib.h"
  19    :  
  20    :  namespace core {
  21    :  
  22    :  namespace {
  23    :  
  24    :  // The size of the intermediate buffers used by the streams. This has no
  25    :  // bearing on the compression performance, but rather limits how often we have
  26    :  // to go in and out of zlib. There is no meaningful way to have the buffers
  27    :  // grow dynamically so we simply use a page of memory.
  28    :  static const size_t kZStreamBufferSize = 4096;
  29    :  
  30    :  }  // namespace
  31    :  
  32  E :  void ZOutStream::z_stream_s_close::operator()(z_stream_s* zstream) const {
  33  E :    if (zstream != NULL) {
  34  E :      deflateEnd(zstream);
  35  E :      delete zstream;
  36    :    }
  37  E :  }
  38    :  
  39    :  ZOutStream::ZOutStream(OutStream* out_stream)
  40  E :      : out_stream_(out_stream), buffer_(kZStreamBufferSize, 0) {
  41  E :  }
  42    :  
  43  E :  ZOutStream::~ZOutStream() { }
  44    :  
  45  E :  bool ZOutStream::Init() {
  46  E :    return Init(Z_DEFAULT_COMPRESSION);
  47  E :  }
  48    :  
  49  E :  bool ZOutStream::Init(int level) {
  50  E :    DCHECK(level == Z_DEFAULT_COMPRESSION || (level >= 0 && level <= 9));
  51    :  
  52  E :    if (zstream_ != NULL)
  53  i :      return true;
  54    :  
  55  E :    scoped_ptr<z_stream_s> zstream(new z_stream_s);
  56  E :    ::memset(zstream.get(), 0, sizeof(*zstream.get()));
  57    :  
  58  E :    int ret = deflateInit(zstream.get(), level);
  59  E :    if (ret != Z_OK) {
  60  i :      LOG(ERROR) << "deflateInit returned " << ret << ": " << zstream_->msg
  61    :                 << ".";
  62  i :      return false;
  63    :    }
  64    :  
  65  E :    zstream->next_out = reinterpret_cast<Bytef*>(&buffer_[0]);
  66  E :    zstream->avail_out = buffer_.size();
  67    :  
  68  E :    zstream_.reset(zstream.release());
  69    :  
  70  E :    return true;
  71  E :  }
  72    :  
  73  E :  bool ZOutStream::Write(size_t length, const Byte* bytes) {
  74  E :    DCHECK(zstream_.get() != NULL);
  75  E :    DCHECK_EQ(buffer_.size(), kZStreamBufferSize);
  76    :  
  77  E :    if (length == 0)
  78  i :      return true;
  79    :  
  80  E :    DCHECK(bytes != NULL);
  81    :  
  82    :    // Continue while we have data to process.
  83  E :    zstream_->avail_in = length;
  84  E :    zstream_->next_in = reinterpret_cast<Bytef*>(const_cast<Byte*>(bytes));
  85  E :    while (zstream_->avail_in > 0) {
  86    :      // We don't do any forced flushing so as to have maximum compression.
  87  E :      int ret = deflate(zstream_.get(), Z_NO_FLUSH);
  88  E :      if (ret != Z_OK && ret != Z_BUF_ERROR) {
  89  i :        LOG(ERROR) << "zlib deflate returned " << ret << ": " << zstream_->msg
  90    :                   << ".";
  91  i :        return false;
  92    :      }
  93    :  
  94    :      // Spit out any output that was produced.
  95  E :      if (!FlushBuffer())
  96  i :        return false;
  97  E :    }
  98    :  
  99  E :    return true;
 100  E :  }
 101    :  
 102  E :  bool ZOutStream::Flush() {
 103  E :    DCHECK(zstream_.get() != NULL);
 104  E :    DCHECK_EQ(buffer_.size(), kZStreamBufferSize);
 105    :  
 106  E :    while (true) {
 107  E :      int ret = deflate(zstream_.get(), Z_FINISH);
 108  E :      if (ret != Z_OK && ret != Z_STREAM_END) {
 109  i :        LOG(ERROR) << "zlib deflate returned " << ret << ": " << zstream_->msg
 110    :                   << ".";
 111    :      }
 112    :  
 113  E :      if (!FlushBuffer())
 114  i :        return false;
 115    :  
 116  E :      if (ret == Z_STREAM_END)
 117  E :        break;
 118  E :    }
 119    :  
 120  E :    zstream_.reset();
 121    :  
 122  E :    return true;
 123  E :  }
 124    :  
 125  E :  bool ZOutStream::FlushBuffer() {
 126  E :    DCHECK(zstream_.get() != NULL);
 127  E :    DCHECK_EQ(buffer_.size(), kZStreamBufferSize);
 128    :  
 129  E :    size_t bytes_to_write = buffer_.size() - zstream_->avail_out;
 130  E :    if (bytes_to_write == 0)
 131  E :      return true;
 132    :  
 133  E :    if (!out_stream_->Write(bytes_to_write, &buffer_[0])) {
 134  i :      LOG(ERROR) << "Unable to write compressed stream.";
 135  i :      return false;
 136    :    }
 137    :  
 138    :    // Update the output buffer data.
 139  E :    zstream_->next_out = reinterpret_cast<Bytef*>(&buffer_[0]);
 140  E :    zstream_->avail_out = buffer_.size();
 141    :  
 142  E :    return true;
 143  E :  }
 144    :  
 145  E :  void ZInStream::z_stream_s_close::operator()(z_stream_s* zstream) const {
 146  E :    if (zstream != NULL) {
 147  E :      inflateEnd(zstream);
 148  E :      delete zstream;
 149    :    }
 150  E :  }
 151    :  
 152    :  ZInStream::ZInStream(InStream* in_stream)
 153  E :      : in_stream_(in_stream), buffer_(kZStreamBufferSize, 0) {
 154  E :    DCHECK(in_stream != NULL);
 155  E :  }
 156    :  
 157  E :  ZInStream::~ZInStream() { }
 158    :  
 159  E :  bool ZInStream::Init() {
 160  E :    if (zstream_.get() != NULL)
 161  i :      return true;
 162    :  
 163  E :    scoped_ptr<z_stream_s> zstream(new z_stream_s);
 164  E :    ::memset(zstream.get(), 0, sizeof(*zstream.get()));
 165    :  
 166  E :    int ret = inflateInit(zstream.get());
 167  E :    if (ret != Z_OK) {
 168  i :      LOG(ERROR) << "inflateInit returned " << ret << ": " << zstream_->msg
 169    :                 << ".";
 170  i :      return false;
 171    :    }
 172    :  
 173  E :    zstream_.reset(zstream.release());
 174    :  
 175  E :    return true;
 176  E :  }
 177    :  
 178  E :  bool ZInStream::ReadImpl(size_t length, Byte* bytes, size_t* bytes_read) {
 179  E :    DCHECK(bytes_read != NULL);
 180    :  
 181  E :    *bytes_read = 0;
 182  E :    if (length == 0)
 183  i :      return true;
 184    :  
 185  E :    DCHECK(bytes != NULL);
 186    :  
 187    :    // If we're not initialized we're at the end of the stream. This is not an
 188    :    // error, there's simply no more data to be consumed from this stream.
 189  E :    if (zstream_.get() == NULL)
 190  i :      return true;
 191    :  
 192  E :    DCHECK_EQ(buffer_.size(), kZStreamBufferSize);
 193    :  
 194  E :    zstream_->next_out = reinterpret_cast<Bytef*>(bytes);
 195  E :    zstream_->avail_out = length;
 196    :  
 197  E :    int ret = Z_OK;
 198  E :    while (true) {
 199    :      // Try reading from the zstream right away. It's possible for the input
 200    :      // buffer to be exhausted, but for there to still be data to output.
 201  E :      ret = inflate(zstream_.get(), Z_NO_FLUSH);
 202  E :      if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) {
 203  i :        LOG(ERROR) << "zlib inflate returned " << ret << ": " << zstream_->msg
 204    :                   << ".";
 205  i :        return false;
 206    :      }
 207    :  
 208    :      // No more data, or no more room to write more data? Then we're done
 209    :      // for now.
 210  E :      if (ret == Z_STREAM_END || zstream_->avail_out == 0)
 211  E :        break;
 212    :  
 213    :      // If we get here, then there was room to output more data yet that wasn't
 214    :      // done. Thus, we must need more input.
 215  E :      if (zstream_->avail_in != 0) {
 216  i :        LOG(ERROR) << "zlib won't emit more data, but has input to work with.";
 217  i :        return false;
 218    :      }
 219    :  
 220    :      // We expect *some* data to be read.
 221  E :      size_t bytes_read = 0;
 222  E :      if (!in_stream_->Read(buffer_.size(), &buffer_[0], &bytes_read)) {
 223  i :        LOG(ERROR) << "Unable to read data from input stream.";
 224  i :        return false;
 225    :      }
 226  E :      if (bytes_read == 0) {
 227  E :        LOG(ERROR) << "zlib expects more data but input stream is exhausted.";
 228  E :        return false;
 229    :      }
 230  E :      zstream_->next_in = reinterpret_cast<Bytef*>(&buffer_[0]);
 231  E :      zstream_->avail_in = bytes_read;
 232  E :    }
 233    :  
 234  E :    *bytes_read = length - zstream_->avail_out;
 235    :  
 236    :    // Is the zstream exhausted? Then we can clean up this stream to indicate
 237    :    // end of stream to further calls.
 238  E :    if (ret == Z_STREAM_END && zstream_->avail_out == 0)
 239  E :      zstream_.reset();
 240    :  
 241  E :    return true;
 242  E :  }
 243    :  
 244    :  }  // namespace core

Coverage information generated Thu Jan 14 17:40:38 2016.