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 <android/util/ProtoReader.h>
21 
22 #include <utils/Errors.h>
23 #include <utils/RefBase.h>
24 
25 #include <stdint.h>
26 #include <vector>
27 
28 namespace android {
29 namespace util {
30 
31 /**
32  * A stream of bytes containing a read pointer and a write pointer,
33  * backed by a set of fixed-size buffers.  There are write functions for the
34  * primitive types stored by protocol buffers, but none of the logic
35  * for tags, inner objects, or any of that.
36  *
37  * Terminology:
38  *      *Pos:       Position in the whole data set (as if it were a single buffer).
39  *      *Index:     Index of a buffer within the mBuffers list.
40  *      *Offset:    Position within a buffer.
41  */
42 class EncodedBuffer : public virtual RefBase
43 {
44 public:
45     EncodedBuffer();
46     explicit EncodedBuffer(size_t chunkSize);
47     virtual ~EncodedBuffer();
48 
49     class Pointer {
50     public:
51         Pointer();
52         explicit Pointer(size_t chunkSize);
53 
54         size_t pos() const;
55         size_t index() const;
56         size_t offset() const;
57 
58         Pointer* move(size_t amt);
move()59         inline Pointer* move() { return move(1); };
60         Pointer* rewind();
61 
62         Pointer copy() const;
63 
64     private:
65         size_t mChunkSize;
66         size_t mIndex;
67         size_t mOffset;
68     };
69 
70     /**
71      * Clears the buffer by rewinding its write pointer to avoid de/allocate buffers in heap.
72      */
73     void clear();
74 
75     /******************************** Write APIs ************************************************/
76 
77     /**
78      * Returns the number of bytes written in the buffer
79      */
80     size_t size() const;
81 
82     /**
83      * Returns the write pointer.
84      */
85     Pointer* wp();
86 
87     /**
88      * Returns the current position of write pointer, if the write buffer is full, it will
89      * automatically rotate to a new buffer with given chunkSize. If NULL is returned, it
90      * means NO_MEMORY.
91      */
92     uint8_t* writeBuffer();
93 
94     /**
95      * Returns the writeable size in the current write buffer .
96      */
97     size_t currentToWrite();
98 
99     /**
100      * Write a single byte to the buffer.
101      */
102     void writeRawByte(uint8_t val);
103 
104     /**
105      * Write a varint32 into the buffer. Return the size of the varint.
106      */
107     size_t writeRawVarint32(uint32_t val);
108 
109     /**
110      * Write a varint64 into the buffer. Return the size of the varint.
111      */
112     size_t writeRawVarint64(uint64_t val);
113 
114     /**
115      * Write Fixed32 into the buffer.
116      */
117     void writeRawFixed32(uint32_t val);
118 
119     /**
120      * Write Fixed64 into the buffer.
121      */
122     void writeRawFixed64(uint64_t val);
123 
124     /**
125      * Write a protobuf header. Return the size of the header.
126      */
127     size_t writeHeader(uint32_t fieldId, uint8_t wireType);
128 
129     /**
130      * Copy the contents of the parameter into the write buffer.
131      */
132     status_t writeRaw(uint8_t const* buf, size_t size);
133 
134     /**
135      * Copy the entire contents of the ProtoReader into the write buffer.
136      */
137     status_t writeRaw(const sp<ProtoReader>& that);
138 
139     /**
140      * Copy the size bytes of contents of the ProtoReader into the write buffer.
141      */
142     status_t writeRaw(const sp<ProtoReader>& that, size_t size);
143 
144     /********************************* Edit APIs ************************************************/
145     /**
146      * Returns the edit pointer.
147      */
148     Pointer* ep();
149 
150     /**
151      * Read a single byte at ep, and move ep to next byte;
152      */
153     uint8_t readRawByte();
154 
155     /**
156      * Read varint starting at ep, ep will move to pos of next byte.
157      */
158     uint64_t readRawVarint();
159 
160     /**
161      * Read 4 bytes starting at ep, ep will move to pos of next byte.
162      */
163     uint32_t readRawFixed32();
164 
165     /**
166      * Read 8 bytes starting at ep, ep will move to pos of next byte.
167      */
168     uint64_t readRawFixed64();
169 
170     /**
171      * Edit 4 bytes starting at pos.
172      */
173     void editRawFixed32(size_t pos, uint32_t val);
174 
175     /**
176      * Copy _size_ bytes of data starting at __srcPos__ to wp, srcPos must be larger than wp.pos().
177      */
178     void copy(size_t srcPos, size_t size);
179 
180     /********************************* Read APIs ************************************************/
181     /**
182      * Returns the Reader of EncodedBuffer so it guarantees consumers won't be able to
183      * modify the buffer.
184      */
185     sp<ProtoReader> read();
186 
187 private:
188     class Reader;
189     friend class Reader;
190     class Reader : public ProtoReader {
191     public:
192         explicit Reader(const sp<EncodedBuffer>& buffer);
193         virtual ~Reader();
194 
195         virtual ssize_t size() const;
196         virtual size_t bytesRead() const;
197         virtual uint8_t const* readBuffer();
198         virtual size_t currentToRead();
199         virtual bool hasNext();
200         virtual uint8_t next();
201         virtual uint64_t readRawVarint();
202         virtual void move(size_t amt);
203 
204     private:
205         const sp<EncodedBuffer> mData;
206         Pointer mRp;
207         friend class EncodedBuffer;
208     };
209 
210     size_t mChunkSize;
211     std::vector<uint8_t*> mBuffers;
212 
213     Pointer mWp;
214     Pointer mEp;
215 
216     inline uint8_t* at(const Pointer& p) const; // helper function to get value
217 };
218 
219 } // util
220 } // android
221 
222 #endif // ANDROID_UTIL_ENCODED_BUFFER_H
223 
224