• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 the ZeroCopyInputStream and ZeroCopyOutputStream
36 // interfaces, which represent abstract I/O streams to and from which
37 // protocol buffers can be read and written.  For a few simple
38 // implementations of these interfaces, see zero_copy_stream_impl.h.
39 //
40 // These interfaces are different from classic I/O streams in that they
41 // try to minimize the amount of data copying that needs to be done.
42 // To accomplish this, responsibility for allocating buffers is moved to
43 // the stream object, rather than being the responsibility of the caller.
44 // So, the stream can return a buffer which actually points directly into
45 // the final data structure where the bytes are to be stored, and the caller
46 // can interact directly with that buffer, eliminating an intermediate copy
47 // operation.
48 //
49 // As an example, consider the common case in which you are reading bytes
50 // from an array that is already in memory (or perhaps an mmap()ed file).
51 // With classic I/O streams, you would do something like:
52 //   char buffer[BUFFER_SIZE];
53 //   input->Read(buffer, BUFFER_SIZE);
54 //   DoSomething(buffer, BUFFER_SIZE);
55 // Then, the stream basically just calls memcpy() to copy the data from
56 // the array into your buffer.  With a ZeroCopyInputStream, you would do
57 // this instead:
58 //   const void* buffer;
59 //   int size;
60 //   input->Next(&buffer, &size);
61 //   DoSomething(buffer, size);
62 // Here, no copy is performed.  The input stream returns a pointer directly
63 // into the backing array, and the caller ends up reading directly from it.
64 //
65 // If you want to be able to read the old-fashion way, you can create
66 // a CodedInputStream or CodedOutputStream wrapping these objects and use
67 // their ReadRaw()/WriteRaw() methods.  These will, of course, add a copy
68 // step, but Coded*Stream will handle buffering so at least it will be
69 // reasonably efficient.
70 //
71 // ZeroCopyInputStream example:
72 //   // Read in a file and print its contents to stdout.
73 //   int fd = open("myfile", O_RDONLY);
74 //   ZeroCopyInputStream* input = new FileInputStream(fd);
75 //
76 //   const void* buffer;
77 //   int size;
78 //   while (input->Next(&buffer, &size)) {
79 //     cout.write(buffer, size);
80 //   }
81 //
82 //   delete input;
83 //   close(fd);
84 //
85 // ZeroCopyOutputStream example:
86 //   // Copy the contents of "infile" to "outfile", using plain read() for
87 //   // "infile" but a ZeroCopyOutputStream for "outfile".
88 //   int infd = open("infile", O_RDONLY);
89 //   int outfd = open("outfile", O_WRONLY);
90 //   ZeroCopyOutputStream* output = new FileOutputStream(outfd);
91 //
92 //   void* buffer;
93 //   int size;
94 //   while (output->Next(&buffer, &size)) {
95 //     int bytes = read(infd, buffer, size);
96 //     if (bytes < size) {
97 //       // Reached EOF.
98 //       output->BackUp(size - bytes);
99 //       break;
100 //     }
101 //   }
102 //
103 //   delete output;
104 //   close(infd);
105 //   close(outfd);
106 
107 #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
108 #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
109 
110 #include <string>
111 #include <google/protobuf/stubs/common.h>
112 
113 #include <google/protobuf/port_def.inc>
114 
115 
116 namespace google {
117 namespace protobuf {
118 namespace io {
119 
120 // Defined in this file.
121 class ZeroCopyInputStream;
122 class ZeroCopyOutputStream;
123 
124 // Abstract interface similar to an input stream but designed to minimize
125 // copying.
126 class PROTOBUF_EXPORT ZeroCopyInputStream {
127  public:
ZeroCopyInputStream()128   ZeroCopyInputStream() {}
~ZeroCopyInputStream()129   virtual ~ZeroCopyInputStream() {}
130 
131   // Obtains a chunk of data from the stream.
132   //
133   // Preconditions:
134   // * "size" and "data" are not NULL.
135   //
136   // Postconditions:
137   // * If the returned value is false, there is no more data to return or
138   //   an error occurred.  All errors are permanent.
139   // * Otherwise, "size" points to the actual number of bytes read and "data"
140   //   points to a pointer to a buffer containing these bytes.
141   // * Ownership of this buffer remains with the stream, and the buffer
142   //   remains valid only until some other method of the stream is called
143   //   or the stream is destroyed.
144   // * It is legal for the returned buffer to have zero size, as long
145   //   as repeatedly calling Next() eventually yields a buffer with non-zero
146   //   size.
147   virtual bool Next(const void** data, int* size) = 0;
148 
149   // Backs up a number of bytes, so that the next call to Next() returns
150   // data again that was already returned by the last call to Next().  This
151   // is useful when writing procedures that are only supposed to read up
152   // to a certain point in the input, then return.  If Next() returns a
153   // buffer that goes beyond what you wanted to read, you can use BackUp()
154   // to return to the point where you intended to finish.
155   //
156   // Preconditions:
157   // * The last method called must have been Next().
158   // * count must be less than or equal to the size of the last buffer
159   //   returned by Next().
160   //
161   // Postconditions:
162   // * The last "count" bytes of the last buffer returned by Next() will be
163   //   pushed back into the stream.  Subsequent calls to Next() will return
164   //   the same data again before producing new data.
165   virtual void BackUp(int count) = 0;
166 
167   // Skips a number of bytes.  Returns false if the end of the stream is
168   // reached or some input error occurred.  In the end-of-stream case, the
169   // stream is advanced to the end of the stream (so ByteCount() will return
170   // the total size of the stream).
171   virtual bool Skip(int count) = 0;
172 
173   // Returns the total number of bytes read since this object was created.
174   virtual int64 ByteCount() const = 0;
175 
176 
177  private:
178   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
179 };
180 
181 // Abstract interface similar to an output stream but designed to minimize
182 // copying.
183 class PROTOBUF_EXPORT ZeroCopyOutputStream {
184  public:
ZeroCopyOutputStream()185   ZeroCopyOutputStream() {}
~ZeroCopyOutputStream()186   virtual ~ZeroCopyOutputStream() {}
187 
188   // Obtains a buffer into which data can be written.  Any data written
189   // into this buffer will eventually (maybe instantly, maybe later on)
190   // be written to the output.
191   //
192   // Preconditions:
193   // * "size" and "data" are not NULL.
194   //
195   // Postconditions:
196   // * If the returned value is false, an error occurred.  All errors are
197   //   permanent.
198   // * Otherwise, "size" points to the actual number of bytes in the buffer
199   //   and "data" points to the buffer.
200   // * Ownership of this buffer remains with the stream, and the buffer
201   //   remains valid only until some other method of the stream is called
202   //   or the stream is destroyed.
203   // * Any data which the caller stores in this buffer will eventually be
204   //   written to the output (unless BackUp() is called).
205   // * It is legal for the returned buffer to have zero size, as long
206   //   as repeatedly calling Next() eventually yields a buffer with non-zero
207   //   size.
208   virtual bool Next(void** data, int* size) = 0;
209 
210   // Backs up a number of bytes, so that the end of the last buffer returned
211   // by Next() is not actually written.  This is needed when you finish
212   // writing all the data you want to write, but the last buffer was bigger
213   // than you needed.  You don't want to write a bunch of garbage after the
214   // end of your data, so you use BackUp() to back up.
215   //
216   // Preconditions:
217   // * The last method called must have been Next().
218   // * count must be less than or equal to the size of the last buffer
219   //   returned by Next().
220   // * The caller must not have written anything to the last "count" bytes
221   //   of that buffer.
222   //
223   // Postconditions:
224   // * The last "count" bytes of the last buffer returned by Next() will be
225   //   ignored.
226   virtual void BackUp(int count) = 0;
227 
228   // Returns the total number of bytes written since this object was created.
229   virtual int64 ByteCount() const = 0;
230 
231   // Write a given chunk of data to the output.  Some output streams may
232   // implement this in a way that avoids copying. Check AllowsAliasing() before
233   // calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is
234   // called on a stream that does not allow aliasing.
235   //
236   // NOTE: It is caller's responsibility to ensure that the chunk of memory
237   // remains live until all of the data has been consumed from the stream.
238   virtual bool WriteAliasedRaw(const void* data, int size);
AllowsAliasing()239   virtual bool AllowsAliasing() const { return false; }
240 
241 
242  private:
243   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream);
244 };
245 
246 }  // namespace io
247 }  // namespace protobuf
248 }  // namespace google
249 
250 #include <google/protobuf/port_undef.inc>
251 
252 #endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
253