1 /*
2  * Copyright (c) 2009-2022, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of Google LLC nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef UPB_IO_ZERO_COPY_INPUT_STREAM_H_
29 #define UPB_IO_ZERO_COPY_INPUT_STREAM_H_
30 
31 #include "upb/base/status.h"
32 
33 // Must be last.
34 #include "upb/port/def.inc"
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 typedef struct upb_ZeroCopyInputStream upb_ZeroCopyInputStream;
41 
42 typedef struct {
43   // Obtains a chunk of data from the stream.
44   //
45   // Preconditions:
46   //   "count" and "status" are not NULL.
47   //
48   // Postconditions:
49   //   All errors are permanent. If an error occurs then:
50   //     - NULL will be returned to the caller.
51   //     - *count will be set to zero.
52   //     - *status will be set to the error.
53   //   EOF is permanent. If EOF is reached then:
54   //     - NULL will be returned to the caller.
55   //     - *count will be set to zero.
56   //     - *status will not be touched.
57   //   Otherwise:
58   //     - The returned value will point to a buffer containing the bytes read.
59   //     - *count will be set to the number of bytes read.
60   //     - *status will not be touched.
61   //
62   // Ownership of this buffer remains with the stream, and the buffer
63   // remains valid only until some other method of the stream is called
64   // or the stream is destroyed.
65   const void* (*Next)(struct upb_ZeroCopyInputStream* z, size_t* count,
66                       upb_Status* status);
67 
68   // Backs up a number of bytes, so that the next call to Next() returns
69   // data again that was already returned by the last call to Next().  This
70   // is useful when writing procedures that are only supposed to read up
71   // to a certain point in the input, then return.  If Next() returns a
72   // buffer that goes beyond what you wanted to read, you can use BackUp()
73   // to return to the point where you intended to finish.
74   //
75   // Preconditions:
76   // * The last method called must have been Next().
77   // * count must be less than or equal to the size of the last buffer
78   //   returned by Next().
79   //
80   // Postconditions:
81   // * The last "count" bytes of the last buffer returned by Next() will be
82   //   pushed back into the stream.  Subsequent calls to Next() will return
83   //   the same data again before producing new data.
84   void (*BackUp)(struct upb_ZeroCopyInputStream* z, size_t count);
85 
86   // Skips a number of bytes. Returns false if the end of the stream is
87   // reached or some input error occurred. In the end-of-stream case, the
88   // stream is advanced to the end of the stream (so ByteCount() will return
89   // the total size of the stream).
90   bool (*Skip)(struct upb_ZeroCopyInputStream* z, size_t count);
91 
92   // Returns the total number of bytes read since this object was created.
93   size_t (*ByteCount)(const struct upb_ZeroCopyInputStream* z);
94 } _upb_ZeroCopyInputStream_VTable;
95 
96 struct upb_ZeroCopyInputStream {
97   const _upb_ZeroCopyInputStream_VTable* vtable;
98 };
99 
upb_ZeroCopyInputStream_Next(upb_ZeroCopyInputStream * z,size_t * count,upb_Status * status)100 UPB_INLINE const void* upb_ZeroCopyInputStream_Next(upb_ZeroCopyInputStream* z,
101                                                     size_t* count,
102                                                     upb_Status* status) {
103   const void* out = z->vtable->Next(z, count, status);
104   UPB_ASSERT((out == NULL) == (*count == 0));
105   return out;
106 }
107 
upb_ZeroCopyInputStream_BackUp(upb_ZeroCopyInputStream * z,size_t count)108 UPB_INLINE void upb_ZeroCopyInputStream_BackUp(upb_ZeroCopyInputStream* z,
109                                                size_t count) {
110   return z->vtable->BackUp(z, count);
111 }
112 
upb_ZeroCopyInputStream_Skip(upb_ZeroCopyInputStream * z,size_t count)113 UPB_INLINE bool upb_ZeroCopyInputStream_Skip(upb_ZeroCopyInputStream* z,
114                                              size_t count) {
115   return z->vtable->Skip(z, count);
116 }
117 
118 UPB_INLINE size_t
upb_ZeroCopyInputStream_ByteCount(const upb_ZeroCopyInputStream * z)119 upb_ZeroCopyInputStream_ByteCount(const upb_ZeroCopyInputStream* z) {
120   return z->vtable->ByteCount(z);
121 }
122 
123 #ifdef __cplusplus
124 } /* extern "C" */
125 #endif
126 
127 #include "upb/port/undef.inc"
128 
129 #endif /* UPB_IO_ZERO_COPY_INPUT_STREAM_H_ */
130