Home | History | Annotate | Download | only in io
      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