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