summaryrefslogtreecommitdiff
path: root/libs/protoutil/include/android/util/EncodedBuffer.h
blob: cf096091c055182d32ef3d057b35ccb897a5054e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_UTIL_ENCODED_BUFFER_H
#define ANDROID_UTIL_ENCODED_BUFFER_H

#include <stdint.h>
#include <vector>

namespace android {
namespace util {

using namespace std;

/**
 * A stream of bytes containing a read pointer and a write pointer,
 * backed by a set of fixed-size buffers.  There are write functions for the
 * primitive types stored by protocol buffers, but none of the logic
 * for tags, inner objects, or any of that.
 *
 * Terminology:
 *      *Pos:       Position in the whole data set (as if it were a single buffer).
 *      *Index:     Index of a buffer within the mBuffers list.
 *      *Offset:    Position within a buffer.
 */
class EncodedBuffer
{
public:
    EncodedBuffer();
    EncodedBuffer(size_t chunkSize);
    ~EncodedBuffer();

    class Pointer {
    public:
        Pointer();
        Pointer(size_t chunkSize);

        size_t pos() const;
        size_t index() const;
        size_t offset() const;

        void move(size_t amt);
        inline void move() { move(1); };

        void rewind();
        Pointer copy() const;

    private:
        size_t mChunkSize;
        size_t mIndex;
        size_t mOffset;
    };

    /******************************** Write APIs ************************************************/

    /**
     * Returns the number of bytes written in the buffer
     */
    size_t size() const;

    /**
     * Returns the write pointer.
     */
    Pointer* wp();

    /**
     * Returns the current position of write pointer, if the write buffer is full, it will automatically
     * rotate to a new buffer with given chunkSize. If NULL is returned, it means NO_MEMORY
     */
    uint8_t* writeBuffer();

    /**
     * Returns the writeable size in the current write buffer .
     */
    size_t currentToWrite();

    /**
     * Write a varint into a vector. Return the size of the varint.
     */
    size_t writeRawVarint(uint32_t val);

    /**
     * Write a protobuf header. Return the size of the header.
     */
    size_t writeHeader(uint32_t fieldId, uint8_t wireType);

    /********************************* Read APIs ************************************************/
    class iterator;
    friend class iterator;
    class iterator {
    public:
        iterator(const EncodedBuffer& buffer);

        /**
         * Returns the number of bytes written in the buffer
         */
        size_t size() const;

        /**
         * Returns the size of total bytes read.
         */
        size_t bytesRead() const;

        /**
         * Returns the read pointer.
         */
        Pointer* rp();

        /**
         * Returns the current position of read pointer, if NULL is returned, it reaches end of buffer.
         */
        uint8_t const* readBuffer();

        /**
         * Returns the readable size in the current read buffer.
         */
        size_t currentToRead();

        /**
         * Returns true if next bytes is available for read.
         */
        bool hasNext();

        /**
         * Reads the current byte and moves pointer 1 bit.
         */
        uint8_t next();

        /**
         * Read varint from iterator, the iterator will point to next available byte.
         * Return the number of bytes of the varint.
         */
        uint32_t readRawVarint();

    private:
        const EncodedBuffer& mData;
        Pointer mRp;
    };

    /**
     * Returns the iterator of EncodedBuffer so it guarantees consumers won't be able to modified the buffer.
     */
    iterator begin() const;

private:
    size_t mChunkSize;
    vector<uint8_t*> mBuffers;

    Pointer mWp;

    inline uint8_t* at(const Pointer& p) const; // helper function to get value
};

} // util
} // android

#endif // ANDROID_UTIL_ENCODED_BUFFER_H