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