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 // This file contains common implementations of the interfaces defined in 36 // zero_copy_stream.h which are only included in the full (non-lite) 37 // protobuf library. These implementations include Unix file descriptors 38 // and C++ iostreams. See also: zero_copy_stream_impl_lite.h 39 40 #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ 41 #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ 42 43 44 #include <iosfwd> 45 #include <string> 46 47 #include <google/protobuf/stubs/common.h> 48 #include <google/protobuf/io/zero_copy_stream.h> 49 #include <google/protobuf/io/zero_copy_stream_impl_lite.h> 50 51 #include <google/protobuf/port_def.inc> 52 53 namespace google { 54 namespace protobuf { 55 namespace io { 56 57 // =================================================================== 58 59 // A ZeroCopyInputStream which reads from a file descriptor. 60 // 61 // FileInputStream is preferred over using an ifstream with IstreamInputStream. 62 // The latter will introduce an extra layer of buffering, harming performance. 63 // Also, it's conceivable that FileInputStream could someday be enhanced 64 // to use zero-copy file descriptors on OSs which support them. 65 class PROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream { 66 public: 67 // Creates a stream that reads from the given Unix file descriptor. 68 // If a block_size is given, it specifies the number of bytes that 69 // should be read and returned with each call to Next(). Otherwise, 70 // a reasonable default is used. 71 explicit FileInputStream(int file_descriptor, int block_size = -1); 72 73 // Flushes any buffers and closes the underlying file. Returns false if 74 // an error occurs during the process; use GetErrno() to examine the error. 75 // Even if an error occurs, the file descriptor is closed when this returns. 76 bool Close(); 77 78 // By default, the file descriptor is not closed when the stream is 79 // destroyed. Call SetCloseOnDelete(true) to change that. WARNING: 80 // This leaves no way for the caller to detect if close() fails. If 81 // detecting close() errors is important to you, you should arrange 82 // to close the descriptor yourself. SetCloseOnDelete(bool value)83 void SetCloseOnDelete(bool value) { copying_input_.SetCloseOnDelete(value); } 84 85 // If an I/O error has occurred on this file descriptor, this is the 86 // errno from that error. Otherwise, this is zero. Once an error 87 // occurs, the stream is broken and all subsequent operations will 88 // fail. GetErrno()89 int GetErrno() const { return copying_input_.GetErrno(); } 90 91 // implements ZeroCopyInputStream ---------------------------------- 92 bool Next(const void** data, int* size) override; 93 void BackUp(int count) override; 94 bool Skip(int count) override; 95 int64_t ByteCount() const override; 96 97 private: 98 class PROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream { 99 public: 100 CopyingFileInputStream(int file_descriptor); 101 ~CopyingFileInputStream() override; 102 103 bool Close(); SetCloseOnDelete(bool value)104 void SetCloseOnDelete(bool value) { close_on_delete_ = value; } GetErrno()105 int GetErrno() const { return errno_; } 106 107 // implements CopyingInputStream --------------------------------- 108 int Read(void* buffer, int size) override; 109 int Skip(int count) override; 110 111 private: 112 // The file descriptor. 113 const int file_; 114 bool close_on_delete_; 115 bool is_closed_; 116 117 // The errno of the I/O error, if one has occurred. Otherwise, zero. 118 int errno_; 119 120 // Did we try to seek once and fail? If so, we assume this file descriptor 121 // doesn't support seeking and won't try again. 122 bool previous_seek_failed_; 123 124 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream); 125 }; 126 127 CopyingFileInputStream copying_input_; 128 CopyingInputStreamAdaptor impl_; 129 130 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream); 131 }; 132 133 // =================================================================== 134 135 // A ZeroCopyOutputStream which writes to a file descriptor. 136 // 137 // FileOutputStream is preferred over using an ofstream with 138 // OstreamOutputStream. The latter will introduce an extra layer of buffering, 139 // harming performance. Also, it's conceivable that FileOutputStream could 140 // someday be enhanced to use zero-copy file descriptors on OSs which 141 // support them. 142 class PROTOBUF_EXPORT FileOutputStream : public CopyingOutputStreamAdaptor { 143 public: 144 // Creates a stream that writes to the given Unix file descriptor. 145 // If a block_size is given, it specifies the size of the buffers 146 // that should be returned by Next(). Otherwise, a reasonable default 147 // is used. 148 explicit FileOutputStream(int file_descriptor, int block_size = -1); 149 150 ~FileOutputStream() override; 151 152 // Flushes any buffers and closes the underlying file. Returns false if 153 // an error occurs during the process; use GetErrno() to examine the error. 154 // Even if an error occurs, the file descriptor is closed when this returns. 155 bool Close(); 156 157 // By default, the file descriptor is not closed when the stream is 158 // destroyed. Call SetCloseOnDelete(true) to change that. WARNING: 159 // This leaves no way for the caller to detect if close() fails. If 160 // detecting close() errors is important to you, you should arrange 161 // to close the descriptor yourself. SetCloseOnDelete(bool value)162 void SetCloseOnDelete(bool value) { copying_output_.SetCloseOnDelete(value); } 163 164 // If an I/O error has occurred on this file descriptor, this is the 165 // errno from that error. Otherwise, this is zero. Once an error 166 // occurs, the stream is broken and all subsequent operations will 167 // fail. GetErrno()168 int GetErrno() const { return copying_output_.GetErrno(); } 169 170 private: 171 class PROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream { 172 public: 173 CopyingFileOutputStream(int file_descriptor); 174 ~CopyingFileOutputStream() override; 175 176 bool Close(); SetCloseOnDelete(bool value)177 void SetCloseOnDelete(bool value) { close_on_delete_ = value; } GetErrno()178 int GetErrno() const { return errno_; } 179 180 // implements CopyingOutputStream -------------------------------- 181 bool Write(const void* buffer, int size) override; 182 183 private: 184 // The file descriptor. 185 const int file_; 186 bool close_on_delete_; 187 bool is_closed_; 188 189 // The errno of the I/O error, if one has occurred. Otherwise, zero. 190 int errno_; 191 192 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream); 193 }; 194 195 CopyingFileOutputStream copying_output_; 196 197 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream); 198 }; 199 200 // =================================================================== 201 202 // A ZeroCopyInputStream which reads from a C++ istream. 203 // 204 // Note that for reading files (or anything represented by a file descriptor), 205 // FileInputStream is more efficient. 206 class PROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream { 207 public: 208 // Creates a stream that reads from the given C++ istream. 209 // If a block_size is given, it specifies the number of bytes that 210 // should be read and returned with each call to Next(). Otherwise, 211 // a reasonable default is used. 212 explicit IstreamInputStream(std::istream* stream, int block_size = -1); 213 214 // implements ZeroCopyInputStream ---------------------------------- 215 bool Next(const void** data, int* size) override; 216 void BackUp(int count) override; 217 bool Skip(int count) override; 218 int64_t ByteCount() const override; 219 220 private: 221 class PROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream { 222 public: 223 CopyingIstreamInputStream(std::istream* input); 224 ~CopyingIstreamInputStream() override; 225 226 // implements CopyingInputStream --------------------------------- 227 int Read(void* buffer, int size) override; 228 // (We use the default implementation of Skip().) 229 230 private: 231 // The stream. 232 std::istream* input_; 233 234 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream); 235 }; 236 237 CopyingIstreamInputStream copying_input_; 238 CopyingInputStreamAdaptor impl_; 239 240 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream); 241 }; 242 243 // =================================================================== 244 245 // A ZeroCopyOutputStream which writes to a C++ ostream. 246 // 247 // Note that for writing files (or anything represented by a file descriptor), 248 // FileOutputStream is more efficient. 249 class PROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream { 250 public: 251 // Creates a stream that writes to the given C++ ostream. 252 // If a block_size is given, it specifies the size of the buffers 253 // that should be returned by Next(). Otherwise, a reasonable default 254 // is used. 255 explicit OstreamOutputStream(std::ostream* stream, int block_size = -1); 256 ~OstreamOutputStream() override; 257 258 // implements ZeroCopyOutputStream --------------------------------- 259 bool Next(void** data, int* size) override; 260 void BackUp(int count) override; 261 int64_t ByteCount() const override; 262 263 private: 264 class PROTOBUF_EXPORT CopyingOstreamOutputStream 265 : public CopyingOutputStream { 266 public: 267 CopyingOstreamOutputStream(std::ostream* output); 268 ~CopyingOstreamOutputStream() override; 269 270 // implements CopyingOutputStream -------------------------------- 271 bool Write(const void* buffer, int size) override; 272 273 private: 274 // The stream. 275 std::ostream* output_; 276 277 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream); 278 }; 279 280 CopyingOstreamOutputStream copying_output_; 281 CopyingOutputStreamAdaptor impl_; 282 283 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream); 284 }; 285 286 // =================================================================== 287 288 // A ZeroCopyInputStream which reads from several other streams in sequence. 289 // ConcatenatingInputStream is unable to distinguish between end-of-stream 290 // and read errors in the underlying streams, so it assumes any errors mean 291 // end-of-stream. So, if the underlying streams fail for any other reason, 292 // ConcatenatingInputStream may do odd things. It is suggested that you do 293 // not use ConcatenatingInputStream on streams that might produce read errors 294 // other than end-of-stream. 295 class PROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream { 296 public: 297 // All streams passed in as well as the array itself must remain valid 298 // until the ConcatenatingInputStream is destroyed. 299 ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count); 300 ~ConcatenatingInputStream() override = default; 301 302 // implements ZeroCopyInputStream ---------------------------------- 303 bool Next(const void** data, int* size) override; 304 void BackUp(int count) override; 305 bool Skip(int count) override; 306 int64_t ByteCount() const override; 307 308 309 private: 310 // As streams are retired, streams_ is incremented and count_ is 311 // decremented. 312 ZeroCopyInputStream* const* streams_; 313 int stream_count_; 314 int64 bytes_retired_; // Bytes read from previous streams. 315 316 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream); 317 }; 318 319 // =================================================================== 320 321 } // namespace io 322 } // namespace protobuf 323 } // namespace google 324 325 #include <google/protobuf/port_undef.inc> 326 327 #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ 328