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