• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 //
12 // This file contains common implementations of the interfaces defined in
13 // zero_copy_stream.h which are only included in the full (non-lite)
14 // protobuf library.  These implementations include Unix file descriptors
15 // and C++ iostreams.  See also:  zero_copy_stream_impl_lite.h
16 
17 #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
18 #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
19 
20 #include <iosfwd>
21 #include <string>
22 
23 #include "google/protobuf/stubs/common.h"
24 #include "google/protobuf/io/zero_copy_stream.h"
25 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
26 
27 // Must be included last.
28 #include "google/protobuf/port_def.inc"
29 
30 namespace google {
31 namespace protobuf {
32 namespace io {
33 
34 // ===================================================================
35 
36 // A ZeroCopyInputStream which reads from a file descriptor.
37 //
38 // FileInputStream is preferred over using an ifstream with IstreamInputStream.
39 // The latter will introduce an extra layer of buffering, harming performance.
40 // Also, it's conceivable that FileInputStream could someday be enhanced
41 // to use zero-copy file descriptors on OSs which support them.
42 class PROTOBUF_EXPORT FileInputStream final : public ZeroCopyInputStream {
43  public:
44   // Creates a stream that reads from the given Unix file descriptor.
45   // If a block_size is given, it specifies the number of bytes that
46   // should be read and returned with each call to Next().  Otherwise,
47   // a reasonable default is used.
48   explicit FileInputStream(int file_descriptor, int block_size = -1);
49   FileInputStream(const FileInputStream&) = delete;
50   FileInputStream& operator=(const FileInputStream&) = delete;
51 
52   // Flushes any buffers and closes the underlying file.  Returns false if
53   // an error occurs during the process; use GetErrno() to examine the error.
54   // Even if an error occurs, the file descriptor is closed when this returns.
55   bool Close();
56 
57   // By default, the file descriptor is not closed when the stream is
58   // destroyed.  Call SetCloseOnDelete(true) to change that.  WARNING:
59   // This leaves no way for the caller to detect if close() fails.  If
60   // detecting close() errors is important to you, you should arrange
61   // to close the descriptor yourself.
SetCloseOnDelete(bool value)62   void SetCloseOnDelete(bool value) { copying_input_.SetCloseOnDelete(value); }
63 
64   // If an I/O error has occurred on this file descriptor, this is the
65   // errno from that error.  Otherwise, this is zero.  Once an error
66   // occurs, the stream is broken and all subsequent operations will
67   // fail.
GetErrno()68   int GetErrno() const { return copying_input_.GetErrno(); }
69 
70   // implements ZeroCopyInputStream ----------------------------------
71   bool Next(const void** data, int* size) override;
72   void BackUp(int count) override;
73   bool Skip(int count) override;
74   int64_t ByteCount() const override;
75 
76  private:
77   class PROTOBUF_EXPORT CopyingFileInputStream final
78       : public CopyingInputStream {
79    public:
80     CopyingFileInputStream(int file_descriptor);
81     CopyingFileInputStream(const CopyingFileInputStream&) = delete;
82     CopyingFileInputStream& operator=(const CopyingFileInputStream&) = delete;
83     ~CopyingFileInputStream() override;
84 
85     bool Close();
SetCloseOnDelete(bool value)86     void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
GetErrno()87     int GetErrno() const { return errno_; }
88 
89     // implements CopyingInputStream ---------------------------------
90     int Read(void* buffer, int size) override;
91     int Skip(int count) override;
92 
93    private:
94     // The file descriptor.
95     const int file_;
96     bool close_on_delete_;
97     bool is_closed_;
98 
99     // The errno of the I/O error, if one has occurred.  Otherwise, zero.
100     int errno_;
101 
102     // Did we try to seek once and fail?  If so, we assume this file descriptor
103     // doesn't support seeking and won't try again.
104     bool previous_seek_failed_;
105   };
106 
107   CopyingFileInputStream copying_input_;
108   CopyingInputStreamAdaptor impl_;
109 };
110 
111 // ===================================================================
112 
113 // A ZeroCopyOutputStream which writes to a file descriptor.
114 //
115 // FileOutputStream is preferred over using an ofstream with
116 // OstreamOutputStream.  The latter will introduce an extra layer of buffering,
117 // harming performance.  Also, it's conceivable that FileOutputStream could
118 // someday be enhanced to use zero-copy file descriptors on OSs which
119 // support them.
120 class PROTOBUF_EXPORT FileOutputStream final
121     : public CopyingOutputStreamAdaptor {
122  public:
123   // Creates a stream that writes to the given Unix file descriptor.
124   // If a block_size is given, it specifies the size of the buffers
125   // that should be returned by Next().  Otherwise, a reasonable default
126   // is used.
127   explicit FileOutputStream(int file_descriptor, int block_size = -1);
128   FileOutputStream(const FileOutputStream&) = delete;
129   FileOutputStream& operator=(const FileOutputStream&) = delete;
130 
131   ~FileOutputStream() override;
132 
133   // Flushes any buffers and closes the underlying file.  Returns false if
134   // an error occurs during the process; use GetErrno() to examine the error.
135   // Even if an error occurs, the file descriptor is closed when this returns.
136   bool Close();
137 
138   // By default, the file descriptor is not closed when the stream is
139   // destroyed.  Call SetCloseOnDelete(true) to change that.  WARNING:
140   // This leaves no way for the caller to detect if close() fails.  If
141   // detecting close() errors is important to you, you should arrange
142   // to close the descriptor yourself.
SetCloseOnDelete(bool value)143   void SetCloseOnDelete(bool value) { copying_output_.SetCloseOnDelete(value); }
144 
145   // If an I/O error has occurred on this file descriptor, this is the
146   // errno from that error.  Otherwise, this is zero.  Once an error
147   // occurs, the stream is broken and all subsequent operations will
148   // fail.
GetErrno()149   int GetErrno() const { return copying_output_.GetErrno(); }
150 
151  private:
152   class PROTOBUF_EXPORT CopyingFileOutputStream final
153       : public CopyingOutputStream {
154    public:
155     CopyingFileOutputStream(int file_descriptor);
156     CopyingFileOutputStream(const CopyingFileOutputStream&) = delete;
157     CopyingFileOutputStream& operator=(const CopyingFileOutputStream&) = delete;
158     ~CopyingFileOutputStream() override;
159 
160     bool Close();
SetCloseOnDelete(bool value)161     void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
GetErrno()162     int GetErrno() const { return errno_; }
163 
164     // implements CopyingOutputStream --------------------------------
165     bool Write(const void* buffer, int size) override;
166 
167    private:
168     // The file descriptor.
169     const int file_;
170     bool close_on_delete_;
171     bool is_closed_;
172 
173     // The errno of the I/O error, if one has occurred.  Otherwise, zero.
174     int errno_;
175   };
176 
177   CopyingFileOutputStream copying_output_;
178 };
179 
180 // ===================================================================
181 
182 // A ZeroCopyInputStream which reads from a C++ istream.
183 //
184 // Note that for reading files (or anything represented by a file descriptor),
185 // FileInputStream is more efficient.
186 class PROTOBUF_EXPORT IstreamInputStream final : public ZeroCopyInputStream {
187  public:
188   // Creates a stream that reads from the given C++ istream.
189   // If a block_size is given, it specifies the number of bytes that
190   // should be read and returned with each call to Next().  Otherwise,
191   // a reasonable default is used.
192   explicit IstreamInputStream(std::istream* stream, int block_size = -1);
193   IstreamInputStream(const IstreamInputStream&) = delete;
194   IstreamInputStream& operator=(const IstreamInputStream&) = delete;
195 
196   // implements ZeroCopyInputStream ----------------------------------
197   bool Next(const void** data, int* size) override;
198   void BackUp(int count) override;
199   bool Skip(int count) override;
200   int64_t ByteCount() const override;
201 
202  private:
203   class PROTOBUF_EXPORT CopyingIstreamInputStream final
204       : public CopyingInputStream {
205    public:
206     CopyingIstreamInputStream(std::istream* input);
207     CopyingIstreamInputStream(const CopyingIstreamInputStream&) = delete;
208     CopyingIstreamInputStream& operator=(const CopyingIstreamInputStream&) =
209         delete;
210     ~CopyingIstreamInputStream() override;
211 
212     // implements CopyingInputStream ---------------------------------
213     int Read(void* buffer, int size) override;
214     // (We use the default implementation of Skip().)
215 
216    private:
217     // The stream.
218     std::istream* input_;
219   };
220 
221   CopyingIstreamInputStream copying_input_;
222   CopyingInputStreamAdaptor impl_;
223 };
224 
225 // ===================================================================
226 
227 // A ZeroCopyOutputStream which writes to a C++ ostream.
228 //
229 // Note that for writing files (or anything represented by a file descriptor),
230 // FileOutputStream is more efficient.
231 class PROTOBUF_EXPORT OstreamOutputStream final : public ZeroCopyOutputStream {
232  public:
233   // Creates a stream that writes to the given C++ ostream.
234   // If a block_size is given, it specifies the size of the buffers
235   // that should be returned by Next().  Otherwise, a reasonable default
236   // is used.
237   explicit OstreamOutputStream(std::ostream* stream, int block_size = -1);
238   OstreamOutputStream(const OstreamOutputStream&) = delete;
239   OstreamOutputStream& operator=(const OstreamOutputStream&) = delete;
240   ~OstreamOutputStream() override;
241 
242   // implements ZeroCopyOutputStream ---------------------------------
243   bool Next(void** data, int* size) override;
244   void BackUp(int count) override;
245   int64_t ByteCount() const override;
246 
247  private:
248   class PROTOBUF_EXPORT CopyingOstreamOutputStream final
249       : public CopyingOutputStream {
250    public:
251     CopyingOstreamOutputStream(std::ostream* output);
252     CopyingOstreamOutputStream(const CopyingOstreamOutputStream&) = delete;
253     CopyingOstreamOutputStream& operator=(const CopyingOstreamOutputStream&) =
254         delete;
255     ~CopyingOstreamOutputStream() override;
256 
257     // implements CopyingOutputStream --------------------------------
258     bool Write(const void* buffer, int size) override;
259 
260    private:
261     // The stream.
262     std::ostream* output_;
263   };
264 
265   CopyingOstreamOutputStream copying_output_;
266   CopyingOutputStreamAdaptor impl_;
267 };
268 
269 // ===================================================================
270 
271 // A ZeroCopyInputStream which reads from several other streams in sequence.
272 // ConcatenatingInputStream is unable to distinguish between end-of-stream
273 // and read errors in the underlying streams, so it assumes any errors mean
274 // end-of-stream.  So, if the underlying streams fail for any other reason,
275 // ConcatenatingInputStream may do odd things.  It is suggested that you do
276 // not use ConcatenatingInputStream on streams that might produce read errors
277 // other than end-of-stream.
278 class PROTOBUF_EXPORT ConcatenatingInputStream final
279     : public ZeroCopyInputStream {
280  public:
281   // All streams passed in as well as the array itself must remain valid
282   // until the ConcatenatingInputStream is destroyed.
283   ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count);
284   ConcatenatingInputStream(const ConcatenatingInputStream&) = delete;
285   ConcatenatingInputStream& operator=(const ConcatenatingInputStream&) = delete;
286   ~ConcatenatingInputStream() override = default;
287 
288   // implements ZeroCopyInputStream ----------------------------------
289   bool Next(const void** data, int* size) override;
290   void BackUp(int count) override;
291   bool Skip(int count) override;
292   int64_t ByteCount() const override;
293 
294 
295  private:
296   // As streams are retired, streams_ is incremented and count_ is
297   // decremented.
298   ZeroCopyInputStream* const* streams_;
299   int stream_count_;
300   int64_t bytes_retired_;  // Bytes read from previous streams.
301 };
302 
303 // ===================================================================
304 
305 }  // namespace io
306 }  // namespace protobuf
307 }  // namespace google
308 
309 #include "google/protobuf/port_undef.inc"
310 
311 #endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
312