1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc.  All rights reserved.
3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// http://code.google.com/p/protobuf/
4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without
6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are
7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met:
8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions of source code must retain the above copyright
10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer.
11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions in binary form must reproduce the above
12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer
13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the
14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution.
15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Neither the name of Google Inc. nor the names of its
16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from
17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission.
18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Author: kenton@google.com (Kenton Varda)
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//  Based on original Protocol Buffers design by
33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//  Sanjay Ghemawat, Jeff Dean, and others.
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _MSC_VER
36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <io.h>
37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else
38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <unistd.h>
39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/types.h>
40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/stat.h>
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <fcntl.h>
42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <errno.h>
44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <iostream>
45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <algorithm>
46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/zero_copy_stream_impl.h>
48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/common.h>
49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/stl_util-inl.h>
50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google {
52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf {
53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace io {
54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32
56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Win32 lseek is broken:  If invoked on a non-seekable file descriptor, its
57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// return value is undefined.  We re-define it to always produce an error.
58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define lseek(fd, offset, origin) ((off_t)-1)
59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace {
62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// EINTR sucks.
64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint close_no_eintr(int fd) {
65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int result;
66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  do {
67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    result = close(fd);
68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } while (result < 0 && errno == EINTR);
69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace
73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFileInputStream::FileInputStream(int file_descriptor, int block_size)
78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : copying_input_(file_descriptor),
79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    impl_(&copying_input_, block_size) {
80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFileInputStream::~FileInputStream() {}
83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FileInputStream::Close() {
85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return copying_input_.Close();
86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FileInputStream::Next(const void** data, int* size) {
89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.Next(data, size);
90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid FileInputStream::BackUp(int count) {
93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  impl_.BackUp(count);
94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FileInputStream::Skip(int count) {
97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.Skip(count);
98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint64 FileInputStream::ByteCount() const {
101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.ByteCount();
102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFileInputStream::CopyingFileInputStream::CopyingFileInputStream(
105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    int file_descriptor)
106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : file_(file_descriptor),
107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    close_on_delete_(false),
108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    is_closed_(false),
109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    errno_(0),
110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    previous_seek_failed_(false) {
111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFileInputStream::CopyingFileInputStream::~CopyingFileInputStream() {
114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (close_on_delete_) {
115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (!Close()) {
116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_);
117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FileInputStream::CopyingFileInputStream::Close() {
122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(!is_closed_);
123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  is_closed_ = true;
125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (close_no_eintr(file_) != 0) {
126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // The docs on close() do not specify whether a file descriptor is still
127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // open after close() fails with EIO.  However, the glibc source code
128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // seems to indicate that it is not.
129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    errno_ = errno;
130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return false;
131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return true;
134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint FileInputStream::CopyingFileInputStream::Read(void* buffer, int size) {
137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(!is_closed_);
138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int result;
140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  do {
141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    result = read(file_, buffer, size);
142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } while (result < 0 && errno == EINTR);
143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (result < 0) {
145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // Read error (not EOF).
146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    errno_ = errno;
147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint FileInputStream::CopyingFileInputStream::Skip(int count) {
153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(!is_closed_);
154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (!previous_seek_failed_ &&
156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      lseek(file_, count, SEEK_CUR) != (off_t)-1) {
157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // Seek succeeded.
158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return count;
159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } else {
160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // Failed to seek.
161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // Note to self:  Don't seek again.  This file descriptor doesn't
163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // support it.
164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    previous_seek_failed_ = true;
165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // Use the default implementation.
167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return CopyingInputStream::Skip(count);
168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFileOutputStream::FileOutputStream(int file_descriptor, int block_size)
174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : copying_output_(file_descriptor),
175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    impl_(&copying_output_, block_size) {
176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFileOutputStream::~FileOutputStream() {
179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  impl_.Flush();
180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FileOutputStream::Close() {
183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  bool flush_succeeded = impl_.Flush();
184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return copying_output_.Close() && flush_succeeded;
185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FileOutputStream::Flush() {
188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.Flush();
189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FileOutputStream::Next(void** data, int* size) {
192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.Next(data, size);
193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid FileOutputStream::BackUp(int count) {
196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  impl_.BackUp(count);
197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint64 FileOutputStream::ByteCount() const {
200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.ByteCount();
201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream(
204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    int file_descriptor)
205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : file_(file_descriptor),
206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    close_on_delete_(false),
207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    is_closed_(false),
208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    errno_(0) {
209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream() {
212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (close_on_delete_) {
213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (!Close()) {
214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_);
215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FileOutputStream::CopyingFileOutputStream::Close() {
220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(!is_closed_);
221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  is_closed_ = true;
223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (close_no_eintr(file_) != 0) {
224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // The docs on close() do not specify whether a file descriptor is still
225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // open after close() fails with EIO.  However, the glibc source code
226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // seems to indicate that it is not.
227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    errno_ = errno;
228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return false;
229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return true;
232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FileOutputStream::CopyingFileOutputStream::Write(
235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const void* buffer, int size) {
236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_CHECK(!is_closed_);
237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int total_written = 0;
238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const uint8* buffer_base = reinterpret_cast<const uint8*>(buffer);
240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  while (total_written < size) {
242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    int bytes;
243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    do {
244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bytes = write(file_, buffer_base + total_written, size - total_written);
245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    } while (bytes < 0 && errno == EINTR);
246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (bytes <= 0) {
248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Write error.
249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // FIXME(kenton):  According to the man page, if write() returns zero,
251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      //   there was no error; write() simply did not write anything.  It's
252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      //   unclear under what circumstances this might happen, but presumably
253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      //   errno won't be set in this case.  I am confused as to how such an
254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      //   event should be handled.  For now I'm treating it as an error, since
255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      //   retrying seems like it could lead to an infinite loop.  I suspect
256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      //   this never actually happens anyway.
257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      if (bytes < 0) {
259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        errno_ = errno;
260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return false;
262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    total_written += bytes;
264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return true;
267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleIstreamInputStream::IstreamInputStream(istream* input, int block_size)
272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : copying_input_(input),
273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    impl_(&copying_input_, block_size) {
274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleIstreamInputStream::~IstreamInputStream() {}
277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool IstreamInputStream::Next(const void** data, int* size) {
279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.Next(data, size);
280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid IstreamInputStream::BackUp(int count) {
283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  impl_.BackUp(count);
284fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
286fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool IstreamInputStream::Skip(int count) {
287fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.Skip(count);
288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint64 IstreamInputStream::ByteCount() const {
291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.ByteCount();
292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleIstreamInputStream::CopyingIstreamInputStream::CopyingIstreamInputStream(
295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    istream* input)
296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : input_(input) {
297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleIstreamInputStream::CopyingIstreamInputStream::~CopyingIstreamInputStream() {}
300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint IstreamInputStream::CopyingIstreamInputStream::Read(
302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    void* buffer, int size) {
303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  input_->read(reinterpret_cast<char*>(buffer), size);
304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int result = input_->gcount();
305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (result == 0 && input_->fail() && !input_->eof()) {
306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return -1;
307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleOstreamOutputStream::OstreamOutputStream(ostream* output, int block_size)
314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : copying_output_(output),
315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    impl_(&copying_output_, block_size) {
316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleOstreamOutputStream::~OstreamOutputStream() {
319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  impl_.Flush();
320fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
321fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
322fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool OstreamOutputStream::Next(void** data, int* size) {
323fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.Next(data, size);
324fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
325fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid OstreamOutputStream::BackUp(int count) {
327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  impl_.BackUp(count);
328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint64 OstreamOutputStream::ByteCount() const {
331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return impl_.ByteCount();
332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
334fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleOstreamOutputStream::CopyingOstreamOutputStream::CopyingOstreamOutputStream(
335fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ostream* output)
336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : output_(output) {
337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleOstreamOutputStream::CopyingOstreamOutputStream::~CopyingOstreamOutputStream() {
340fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
341fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
342fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool OstreamOutputStream::CopyingOstreamOutputStream::Write(
343fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const void* buffer, int size) {
344fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  output_->write(reinterpret_cast<const char*>(buffer), size);
345fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return output_->good();
346fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
347fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
348fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
349fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
350fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleConcatenatingInputStream::ConcatenatingInputStream(
351fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ZeroCopyInputStream* const streams[], int count)
352fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : streams_(streams), stream_count_(count), bytes_retired_(0) {
353fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
354fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
355fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleConcatenatingInputStream::~ConcatenatingInputStream() {
356fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
357fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool ConcatenatingInputStream::Next(const void** data, int* size) {
359fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  while (stream_count_ > 0) {
360fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (streams_[0]->Next(data, size)) return true;
361fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
362fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // That stream is done.  Advance to the next one.
363fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    bytes_retired_ += streams_[0]->ByteCount();
364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ++streams_;
365fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    --stream_count_;
366fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
367fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
368fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // No more streams.
369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return false;
370fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
371fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
372fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid ConcatenatingInputStream::BackUp(int count) {
373fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (stream_count_ > 0) {
374fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    streams_[0]->BackUp(count);
375fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } else {
376fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    GOOGLE_LOG(DFATAL) << "Can't BackUp() after failed Next().";
377fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
378fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
379fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
380fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool ConcatenatingInputStream::Skip(int count) {
381fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  while (stream_count_ > 0) {
382fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // Assume that ByteCount() can be used to find out how much we actually
383fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // skipped when Skip() fails.
384fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    int64 target_byte_count = streams_[0]->ByteCount() + count;
385fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (streams_[0]->Skip(count)) return true;
386fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
387fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // Hit the end of the stream.  Figure out how many more bytes we still have
388fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // to skip.
389fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    int64 final_byte_count = streams_[0]->ByteCount();
390fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    GOOGLE_DCHECK_LT(final_byte_count, target_byte_count);
391fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    count = target_byte_count - final_byte_count;
392fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
393fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // That stream is done.  Advance to the next one.
394fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    bytes_retired_ += final_byte_count;
395fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ++streams_;
396fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    --stream_count_;
397fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
398fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
399fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return false;
400fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
401fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
402fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint64 ConcatenatingInputStream::ByteCount() const {
403fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (stream_count_ == 0) {
404fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return bytes_retired_;
405fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } else {
406fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return bytes_retired_ + streams_[0]->ByteCount();
407fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
408fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
409fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
410fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
411fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
412fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
413fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleLimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input,
414fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                                         int64 limit)
415fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : input_(input), limit_(limit) {}
416fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
417fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleLimitingInputStream::~LimitingInputStream() {
418fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // If we overshot the limit, back up.
419fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (limit_ < 0) input_->BackUp(-limit_);
420fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
421fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
422fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool LimitingInputStream::Next(const void** data, int* size) {
423fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (limit_ <= 0) return false;
424fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (!input_->Next(data, size)) return false;
425fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
426fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  limit_ -= *size;
427fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (limit_ < 0) {
428fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // We overshot the limit.  Reduce *size to hide the rest of the buffer.
429fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    *size += limit_;
430fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
431fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return true;
432fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
433fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
434fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid LimitingInputStream::BackUp(int count) {
435fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (limit_ < 0) {
436fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    input_->BackUp(count - limit_);
437fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    limit_ = count;
438fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } else {
439fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    input_->BackUp(count);
440fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    limit_ += count;
441fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
442fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
443fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
444fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool LimitingInputStream::Skip(int count) {
445fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (count > limit_) {
446fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (limit_ < 0) return false;
447fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    input_->Skip(limit_);
448fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    limit_ = 0;
449fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return false;
450fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } else {
451fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (!input_->Skip(count)) return false;
452fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    limit_ -= count;
453fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return true;
454fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
455fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
456fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
457fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint64 LimitingInputStream::ByteCount() const {
458fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (limit_ < 0) {
459fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return input_->ByteCount() + limit_;
460fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } else {
461fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return input_->ByteCount();
462fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
463fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
464fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
465fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
466fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
467fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
468fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace io
469fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace protobuf
470fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace google
471