LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf/io - zero_copy_stream_impl_lite.cc (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 112 192 58.3 %
Date: 2015-10-10 Functions: 25 43 58.1 %

          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: kenton@google.com (Kenton Varda)
      32             : //  Based on original Protocol Buffers design by
      33             : //  Sanjay Ghemawat, Jeff Dean, and others.
      34             : 
      35             : #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
      36             : 
      37             : #include <algorithm>
      38             : #include <limits>
      39             : 
      40             : #include <google/protobuf/stubs/casts.h>
      41             : #include <google/protobuf/stubs/common.h>
      42             : #include <google/protobuf/stubs/logging.h>
      43             : #include <google/protobuf/stubs/stl_util.h>
      44             : 
      45             : namespace google {
      46             : namespace protobuf {
      47             : namespace io {
      48             : 
      49             : namespace {
      50             : 
      51             : // Default block size for Copying{In,Out}putStreamAdaptor.
      52             : static const int kDefaultBlockSize = 8192;
      53             : 
      54             : }  // namespace
      55             : 
      56             : // ===================================================================
      57             : 
      58          55 : ArrayInputStream::ArrayInputStream(const void* data, int size,
      59             :                                    int block_size)
      60             :   : data_(reinterpret_cast<const uint8*>(data)),
      61             :     size_(size),
      62             :     block_size_(block_size > 0 ? block_size : size),
      63             :     position_(0),
      64         110 :     last_returned_size_(0) {
      65          55 : }
      66             : 
      67          55 : ArrayInputStream::~ArrayInputStream() {
      68          55 : }
      69             : 
      70         110 : bool ArrayInputStream::Next(const void** data, int* size) {
      71         110 :   if (position_ < size_) {
      72         110 :     last_returned_size_ = min(block_size_, size_ - position_);
      73          55 :     *data = data_ + position_;
      74          55 :     *size = last_returned_size_;
      75          55 :     position_ += last_returned_size_;
      76          55 :     return true;
      77             :   } else {
      78             :     // We're at the end of the array.
      79          55 :     last_returned_size_ = 0;   // Don't let caller back up.
      80          55 :     return false;
      81             :   }
      82             : }
      83             : 
      84           0 : void ArrayInputStream::BackUp(int count) {
      85           0 :   GOOGLE_CHECK_GT(last_returned_size_, 0)
      86           0 :       << "BackUp() can only be called after a successful Next().";
      87           0 :   GOOGLE_CHECK_LE(count, last_returned_size_);
      88           0 :   GOOGLE_CHECK_GE(count, 0);
      89           0 :   position_ -= count;
      90           0 :   last_returned_size_ = 0;  // Don't let caller back up further.
      91           0 : }
      92             : 
      93           0 : bool ArrayInputStream::Skip(int count) {
      94           0 :   GOOGLE_CHECK_GE(count, 0);
      95           0 :   last_returned_size_ = 0;   // Don't let caller back up.
      96           0 :   if (count > size_ - position_) {
      97           0 :     position_ = size_;
      98           0 :     return false;
      99             :   } else {
     100           0 :     position_ += count;
     101           0 :     return true;
     102             :   }
     103             : }
     104             : 
     105           0 : int64 ArrayInputStream::ByteCount() const {
     106           0 :   return position_;
     107             : }
     108             : 
     109             : 
     110             : // ===================================================================
     111             : 
     112           9 : ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
     113             :   : data_(reinterpret_cast<uint8*>(data)),
     114             :     size_(size),
     115             :     block_size_(block_size > 0 ? block_size : size),
     116             :     position_(0),
     117          18 :     last_returned_size_(0) {
     118           9 : }
     119             : 
     120           9 : ArrayOutputStream::~ArrayOutputStream() {
     121           9 : }
     122             : 
     123           9 : bool ArrayOutputStream::Next(void** data, int* size) {
     124           9 :   if (position_ < size_) {
     125          18 :     last_returned_size_ = min(block_size_, size_ - position_);
     126           9 :     *data = data_ + position_;
     127           9 :     *size = last_returned_size_;
     128           9 :     position_ += last_returned_size_;
     129           9 :     return true;
     130             :   } else {
     131             :     // We're at the end of the array.
     132           0 :     last_returned_size_ = 0;   // Don't let caller back up.
     133           0 :     return false;
     134             :   }
     135             : }
     136             : 
     137           0 : void ArrayOutputStream::BackUp(int count) {
     138           0 :   GOOGLE_CHECK_GT(last_returned_size_, 0)
     139           0 :       << "BackUp() can only be called after a successful Next().";
     140           0 :   GOOGLE_CHECK_LE(count, last_returned_size_);
     141           0 :   GOOGLE_CHECK_GE(count, 0);
     142           0 :   position_ -= count;
     143           0 :   last_returned_size_ = 0;  // Don't let caller back up further.
     144           0 : }
     145             : 
     146           0 : int64 ArrayOutputStream::ByteCount() const {
     147           0 :   return position_;
     148             : }
     149             : 
     150             : // ===================================================================
     151             : 
     152        1227 : StringOutputStream::StringOutputStream(string* target)
     153        2454 :   : target_(target) {
     154        1227 : }
     155             : 
     156        1357 : StringOutputStream::~StringOutputStream() {
     157        1357 : }
     158             : 
     159        3066 : bool StringOutputStream::Next(void** data, int* size) {
     160        6132 :   int old_size = target_->size();
     161             : 
     162             :   // Grow the string.
     163        6132 :   if (old_size < target_->capacity()) {
     164             :     // Resize the string to match its capacity, since we can get away
     165             :     // without a memory allocation this way.
     166         313 :     STLStringResizeUninitialized(target_, target_->capacity());
     167             :   } else {
     168             :     // Size has reached capacity, try to double the size.
     169        2753 :     if (old_size > std::numeric_limits<int>::max() / 2) {
     170             :       // Can not double the size otherwise it is going to cause integer
     171             :       // overflow in the expression below: old_size * 2 ";
     172           0 :       GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for "
     173           0 :                  << "StringOutputStream.";
     174           0 :       return false;
     175             :     }
     176             :     // Double the size, also make sure that the new size is at least
     177             :     // kMinimumSize.
     178             :     STLStringResizeUninitialized(
     179             :       target_,
     180        2753 :       max(old_size * 2,
     181       11012 :           kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
     182             :   }
     183             : 
     184        6132 :   *data = mutable_string_data(target_) + old_size;
     185        6132 :   *size = target_->size() - old_size;
     186        3066 :   return true;
     187             : }
     188             : 
     189        1221 : void StringOutputStream::BackUp(int count) {
     190        1221 :   GOOGLE_CHECK_GE(count, 0);
     191        2442 :   GOOGLE_CHECK_LE(count, target_->size());
     192        2442 :   target_->resize(target_->size() - count);
     193        1221 : }
     194             : 
     195           0 : int64 StringOutputStream::ByteCount() const {
     196           0 :   return target_->size();
     197             : }
     198             : 
     199             : // ===================================================================
     200             : 
     201         143 : CopyingInputStream::~CopyingInputStream() {}
     202             : 
     203           0 : int CopyingInputStream::Skip(int count) {
     204             :   char junk[4096];
     205           0 :   int skipped = 0;
     206           0 :   while (skipped < count) {
     207           0 :     int bytes = Read(junk, min(count - skipped,
     208           0 :                                implicit_cast<int>(sizeof(junk))));
     209           0 :     if (bytes <= 0) {
     210             :       // EOF or read error.
     211             :       return skipped;
     212             :     }
     213           0 :     skipped += bytes;
     214             :   }
     215             :   return skipped;
     216             : }
     217             : 
     218         143 : CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
     219             :     CopyingInputStream* copying_stream, int block_size)
     220             :   : copying_stream_(copying_stream),
     221             :     owns_copying_stream_(false),
     222             :     failed_(false),
     223             :     position_(0),
     224             :     buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
     225             :     buffer_used_(0),
     226         429 :     backup_bytes_(0) {
     227         143 : }
     228             : 
     229         429 : CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
     230         143 :   if (owns_copying_stream_) {
     231           0 :     delete copying_stream_;
     232             :   }
     233         143 : }
     234             : 
     235         214 : bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
     236         214 :   if (failed_) {
     237             :     // Already failed on a previous read.
     238             :     return false;
     239             :   }
     240             : 
     241         214 :   AllocateBufferIfNeeded();
     242             : 
     243         214 :   if (backup_bytes_ > 0) {
     244             :     // We have data left over from a previous BackUp(), so just return that.
     245           0 :     *data = buffer_.get() + buffer_used_ - backup_bytes_;
     246           0 :     *size = backup_bytes_;
     247           0 :     backup_bytes_ = 0;
     248           0 :     return true;
     249             :   }
     250             : 
     251             :   // Read new data into the buffer.
     252         428 :   buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
     253         214 :   if (buffer_used_ <= 0) {
     254             :     // EOF or read error.  We don't need the buffer anymore.
     255          86 :     if (buffer_used_ < 0) {
     256             :       // Read error (not EOF).
     257           0 :       failed_ = true;
     258             :     }
     259          86 :     FreeBuffer();
     260          86 :     return false;
     261             :   }
     262         128 :   position_ += buffer_used_;
     263             : 
     264         128 :   *size = buffer_used_;
     265         256 :   *data = buffer_.get();
     266         128 :   return true;
     267             : }
     268             : 
     269           0 : void CopyingInputStreamAdaptor::BackUp(int count) {
     270           0 :   GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
     271           0 :     << " BackUp() can only be called after Next().";
     272           0 :   GOOGLE_CHECK_LE(count, buffer_used_)
     273             :     << " Can't back up over more bytes than were returned by the last call"
     274           0 :        " to Next().";
     275           0 :   GOOGLE_CHECK_GE(count, 0)
     276           0 :     << " Parameter to BackUp() can't be negative.";
     277             : 
     278           0 :   backup_bytes_ = count;
     279           0 : }
     280             : 
     281           0 : bool CopyingInputStreamAdaptor::Skip(int count) {
     282           0 :   GOOGLE_CHECK_GE(count, 0);
     283             : 
     284           0 :   if (failed_) {
     285             :     // Already failed on a previous read.
     286             :     return false;
     287             :   }
     288             : 
     289             :   // First skip any bytes left over from a previous BackUp().
     290           0 :   if (backup_bytes_ >= count) {
     291             :     // We have more data left over than we're trying to skip.  Just chop it.
     292           0 :     backup_bytes_ -= count;
     293           0 :     return true;
     294             :   }
     295             : 
     296           0 :   count -= backup_bytes_;
     297           0 :   backup_bytes_ = 0;
     298             : 
     299           0 :   int skipped = copying_stream_->Skip(count);
     300           0 :   position_ += skipped;
     301           0 :   return skipped == count;
     302             : }
     303             : 
     304           0 : int64 CopyingInputStreamAdaptor::ByteCount() const {
     305           0 :   return position_ - backup_bytes_;
     306             : }
     307             : 
     308         214 : void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
     309         428 :   if (buffer_.get() == NULL) {
     310          86 :     buffer_.reset(new uint8[buffer_size_]);
     311             :   }
     312         214 : }
     313             : 
     314          86 : void CopyingInputStreamAdaptor::FreeBuffer() {
     315          86 :   GOOGLE_CHECK_EQ(backup_bytes_, 0);
     316          86 :   buffer_used_ = 0;
     317          86 :   buffer_.reset();
     318          86 : }
     319             : 
     320             : // ===================================================================
     321             : 
     322           8 : CopyingOutputStream::~CopyingOutputStream() {}
     323             : 
     324           8 : CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
     325             :     CopyingOutputStream* copying_stream, int block_size)
     326             :   : copying_stream_(copying_stream),
     327             :     owns_copying_stream_(false),
     328             :     failed_(false),
     329             :     position_(0),
     330             :     buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
     331          24 :     buffer_used_(0) {
     332           8 : }
     333             : 
     334          24 : CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
     335           8 :   WriteBuffer();
     336           8 :   if (owns_copying_stream_) {
     337           0 :     delete copying_stream_;
     338             :   }
     339           8 : }
     340             : 
     341           8 : bool CopyingOutputStreamAdaptor::Flush() {
     342           8 :   return WriteBuffer();
     343             : }
     344             : 
     345          18 : bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
     346          18 :   if (buffer_used_ == buffer_size_) {
     347          10 :     if (!WriteBuffer()) return false;
     348             :   }
     349             : 
     350          18 :   AllocateBufferIfNeeded();
     351             : 
     352          36 :   *data = buffer_.get() + buffer_used_;
     353          18 :   *size = buffer_size_ - buffer_used_;
     354          18 :   buffer_used_ = buffer_size_;
     355          18 :   return true;
     356             : }
     357             : 
     358           8 : void CopyingOutputStreamAdaptor::BackUp(int count) {
     359           8 :   GOOGLE_CHECK_GE(count, 0);
     360           8 :   GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
     361          16 :     << " BackUp() can only be called after Next().";
     362           8 :   GOOGLE_CHECK_LE(count, buffer_used_)
     363             :     << " Can't back up over more bytes than were returned by the last call"
     364          16 :        " to Next().";
     365             : 
     366           8 :   buffer_used_ -= count;
     367           8 : }
     368             : 
     369           0 : int64 CopyingOutputStreamAdaptor::ByteCount() const {
     370           0 :   return position_ + buffer_used_;
     371             : }
     372             : 
     373          26 : bool CopyingOutputStreamAdaptor::WriteBuffer() {
     374          26 :   if (failed_) {
     375             :     // Already failed on a previous write.
     376             :     return false;
     377             :   }
     378             : 
     379          26 :   if (buffer_used_ == 0) return true;
     380             : 
     381          36 :   if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
     382          18 :     position_ += buffer_used_;
     383          18 :     buffer_used_ = 0;
     384          18 :     return true;
     385             :   } else {
     386           0 :     failed_ = true;
     387           0 :     FreeBuffer();
     388           0 :     return false;
     389             :   }
     390             : }
     391             : 
     392          18 : void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
     393          36 :   if (buffer_ == NULL) {
     394           8 :     buffer_.reset(new uint8[buffer_size_]);
     395             :   }
     396          18 : }
     397             : 
     398           0 : void CopyingOutputStreamAdaptor::FreeBuffer() {
     399           0 :   buffer_used_ = 0;
     400           0 :   buffer_.reset();
     401           0 : }
     402             : 
     403             : // ===================================================================
     404             : 
     405             : }  // namespace io
     406             : }  // namespace protobuf
     407             : }  // namespace google

Generated by: LCOV version 1.10