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