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: [email protected] (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 int64 prior_bytes_read_; // Bytes read on underlying stream at construction
348
349 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
350};
351
352// ===================================================================
353
354} // namespace io
355} // namespace protobuf
356
357} // namespace google
358#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
359