15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: kenton@google.com (Kenton Varda)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Based on original Protocol Buffers design by
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Sanjay Ghemawat, Jeff Dean, and others.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/common.h>
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/stubs/stl_util.h>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <algorithm>
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace io {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default block size for Copying{In,Out}putStreamAdaptor.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDefaultBlockSize = 8192;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ArrayInputStream::ArrayInputStream(const void* data, int size,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int block_size)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : data_(reinterpret_cast<const uint8*>(data)),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_(size),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_size_(block_size > 0 ? block_size : size),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_(0),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_returned_size_(0) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ArrayInputStream::~ArrayInputStream() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ArrayInputStream::Next(const void** data, int* size) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (position_ < size_) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_returned_size_ = min(block_size_, size_ - position_);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *data = data_ + position_;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *size = last_returned_size_;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_ += last_returned_size_;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're at the end of the array.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_returned_size_ = 0;   // Don't let caller back up.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ArrayInputStream::BackUp(int count) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GT(last_returned_size_, 0)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "BackUp() can only be called after a successful Next().";
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_LE(count, last_returned_size_);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GE(count, 0);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position_ -= count;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_returned_size_ = 0;  // Don't let caller back up further.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ArrayInputStream::Skip(int count) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GE(count, 0);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_returned_size_ = 0;   // Don't let caller back up.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (count > size_ - position_) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_ = size_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_ += count;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 ArrayInputStream::ByteCount() const {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return position_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : data_(reinterpret_cast<uint8*>(data)),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_(size),
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_size_(block_size > 0 ? block_size : size),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_(0),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_returned_size_(0) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ArrayOutputStream::~ArrayOutputStream() {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ArrayOutputStream::Next(void** data, int* size) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (position_ < size_) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_returned_size_ = min(block_size_, size_ - position_);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *data = data_ + position_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *size = last_returned_size_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_ += last_returned_size_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're at the end of the array.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_returned_size_ = 0;   // Don't let caller back up.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ArrayOutputStream::BackUp(int count) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GT(last_returned_size_, 0)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "BackUp() can only be called after a successful Next().";
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_LE(count, last_returned_size_);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GE(count, 0);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position_ -= count;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_returned_size_ = 0;  // Don't let caller back up further.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 ArrayOutputStream::ByteCount() const {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return position_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringOutputStream::StringOutputStream(string* target)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : target_(target) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringOutputStream::~StringOutputStream() {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StringOutputStream::Next(void** data, int* size) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int old_size = target_->size();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Grow the string.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_size < target_->capacity()) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Resize the string to match its capacity, since we can get away
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // without a memory allocation this way.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLStringResizeUninitialized(target_, target_->capacity());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Size has reached capacity, so double the size.  Also make sure
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that the new size is at least kMinimumSize.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLStringResizeUninitialized(
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max(old_size * 2,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *data = string_as_array(target_) + old_size;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *size = target_->size() - old_size;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StringOutputStream::BackUp(int count) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GE(count, 0);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_LE(count, target_->size());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_->resize(target_->size() - count);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 StringOutputStream::ByteCount() const {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return target_->size();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CopyingInputStream::~CopyingInputStream() {}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CopyingInputStream::Skip(int count) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char junk[4096];
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int skipped = 0;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (skipped < count) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int bytes = Read(junk, min(count - skipped,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               implicit_cast<int>(sizeof(junk))));
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bytes <= 0) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // EOF or read error.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return skipped;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    skipped += bytes;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return skipped;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CopyingInputStream* copying_stream, int block_size)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : copying_stream_(copying_stream),
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    owns_copying_stream_(false),
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    failed_(false),
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_(0),
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_used_(0),
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backup_bytes_(0) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (owns_copying_stream_) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete copying_stream_;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (failed_) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Already failed on a previous read.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AllocateBufferIfNeeded();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (backup_bytes_ > 0) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have data left over from a previous BackUp(), so just return that.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *data = buffer_.get() + buffer_used_ - backup_bytes_;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *size = backup_bytes_;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backup_bytes_ = 0;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read new data into the buffer.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_used_ <= 0) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // EOF or read error.  We don't need the buffer anymore.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffer_used_ < 0) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Read error (not EOF).
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      failed_ = true;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FreeBuffer();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position_ += buffer_used_;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *size = buffer_used_;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *data = buffer_.get();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyingInputStreamAdaptor::BackUp(int count) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << " BackUp() can only be called after Next().";
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_LE(count, buffer_used_)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << " Can't back up over more bytes than were returned by the last call"
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " to Next().";
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GE(count, 0)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << " Parameter to BackUp() can't be negative.";
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backup_bytes_ = count;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CopyingInputStreamAdaptor::Skip(int count) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GE(count, 0);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (failed_) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Already failed on a previous read.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First skip any bytes left over from a previous BackUp().
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (backup_bytes_ >= count) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have more data left over than we're trying to skip.  Just chop it.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backup_bytes_ -= count;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  count -= backup_bytes_;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backup_bytes_ = 0;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int skipped = copying_stream_->Skip(count);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position_ += skipped;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return skipped == count;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 CopyingInputStreamAdaptor::ByteCount() const {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return position_ - backup_bytes_;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_.get() == NULL) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_.reset(new uint8[buffer_size_]);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyingInputStreamAdaptor::FreeBuffer() {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_EQ(backup_bytes_, 0);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_used_ = 0;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_.reset();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CopyingOutputStream::~CopyingOutputStream() {}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CopyingOutputStream* copying_stream, int block_size)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : copying_stream_(copying_stream),
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    owns_copying_stream_(false),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    failed_(false),
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_(0),
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_used_(0) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteBuffer();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (owns_copying_stream_) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete copying_stream_;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CopyingOutputStreamAdaptor::Flush() {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WriteBuffer();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_used_ == buffer_size_) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!WriteBuffer()) return false;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AllocateBufferIfNeeded();
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *data = buffer_.get() + buffer_used_;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *size = buffer_size_ - buffer_used_;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_used_ = buffer_size_;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyingOutputStreamAdaptor::BackUp(int count) {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_GE(count, 0);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << " BackUp() can only be called after Next().";
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_CHECK_LE(count, buffer_used_)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << " Can't back up over more bytes than were returned by the last call"
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " to Next().";
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_used_ -= count;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 CopyingOutputStreamAdaptor::ByteCount() const {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return position_ + buffer_used_;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CopyingOutputStreamAdaptor::WriteBuffer() {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (failed_) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Already failed on a previous write.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_used_ == 0) return true;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    position_ += buffer_used_;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_used_ = 0;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    failed_ = true;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FreeBuffer();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_ == NULL) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_.reset(new uint8[buffer_size_]);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyingOutputStreamAdaptor::FreeBuffer() {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_used_ = 0;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_.reset();
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace io
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protobuf
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace google
396