|
||||
File indexing completed on 2025-01-31 10:12:02
0001 // Protocol Buffers - Google's data interchange format 0002 // Copyright 2008 Google Inc. All rights reserved. 0003 // 0004 // Use of this source code is governed by a BSD-style 0005 // license that can be found in the LICENSE file or at 0006 // https://developers.google.com/open-source/licenses/bsd 0007 0008 // Author: kenton@google.com (Kenton Varda) 0009 // Based on original Protocol Buffers design by 0010 // Sanjay Ghemawat, Jeff Dean, and others. 0011 // 0012 // This file contains the ZeroCopyInputStream and ZeroCopyOutputStream 0013 // interfaces, which represent abstract I/O streams to and from which 0014 // protocol buffers can be read and written. For a few simple 0015 // implementations of these interfaces, see zero_copy_stream_impl.h. 0016 // 0017 // These interfaces are different from classic I/O streams in that they 0018 // try to minimize the amount of data copying that needs to be done. 0019 // To accomplish this, responsibility for allocating buffers is moved to 0020 // the stream object, rather than being the responsibility of the caller. 0021 // So, the stream can return a buffer which actually points directly into 0022 // the final data structure where the bytes are to be stored, and the caller 0023 // can interact directly with that buffer, eliminating an intermediate copy 0024 // operation. 0025 // 0026 // As an example, consider the common case in which you are reading bytes 0027 // from an array that is already in memory (or perhaps an mmap()ed file). 0028 // With classic I/O streams, you would do something like: 0029 // char buffer[BUFFER_SIZE]; 0030 // input->Read(buffer, BUFFER_SIZE); 0031 // DoSomething(buffer, BUFFER_SIZE); 0032 // Then, the stream basically just calls memcpy() to copy the data from 0033 // the array into your buffer. With a ZeroCopyInputStream, you would do 0034 // this instead: 0035 // const void* buffer; 0036 // int size; 0037 // input->Next(&buffer, &size); 0038 // DoSomething(buffer, size); 0039 // Here, no copy is performed. The input stream returns a pointer directly 0040 // into the backing array, and the caller ends up reading directly from it. 0041 // 0042 // If you want to be able to read the old-fashion way, you can create 0043 // a CodedInputStream or CodedOutputStream wrapping these objects and use 0044 // their ReadRaw()/WriteRaw() methods. These will, of course, add a copy 0045 // step, but Coded*Stream will handle buffering so at least it will be 0046 // reasonably efficient. 0047 // 0048 // ZeroCopyInputStream example: 0049 // // Read in a file and print its contents to stdout. 0050 // int fd = open("myfile", O_RDONLY); 0051 // ZeroCopyInputStream* input = new FileInputStream(fd); 0052 // 0053 // const void* buffer; 0054 // int size; 0055 // while (input->Next(&buffer, &size)) { 0056 // cout.write(buffer, size); 0057 // } 0058 // 0059 // delete input; 0060 // close(fd); 0061 // 0062 // ZeroCopyOutputStream example: 0063 // // Copy the contents of "infile" to "outfile", using plain read() for 0064 // // "infile" but a ZeroCopyOutputStream for "outfile". 0065 // int infd = open("infile", O_RDONLY); 0066 // int outfd = open("outfile", O_WRONLY); 0067 // ZeroCopyOutputStream* output = new FileOutputStream(outfd); 0068 // 0069 // void* buffer; 0070 // int size; 0071 // while (output->Next(&buffer, &size)) { 0072 // int bytes = read(infd, buffer, size); 0073 // if (bytes < size) { 0074 // // Reached EOF. 0075 // output->BackUp(size - bytes); 0076 // break; 0077 // } 0078 // } 0079 // 0080 // delete output; 0081 // close(infd); 0082 // close(outfd); 0083 0084 #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ 0085 #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ 0086 0087 #include "google/protobuf/stubs/common.h" 0088 #include "absl/strings/cord.h" 0089 #include "google/protobuf/port.h" 0090 0091 0092 // Must be included last. 0093 #include "google/protobuf/port_def.inc" 0094 0095 namespace google { 0096 namespace protobuf { 0097 namespace io { 0098 0099 // Abstract interface similar to an input stream but designed to minimize 0100 // copying. 0101 class PROTOBUF_EXPORT ZeroCopyInputStream { 0102 public: 0103 ZeroCopyInputStream() = default; 0104 virtual ~ZeroCopyInputStream() = default; 0105 0106 ZeroCopyInputStream(const ZeroCopyInputStream&) = delete; 0107 ZeroCopyInputStream& operator=(const ZeroCopyInputStream&) = delete; 0108 ZeroCopyInputStream(ZeroCopyInputStream&&) = delete; 0109 ZeroCopyInputStream& operator=(ZeroCopyInputStream&&) = delete; 0110 0111 // Obtains a chunk of data from the stream. 0112 // 0113 // Preconditions: 0114 // * "size" and "data" are not NULL. 0115 // 0116 // Postconditions: 0117 // * If the returned value is false, there is no more data to return or 0118 // an error occurred. All errors are permanent. 0119 // * Otherwise, "size" points to the actual number of bytes read and "data" 0120 // points to a pointer to a buffer containing these bytes. 0121 // * Ownership of this buffer remains with the stream, and the buffer 0122 // remains valid only until some other method of the stream is called 0123 // or the stream is destroyed. 0124 // * It is legal for the returned buffer to have zero size, as long 0125 // as repeatedly calling Next() eventually yields a buffer with non-zero 0126 // size. 0127 virtual bool Next(const void** data, int* size) = 0; 0128 0129 // Backs up a number of bytes, so that the next call to Next() returns 0130 // data again that was already returned by the last call to Next(). This 0131 // is useful when writing procedures that are only supposed to read up 0132 // to a certain point in the input, then return. If Next() returns a 0133 // buffer that goes beyond what you wanted to read, you can use BackUp() 0134 // to return to the point where you intended to finish. 0135 // 0136 // Preconditions: 0137 // * The last method called must have been Next(). 0138 // * count must be less than or equal to the size of the last buffer 0139 // returned by Next(). 0140 // 0141 // Postconditions: 0142 // * The last "count" bytes of the last buffer returned by Next() will be 0143 // pushed back into the stream. Subsequent calls to Next() will return 0144 // the same data again before producing new data. 0145 virtual void BackUp(int count) = 0; 0146 0147 // Skips `count` number of bytes. 0148 // Returns true on success, or false if some input error occurred, or `count` 0149 // exceeds the end of the stream. This function may skip up to `count - 1` 0150 // bytes in case of failure. 0151 // 0152 // Preconditions: 0153 // * `count` is non-negative. 0154 // 0155 virtual bool Skip(int count) = 0; 0156 0157 // Returns the total number of bytes read since this object was created. 0158 virtual int64_t ByteCount() const = 0; 0159 0160 // Read the next `count` bytes and append it to the given Cord. 0161 // 0162 // In the case of a read error, the method reads as much data as possible into 0163 // the cord before returning false. The default implementation iterates over 0164 // the buffers and appends up to `count` bytes of data into `cord` using the 0165 // `absl::CordBuffer` API. 0166 // 0167 // Some streams may implement this in a way that avoids copying by sharing or 0168 // reference counting existing data managed by the stream implementation. 0169 // 0170 virtual bool ReadCord(absl::Cord* cord, int count); 0171 0172 }; 0173 0174 // Abstract interface similar to an output stream but designed to minimize 0175 // copying. 0176 class PROTOBUF_EXPORT ZeroCopyOutputStream { 0177 public: 0178 ZeroCopyOutputStream() {} 0179 ZeroCopyOutputStream(const ZeroCopyOutputStream&) = delete; 0180 ZeroCopyOutputStream& operator=(const ZeroCopyOutputStream&) = delete; 0181 virtual ~ZeroCopyOutputStream() {} 0182 0183 // Obtains a buffer into which data can be written. Any data written 0184 // into this buffer will eventually (maybe instantly, maybe later on) 0185 // be written to the output. 0186 // 0187 // Preconditions: 0188 // * "size" and "data" are not NULL. 0189 // 0190 // Postconditions: 0191 // * If the returned value is false, an error occurred. All errors are 0192 // permanent. 0193 // * Otherwise, "size" points to the actual number of bytes in the buffer 0194 // and "data" points to the buffer. 0195 // * Ownership of this buffer remains with the stream, and the buffer 0196 // remains valid only until some other method of the stream is called 0197 // or the stream is destroyed. 0198 // * Any data which the caller stores in this buffer will eventually be 0199 // written to the output (unless BackUp() is called). 0200 // * It is legal for the returned buffer to have zero size, as long 0201 // as repeatedly calling Next() eventually yields a buffer with non-zero 0202 // size. 0203 virtual bool Next(void** data, int* size) = 0; 0204 0205 // Backs up a number of bytes, so that the end of the last buffer returned 0206 // by Next() is not actually written. This is needed when you finish 0207 // writing all the data you want to write, but the last buffer was bigger 0208 // than you needed. You don't want to write a bunch of garbage after the 0209 // end of your data, so you use BackUp() to back up. 0210 // 0211 // This method can be called with `count = 0` to finalize (flush) any 0212 // previously returned buffer. For example, a file output stream can 0213 // flush buffers returned from a previous call to Next() upon such 0214 // BackUp(0) invocations. ZeroCopyOutputStream callers should always 0215 // invoke BackUp() after a final Next() call, even if there is no 0216 // excess buffer data to be backed up to indicate a flush point. 0217 // 0218 // Preconditions: 0219 // * The last method called must have been Next(). 0220 // * count must be less than or equal to the size of the last buffer 0221 // returned by Next(). 0222 // * The caller must not have written anything to the last "count" bytes 0223 // of that buffer. 0224 // 0225 // Postconditions: 0226 // * The last "count" bytes of the last buffer returned by Next() will be 0227 // ignored. 0228 virtual void BackUp(int count) = 0; 0229 0230 // Returns the total number of bytes written since this object was created. 0231 virtual int64_t ByteCount() const = 0; 0232 0233 // Write a given chunk of data to the output. Some output streams may 0234 // implement this in a way that avoids copying. Check AllowsAliasing() before 0235 // calling WriteAliasedRaw(). It will ABSL_CHECK fail if WriteAliasedRaw() is 0236 // called on a stream that does not allow aliasing. 0237 // 0238 // NOTE: It is caller's responsibility to ensure that the chunk of memory 0239 // remains live until all of the data has been consumed from the stream. 0240 virtual bool WriteAliasedRaw(const void* data, int size); 0241 virtual bool AllowsAliasing() const { return false; } 0242 0243 // Writes the given Cord to the output. 0244 // 0245 // The default implementation iterates over all Cord chunks copying all cord 0246 // data into the buffer(s) returned by the stream's `Next()` method. 0247 // 0248 // Some streams may implement this in a way that avoids copying the cord 0249 // data by copying and managing a copy of the provided cord instead. 0250 virtual bool WriteCord(const absl::Cord& cord); 0251 0252 }; 0253 0254 } // namespace io 0255 } // namespace protobuf 0256 } // namespace google 0257 0258 #include "google/protobuf/port_undef.inc" 0259 0260 #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |