Line data Source code
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: 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 :
50 : namespace google {
51 : namespace protobuf {
52 : namespace 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.
63 : class 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 135 : 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 8 : 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 135 : 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.
141 : class 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 0 : 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.
215 : class 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.
259 : class 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.
304 : class 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.
332 : class 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__
|