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