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    :  // Functor that takes care of cleaning up a zstream object that was initialized
  33    :  // with deflateInit.
  34    :  struct ZOutStream::z_stream_s_close {
  35  E :    inline void operator()(z_stream_s* zstream) const {
  36  E :      if (zstream != NULL) {
  37  E :        deflateEnd(zstream);
  38  E :        delete zstream;
  39    :      }
  40  E :    }
  41    :  };
  42    :  
  43    :  ZOutStream::ZOutStream(OutStream* out_stream)
  44  E :      : out_stream_(out_stream), buffer_(kZStreamBufferSize, 0) {
  45  E :  }
  46    :  
  47  E :  ZOutStream::~ZOutStream() { }
  48    :  
  49  E :  bool ZOutStream::Init() {
  50  E :    return Init(Z_DEFAULT_COMPRESSION);
  51  E :  }
  52    :  
  53  E :  bool ZOutStream::Init(int level) {
  54  E :    DCHECK(level == Z_DEFAULT_COMPRESSION || (level >= 0 && level <= 9));
  55    :  
  56  E :    if (zstream_ != NULL)
  57  i :      return true;
  58    :  
  59  E :    scoped_ptr<z_stream_s> zstream(new z_stream_s);
  60  E :    ::memset(zstream.get(), 0, sizeof(*zstream.get()));
  61    :  
  62  E :    int ret = deflateInit(zstream.get(), level);
  63  E :    if (ret != Z_OK) {
  64  i :      LOG(ERROR) << "deflateInit returned " << ret << ": " << zstream_->msg
  65    :                 << ".";
  66  i :      return false;
  67    :    }
  68    :  
  69  E :    zstream->next_out = reinterpret_cast<Bytef*>(&buffer_[0]);
  70  E :    zstream->avail_out = buffer_.size();
  71    :  
  72  E :    zstream_.reset(zstream.release());
  73    :  
  74  E :    return true;
  75  E :  }
  76    :  
  77  E :  bool ZOutStream::Write(size_t length, const Byte* bytes) {
  78  E :    DCHECK(zstream_.get() != NULL);
  79  E :    DCHECK_EQ(buffer_.size(), kZStreamBufferSize);
  80    :  
  81  E :    if (length == 0)
  82  i :      return true;
  83    :  
  84  E :    DCHECK(bytes != NULL);
  85    :  
  86    :    // Continue while we have data to process.
  87  E :    zstream_->avail_in = length;
  88  E :    zstream_->next_in = reinterpret_cast<Bytef*>(const_cast<Byte*>(bytes));
  89  E :    while (zstream_->avail_in > 0) {
  90    :      // We don't do any forced flushing so as to have maximum compression.
  91  E :      int ret = deflate(zstream_.get(), Z_NO_FLUSH);
  92  E :      if (ret != Z_OK && ret != Z_BUF_ERROR) {
  93  i :        LOG(ERROR) << "zlib deflate returned " << ret << ": " << zstream_->msg
  94    :                   << ".";
  95  i :        return false;
  96    :      }
  97    :  
  98    :      // Spit out any output that was produced.
  99  E :      if (!FlushBuffer())
 100  i :        return false;
 101  E :    }
 102    :  
 103  E :    return true;
 104  E :  }
 105    :  
 106  E :  bool ZOutStream::Flush() {
 107  E :    DCHECK(zstream_.get() != NULL);
 108  E :    DCHECK_EQ(buffer_.size(), kZStreamBufferSize);
 109    :  
 110  E :    while (true) {
 111  E :      int ret = deflate(zstream_.get(), Z_FINISH);
 112  E :      if (ret != Z_OK && ret != Z_STREAM_END) {
 113  i :        LOG(ERROR) << "zlib deflate returned " << ret << ": " << zstream_->msg
 114    :                   << ".";
 115    :      }
 116    :  
 117  E :      if (!FlushBuffer())
 118  i :        return false;
 119    :  
 120  E :      if (ret == Z_STREAM_END)
 121  E :        break;
 122  E :    }
 123    :  
 124  E :    zstream_.reset();
 125    :  
 126  E :    return true;
 127  E :  }
 128    :  
 129  E :  bool ZOutStream::FlushBuffer() {
 130  E :    DCHECK(zstream_.get() != NULL);
 131  E :    DCHECK_EQ(buffer_.size(), kZStreamBufferSize);
 132    :  
 133  E :    size_t bytes_to_write = buffer_.size() - zstream_->avail_out;
 134  E :    if (bytes_to_write == 0)
 135  E :      return true;
 136    :  
 137  E :    if (!out_stream_->Write(bytes_to_write, &buffer_[0])) {
 138  i :      LOG(ERROR) << "Unable to write compressed stream.";
 139  i :      return false;
 140    :    }
 141    :  
 142    :    // Update the output buffer data.
 143  E :    zstream_->next_out = reinterpret_cast<Bytef*>(&buffer_[0]);
 144  E :    zstream_->avail_out = buffer_.size();
 145    :  
 146  E :    return true;
 147  E :  }
 148    :  
 149    :  // Functor that takes care of cleaning up a zstream object that was initialized
 150    :  // with inflateInit.
 151    :  struct ZInStream::z_stream_s_close {
 152  E :    inline void operator()(z_stream_s* zstream) const {
 153  E :      if (zstream != NULL) {
 154  E :        inflateEnd(zstream);
 155  E :        delete zstream;
 156    :      }
 157  E :    }
 158    :  };
 159    :  
 160    :  ZInStream::ZInStream(InStream* in_stream)
 161  E :      : in_stream_(in_stream), buffer_(kZStreamBufferSize, 0) {
 162  E :    DCHECK(in_stream != NULL);
 163  E :  }
 164    :  
 165  E :  ZInStream::~ZInStream() { }
 166    :  
 167  E :  bool ZInStream::Init() {
 168  E :    if (zstream_.get() != NULL)
 169  i :      return true;
 170    :  
 171  E :    scoped_ptr<z_stream_s> zstream(new z_stream_s);
 172  E :    ::memset(zstream.get(), 0, sizeof(*zstream.get()));
 173    :  
 174  E :    int ret = inflateInit(zstream.get());
 175  E :    if (ret != Z_OK) {
 176  i :      LOG(ERROR) << "inflateInit returned " << ret << ": " << zstream_->msg
 177    :                 << ".";
 178  i :      return false;
 179    :    }
 180    :  
 181  E :    zstream_.reset(zstream.release());
 182    :  
 183  E :    return true;
 184  E :  }
 185    :  
 186  E :  bool ZInStream::ReadImpl(size_t length, Byte* bytes, size_t* bytes_read) {
 187  E :    DCHECK(bytes_read != NULL);
 188    :  
 189  E :    *bytes_read = 0;
 190  E :    if (length == 0)
 191  i :      return true;
 192    :  
 193  E :    DCHECK(bytes != NULL);
 194    :  
 195    :    // If we're not initialized we're at the end of the stream. This is not an
 196    :    // error, there's simply no more data to be consumed from this stream.
 197  E :    if (zstream_.get() == NULL)
 198  i :      return true;
 199    :  
 200  E :    DCHECK_EQ(buffer_.size(), kZStreamBufferSize);
 201    :  
 202  E :    zstream_->next_out = reinterpret_cast<Bytef*>(bytes);
 203  E :    zstream_->avail_out = length;
 204    :  
 205  E :    int ret = Z_OK;
 206  E :    while (true) {
 207    :      // Try reading from the zstream right away. It's possible for the input
 208    :      // buffer to be exhausted, but for there to still be data to output.
 209  E :      ret = inflate(zstream_.get(), Z_NO_FLUSH);
 210  E :      if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) {
 211  i :        LOG(ERROR) << "zlib inflate returned " << ret << ": " << zstream_->msg
 212    :                   << ".";
 213  i :        return false;
 214    :      }
 215    :  
 216    :      // No more data, or no more room to write more data? Then we're done
 217    :      // for now.
 218  E :      if (ret == Z_STREAM_END || zstream_->avail_out == 0)
 219  E :        break;
 220    :  
 221    :      // If we get here, then there was room to output more data yet that wasn't
 222    :      // done. Thus, we must need more input.
 223  E :      if (zstream_->avail_in != 0) {
 224  i :        LOG(ERROR) << "zlib won't emit more data, but has input to work with.";
 225  i :        return false;
 226    :      }
 227    :  
 228    :      // We expect *some* data to be read.
 229  E :      size_t bytes_read = 0;
 230  E :      if (!in_stream_->Read(buffer_.size(), &buffer_[0], &bytes_read)) {
 231  i :        LOG(ERROR) << "Unable to read data from input stream.";
 232  i :        return false;
 233    :      }
 234  E :      if (bytes_read == 0) {
 235  E :        LOG(ERROR) << "zlib expects more data but input stream is exhausted.";
 236  E :        return false;
 237    :      }
 238  E :      zstream_->next_in = reinterpret_cast<Bytef*>(&buffer_[0]);
 239  E :      zstream_->avail_in = bytes_read;
 240  E :    }
 241    :  
 242  E :    *bytes_read = length - zstream_->avail_out;
 243    :  
 244    :    // Is the zstream exhausted? Then we can clean up this stream to indicate
 245    :    // end of stream to further calls.
 246  E :    if (ret == Z_STREAM_END && zstream_->avail_out == 0)
 247  E :      zstream_.reset();
 248    :  
 249  E :    return true;
 250  E :  }
 251    :  
 252    :  }  // namespace core

Coverage information generated Tue Jun 25 13:56:24 2013.