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 <string>
48 : #include <iosfwd>
49 : #include <google/protobuf/io/zero_copy_stream.h>
50 : #include <google/protobuf/stubs/common.h>
51 : #include <google/protobuf/stubs/scoped_ptr.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 is mutated in arbitrary
132 : // ways and MUST NOT be accessed in any way until you're done with the
133 : // stream. Either be sure there's no further usage, or (safest) destroy the
134 : // stream before using the contents.
135 : //
136 : // Hint: If you call target->reserve(n) before creating the stream,
137 : // the first call to Next() will return at least n bytes of buffer
138 : // space.
139 : explicit StringOutputStream(string* target);
140 : ~StringOutputStream();
141 :
142 : // implements ZeroCopyOutputStream ---------------------------------
143 : bool Next(void** data, int* size);
144 : void BackUp(int count);
145 : int64 ByteCount() const;
146 :
147 : private:
148 : static const int kMinimumSize = 16;
149 :
150 : string* target_;
151 :
152 : GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
153 : };
154 :
155 : // Note: There is no StringInputStream. Instead, just create an
156 : // ArrayInputStream as follows:
157 : // ArrayInputStream input(str.data(), str.size());
158 :
159 : // ===================================================================
160 :
161 : // A generic traditional input stream interface.
162 : //
163 : // Lots of traditional input streams (e.g. file descriptors, C stdio
164 : // streams, and C++ iostreams) expose an interface where every read
165 : // involves copying bytes into a buffer. If you want to take such an
166 : // interface and make a ZeroCopyInputStream based on it, simply implement
167 : // CopyingInputStream and then use CopyingInputStreamAdaptor.
168 : //
169 : // CopyingInputStream implementations should avoid buffering if possible.
170 : // CopyingInputStreamAdaptor does its own buffering and will read data
171 : // in large blocks.
172 143 : class LIBPROTOBUF_EXPORT CopyingInputStream {
173 : public:
174 : virtual ~CopyingInputStream();
175 :
176 : // Reads up to "size" bytes into the given buffer. Returns the number of
177 : // bytes read. Read() waits until at least one byte is available, or
178 : // returns zero if no bytes will ever become available (EOF), or -1 if a
179 : // permanent read error occurred.
180 : virtual int Read(void* buffer, int size) = 0;
181 :
182 : // Skips the next "count" bytes of input. Returns the number of bytes
183 : // actually skipped. This will always be exactly equal to "count" unless
184 : // EOF was reached or a permanent read error occurred.
185 : //
186 : // The default implementation just repeatedly calls Read() into a scratch
187 : // buffer.
188 : virtual int Skip(int count);
189 : };
190 :
191 : // A ZeroCopyInputStream which reads from a CopyingInputStream. This is
192 : // useful for implementing ZeroCopyInputStreams that read from traditional
193 : // streams. Note that this class is not really zero-copy.
194 : //
195 : // If you want to read from file descriptors or C++ istreams, this is
196 : // already implemented for you: use FileInputStream or IstreamInputStream
197 : // respectively.
198 : class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
199 : public:
200 : // Creates a stream that reads from the given CopyingInputStream.
201 : // If a block_size is given, it specifies the number of bytes that
202 : // should be read and returned with each call to Next(). Otherwise,
203 : // a reasonable default is used. The caller retains ownership of
204 : // copying_stream unless SetOwnsCopyingStream(true) is called.
205 : explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
206 : int block_size = -1);
207 : ~CopyingInputStreamAdaptor();
208 :
209 : // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
210 : // delete the underlying CopyingInputStream when it is destroyed.
211 : void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
212 :
213 : // implements ZeroCopyInputStream ----------------------------------
214 : bool Next(const void** data, int* size);
215 : void BackUp(int count);
216 : bool Skip(int count);
217 : int64 ByteCount() const;
218 :
219 : private:
220 : // Insures that buffer_ is not NULL.
221 : void AllocateBufferIfNeeded();
222 : // Frees the buffer and resets buffer_used_.
223 : void FreeBuffer();
224 :
225 : // The underlying copying stream.
226 : CopyingInputStream* copying_stream_;
227 : bool owns_copying_stream_;
228 :
229 : // True if we have seen a permenant error from the underlying stream.
230 : bool failed_;
231 :
232 : // The current position of copying_stream_, relative to the point where
233 : // we started reading.
234 : int64 position_;
235 :
236 : // Data is read into this buffer. It may be NULL if no buffer is currently
237 : // in use. Otherwise, it points to an array of size buffer_size_.
238 : scoped_array<uint8> buffer_;
239 : const int buffer_size_;
240 :
241 : // Number of valid bytes currently in the buffer (i.e. the size last
242 : // returned by Next()). 0 <= buffer_used_ <= buffer_size_.
243 : int buffer_used_;
244 :
245 : // Number of bytes in the buffer which were backed up over by a call to
246 : // BackUp(). These need to be returned again.
247 : // 0 <= backup_bytes_ <= buffer_used_
248 : int backup_bytes_;
249 :
250 : GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
251 : };
252 :
253 : // ===================================================================
254 :
255 : // A generic traditional output stream interface.
256 : //
257 : // Lots of traditional output streams (e.g. file descriptors, C stdio
258 : // streams, and C++ iostreams) expose an interface where every write
259 : // involves copying bytes from a buffer. If you want to take such an
260 : // interface and make a ZeroCopyOutputStream based on it, simply implement
261 : // CopyingOutputStream and then use CopyingOutputStreamAdaptor.
262 : //
263 : // CopyingOutputStream implementations should avoid buffering if possible.
264 : // CopyingOutputStreamAdaptor does its own buffering and will write data
265 : // in large blocks.
266 8 : class LIBPROTOBUF_EXPORT CopyingOutputStream {
267 : public:
268 : virtual ~CopyingOutputStream();
269 :
270 : // Writes "size" bytes from the given buffer to the output. Returns true
271 : // if successful, false on a write error.
272 : virtual bool Write(const void* buffer, int size) = 0;
273 : };
274 :
275 : // A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is
276 : // useful for implementing ZeroCopyOutputStreams that write to traditional
277 : // streams. Note that this class is not really zero-copy.
278 : //
279 : // If you want to write to file descriptors or C++ ostreams, this is
280 : // already implemented for you: use FileOutputStream or OstreamOutputStream
281 : // respectively.
282 : class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
283 : public:
284 : // Creates a stream that writes to the given Unix file descriptor.
285 : // If a block_size is given, it specifies the size of the buffers
286 : // that should be returned by Next(). Otherwise, a reasonable default
287 : // is used.
288 : explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
289 : int block_size = -1);
290 : ~CopyingOutputStreamAdaptor();
291 :
292 : // Writes all pending data to the underlying stream. Returns false if a
293 : // write error occurred on the underlying stream. (The underlying
294 : // stream itself is not necessarily flushed.)
295 : bool Flush();
296 :
297 : // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
298 : // delete the underlying CopyingOutputStream when it is destroyed.
299 : void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
300 :
301 : // implements ZeroCopyOutputStream ---------------------------------
302 : bool Next(void** data, int* size);
303 : void BackUp(int count);
304 : int64 ByteCount() const;
305 :
306 : private:
307 : // Write the current buffer, if it is present.
308 : bool WriteBuffer();
309 : // Insures that buffer_ is not NULL.
310 : void AllocateBufferIfNeeded();
311 : // Frees the buffer.
312 : void FreeBuffer();
313 :
314 : // The underlying copying stream.
315 : CopyingOutputStream* copying_stream_;
316 : bool owns_copying_stream_;
317 :
318 : // True if we have seen a permenant error from the underlying stream.
319 : bool failed_;
320 :
321 : // The current position of copying_stream_, relative to the point where
322 : // we started writing.
323 : int64 position_;
324 :
325 : // Data is written from this buffer. It may be NULL if no buffer is
326 : // currently in use. Otherwise, it points to an array of size buffer_size_.
327 : scoped_array<uint8> buffer_;
328 : const int buffer_size_;
329 :
330 : // Number of valid bytes currently in the buffer (i.e. the size last
331 : // returned by Next()). When BackUp() is called, we just reduce this.
332 : // 0 <= buffer_used_ <= buffer_size_.
333 : int buffer_used_;
334 :
335 : GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
336 : };
337 :
338 : // ===================================================================
339 :
340 : // mutable_string_data() and as_string_data() are workarounds to improve
341 : // the performance of writing new data to an existing string. Unfortunately
342 : // the methods provided by the string class are suboptimal, and using memcpy()
343 : // is mildly annoying because it requires its pointer args to be non-NULL even
344 : // if we ask it to copy 0 bytes. Furthermore, string_as_array() has the
345 : // property that it always returns NULL if its arg is the empty string, exactly
346 : // what we want to avoid if we're using it in conjunction with memcpy()!
347 : // With C++11, the desired memcpy() boils down to memcpy(..., &(*s)[0], size),
348 : // where s is a string*. Without C++11, &(*s)[0] is not guaranteed to be safe,
349 : // so we use string_as_array(), and live with the extra logic that tests whether
350 : // *s is empty.
351 :
352 : // Return a pointer to mutable characters underlying the given string. The
353 : // return value is valid until the next time the string is resized. We
354 : // trust the caller to treat the return value as an array of length s->size().
355 : inline char* mutable_string_data(string* s) {
356 : #ifdef LANG_CXX11
357 : // This should be simpler & faster than string_as_array() because the latter
358 : // is guaranteed to return NULL when *s is empty, so it has to check for that.
359 : return &(*s)[0];
360 : #else
361 1522395 : return string_as_array(s);
362 : #endif
363 : }
364 :
365 : // as_string_data(s) is equivalent to
366 : // ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); })
367 : // Sometimes it's faster: in some scenarios p cannot be NULL, and then the
368 : // code can avoid that check.
369 1518553 : inline std::pair<char*, bool> as_string_data(string* s) {
370 1518584 : char *p = mutable_string_data(s);
371 : #ifdef LANG_CXX11
372 : return std::make_pair(p, true);
373 : #else
374 3037168 : return make_pair(p, p != NULL);
375 : #endif
376 : }
377 :
378 : } // namespace io
379 : } // namespace protobuf
380 :
381 : } // namespace google
382 : #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|