1 package com.google.flatbuffers;
2 
3 import 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  */
14 public class ArrayReadWriteBuf implements ReadWriteBuf {
15 
16   private byte[] buffer;
17   private int writePos;
18 
ArrayReadWriteBuf()19   public ArrayReadWriteBuf() {
20     this(10);
21   }
22 
ArrayReadWriteBuf(int initialCapacity)23   public ArrayReadWriteBuf(int initialCapacity) {
24     this(new byte[initialCapacity]);
25   }
26 
ArrayReadWriteBuf(byte[] buffer)27   public ArrayReadWriteBuf(byte[] buffer) {
28     this.buffer = buffer;
29     this.writePos = 0;
30   }
31 
ArrayReadWriteBuf(byte[] buffer, int startPos)32   public ArrayReadWriteBuf(byte[] buffer, int startPos) {
33     this.buffer = buffer;
34     this.writePos = startPos;
35   }
36 
37   @Override
clear()38   public void clear() {
39     this.writePos = 0;
40   }
41 
42   @Override
getBoolean(int index)43   public boolean getBoolean(int index) {
44     return buffer[index] != 0;
45   }
46 
47   @Override
get(int index)48   public byte get(int index) {
49     return buffer[index];
50   }
51 
52   @Override
getShort(int index)53   public short getShort(int index) {
54     return (short) ((buffer[index+ 1] << 8) | (buffer[index] & 0xff));
55   }
56 
57   @Override
getInt(int index)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
getLong(int index)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
getFloat(int index)78   public float getFloat(int index) {
79     return Float.intBitsToFloat(getInt(index));
80   }
81 
82   @Override
getDouble(int index)83   public double getDouble(int index) {
84     return Double.longBitsToDouble(getLong(index));
85   }
86 
87   @Override
getString(int start, int size)88   public String getString(int start, int size) {
89     return Utf8Safe.decodeUtf8Array(buffer, start, size);
90   }
91 
92   @Override
data()93   public byte[] data() {
94     return buffer;
95   }
96 
97 
98   @Override
putBoolean(boolean value)99   public void putBoolean(boolean value) {
100       setBoolean(writePos, value);
101       writePos++;
102   }
103 
104   @Override
put(byte[] value, int start, int length)105   public void put(byte[] value, int start, int length) {
106     set(writePos, value, start, length);
107     writePos+=length;
108   }
109 
110   @Override
put(byte value)111   public void put(byte value) {
112     set(writePos, value);
113     writePos++;
114   }
115 
116   @Override
putShort(short value)117   public void putShort(short value) {
118     setShort(writePos, value);
119     writePos +=2;
120   }
121 
122   @Override
putInt(int value)123   public void putInt(int value) {
124     setInt(writePos, value);
125     writePos +=4;
126   }
127 
128   @Override
putLong(long value)129   public void putLong(long value) {
130     setLong(writePos, value);
131     writePos +=8;
132   }
133 
134   @Override
putFloat(float value)135   public void putFloat(float value) {
136     setFloat(writePos, value);
137     writePos +=4;
138   }
139 
140   @Override
putDouble(double value)141   public void putDouble(double value) {
142     setDouble(writePos, value);
143     writePos +=8;
144   }
145 
146   @Override
setBoolean(int index, boolean value)147   public void setBoolean(int index, boolean value) {
148     set(index, value ? (byte)1 : (byte)0);
149   }
150 
151   @Override
set(int index, byte value)152   public void set(int index, byte value) {
153     requestCapacity(index + 1);
154     buffer[index] = value;
155   }
156 
157   @Override
set(int index, byte[] toCopy, int start, int length)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
setShort(int index, short value)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
setInt(int index, int value)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
setLong(int index, long value)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
setFloat(int index, float value)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
setDouble(int index, double value)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
limit()226   public int limit() {
227     return writePos;
228   }
229 
230   @Override
writePosition()231   public int writePosition() {
232     return writePos;
233   }
234 
235   @Override
requestCapacity(int capacity)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 }
253