zero_copy_stream_impl.cc
Go to the documentation of this file.
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 #ifndef _MSC_VER
36 #include <fcntl.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40 #endif
41 #include <errno.h>
42 #include <algorithm>
43 #include <iostream>
49 
50 
51 namespace google {
52 namespace protobuf {
53 namespace io {
54 
55 #ifdef _WIN32
56 // Win32 lseek is broken: If invoked on a non-seekable file descriptor, its
57 // return value is undefined. We re-define it to always produce an error.
58 #define lseek(fd, offset, origin) ((off_t)-1)
59 // DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
60 // them like we do below.
62 using google::protobuf::io::win32::close;
63 using google::protobuf::io::win32::open;
64 using google::protobuf::io::win32::read;
65 using google::protobuf::io::win32::write;
66 #endif
67 
68 namespace {
69 
70 // EINTR sucks.
71 int close_no_eintr(int fd) {
72  int result;
73  do {
74  result = close(fd);
75  } while (result < 0 && errno == EINTR);
76  return result;
77 }
78 
79 } // namespace
80 
81 // ===================================================================
82 
83 FileInputStream::FileInputStream(int file_descriptor, int block_size)
84  : copying_input_(file_descriptor), impl_(&copying_input_, block_size) {}
85 
87 
88 bool FileInputStream::Next(const void** data, int* size) {
89  return impl_.Next(data, size);
90 }
91 
93 
94 bool FileInputStream::Skip(int count) { return impl_.Skip(count); }
95 
97 
99  int file_descriptor)
100  : file_(file_descriptor),
101  close_on_delete_(false),
102  is_closed_(false),
103  errno_(0),
104  previous_seek_failed_(false) {}
105 
107  if (close_on_delete_) {
108  if (!Close()) {
109  GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_);
110  }
111  }
112 }
113 
115  GOOGLE_CHECK(!is_closed_);
116 
117  is_closed_ = true;
118  if (close_no_eintr(file_) != 0) {
119  // The docs on close() do not specify whether a file descriptor is still
120  // open after close() fails with EIO. However, the glibc source code
121  // seems to indicate that it is not.
122  errno_ = errno;
123  return false;
124  }
125 
126  return true;
127 }
128 
130  GOOGLE_CHECK(!is_closed_);
131 
132  int result;
133  do {
134  result = read(file_, buffer, size);
135  } while (result < 0 && errno == EINTR);
136 
137  if (result < 0) {
138  // Read error (not EOF).
139  errno_ = errno;
140  }
141 
142  return result;
143 }
144 
146  GOOGLE_CHECK(!is_closed_);
147 
148  if (!previous_seek_failed_ && lseek(file_, count, SEEK_CUR) != (off_t)-1) {
149  // Seek succeeded.
150  return count;
151  } else {
152  // Failed to seek.
153 
154  // Note to self: Don't seek again. This file descriptor doesn't
155  // support it.
156  previous_seek_failed_ = true;
157 
158  // Use the default implementation.
160  }
161 }
162 
163 // ===================================================================
164 
165 FileOutputStream::FileOutputStream(int file_descriptor, int block_size)
166  : copying_output_(file_descriptor), impl_(&copying_output_, block_size) {}
167 
169 
171  bool flush_succeeded = impl_.Flush();
172  return copying_output_.Close() && flush_succeeded;
173 }
174 
175 bool FileOutputStream::Flush() { return impl_.Flush(); }
176 
177 bool FileOutputStream::Next(void** data, int* size) {
178  return impl_.Next(data, size);
179 }
180 
182 
184 
186  int file_descriptor)
187  : file_(file_descriptor),
188  close_on_delete_(false),
189  is_closed_(false),
190  errno_(0) {}
191 
193  if (close_on_delete_) {
194  if (!Close()) {
195  GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_);
196  }
197  }
198 }
199 
201  GOOGLE_CHECK(!is_closed_);
202 
203  is_closed_ = true;
204  if (close_no_eintr(file_) != 0) {
205  // The docs on close() do not specify whether a file descriptor is still
206  // open after close() fails with EIO. However, the glibc source code
207  // seems to indicate that it is not.
208  errno_ = errno;
209  return false;
210  }
211 
212  return true;
213 }
214 
216  int size) {
217  GOOGLE_CHECK(!is_closed_);
218  int total_written = 0;
219 
220  const uint8* buffer_base = reinterpret_cast<const uint8*>(buffer);
221 
222  while (total_written < size) {
223  int bytes;
224  do {
225  bytes = write(file_, buffer_base + total_written, size - total_written);
226  } while (bytes < 0 && errno == EINTR);
227 
228  if (bytes <= 0) {
229  // Write error.
230 
231  // FIXME(kenton): According to the man page, if write() returns zero,
232  // there was no error; write() simply did not write anything. It's
233  // unclear under what circumstances this might happen, but presumably
234  // errno won't be set in this case. I am confused as to how such an
235  // event should be handled. For now I'm treating it as an error, since
236  // retrying seems like it could lead to an infinite loop. I suspect
237  // this never actually happens anyway.
238 
239  if (bytes < 0) {
240  errno_ = errno;
241  }
242  return false;
243  }
244  total_written += bytes;
245  }
246 
247  return true;
248 }
249 
250 // ===================================================================
251 
252 IstreamInputStream::IstreamInputStream(std::istream* input, int block_size)
253  : copying_input_(input), impl_(&copying_input_, block_size) {}
254 
255 bool IstreamInputStream::Next(const void** data, int* size) {
256  return impl_.Next(data, size);
257 }
258 
260 
262 
264 
266  std::istream* input)
267  : input_(input) {}
268 
270 
272  int size) {
273  input_->read(reinterpret_cast<char*>(buffer), size);
274  int result = input_->gcount();
275  if (result == 0 && input_->fail() && !input_->eof()) {
276  return -1;
277  }
278  return result;
279 }
280 
281 // ===================================================================
282 
283 OstreamOutputStream::OstreamOutputStream(std::ostream* output, int block_size)
284  : copying_output_(output), impl_(&copying_output_, block_size) {}
285 
287 
288 bool OstreamOutputStream::Next(void** data, int* size) {
289  return impl_.Next(data, size);
290 }
291 
293 
295 
297  std::ostream* output)
298  : output_(output) {}
299 
301 }
302 
304  int size) {
305  output_->write(reinterpret_cast<const char*>(buffer), size);
306  return output_->good();
307 }
308 
309 // ===================================================================
310 
312  ZeroCopyInputStream* const streams[], int count)
313  : streams_(streams), stream_count_(count), bytes_retired_(0) {
314 }
315 
316 bool ConcatenatingInputStream::Next(const void** data, int* size) {
317  while (stream_count_ > 0) {
318  if (streams_[0]->Next(data, size)) return true;
319 
320  // That stream is done. Advance to the next one.
322  ++streams_;
323  --stream_count_;
324  }
325 
326  // No more streams.
327  return false;
328 }
329 
331  if (stream_count_ > 0) {
332  streams_[0]->BackUp(count);
333  } else {
334  GOOGLE_LOG(DFATAL) << "Can't BackUp() after failed Next().";
335  }
336 }
337 
339  while (stream_count_ > 0) {
340  // Assume that ByteCount() can be used to find out how much we actually
341  // skipped when Skip() fails.
342  int64 target_byte_count = streams_[0]->ByteCount() + count;
343  if (streams_[0]->Skip(count)) return true;
344 
345  // Hit the end of the stream. Figure out how many more bytes we still have
346  // to skip.
347  int64 final_byte_count = streams_[0]->ByteCount();
348  GOOGLE_DCHECK_LT(final_byte_count, target_byte_count);
349  count = target_byte_count - final_byte_count;
350 
351  // That stream is done. Advance to the next one.
352  bytes_retired_ += final_byte_count;
353  ++streams_;
354  --stream_count_;
355  }
356 
357  return false;
358 }
359 
361  if (stream_count_ == 0) {
362  return bytes_retired_;
363  } else {
364  return bytes_retired_ + streams_[0]->ByteCount();
365  }
366 }
367 
368 
369 // ===================================================================
370 
371 } // namespace io
372 } // namespace protobuf
373 } // namespace google
google::protobuf::io::FileOutputStream::Flush
bool Flush()
Definition: zero_copy_stream_impl.cc:175
google::protobuf::io::FileOutputStream::copying_output_
CopyingFileOutputStream copying_output_
Definition: zero_copy_stream_impl.h:203
google::protobuf::io::ConcatenatingInputStream::ByteCount
int64 ByteCount() const override
Definition: zero_copy_stream_impl.cc:360
google::protobuf::io::IstreamInputStream::IstreamInputStream
IstreamInputStream(std::istream *stream, int block_size=-1)
Definition: zero_copy_stream_impl.cc:252
google::protobuf::io::FileOutputStream::CopyingFileOutputStream::Write
bool Write(const void *buffer, int size) override
Definition: zero_copy_stream_impl.cc:215
google::protobuf::io::CopyingInputStreamAdaptor::Next
bool Next(const void **data, int *size) override
Definition: zero_copy_stream_impl_lite.cc:217
google::protobuf::io::FileOutputStream::Next
bool Next(void **data, int *size) override
Definition: zero_copy_stream_impl.cc:177
google::protobuf::io::FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream
CopyingFileOutputStream(int file_descriptor)
Definition: zero_copy_stream_impl.cc:185
zero_copy_stream_impl.h
input_
std::unique_ptr< io::Tokenizer > input_
Definition: parser_unittest.cc:186
google::protobuf::io::ConcatenatingInputStream::BackUp
void BackUp(int count) override
Definition: zero_copy_stream_impl.cc:330
google::protobuf::int64
int64_t int64
Definition: protobuf/src/google/protobuf/stubs/port.h:151
EINTR
#define EINTR
Definition: errno.hpp:7
input
std::string input
Definition: tokenizer_unittest.cc:197
google::protobuf::io::ConcatenatingInputStream::ConcatenatingInputStream
ConcatenatingInputStream(ZeroCopyInputStream *const streams[], int count)
Definition: zero_copy_stream_impl.cc:311
google::protobuf::uint8
uint8_t uint8
Definition: protobuf/src/google/protobuf/stubs/port.h:153
google::protobuf::io::OstreamOutputStream::OstreamOutputStream
OstreamOutputStream(std::ostream *stream, int block_size=-1)
Definition: zero_copy_stream_impl.cc:283
google::protobuf::io::FileOutputStream::BackUp
void BackUp(int count) override
Definition: zero_copy_stream_impl.cc:181
errno
int errno
google::protobuf::io::FileInputStream::ByteCount
int64 ByteCount() const override
Definition: zero_copy_stream_impl.cc:96
google::protobuf::io::ZeroCopyInputStream::ByteCount
virtual int64 ByteCount() const =0
google::protobuf::io::FileInputStream::impl_
CopyingInputStreamAdaptor impl_
Definition: zero_copy_stream_impl.h:127
google::protobuf::io::OstreamOutputStream::CopyingOstreamOutputStream::~CopyingOstreamOutputStream
~CopyingOstreamOutputStream() override
Definition: zero_copy_stream_impl.cc:300
bytes
uint8 bytes[10]
Definition: coded_stream_unittest.cc:153
google::protobuf::io::OstreamOutputStream::Next
bool Next(void **data, int *size) override
Definition: zero_copy_stream_impl.cc:288
output_
std::string output_
Definition: text_format.cc:1531
google::protobuf::io::FileInputStream::Next
bool Next(const void **data, int *size) override
Definition: zero_copy_stream_impl.cc:88
google::protobuf::io::CopyingInputStreamAdaptor::Skip
bool Skip(int count) override
Definition: zero_copy_stream_impl_lite.cc:262
google::protobuf::io::ConcatenatingInputStream::bytes_retired_
int64 bytes_retired_
Definition: zero_copy_stream_impl.h:323
access
GLuint GLint GLboolean GLint GLenum access
Definition: glcorearb.h:4266
google::protobuf::io::ConcatenatingInputStream::streams_
ZeroCopyInputStream *const * streams_
Definition: zero_copy_stream_impl.h:321
google::protobuf::io::ConcatenatingInputStream::stream_count_
int stream_count_
Definition: zero_copy_stream_impl.h:322
google::protobuf::io::FileInputStream::Close
bool Close()
Definition: zero_copy_stream_impl.cc:86
google::protobuf::io::CopyingOutputStreamAdaptor::Next
bool Next(void **data, int *size) override
Definition: zero_copy_stream_impl_lite.cc:321
google::protobuf::io::FileInputStream::CopyingFileInputStream::Skip
int Skip(int count) override
Definition: zero_copy_stream_impl.cc:145
buffer
GLuint buffer
Definition: glcorearb.h:2939
google::protobuf::io::ConcatenatingInputStream::Next
bool Next(const void **data, int *size) override
Definition: zero_copy_stream_impl.cc:316
google::protobuf::io::IstreamInputStream::Skip
bool Skip(int count) override
Definition: zero_copy_stream_impl.cc:261
google::protobuf::io::FileOutputStream::CopyingFileOutputStream::Close
bool Close()
Definition: zero_copy_stream_impl.cc:200
google::protobuf::io::FileInputStream::FileInputStream
FileInputStream(int file_descriptor, int block_size=-1)
Definition: zero_copy_stream_impl.cc:83
GOOGLE_LOG
#define GOOGLE_LOG(LEVEL)
Definition: logging.h:146
google::protobuf::io::OstreamOutputStream::impl_
CopyingOutputStreamAdaptor impl_
Definition: zero_copy_stream_impl.h:290
google::protobuf::io::CopyingInputStreamAdaptor::ByteCount
int64 ByteCount() const override
Definition: zero_copy_stream_impl_lite.cc:285
google::protobuf::io::OstreamOutputStream::BackUp
void BackUp(int count) override
Definition: zero_copy_stream_impl.cc:292
google::protobuf::io::FileOutputStream::~FileOutputStream
~FileOutputStream() override
Definition: zero_copy_stream_impl.cc:168
buffer
Definition: buffer_processor.h:43
google::protobuf::io::FileInputStream::copying_input_
CopyingFileInputStream copying_input_
Definition: zero_copy_stream_impl.h:126
google::protobuf::io::IstreamInputStream::CopyingIstreamInputStream::~CopyingIstreamInputStream
~CopyingIstreamInputStream() override
Definition: zero_copy_stream_impl.cc:269
google::protobuf::ERROR
static const LogLevel ERROR
Definition: protobuf/src/google/protobuf/testing/googletest.h:70
google::protobuf::io::FileInputStream::CopyingFileInputStream::Read
int Read(void *buffer, int size) override
Definition: zero_copy_stream_impl.cc:129
GOOGLE_CHECK
#define GOOGLE_CHECK(EXPRESSION)
Definition: logging.h:153
google::protobuf::io::IstreamInputStream::ByteCount
int64 ByteCount() const override
Definition: zero_copy_stream_impl.cc:263
google::protobuf::io::ZeroCopyInputStream
Definition: zero_copy_stream.h:126
google::protobuf::io::OstreamOutputStream::~OstreamOutputStream
~OstreamOutputStream() override
Definition: zero_copy_stream_impl.cc:286
google::protobuf::io::CopyingOutputStreamAdaptor::Flush
bool Flush()
Definition: zero_copy_stream_impl_lite.cc:319
google::protobuf::io::FileOutputStream::ByteCount
int64 ByteCount() const override
Definition: zero_copy_stream_impl.cc:183
google::protobuf::io::CopyingOutputStreamAdaptor::BackUp
void BackUp(int count) override
Definition: zero_copy_stream_impl_lite.cc:334
common.h
google::protobuf::io::OstreamOutputStream::CopyingOstreamOutputStream::CopyingOstreamOutputStream
CopyingOstreamOutputStream(std::ostream *output)
Definition: zero_copy_stream_impl.cc:296
google::protobuf::io::IstreamInputStream::CopyingIstreamInputStream::Read
int Read(void *buffer, int size) override
Definition: zero_copy_stream_impl.cc:271
google::protobuf::io::ConcatenatingInputStream::Skip
bool Skip(int count) override
Definition: zero_copy_stream_impl.cc:338
google::protobuf::io::FileInputStream::CopyingFileInputStream::Close
bool Close()
Definition: zero_copy_stream_impl.cc:114
size
GLsizeiptr size
Definition: glcorearb.h:2943
stl_util.h
google::protobuf::io::CopyingOutputStreamAdaptor::ByteCount
int64 ByteCount() const override
Definition: zero_copy_stream_impl_lite.cc:345
logging.h
google::protobuf::io::IstreamInputStream::BackUp
void BackUp(int count) override
Definition: zero_copy_stream_impl.cc:259
google::protobuf::io::FileInputStream::Skip
bool Skip(int count) override
Definition: zero_copy_stream_impl.cc:94
google::protobuf::io::IstreamInputStream::Next
bool Next(const void **data, int *size) override
Definition: zero_copy_stream_impl.cc:255
strerror
char * strerror(int errno)
google::protobuf::io::IstreamInputStream::impl_
CopyingInputStreamAdaptor impl_
Definition: zero_copy_stream_impl.h:247
google::protobuf::io::FileOutputStream::Close
bool Close()
Definition: zero_copy_stream_impl.cc:170
io_win32.h
google::protobuf::io::IstreamInputStream::CopyingIstreamInputStream::CopyingIstreamInputStream
CopyingIstreamInputStream(std::istream *input)
Definition: zero_copy_stream_impl.cc:265
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: glcorearb.h:2879
GOOGLE_DCHECK_LT
#define GOOGLE_DCHECK_LT
Definition: logging.h:198
google::protobuf::io::FileInputStream::CopyingFileInputStream::~CopyingFileInputStream
~CopyingFileInputStream() override
Definition: zero_copy_stream_impl.cc:106
google::protobuf::io::ZeroCopyInputStream::BackUp
virtual void BackUp(int count)=0
google::protobuf::io::FileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream
~CopyingFileOutputStream() override
Definition: zero_copy_stream_impl.cc:192
google::protobuf::io::FileInputStream::CopyingFileInputStream::CopyingFileInputStream
CopyingFileInputStream(int file_descriptor)
Definition: zero_copy_stream_impl.cc:98
google::protobuf::io::CopyingInputStreamAdaptor::BackUp
void BackUp(int count) override
Definition: zero_copy_stream_impl_lite.cc:251
google::protobuf::io::FileInputStream::BackUp
void BackUp(int count) override
Definition: zero_copy_stream_impl.cc:92
google::protobuf::io::CopyingInputStream::Skip
virtual int Skip(int count)
Definition: zero_copy_stream_impl_lite.cc:186
output
const upb_json_parsermethod const upb_symtab upb_sink * output
Definition: ruby/ext/google/protobuf_c/upb.h:10503
count
GLint GLsizei count
Definition: glcorearb.h:2830
false
#define false
Definition: cJSON.c:70
file_
FileDescriptorProto * file_
Definition: annotation_test_util.cc:68
google
Definition: data_proto2_to_proto3_util.h:11
google::protobuf::io::OstreamOutputStream::CopyingOstreamOutputStream::Write
bool Write(const void *buffer, int size) override
Definition: zero_copy_stream_impl.cc:303
google::protobuf::io::FileOutputStream::FileOutputStream
FileOutputStream(int file_descriptor, int block_size=-1)
Definition: zero_copy_stream_impl.cc:165
google::protobuf::io::FileOutputStream::impl_
CopyingOutputStreamAdaptor impl_
Definition: zero_copy_stream_impl.h:204
google::protobuf::io::OstreamOutputStream::ByteCount
int64 ByteCount() const override
Definition: zero_copy_stream_impl.cc:294


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:07:02