zero_copy_stream.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  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. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. //
  34. // This file contains the ZeroCopyInputStream and ZeroCopyOutputStream
  35. // interfaces, which represent abstract I/O streams to and from which
  36. // protocol buffers can be read and written. For a few simple
  37. // implementations of these interfaces, see zero_copy_stream_impl.h.
  38. //
  39. // These interfaces are different from classic I/O streams in that they
  40. // try to minimize the amount of data copying that needs to be done.
  41. // To accomplish this, responsibility for allocating buffers is moved to
  42. // the stream object, rather than being the responsibility of the caller.
  43. // So, the stream can return a buffer which actually points directly into
  44. // the final data structure where the bytes are to be stored, and the caller
  45. // can interact directly with that buffer, eliminating an intermediate copy
  46. // operation.
  47. //
  48. // As an example, consider the common case in which you are reading bytes
  49. // from an array that is already in memory (or perhaps an mmap()ed file).
  50. // With classic I/O streams, you would do something like:
  51. // char buffer[BUFFER_SIZE];
  52. // input->Read(buffer, BUFFER_SIZE);
  53. // DoSomething(buffer, BUFFER_SIZE);
  54. // Then, the stream basically just calls memcpy() to copy the data from
  55. // the array into your buffer. With a ZeroCopyInputStream, you would do
  56. // this instead:
  57. // const void* buffer;
  58. // int size;
  59. // input->Next(&buffer, &size);
  60. // DoSomething(buffer, size);
  61. // Here, no copy is performed. The input stream returns a pointer directly
  62. // into the backing array, and the caller ends up reading directly from it.
  63. //
  64. // If you want to be able to read the old-fashion way, you can create
  65. // a CodedInputStream or CodedOutputStream wrapping these objects and use
  66. // their ReadRaw()/WriteRaw() methods. These will, of course, add a copy
  67. // step, but Coded*Stream will handle buffering so at least it will be
  68. // reasonably efficient.
  69. //
  70. // ZeroCopyInputStream example:
  71. // // Read in a file and print its contents to stdout.
  72. // int fd = open("myfile", O_RDONLY);
  73. // ZeroCopyInputStream* input = new FileInputStream(fd);
  74. //
  75. // const void* buffer;
  76. // int size;
  77. // while (input->Next(&buffer, &size)) {
  78. // cout.write(buffer, size);
  79. // }
  80. //
  81. // delete input;
  82. // close(fd);
  83. //
  84. // ZeroCopyOutputStream example:
  85. // // Copy the contents of "infile" to "outfile", using plain read() for
  86. // // "infile" but a ZeroCopyOutputStream for "outfile".
  87. // int infd = open("infile", O_RDONLY);
  88. // int outfd = open("outfile", O_WRONLY);
  89. // ZeroCopyOutputStream* output = new FileOutputStream(outfd);
  90. //
  91. // void* buffer;
  92. // int size;
  93. // while (output->Next(&buffer, &size)) {
  94. // int bytes = read(infd, buffer, size);
  95. // if (bytes < size) {
  96. // // Reached EOF.
  97. // output->BackUp(size - bytes);
  98. // break;
  99. // }
  100. // }
  101. //
  102. // delete output;
  103. // close(infd);
  104. // close(outfd);
  105. #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
  106. #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
  107. #include <string>
  108. #include <google/protobuf/stubs/common.h>
  109. #include <google/protobuf/port_def.inc>
  110. namespace google {
  111. namespace protobuf {
  112. namespace io {
  113. // Defined in this file.
  114. class ZeroCopyInputStream;
  115. class ZeroCopyOutputStream;
  116. // Abstract interface similar to an input stream but designed to minimize
  117. // copying.
  118. class PROTOBUF_EXPORT ZeroCopyInputStream {
  119. public:
  120. ZeroCopyInputStream() {}
  121. virtual ~ZeroCopyInputStream() {}
  122. // Obtains a chunk of data from the stream.
  123. //
  124. // Preconditions:
  125. // * "size" and "data" are not NULL.
  126. //
  127. // Postconditions:
  128. // * If the returned value is false, there is no more data to return or
  129. // an error occurred. All errors are permanent.
  130. // * Otherwise, "size" points to the actual number of bytes read and "data"
  131. // points to a pointer to a buffer containing these bytes.
  132. // * Ownership of this buffer remains with the stream, and the buffer
  133. // remains valid only until some other method of the stream is called
  134. // or the stream is destroyed.
  135. // * It is legal for the returned buffer to have zero size, as long
  136. // as repeatedly calling Next() eventually yields a buffer with non-zero
  137. // size.
  138. virtual bool Next(const void** data, int* size) = 0;
  139. // Backs up a number of bytes, so that the next call to Next() returns
  140. // data again that was already returned by the last call to Next(). This
  141. // is useful when writing procedures that are only supposed to read up
  142. // to a certain point in the input, then return. If Next() returns a
  143. // buffer that goes beyond what you wanted to read, you can use BackUp()
  144. // to return to the point where you intended to finish.
  145. //
  146. // Preconditions:
  147. // * The last method called must have been Next().
  148. // * count must be less than or equal to the size of the last buffer
  149. // returned by Next().
  150. //
  151. // Postconditions:
  152. // * The last "count" bytes of the last buffer returned by Next() will be
  153. // pushed back into the stream. Subsequent calls to Next() will return
  154. // the same data again before producing new data.
  155. virtual void BackUp(int count) = 0;
  156. // Skips a number of bytes. Returns false if the end of the stream is
  157. // reached or some input error occurred. In the end-of-stream case, the
  158. // stream is advanced to the end of the stream (so ByteCount() will return
  159. // the total size of the stream).
  160. virtual bool Skip(int count) = 0;
  161. // Returns the total number of bytes read since this object was created.
  162. virtual int64_t ByteCount() const = 0;
  163. private:
  164. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
  165. };
  166. // Abstract interface similar to an output stream but designed to minimize
  167. // copying.
  168. class PROTOBUF_EXPORT ZeroCopyOutputStream {
  169. public:
  170. ZeroCopyOutputStream() {}
  171. virtual ~ZeroCopyOutputStream() {}
  172. // Obtains a buffer into which data can be written. Any data written
  173. // into this buffer will eventually (maybe instantly, maybe later on)
  174. // be written to the output.
  175. //
  176. // Preconditions:
  177. // * "size" and "data" are not NULL.
  178. //
  179. // Postconditions:
  180. // * If the returned value is false, an error occurred. All errors are
  181. // permanent.
  182. // * Otherwise, "size" points to the actual number of bytes in the buffer
  183. // and "data" points to the buffer.
  184. // * Ownership of this buffer remains with the stream, and the buffer
  185. // remains valid only until some other method of the stream is called
  186. // or the stream is destroyed.
  187. // * Any data which the caller stores in this buffer will eventually be
  188. // written to the output (unless BackUp() is called).
  189. // * It is legal for the returned buffer to have zero size, as long
  190. // as repeatedly calling Next() eventually yields a buffer with non-zero
  191. // size.
  192. virtual bool Next(void** data, int* size) = 0;
  193. // Backs up a number of bytes, so that the end of the last buffer returned
  194. // by Next() is not actually written. This is needed when you finish
  195. // writing all the data you want to write, but the last buffer was bigger
  196. // than you needed. You don't want to write a bunch of garbage after the
  197. // end of your data, so you use BackUp() to back up.
  198. //
  199. // Preconditions:
  200. // * The last method called must have been Next().
  201. // * count must be less than or equal to the size of the last buffer
  202. // returned by Next().
  203. // * The caller must not have written anything to the last "count" bytes
  204. // of that buffer.
  205. //
  206. // Postconditions:
  207. // * The last "count" bytes of the last buffer returned by Next() will be
  208. // ignored.
  209. virtual void BackUp(int count) = 0;
  210. // Returns the total number of bytes written since this object was created.
  211. virtual int64_t ByteCount() const = 0;
  212. // Write a given chunk of data to the output. Some output streams may
  213. // implement this in a way that avoids copying. Check AllowsAliasing() before
  214. // calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is
  215. // called on a stream that does not allow aliasing.
  216. //
  217. // NOTE: It is caller's responsibility to ensure that the chunk of memory
  218. // remains live until all of the data has been consumed from the stream.
  219. virtual bool WriteAliasedRaw(const void* data, int size);
  220. virtual bool AllowsAliasing() const { return false; }
  221. private:
  222. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream);
  223. };
  224. } // namespace io
  225. } // namespace protobuf
  226. } // namespace google
  227. #include <google/protobuf/port_undef.inc>
  228. #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__