1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // http://code.google.com/p/protobuf/ 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 (at) 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 namespace google { 114 115 namespace protobuf { 116 namespace io { 117 118 // Defined in this file. 119 class ZeroCopyInputStream; 120 class ZeroCopyOutputStream; 121 122 // Abstract interface similar to an input stream but designed to minimize 123 // copying. 124 class 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. 181 class 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 230 private: 231 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream); 232 }; 233 234 } // namespace io 235 } // namespace protobuf 236 237 } // namespace google 238 #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ 239