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