1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_UTIL_ENCODED_BUFFER_H
18 #define ANDROID_UTIL_ENCODED_BUFFER_H
19 
20 #include <stdint.h>
21 #include <vector>
22 
23 namespace android {
24 namespace util {
25 
26 /**
27  * A stream of bytes containing a read pointer and a write pointer,
28  * backed by a set of fixed-size buffers.  There are write functions for the
29  * primitive types stored by protocol buffers, but none of the logic
30  * for tags, inner objects, or any of that.
31  *
32  * Terminology:
33  *      *Pos:       Position in the whole data set (as if it were a single buffer).
34  *      *Index:     Index of a buffer within the mBuffers list.
35  *      *Offset:    Position within a buffer.
36  */
37 class EncodedBuffer
38 {
39 public:
40     EncodedBuffer();
41     EncodedBuffer(size_t chunkSize);
42     ~EncodedBuffer();
43 
44     class Pointer {
45     public:
46         Pointer();
47         Pointer(size_t chunkSize);
48 
49         size_t pos() const;
50         size_t index() const;
51         size_t offset() const;
52 
53         Pointer* move(size_t amt);
move()54         inline Pointer* move() { return move(1); };
55         Pointer* rewind();
56 
57         Pointer copy() const;
58 
59     private:
60         size_t mChunkSize;
61         size_t mIndex;
62         size_t mOffset;
63     };
64 
65     /**
66      * Clears the buffer by rewinding its write pointer to avoid de/allocate buffers in heap.
67      */
68     void clear();
69 
70     /******************************** Write APIs ************************************************/
71 
72     /**
73      * Returns the number of bytes written in the buffer
74      */
75     size_t size() const;
76 
77     /**
78      * Returns the write pointer.
79      */
80     Pointer* wp();
81 
82     /**
83      * Returns the current position of write pointer, if the write buffer is full, it will automatically
84      * rotate to a new buffer with given chunkSize. If NULL is returned, it means NO_MEMORY
85      */
86     uint8_t* writeBuffer();
87 
88     /**
89      * Returns the writeable size in the current write buffer .
90      */
91     size_t currentToWrite();
92 
93     /**
94      * Write a single byte to the buffer.
95      */
96     void writeRawByte(uint8_t val);
97 
98     /**
99      * Write a varint32 into the buffer. Return the size of the varint.
100      */
101     size_t writeRawVarint32(uint32_t val);
102 
103     /**
104      * Write a varint64 into the buffer. Return the size of the varint.
105      */
106     size_t writeRawVarint64(uint64_t val);
107 
108     /**
109      * Write Fixed32 into the buffer.
110      */
111     void writeRawFixed32(uint32_t val);
112 
113     /**
114      * Write Fixed64 into the buffer.
115      */
116     void writeRawFixed64(uint64_t val);
117 
118     /**
119      * Write a protobuf header. Return the size of the header.
120      */
121     size_t writeHeader(uint32_t fieldId, uint8_t wireType);
122 
123     /********************************* Edit APIs ************************************************/
124     /**
125      * Returns the edit pointer.
126      */
127     Pointer* ep();
128 
129     /**
130      * Read a single byte at ep, and move ep to next byte;
131      */
132     uint8_t readRawByte();
133 
134     /**
135      * Read varint starting at ep, ep will move to pos of next byte.
136      */
137     uint64_t readRawVarint();
138 
139     /**
140      * Read 4 bytes starting at ep, ep will move to pos of next byte.
141      */
142     uint32_t readRawFixed32();
143 
144     /**
145      * Read 8 bytes starting at ep, ep will move to pos of next byte.
146      */
147     uint64_t readRawFixed64();
148 
149     /**
150      * Edit 4 bytes starting at pos.
151      */
152     void editRawFixed32(size_t pos, uint32_t val);
153 
154     /**
155      * Copy _size_ bytes of data starting at __srcPos__ to wp, srcPos must be larger than wp.pos().
156      */
157     void copy(size_t srcPos, size_t size);
158 
159     /********************************* Read APIs ************************************************/
160     class iterator;
161     friend class iterator;
162     class iterator {
163     public:
164         iterator(const EncodedBuffer& buffer);
165 
166         /**
167          * Returns the number of bytes written in the buffer
168          */
169         size_t size() const;
170 
171         /**
172          * Returns the size of total bytes read.
173          */
174         size_t bytesRead() const;
175 
176         /**
177          * Returns the read pointer.
178          */
179         Pointer* rp();
180 
181         /**
182          * Returns the current position of read pointer, if NULL is returned, it reaches end of buffer.
183          */
184         uint8_t const* readBuffer();
185 
186         /**
187          * Returns the readable size in the current read buffer.
188          */
189         size_t currentToRead();
190 
191         /**
192          * Returns true if next bytes is available for read.
193          */
194         bool hasNext();
195 
196         /**
197          * Reads the current byte and moves pointer 1 bit.
198          */
199         uint8_t next();
200 
201         /**
202          * Read varint from iterator, the iterator will point to next available byte.
203          */
204         uint64_t readRawVarint();
205 
206     private:
207         const EncodedBuffer& mData;
208         Pointer mRp;
209     };
210 
211     /**
212      * Returns the iterator of EncodedBuffer so it guarantees consumers won't be able to modified the buffer.
213      */
214     iterator begin() const;
215 
216 private:
217     size_t mChunkSize;
218     std::vector<uint8_t*> mBuffers;
219 
220     Pointer mWp;
221     Pointer mEp;
222 
223     inline uint8_t* at(const Pointer& p) const; // helper function to get value
224 };
225 
226 } // util
227 } // android
228 
229 #endif // ANDROID_UTIL_ENCODED_BUFFER_H
230 
231