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