blob: b7573d6e10cd353e5d99049d1c01ad78724bd70a [file] [log] [blame]
Austin Schuh272c6132020-11-14 16:37:52 -08001package com.google.flatbuffers;
2
3import java.util.Arrays;
4
5/**
6 * Implements {@code ReadBuf} using an array of bytes
7 * as a backing storage. Using array of bytes are
8 * usually faster than {@code ByteBuffer}.
9 *
10 * This class is not thread-safe, meaning that
11 * it must operate on a single thread. Operating from
12 * multiple thread leads into a undefined behavior
13 */
14public class ArrayReadWriteBuf implements ReadWriteBuf {
15
16 private byte[] buffer;
17 private int writePos;
18
19 public ArrayReadWriteBuf() {
20 this(10);
21 }
22
23 public ArrayReadWriteBuf(int initialCapacity) {
24 this(new byte[initialCapacity]);
25 }
26
27 public ArrayReadWriteBuf(byte[] buffer) {
28 this.buffer = buffer;
29 this.writePos = 0;
30 }
31
32 public ArrayReadWriteBuf(byte[] buffer, int startPos) {
33 this.buffer = buffer;
34 this.writePos = startPos;
35 }
36
37 @Override
38 public void clear() {
39 this.writePos = 0;
40 }
41
42 @Override
43 public boolean getBoolean(int index) {
44 return buffer[index] != 0;
45 }
46
47 @Override
48 public byte get(int index) {
49 return buffer[index];
50 }
51
52 @Override
53 public short getShort(int index) {
54 return (short) ((buffer[index+ 1] << 8) | (buffer[index] & 0xff));
55 }
56
57 @Override
58 public int getInt(int index) {
59 return (((buffer[index + 3]) << 24) |
60 ((buffer[index + 2] & 0xff) << 16) |
61 ((buffer[index + 1] & 0xff) << 8) |
62 ((buffer[index] & 0xff)));
63 }
64
65 @Override
66 public long getLong(int index) {
67 return ((((long) buffer[index++] & 0xff)) |
68 (((long) buffer[index++] & 0xff) << 8) |
69 (((long) buffer[index++] & 0xff) << 16) |
70 (((long) buffer[index++] & 0xff) << 24) |
71 (((long) buffer[index++] & 0xff) << 32) |
72 (((long) buffer[index++] & 0xff) << 40) |
73 (((long) buffer[index++] & 0xff) << 48) |
74 (((long) buffer[index]) << 56));
75 }
76
77 @Override
78 public float getFloat(int index) {
79 return Float.intBitsToFloat(getInt(index));
80 }
81
82 @Override
83 public double getDouble(int index) {
84 return Double.longBitsToDouble(getLong(index));
85 }
86
87 @Override
88 public String getString(int start, int size) {
89 return Utf8Safe.decodeUtf8Array(buffer, start, size);
90 }
91
92 @Override
93 public byte[] data() {
94 return buffer;
95 }
96
97
98 @Override
99 public void putBoolean(boolean value) {
100 setBoolean(writePos, value);
101 writePos++;
102 }
103
104 @Override
105 public void put(byte[] value, int start, int length) {
106 set(writePos, value, start, length);
107 writePos+=length;
108 }
109
110 @Override
111 public void put(byte value) {
112 set(writePos, value);
113 writePos++;
114 }
115
116 @Override
117 public void putShort(short value) {
118 setShort(writePos, value);
119 writePos +=2;
120 }
121
122 @Override
123 public void putInt(int value) {
124 setInt(writePos, value);
125 writePos +=4;
126 }
127
128 @Override
129 public void putLong(long value) {
130 setLong(writePos, value);
131 writePos +=8;
132 }
133
134 @Override
135 public void putFloat(float value) {
136 setFloat(writePos, value);
137 writePos +=4;
138 }
139
140 @Override
141 public void putDouble(double value) {
142 setDouble(writePos, value);
143 writePos +=8;
144 }
145
146 @Override
147 public void setBoolean(int index, boolean value) {
148 set(index, value ? (byte)1 : (byte)0);
149 }
150
151 @Override
152 public void set(int index, byte value) {
153 requestCapacity(index + 1);
154 buffer[index] = value;
155 }
156
157 @Override
158 public void set(int index, byte[] toCopy, int start, int length) {
159 requestCapacity(index + (length - start));
160 System.arraycopy(toCopy, start, buffer, index, length);
161 }
162
163 @Override
164 public void setShort(int index, short value) {
165 requestCapacity(index + 2);
166
167 buffer[index++] = (byte) ((value) & 0xff);
168 buffer[index ] = (byte) ((value >> 8) & 0xff);
169 }
170
171 @Override
172 public void setInt(int index, int value) {
173 requestCapacity(index + 4);
174
175 buffer[index++] = (byte) ((value) & 0xff);
176 buffer[index++] = (byte) ((value >> 8) & 0xff);
177 buffer[index++] = (byte) ((value >> 16) & 0xff);
178 buffer[index ] = (byte) ((value >> 24) & 0xff);
179 }
180
181 @Override
182 public void setLong(int index, long value) {
183 requestCapacity(index + 8);
184
185 int i = (int) value;
186 buffer[index++] = (byte) ((i) & 0xff);
187 buffer[index++] = (byte) ((i >> 8) & 0xff);
188 buffer[index++] = (byte) ((i >> 16) & 0xff);
189 buffer[index++] = (byte) ((i >> 24) & 0xff);
190 i = (int) (value >> 32);
191 buffer[index++] = (byte) ((i) & 0xff);
192 buffer[index++] = (byte) ((i >> 8) & 0xff);
193 buffer[index++] = (byte) ((i >> 16) & 0xff);
194 buffer[index ] = (byte) ((i >> 24) & 0xff);
195 }
196
197 @Override
198 public void setFloat(int index, float value) {
199 requestCapacity(index + 4);
200
201 int iValue = Float.floatToRawIntBits(value);
202 buffer[index++] = (byte) ((iValue) & 0xff);
203 buffer[index++] = (byte) ((iValue >> 8) & 0xff);
204 buffer[index++] = (byte) ((iValue >> 16) & 0xff);
205 buffer[index ] = (byte) ((iValue >> 24) & 0xff);
206 }
207
208 @Override
209 public void setDouble(int index, double value) {
210 requestCapacity(index + 8);
211
212 long lValue = Double.doubleToRawLongBits(value);
213 int i = (int) lValue;
214 buffer[index++] = (byte) ((i) & 0xff);
215 buffer[index++] = (byte) ((i >> 8) & 0xff);
216 buffer[index++] = (byte) ((i >> 16) & 0xff);
217 buffer[index++] = (byte) ((i >> 24) & 0xff);
218 i = (int) (lValue >> 32);
219 buffer[index++] = (byte) ((i) & 0xff);
220 buffer[index++] = (byte) ((i >> 8) & 0xff);
221 buffer[index++] = (byte) ((i >> 16) & 0xff);
222 buffer[index ] = (byte) ((i >> 24) & 0xff);
223 }
224
225 @Override
226 public int limit() {
227 return writePos;
228 }
229
230 @Override
231 public int writePosition() {
232 return writePos;
233 }
234
235 @Override
236 public boolean requestCapacity(int capacity) {
237 if (capacity < 0) {
238 throw new IllegalArgumentException("Capacity may not be negative (likely a previous int overflow)");
239 }
240 if (buffer.length >= capacity) {
241 return true;
242 }
243 // implemented in the same growing fashion as ArrayList
244 int oldCapacity = buffer.length;
245 int newCapacity = oldCapacity + (oldCapacity >> 1);
246 if (newCapacity < capacity) { // Note: this also catches newCapacity int overflow
247 newCapacity = capacity;
248 }
249 buffer = Arrays.copyOf(buffer, newCapacity);
250 return true;
251 }
252}