1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // http://code.google.com/p/protobuf/ 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 <string> 44 #include <iosfwd> 45 #include <google/protobuf/io/zero_copy_stream.h> 46 #include <google/protobuf/io/zero_copy_stream_impl_lite.h> 47 #include <google/protobuf/stubs/common.h> 48 49 50 namespace google { 51 namespace protobuf { 52 namespace io { 53 54 55 // =================================================================== 56 57 // A ZeroCopyInputStream which reads from a file descriptor. 58 // 59 // FileInputStream is preferred over using an ifstream with IstreamInputStream. 60 // The latter will introduce an extra layer of buffering, harming performance. 61 // Also, it's conceivable that FileInputStream could someday be enhanced 62 // to use zero-copy file descriptors on OSs which support them. 63 class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream { 64 public: 65 // Creates a stream that reads from the given Unix file descriptor. 66 // If a block_size is given, it specifies the number of bytes that 67 // should be read and returned with each call to Next(). Otherwise, 68 // a reasonable default is used. 69 explicit FileInputStream(int file_descriptor, int block_size = -1); 70 ~FileInputStream(); 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() { return copying_input_.GetErrno(); } 89 90 // implements ZeroCopyInputStream ---------------------------------- 91 bool Next(const void** data, int* size); 92 void BackUp(int count); 93 bool Skip(int count); 94 int64 ByteCount() const; 95 96 private: 97 class LIBPROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream { 98 public: 99 CopyingFileInputStream(int file_descriptor); 100 ~CopyingFileInputStream(); 101 102 bool Close(); SetCloseOnDelete(bool value)103 void SetCloseOnDelete(bool value) { close_on_delete_ = value; } GetErrno()104 int GetErrno() { return errno_; } 105 106 // implements CopyingInputStream --------------------------------- 107 int Read(void* buffer, int size); 108 int Skip(int count); 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 LIBPROTOBUF_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(); 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() { return copying_output_.GetErrno(); } 172 173 // implements ZeroCopyOutputStream --------------------------------- 174 bool Next(void** data, int* size); 175 void BackUp(int count); 176 int64 ByteCount() const; 177 178 private: 179 class LIBPROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream { 180 public: 181 CopyingFileOutputStream(int file_descriptor); 182 ~CopyingFileOutputStream(); 183 184 bool Close(); SetCloseOnDelete(bool value)185 void SetCloseOnDelete(bool value) { close_on_delete_ = value; } GetErrno()186 int GetErrno() { return errno_; } 187 188 // implements CopyingOutputStream -------------------------------- 189 bool Write(const void* buffer, int size); 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 LIBPROTOBUF_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(istream* stream, int block_size = -1); 222 ~IstreamInputStream(); 223 224 // implements ZeroCopyInputStream ---------------------------------- 225 bool Next(const void** data, int* size); 226 void BackUp(int count); 227 bool Skip(int count); 228 int64 ByteCount() const; 229 230 private: 231 class LIBPROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream { 232 public: 233 CopyingIstreamInputStream(istream* input); 234 ~CopyingIstreamInputStream(); 235 236 // implements CopyingInputStream --------------------------------- 237 int Read(void* buffer, int size); 238 // (We use the default implementation of Skip().) 239 240 private: 241 // The stream. 242 istream* input_; 243 244 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream); 245 }; 246 247 CopyingIstreamInputStream copying_input_; 248 CopyingInputStreamAdaptor impl_; 249 250 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream); 251 }; 252 253 // =================================================================== 254 255 // A ZeroCopyOutputStream which writes to a C++ ostream. 256 // 257 // Note that for writing files (or anything represented by a file descriptor), 258 // FileOutputStream is more efficient. 259 class LIBPROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream { 260 public: 261 // Creates a stream that writes to the given C++ ostream. 262 // If a block_size is given, it specifies the size of the buffers 263 // that should be returned by Next(). Otherwise, a reasonable default 264 // is used. 265 explicit OstreamOutputStream(ostream* stream, int block_size = -1); 266 ~OstreamOutputStream(); 267 268 // implements ZeroCopyOutputStream --------------------------------- 269 bool Next(void** data, int* size); 270 void BackUp(int count); 271 int64 ByteCount() const; 272 273 private: 274 class LIBPROTOBUF_EXPORT CopyingOstreamOutputStream : public CopyingOutputStream { 275 public: 276 CopyingOstreamOutputStream(ostream* output); 277 ~CopyingOstreamOutputStream(); 278 279 // implements CopyingOutputStream -------------------------------- 280 bool Write(const void* buffer, int size); 281 282 private: 283 // The stream. 284 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 LIBPROTOBUF_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(); 310 311 // implements ZeroCopyInputStream ---------------------------------- 312 bool Next(const void** data, int* size); 313 void BackUp(int count); 314 bool Skip(int count); 315 int64 ByteCount() const; 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 // A ZeroCopyInputStream which wraps some other stream and limits it to 331 // a particular byte count. 332 class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream { 333 public: 334 LimitingInputStream(ZeroCopyInputStream* input, int64 limit); 335 ~LimitingInputStream(); 336 337 // implements ZeroCopyInputStream ---------------------------------- 338 bool Next(const void** data, int* size); 339 void BackUp(int count); 340 bool Skip(int count); 341 int64 ByteCount() const; 342 343 344 private: 345 ZeroCopyInputStream* input_; 346 int64 limit_; // Decreases as we go, becomes negative if we overshoot. 347 348 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream); 349 }; 350 351 // =================================================================== 352 353 } // namespace io 354 } // namespace protobuf 355 356 } // namespace google 357 #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ 358