zero_copy_stream_impl.h revision d0332953cda33fb4f8e24ebff9c49159b69c43d6
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