Back to home page

EIC code displayed by LXR

 
 

    


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__