// 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: [email protected] (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // // This file contains common implementations of the interfaces defined in // zero_copy_stream.h which are included in the "lite" protobuf library. // These implementations cover I/O on raw arrays and strings, as well as // adaptors which make it easy to implement streams based on traditional // streams. Of course, many users will probably want to write their own // implementations of these interfaces specific to the particular I/O // abstractions they prefer to use, but these should cover the most common // cases. #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ #include <iosfwd> #include <memory> #include <string> #include <google/protobuf/stubs/callback.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/stubs/stl_util.h> // Must be included last. #include <google/protobuf/port_def.inc> namespace google { namespace protobuf { namespace io { // =================================================================== // A ZeroCopyInputStream backed by an in-memory array of bytes. class PROTOBUF_EXPORT ArrayInputStream PROTOBUF_FUTURE_FINAL : public ZeroCopyInputStream { … }; // =================================================================== // A ZeroCopyOutputStream backed by an in-memory array of bytes. class PROTOBUF_EXPORT ArrayOutputStream PROTOBUF_FUTURE_FINAL : public ZeroCopyOutputStream { … }; // =================================================================== // A ZeroCopyOutputStream which appends bytes to a string. class PROTOBUF_EXPORT StringOutputStream PROTOBUF_FUTURE_FINAL : public ZeroCopyOutputStream { … }; // Note: There is no StringInputStream. Instead, just create an // ArrayInputStream as follows: // ArrayInputStream input(str.data(), str.size()); // =================================================================== // A generic traditional input stream interface. // // Lots of traditional input streams (e.g. file descriptors, C stdio // streams, and C++ iostreams) expose an interface where every read // involves copying bytes into a buffer. If you want to take such an // interface and make a ZeroCopyInputStream based on it, simply implement // CopyingInputStream and then use CopyingInputStreamAdaptor. // // CopyingInputStream implementations should avoid buffering if possible. // CopyingInputStreamAdaptor does its own buffering and will read data // in large blocks. class PROTOBUF_EXPORT CopyingInputStream { … }; // A ZeroCopyInputStream which reads from a CopyingInputStream. This is // useful for implementing ZeroCopyInputStreams that read from traditional // streams. Note that this class is not really zero-copy. // // If you want to read from file descriptors or C++ istreams, this is // already implemented for you: use FileInputStream or IstreamInputStream // respectively. class PROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream { … }; // =================================================================== // A generic traditional output stream interface. // // Lots of traditional output streams (e.g. file descriptors, C stdio // streams, and C++ iostreams) expose an interface where every write // involves copying bytes from a buffer. If you want to take such an // interface and make a ZeroCopyOutputStream based on it, simply implement // CopyingOutputStream and then use CopyingOutputStreamAdaptor. // // CopyingOutputStream implementations should avoid buffering if possible. // CopyingOutputStreamAdaptor does its own buffering and will write data // in large blocks. class PROTOBUF_EXPORT CopyingOutputStream { … }; // A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is // useful for implementing ZeroCopyOutputStreams that write to traditional // streams. Note that this class is not really zero-copy. // // If you want to write to file descriptors or C++ ostreams, this is // already implemented for you: use FileOutputStream or OstreamOutputStream // respectively. class PROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream { … }; // =================================================================== // A ZeroCopyInputStream which wraps some other stream and limits it to // a particular byte count. class PROTOBUF_EXPORT LimitingInputStream PROTOBUF_FUTURE_FINAL : public ZeroCopyInputStream { … }; // =================================================================== // mutable_string_data() and as_string_data() are workarounds to improve // the performance of writing new data to an existing string. Unfortunately // the methods provided by the string class are suboptimal, and using memcpy() // is mildly annoying because it requires its pointer args to be non-NULL even // if we ask it to copy 0 bytes. Furthermore, string_as_array() has the // property that it always returns NULL if its arg is the empty string, exactly // what we want to avoid if we're using it in conjunction with memcpy()! // With C++11, the desired memcpy() boils down to memcpy(..., &(*s)[0], size), // where s is a string*. Without C++11, &(*s)[0] is not guaranteed to be safe, // so we use string_as_array(), and live with the extra logic that tests whether // *s is empty. // Return a pointer to mutable characters underlying the given string. The // return value is valid until the next time the string is resized. We // trust the caller to treat the return value as an array of length s->size(). inline char* mutable_string_data(std::string* s) { … } // as_string_data(s) is equivalent to // ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); }) // Sometimes it's faster: in some scenarios p cannot be NULL, and then the // code can avoid that check. inline std::pair<char*, bool> as_string_data(std::string* s) { … } } // namespace io } // namespace protobuf } // namespace google #include <google/protobuf/port_undef.inc> #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__