1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
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
40 #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
41 #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
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>
55 // ===================================================================
57 // A ZeroCopyInputStream which reads from a file descriptor.
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 {
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);
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.
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); }
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
88 int GetErrno() { return copying_input_.GetErrno(); }
90 // implements ZeroCopyInputStream ----------------------------------
91 bool Next(const void** data, int* size);
92 void BackUp(int count);
94 int64 ByteCount() const;
97 class LIBPROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream {
99 CopyingFileInputStream(int file_descriptor);
100 ~CopyingFileInputStream();
103 void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
104 int GetErrno() { return errno_; }
106 // implements CopyingInputStream ---------------------------------
107 int Read(void* buffer, int size);
111 // The file descriptor.
113 bool close_on_delete_;
116 // The errno of the I/O error, if one has occurred. Otherwise, zero.
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_;
123 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream);
126 CopyingFileInputStream copying_input_;
127 CopyingInputStreamAdaptor impl_;
129 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream);
132 // ===================================================================
134 // A ZeroCopyOutputStream which writes to a file descriptor.
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
141 class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
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
147 explicit FileOutputStream(int file_descriptor, int block_size = -1);
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.
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.
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); }
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
171 int GetErrno() { return copying_output_.GetErrno(); }
173 // implements ZeroCopyOutputStream ---------------------------------
174 bool Next(void** data, int* size);
175 void BackUp(int count);
176 int64 ByteCount() const;
179 class LIBPROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream {
181 CopyingFileOutputStream(int file_descriptor);
182 ~CopyingFileOutputStream();
185 void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
186 int GetErrno() { return errno_; }
188 // implements CopyingOutputStream --------------------------------
189 bool Write(const void* buffer, int size);
192 // The file descriptor.
194 bool close_on_delete_;
197 // The errno of the I/O error, if one has occurred. Otherwise, zero.
200 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream);
203 CopyingFileOutputStream copying_output_;
204 CopyingOutputStreamAdaptor impl_;
206 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream);
209 // ===================================================================
211 // A ZeroCopyInputStream which reads from a C++ istream.
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 {
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();
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;
231 class LIBPROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream {
233 CopyingIstreamInputStream(istream* input);
234 ~CopyingIstreamInputStream();
236 // implements CopyingInputStream ---------------------------------
237 int Read(void* buffer, int size);
238 // (We use the default implementation of Skip().)
244 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream);
247 CopyingIstreamInputStream copying_input_;
248 CopyingInputStreamAdaptor impl_;
250 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream);
253 // ===================================================================
255 // A ZeroCopyOutputStream which writes to a C++ ostream.
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 {
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
265 explicit OstreamOutputStream(ostream* stream, int block_size = -1);
266 ~OstreamOutputStream();
268 // implements ZeroCopyOutputStream ---------------------------------
269 bool Next(void** data, int* size);
270 void BackUp(int count);
271 int64 ByteCount() const;
274 class LIBPROTOBUF_EXPORT CopyingOstreamOutputStream : public CopyingOutputStream {
276 CopyingOstreamOutputStream(ostream* output);
277 ~CopyingOstreamOutputStream();
279 // implements CopyingOutputStream --------------------------------
280 bool Write(const void* buffer, int size);
286 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream);
289 CopyingOstreamOutputStream copying_output_;
290 CopyingOutputStreamAdaptor impl_;
292 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream);
295 // ===================================================================
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 {
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();
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;
319 // As streams are retired, streams_ is incremented and count_ is
321 ZeroCopyInputStream* const* streams_;
323 int64 bytes_retired_; // Bytes read from previous streams.
325 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream);
328 // ===================================================================
330 // A ZeroCopyInputStream which wraps some other stream and limits it to
331 // a particular byte count.
332 class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream {
334 LimitingInputStream(ZeroCopyInputStream* input, int64 limit);
335 ~LimitingInputStream();
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;
345 ZeroCopyInputStream* input_;
346 int64 limit_; // Decreases as we go, becomes negative if we overshoot.
348 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
351 // ===================================================================
354 } // namespace protobuf
356 } // namespace google
357 #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__