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