| // Protocol Buffers - Google's data interchange format | |
| // Copyright 2008 Google Inc. All rights reserved. | |
| // https://developers.google.com/protocol-buffers/ | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are | |
| // met: | |
| // | |
| // * Redistributions of source code must retain the above copyright | |
| // notice, this list of conditions and the following disclaimer. | |
| // * Redistributions in binary form must reproduce the above | |
| // copyright notice, this list of conditions and the following disclaimer | |
| // in the documentation and/or other materials provided with the | |
| // distribution. | |
| // * Neither the name of Google Inc. nor the names of its | |
| // contributors may be used to endorse or promote products derived from | |
| // this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| // Author: kenton@google.com (Kenton Varda) | |
| // Based on original Protocol Buffers design by | |
| // Sanjay Ghemawat, Jeff Dean, and others. | |
| // | |
| // This file contains the ZeroCopyInputStream and ZeroCopyOutputStream | |
| // interfaces, which represent abstract I/O streams to and from which | |
| // protocol buffers can be read and written. For a few simple | |
| // implementations of these interfaces, see zero_copy_stream_impl.h. | |
| // | |
| // These interfaces are different from classic I/O streams in that they | |
| // try to minimize the amount of data copying that needs to be done. | |
| // To accomplish this, responsibility for allocating buffers is moved to | |
| // the stream object, rather than being the responsibility of the caller. | |
| // So, the stream can return a buffer which actually points directly into | |
| // the final data structure where the bytes are to be stored, and the caller | |
| // can interact directly with that buffer, eliminating an intermediate copy | |
| // operation. | |
| // | |
| // As an example, consider the common case in which you are reading bytes | |
| // from an array that is already in memory (or perhaps an mmap()ed file). | |
| // With classic I/O streams, you would do something like: | |
| // char buffer[BUFFER_SIZE]; | |
| // input->Read(buffer, BUFFER_SIZE); | |
| // DoSomething(buffer, BUFFER_SIZE); | |
| // Then, the stream basically just calls memcpy() to copy the data from | |
| // the array into your buffer. With a ZeroCopyInputStream, you would do | |
| // this instead: | |
| // const void* buffer; | |
| // int size; | |
| // input->Next(&buffer, &size); | |
| // DoSomething(buffer, size); | |
| // Here, no copy is performed. The input stream returns a pointer directly | |
| // into the backing array, and the caller ends up reading directly from it. | |
| // | |
| // If you want to be able to read the old-fashion way, you can create | |
| // a CodedInputStream or CodedOutputStream wrapping these objects and use | |
| // their ReadRaw()/WriteRaw() methods. These will, of course, add a copy | |
| // step, but Coded*Stream will handle buffering so at least it will be | |
| // reasonably efficient. | |
| // | |
| // ZeroCopyInputStream example: | |
| // // Read in a file and print its contents to stdout. | |
| // int fd = open("myfile", O_RDONLY); | |
| // ZeroCopyInputStream* input = new FileInputStream(fd); | |
| // | |
| // const void* buffer; | |
| // int size; | |
| // while (input->Next(&buffer, &size)) { | |
| // cout.write(buffer, size); | |
| // } | |
| // | |
| // delete input; | |
| // close(fd); | |
| // | |
| // ZeroCopyOutputStream example: | |
| // // Copy the contents of "infile" to "outfile", using plain read() for | |
| // // "infile" but a ZeroCopyOutputStream for "outfile". | |
| // int infd = open("infile", O_RDONLY); | |
| // int outfd = open("outfile", O_WRONLY); | |
| // ZeroCopyOutputStream* output = new FileOutputStream(outfd); | |
| // | |
| // void* buffer; | |
| // int size; | |
| // while (output->Next(&buffer, &size)) { | |
| // int bytes = read(infd, buffer, size); | |
| // if (bytes < size) { | |
| // // Reached EOF. | |
| // output->BackUp(size - bytes); | |
| // break; | |
| // } | |
| // } | |
| // | |
| // delete output; | |
| // close(infd); | |
| // close(outfd); | |
| namespace google { | |
| namespace protobuf { | |
| namespace io { | |
| // Defined in this file. | |
| class ZeroCopyInputStream; | |
| class ZeroCopyOutputStream; | |
| // Abstract interface similar to an input stream but designed to minimize | |
| // copying. | |
| class LIBPROTOBUF_EXPORT ZeroCopyInputStream { | |
| public: | |
| ZeroCopyInputStream() {} | |
| virtual ~ZeroCopyInputStream() {} | |
| // Obtains a chunk of data from the stream. | |
| // | |
| // Preconditions: | |
| // * "size" and "data" are not NULL. | |
| // | |
| // Postconditions: | |
| // * If the returned value is false, there is no more data to return or | |
| // an error occurred. All errors are permanent. | |
| // * Otherwise, "size" points to the actual number of bytes read and "data" | |
| // points to a pointer to a buffer containing these bytes. | |
| // * Ownership of this buffer remains with the stream, and the buffer | |
| // remains valid only until some other method of the stream is called | |
| // or the stream is destroyed. | |
| // * It is legal for the returned buffer to have zero size, as long | |
| // as repeatedly calling Next() eventually yields a buffer with non-zero | |
| // size. | |
| virtual bool Next(const void** data, int* size) = 0; | |
| // Backs up a number of bytes, so that the next call to Next() returns | |
| // data again that was already returned by the last call to Next(). This | |
| // is useful when writing procedures that are only supposed to read up | |
| // to a certain point in the input, then return. If Next() returns a | |
| // buffer that goes beyond what you wanted to read, you can use BackUp() | |
| // to return to the point where you intended to finish. | |
| // | |
| // Preconditions: | |
| // * The last method called must have been Next(). | |
| // * count must be less than or equal to the size of the last buffer | |
| // returned by Next(). | |
| // | |
| // Postconditions: | |
| // * The last "count" bytes of the last buffer returned by Next() will be | |
| // pushed back into the stream. Subsequent calls to Next() will return | |
| // the same data again before producing new data. | |
| virtual void BackUp(int count) = 0; | |
| // Skips a number of bytes. Returns false if the end of the stream is | |
| // reached or some input error occurred. In the end-of-stream case, the | |
| // stream is advanced to the end of the stream (so ByteCount() will return | |
| // the total size of the stream). | |
| virtual bool Skip(int count) = 0; | |
| // Returns the total number of bytes read since this object was created. | |
| virtual int64 ByteCount() const = 0; | |
| private: | |
| GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream); | |
| }; | |
| // Abstract interface similar to an output stream but designed to minimize | |
| // copying. | |
| class LIBPROTOBUF_EXPORT ZeroCopyOutputStream { | |
| public: | |
| ZeroCopyOutputStream() {} | |
| virtual ~ZeroCopyOutputStream() {} | |
| // Obtains a buffer into which data can be written. Any data written | |
| // into this buffer will eventually (maybe instantly, maybe later on) | |
| // be written to the output. | |
| // | |
| // Preconditions: | |
| // * "size" and "data" are not NULL. | |
| // | |
| // Postconditions: | |
| // * If the returned value is false, an error occurred. All errors are | |
| // permanent. | |
| // * Otherwise, "size" points to the actual number of bytes in the buffer | |
| // and "data" points to the buffer. | |
| // * Ownership of this buffer remains with the stream, and the buffer | |
| // remains valid only until some other method of the stream is called | |
| // or the stream is destroyed. | |
| // * Any data which the caller stores in this buffer will eventually be | |
| // written to the output (unless BackUp() is called). | |
| // * It is legal for the returned buffer to have zero size, as long | |
| // as repeatedly calling Next() eventually yields a buffer with non-zero | |
| // size. | |
| virtual bool Next(void** data, int* size) = 0; | |
| // Backs up a number of bytes, so that the end of the last buffer returned | |
| // by Next() is not actually written. This is needed when you finish | |
| // writing all the data you want to write, but the last buffer was bigger | |
| // than you needed. You don't want to write a bunch of garbage after the | |
| // end of your data, so you use BackUp() to back up. | |
| // | |
| // Preconditions: | |
| // * The last method called must have been Next(). | |
| // * count must be less than or equal to the size of the last buffer | |
| // returned by Next(). | |
| // * The caller must not have written anything to the last "count" bytes | |
| // of that buffer. | |
| // | |
| // Postconditions: | |
| // * The last "count" bytes of the last buffer returned by Next() will be | |
| // ignored. | |
| virtual void BackUp(int count) = 0; | |
| // Returns the total number of bytes written since this object was created. | |
| virtual int64 ByteCount() const = 0; | |
| // Write a given chunk of data to the output. Some output streams may | |
| // implement this in a way that avoids copying. Check AllowsAliasing() before | |
| // calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is | |
| // called on a stream that does not allow aliasing. | |
| // | |
| // NOTE: It is caller's responsibility to ensure that the chunk of memory | |
| // remains live until all of the data has been consumed from the stream. | |
| virtual bool WriteAliasedRaw(const void* data, int size); | |
| virtual bool AllowsAliasing() const { return false; } | |
| private: | |
| GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream); | |
| }; | |
| } // namespace io | |
| } // namespace protobuf | |
| } // namespace google | |