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 113namespace google { 114 115namespace protobuf { 116namespace io { 117 118// Defined in this file. 119class ZeroCopyInputStream; 120class ZeroCopyOutputStream; 121 122// Abstract interface similar to an input stream but designed to minimize 123// copying. 124class LIBPROTOBUF_EXPORT ZeroCopyInputStream { 125 public: 126 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. 181class LIBPROTOBUF_EXPORT ZeroCopyOutputStream { 182 public: 183 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 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__ 249