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
111#include <google/protobuf/stubs/common.h>
112
113
114// Must be included last.
115#include <google/protobuf/port_def.inc>
116
117namespace google {
118namespace protobuf {
119namespace io {
120
121// Defined in this file.
122class ZeroCopyInputStream;
123class ZeroCopyOutputStream;
124
125// Abstract interface similar to an input stream but designed to minimize
126// copying.
127class PROTOBUF_EXPORT ZeroCopyInputStream {
128 public:
129 ZeroCopyInputStream() {}
130 virtual ~ZeroCopyInputStream() {}
131
132 // Obtains a chunk of data from the stream.
133 //
134 // Preconditions:
135 // * "size" and "data" are not NULL.
136 //
137 // Postconditions:
138 // * If the returned value is false, there is no more data to return or
139 // an error occurred. All errors are permanent.
140 // * Otherwise, "size" points to the actual number of bytes read and "data"
141 // points to a pointer to a buffer containing these bytes.
142 // * Ownership of this buffer remains with the stream, and the buffer
143 // remains valid only until some other method of the stream is called
144 // or the stream is destroyed.
145 // * It is legal for the returned buffer to have zero size, as long
146 // as repeatedly calling Next() eventually yields a buffer with non-zero
147 // size.
148 virtual bool Next(const void** data, int* size) = 0;
149
150 // Backs up a number of bytes, so that the next call to Next() returns
151 // data again that was already returned by the last call to Next(). This
152 // is useful when writing procedures that are only supposed to read up
153 // to a certain point in the input, then return. If Next() returns a
154 // buffer that goes beyond what you wanted to read, you can use BackUp()
155 // to return to the point where you intended to finish.
156 //
157 // This method can be called with `count = 0` to finalize (flush) any
158 // previously returned buffer. For example, a file output stream can
159 // flush buffers returned from a previous call to Next() upon such
160 // BackUp(0) invocations. ZeroCopyOutputStream callers should always
161 // invoke BackUp() after a final Next() call, even if there is no
162 // excess buffer data to be backed up to indicate a flush point.
163 //
164 // Preconditions:
165 // * The last method called must have been Next().
166 // * count must be less than or equal to the size of the last buffer
167 // returned by Next().
168 //
169 // Postconditions:
170 // * The last "count" bytes of the last buffer returned by Next() will be
171 // pushed back into the stream. Subsequent calls to Next() will return
172 // the same data again before producing new data.
173 virtual void BackUp(int count) = 0;
174
175 // Skips a number of bytes. Returns false if the end of the stream is
176 // reached or some input error occurred. In the end-of-stream case, the
177 // stream is advanced to the end of the stream (so ByteCount() will return
178 // the total size of the stream).
179 virtual bool Skip(int count) = 0;
180
181 // Returns the total number of bytes read since this object was created.
182 virtual int64_t ByteCount() const = 0;
183
184
185 private:
186 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
187};
188
189// Abstract interface similar to an output stream but designed to minimize
190// copying.
191class PROTOBUF_EXPORT ZeroCopyOutputStream {
192 public:
193 ZeroCopyOutputStream() {}
194 virtual ~ZeroCopyOutputStream() {}
195
196 // Obtains a buffer into which data can be written. Any data written
197 // into this buffer will eventually (maybe instantly, maybe later on)
198 // be written to the output.
199 //
200 // Preconditions:
201 // * "size" and "data" are not NULL.
202 //
203 // Postconditions:
204 // * If the returned value is false, an error occurred. All errors are
205 // permanent.
206 // * Otherwise, "size" points to the actual number of bytes in the buffer
207 // and "data" points to the buffer.
208 // * Ownership of this buffer remains with the stream, and the buffer
209 // remains valid only until some other method of the stream is called
210 // or the stream is destroyed.
211 // * Any data which the caller stores in this buffer will eventually be
212 // written to the output (unless BackUp() is called).
213 // * It is legal for the returned buffer to have zero size, as long
214 // as repeatedly calling Next() eventually yields a buffer with non-zero
215 // size.
216 virtual bool Next(void** data, int* size) = 0;
217
218 // Backs up a number of bytes, so that the end of the last buffer returned
219 // by Next() is not actually written. This is needed when you finish
220 // writing all the data you want to write, but the last buffer was bigger
221 // than you needed. You don't want to write a bunch of garbage after the
222 // end of your data, so you use BackUp() to back up.
223 //
224 // Preconditions:
225 // * The last method called must have been Next().
226 // * count must be less than or equal to the size of the last buffer
227 // returned by Next().
228 // * The caller must not have written anything to the last "count" bytes
229 // of that buffer.
230 //
231 // Postconditions:
232 // * The last "count" bytes of the last buffer returned by Next() will be
233 // ignored.
234 virtual void BackUp(int count) = 0;
235
236 // Returns the total number of bytes written since this object was created.
237 virtual int64_t ByteCount() const = 0;
238
239 // Write a given chunk of data to the output. Some output streams may
240 // implement this in a way that avoids copying. Check AllowsAliasing() before
241 // calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is
242 // called on a stream that does not allow aliasing.
243 //
244 // NOTE: It is caller's responsibility to ensure that the chunk of memory
245 // remains live until all of the data has been consumed from the stream.
246 virtual bool WriteAliasedRaw(const void* data, int size);
247 virtual bool AllowsAliasing() const { return false; }
248
249
250 private:
251 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream);
252};
253
254} // namespace io
255} // namespace protobuf
256} // namespace google
257
258#include <google/protobuf/port_undef.inc>
259
260#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
261