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 included in the "lite" protobuf library.
37// These implementations cover I/O on raw arrays and strings, as well as
38// adaptors which make it easy to implement streams based on traditional
39// streams.  Of course, many users will probably want to write their own
40// implementations of these interfaces specific to the particular I/O
41// abstractions they prefer to use, but these should cover the most common
42// cases.
43
44#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
45#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
46
47#include <string>
48#include <iosfwd>
49#include <google/protobuf/io/zero_copy_stream.h>
50#include <google/protobuf/stubs/common.h>
51
52
53namespace google {
54namespace protobuf {
55namespace io {
56
57// ===================================================================
58
59// A ZeroCopyInputStream backed by an in-memory array of bytes.
60class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
61 public:
62  // Create an InputStream that returns the bytes pointed to by "data".
63  // "data" remains the property of the caller but must remain valid until
64  // the stream is destroyed.  If a block_size is given, calls to Next()
65  // will return data blocks no larger than the given size.  Otherwise, the
66  // first call to Next() returns the entire array.  block_size is mainly
67  // useful for testing; in production you would probably never want to set
68  // it.
69  ArrayInputStream(const void* data, int size, int block_size = -1);
70  ~ArrayInputStream();
71
72  // implements ZeroCopyInputStream ----------------------------------
73  bool Next(const void** data, int* size);
74  void BackUp(int count);
75  bool Skip(int count);
76  int64 ByteCount() const;
77
78
79 private:
80  const uint8* const data_;  // The byte array.
81  const int size_;           // Total size of the array.
82  const int block_size_;     // How many bytes to return at a time.
83
84  int position_;
85  int last_returned_size_;   // How many bytes we returned last time Next()
86                             // was called (used for error checking only).
87
88  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
89};
90
91// ===================================================================
92
93// A ZeroCopyOutputStream backed by an in-memory array of bytes.
94class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
95 public:
96  // Create an OutputStream that writes to the bytes pointed to by "data".
97  // "data" remains the property of the caller but must remain valid until
98  // the stream is destroyed.  If a block_size is given, calls to Next()
99  // will return data blocks no larger than the given size.  Otherwise, the
100  // first call to Next() returns the entire array.  block_size is mainly
101  // useful for testing; in production you would probably never want to set
102  // it.
103  ArrayOutputStream(void* data, int size, int block_size = -1);
104  ~ArrayOutputStream();
105
106  // implements ZeroCopyOutputStream ---------------------------------
107  bool Next(void** data, int* size);
108  void BackUp(int count);
109  int64 ByteCount() const;
110
111 private:
112  uint8* const data_;        // The byte array.
113  const int size_;           // Total size of the array.
114  const int block_size_;     // How many bytes to return at a time.
115
116  int position_;
117  int last_returned_size_;   // How many bytes we returned last time Next()
118                             // was called (used for error checking only).
119
120  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
121};
122
123// ===================================================================
124
125// A ZeroCopyOutputStream which appends bytes to a string.
126class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
127 public:
128  // Create a StringOutputStream which appends bytes to the given string.
129  // The string remains property of the caller, but it MUST NOT be accessed
130  // in any way until the stream is destroyed.
131  //
132  // Hint:  If you call target->reserve(n) before creating the stream,
133  //   the first call to Next() will return at least n bytes of buffer
134  //   space.
135  explicit StringOutputStream(string* target);
136  ~StringOutputStream();
137
138  // implements ZeroCopyOutputStream ---------------------------------
139  bool Next(void** data, int* size);
140  void BackUp(int count);
141  int64 ByteCount() const;
142
143 private:
144  static const int kMinimumSize = 16;
145
146  string* target_;
147
148  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
149};
150
151// Note:  There is no StringInputStream.  Instead, just create an
152// ArrayInputStream as follows:
153//   ArrayInputStream input(str.data(), str.size());
154
155// ===================================================================
156
157// A generic traditional input stream interface.
158//
159// Lots of traditional input streams (e.g. file descriptors, C stdio
160// streams, and C++ iostreams) expose an interface where every read
161// involves copying bytes into a buffer.  If you want to take such an
162// interface and make a ZeroCopyInputStream based on it, simply implement
163// CopyingInputStream and then use CopyingInputStreamAdaptor.
164//
165// CopyingInputStream implementations should avoid buffering if possible.
166// CopyingInputStreamAdaptor does its own buffering and will read data
167// in large blocks.
168class LIBPROTOBUF_EXPORT CopyingInputStream {
169 public:
170  virtual ~CopyingInputStream();
171
172  // Reads up to "size" bytes into the given buffer.  Returns the number of
173  // bytes read.  Read() waits until at least one byte is available, or
174  // returns zero if no bytes will ever become available (EOF), or -1 if a
175  // permanent read error occurred.
176  virtual int Read(void* buffer, int size) = 0;
177
178  // Skips the next "count" bytes of input.  Returns the number of bytes
179  // actually skipped.  This will always be exactly equal to "count" unless
180  // EOF was reached or a permanent read error occurred.
181  //
182  // The default implementation just repeatedly calls Read() into a scratch
183  // buffer.
184  virtual int Skip(int count);
185};
186
187// A ZeroCopyInputStream which reads from a CopyingInputStream.  This is
188// useful for implementing ZeroCopyInputStreams that read from traditional
189// streams.  Note that this class is not really zero-copy.
190//
191// If you want to read from file descriptors or C++ istreams, this is
192// already implemented for you:  use FileInputStream or IstreamInputStream
193// respectively.
194class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
195 public:
196  // Creates a stream that reads from the given CopyingInputStream.
197  // If a block_size is given, it specifies the number of bytes that
198  // should be read and returned with each call to Next().  Otherwise,
199  // a reasonable default is used.  The caller retains ownership of
200  // copying_stream unless SetOwnsCopyingStream(true) is called.
201  explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
202                                     int block_size = -1);
203  ~CopyingInputStreamAdaptor();
204
205  // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
206  // delete the underlying CopyingInputStream when it is destroyed.
207  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
208
209  // implements ZeroCopyInputStream ----------------------------------
210  bool Next(const void** data, int* size);
211  void BackUp(int count);
212  bool Skip(int count);
213  int64 ByteCount() const;
214
215 private:
216  // Insures that buffer_ is not NULL.
217  void AllocateBufferIfNeeded();
218  // Frees the buffer and resets buffer_used_.
219  void FreeBuffer();
220
221  // The underlying copying stream.
222  CopyingInputStream* copying_stream_;
223  bool owns_copying_stream_;
224
225  // True if we have seen a permenant error from the underlying stream.
226  bool failed_;
227
228  // The current position of copying_stream_, relative to the point where
229  // we started reading.
230  int64 position_;
231
232  // Data is read into this buffer.  It may be NULL if no buffer is currently
233  // in use.  Otherwise, it points to an array of size buffer_size_.
234  scoped_array<uint8> buffer_;
235  const int buffer_size_;
236
237  // Number of valid bytes currently in the buffer (i.e. the size last
238  // returned by Next()).  0 <= buffer_used_ <= buffer_size_.
239  int buffer_used_;
240
241  // Number of bytes in the buffer which were backed up over by a call to
242  // BackUp().  These need to be returned again.
243  // 0 <= backup_bytes_ <= buffer_used_
244  int backup_bytes_;
245
246  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
247};
248
249// ===================================================================
250
251// A generic traditional output stream interface.
252//
253// Lots of traditional output streams (e.g. file descriptors, C stdio
254// streams, and C++ iostreams) expose an interface where every write
255// involves copying bytes from a buffer.  If you want to take such an
256// interface and make a ZeroCopyOutputStream based on it, simply implement
257// CopyingOutputStream and then use CopyingOutputStreamAdaptor.
258//
259// CopyingOutputStream implementations should avoid buffering if possible.
260// CopyingOutputStreamAdaptor does its own buffering and will write data
261// in large blocks.
262class LIBPROTOBUF_EXPORT CopyingOutputStream {
263 public:
264  virtual ~CopyingOutputStream();
265
266  // Writes "size" bytes from the given buffer to the output.  Returns true
267  // if successful, false on a write error.
268  virtual bool Write(const void* buffer, int size) = 0;
269};
270
271// A ZeroCopyOutputStream which writes to a CopyingOutputStream.  This is
272// useful for implementing ZeroCopyOutputStreams that write to traditional
273// streams.  Note that this class is not really zero-copy.
274//
275// If you want to write to file descriptors or C++ ostreams, this is
276// already implemented for you:  use FileOutputStream or OstreamOutputStream
277// respectively.
278class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
279 public:
280  // Creates a stream that writes to the given Unix file descriptor.
281  // If a block_size is given, it specifies the size of the buffers
282  // that should be returned by Next().  Otherwise, a reasonable default
283  // is used.
284  explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
285                                      int block_size = -1);
286  ~CopyingOutputStreamAdaptor();
287
288  // Writes all pending data to the underlying stream.  Returns false if a
289  // write error occurred on the underlying stream.  (The underlying
290  // stream itself is not necessarily flushed.)
291  bool Flush();
292
293  // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
294  // delete the underlying CopyingOutputStream when it is destroyed.
295  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
296
297  // implements ZeroCopyOutputStream ---------------------------------
298  bool Next(void** data, int* size);
299  void BackUp(int count);
300  int64 ByteCount() const;
301
302 private:
303  // Write the current buffer, if it is present.
304  bool WriteBuffer();
305  // Insures that buffer_ is not NULL.
306  void AllocateBufferIfNeeded();
307  // Frees the buffer.
308  void FreeBuffer();
309
310  // The underlying copying stream.
311  CopyingOutputStream* copying_stream_;
312  bool owns_copying_stream_;
313
314  // True if we have seen a permenant error from the underlying stream.
315  bool failed_;
316
317  // The current position of copying_stream_, relative to the point where
318  // we started writing.
319  int64 position_;
320
321  // Data is written from this buffer.  It may be NULL if no buffer is
322  // currently in use.  Otherwise, it points to an array of size buffer_size_.
323  scoped_array<uint8> buffer_;
324  const int buffer_size_;
325
326  // Number of valid bytes currently in the buffer (i.e. the size last
327  // returned by Next()).  When BackUp() is called, we just reduce this.
328  // 0 <= buffer_used_ <= buffer_size_.
329  int buffer_used_;
330
331  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
332};
333
334// ===================================================================
335
336}  // namespace io
337}  // namespace protobuf
338
339}  // namespace google
340#endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
341