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 50namespace google { 51namespace protobuf { 52namespace 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. 63class 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. 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. 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(); 103 void SetCloseOnDelete(bool value) { close_on_delete_ = value; } 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. 141class 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. 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. 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(); 185 void SetCloseOnDelete(bool value) { close_on_delete_ = value; } 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. 215class 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. 259class 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. 304class 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. 332class 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