blob: 7f416396e300f73480c698fb57f1a7a449d6e9d6 [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001/*
2 * Copyright 2014 Google Inc. All rights reserved.
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
17package com.google.flatbuffers;
18
19import static com.google.flatbuffers.Constants.*;
20import java.nio.ByteBuffer;
21import java.nio.ByteOrder;
Austin Schuhe89fa2d2019-08-14 20:24:23 -070022
23/// @cond FLATBUFFERS_INTERNAL
24
25/**
26 * All tables in the generated code derive from this class, and add their own accessors.
27 */
28public class Table {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070029 /** Used to hold the position of the `bb` buffer. */
30 protected int bb_pos;
31 /** The underlying ByteBuffer to hold the data of the Table. */
32 protected ByteBuffer bb;
33 /** Used to hold the vtable position. */
34 private int vtable_start;
35 /** Used to hold the vtable size. */
36 private int vtable_size;
37 Utf8 utf8 = Utf8.getDefault();
38
39 /**
40 * Get the underlying ByteBuffer.
41 *
42 * @return Returns the Table's ByteBuffer.
43 */
44 public ByteBuffer getByteBuffer() { return bb; }
45
46 /**
47 * Look up a field in the vtable.
48 *
49 * @param vtable_offset An `int` offset to the vtable in the Table's ByteBuffer.
50 * @return Returns an offset into the object, or `0` if the field is not present.
51 */
52 protected int __offset(int vtable_offset) {
53 return vtable_offset < vtable_size ? bb.getShort(vtable_start + vtable_offset) : 0;
54 }
55
56 protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
57 int vtable = bb.capacity() - offset;
58 return bb.getShort(vtable + vtable_offset - bb.getInt(vtable)) + vtable;
59 }
60
61 /**
62 * Retrieve a relative offset.
63 *
64 * @param offset An `int` index into the Table's ByteBuffer containing the relative offset.
65 * @return Returns the relative offset stored at `offset`.
66 */
67 protected int __indirect(int offset) {
68 return offset + bb.getInt(offset);
69 }
70
Austin Schuh272c6132020-11-14 16:37:52 -080071 /**
72 * Retrieve a relative offset.
73 *
74 * @param offset An `int` index into a ByteBuffer containing the relative offset.
75 * @param bb from which the relative offset will be retrieved.
76 * @return Returns the relative offset stored at `offset`.
77 */
Austin Schuhe89fa2d2019-08-14 20:24:23 -070078 protected static int __indirect(int offset, ByteBuffer bb) {
79 return offset + bb.getInt(offset);
80 }
81
82 /**
83 * Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
84 *
85 * This allocates a new string and converts to wide chars upon each access,
86 * which is not very efficient. Instead, each FlatBuffer string also comes with an
87 * accessor based on __vector_as_bytebuffer below, which is much more efficient,
88 * assuming your Java program can handle UTF-8 data directly.
89 *
90 * @param offset An `int` index into the Table's ByteBuffer.
91 * @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
92 */
93 protected String __string(int offset) {
Austin Schuh272c6132020-11-14 16:37:52 -080094 return __string(offset, bb, utf8);
95 }
96
97 /**
98 * Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
99 *
100 * This allocates a new string and converts to wide chars upon each access,
101 * which is not very efficient. Instead, each FlatBuffer string also comes with an
102 * accessor based on __vector_as_bytebuffer below, which is much more efficient,
103 * assuming your Java program can handle UTF-8 data directly.
104 *
105 * @param offset An `int` index into the Table's ByteBuffer.
106 * @param bb Table ByteBuffer used to read a string at given offset.
107 * @param utf8 decoder that creates a Java `String` from UTF-8 characters.
108 * @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
109 */
110 protected static String __string(int offset, ByteBuffer bb, Utf8 utf8) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700111 offset += bb.getInt(offset);
112 int length = bb.getInt(offset);
113 return utf8.decodeUtf8(bb, offset + SIZEOF_INT, length);
114 }
115
116 /**
117 * Get the length of a vector.
118 *
119 * @param offset An `int` index into the Table's ByteBuffer.
120 * @return Returns the length of the vector whose offset is stored at `offset`.
121 */
122 protected int __vector_len(int offset) {
123 offset += bb_pos;
124 offset += bb.getInt(offset);
125 return bb.getInt(offset);
126 }
127
128 /**
129 * Get the start data of a vector.
130 *
131 * @param offset An `int` index into the Table's ByteBuffer.
132 * @return Returns the start of the vector data whose offset is stored at `offset`.
133 */
134 protected int __vector(int offset) {
135 offset += bb_pos;
136 return offset + bb.getInt(offset) + SIZEOF_INT; // data starts after the length
137 }
138
139 /**
140 * Get a whole vector as a ByteBuffer.
141 *
142 * This is efficient, since it only allocates a new {@link ByteBuffer} object,
143 * but does not actually copy the data, it still refers to the same bytes
144 * as the original ByteBuffer. Also useful with nested FlatBuffers, etc.
145 *
146 * @param vector_offset The position of the vector in the byte buffer
147 * @param elem_size The size of each element in the array
148 * @return The {@link ByteBuffer} for the array
149 */
150 protected ByteBuffer __vector_as_bytebuffer(int vector_offset, int elem_size) {
151 int o = __offset(vector_offset);
152 if (o == 0) return null;
153 ByteBuffer bb = this.bb.duplicate().order(ByteOrder.LITTLE_ENDIAN);
154 int vectorstart = __vector(o);
155 bb.position(vectorstart);
156 bb.limit(vectorstart + __vector_len(o) * elem_size);
157 return bb;
158 }
159
160 /**
161 * Initialize vector as a ByteBuffer.
162 *
163 * This is more efficient than using duplicate, since it doesn't copy the data
164 * nor allocattes a new {@link ByteBuffer}, creating no garbage to be collected.
165 *
166 * @param bb The {@link ByteBuffer} for the array
167 * @param vector_offset The position of the vector in the byte buffer
168 * @param elem_size The size of each element in the array
169 * @return The {@link ByteBuffer} for the array
170 */
171 protected ByteBuffer __vector_in_bytebuffer(ByteBuffer bb, int vector_offset, int elem_size) {
172 int o = this.__offset(vector_offset);
173 if (o == 0) return null;
174 int vectorstart = __vector(o);
175 bb.rewind();
176 bb.limit(vectorstart + __vector_len(o) * elem_size);
177 bb.position(vectorstart);
178 return bb;
179 }
180
181 /**
182 * Initialize any Table-derived type to point to the union at the given `offset`.
183 *
184 * @param t A `Table`-derived type that should point to the union at `offset`.
185 * @param offset An `int` index into the Table's ByteBuffer.
186 * @return Returns the Table that points to the union at `offset`.
187 */
188 protected Table __union(Table t, int offset) {
Austin Schuh272c6132020-11-14 16:37:52 -0800189 return __union(t, offset, bb);
190 }
191
192 /**
193 * Initialize any Table-derived type to point to the union at the given `offset`.
194 *
195 * @param t A `Table`-derived type that should point to the union at `offset`.
196 * @param offset An `int` index into the Table's ByteBuffer.
197 * @param bb Table ByteBuffer used to initialize the object Table-derived type.
198 * @return Returns the Table that points to the union at `offset`.
199 */
200 protected static Table __union(Table t, int offset, ByteBuffer bb) {
201 t.__reset(__indirect(offset, bb), bb);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700202 return t;
203 }
204
205 /**
206 * Check if a {@link ByteBuffer} contains a file identifier.
207 *
208 * @param bb A {@code ByteBuffer} to check if it contains the identifier
209 * `ident`.
210 * @param ident A `String` identifier of the FlatBuffer file.
211 * @return True if the buffer contains the file identifier
212 */
213 protected static boolean __has_identifier(ByteBuffer bb, String ident) {
214 if (ident.length() != FILE_IDENTIFIER_LENGTH)
215 throw new AssertionError("FlatBuffers: file identifier must be length " +
216 FILE_IDENTIFIER_LENGTH);
217 for (int i = 0; i < FILE_IDENTIFIER_LENGTH; i++) {
218 if (ident.charAt(i) != (char)bb.get(bb.position() + SIZEOF_INT + i)) return false;
219 }
220 return true;
221 }
222
223 /**
224 * Sort tables by the key.
225 *
226 * @param offsets An 'int' indexes of the tables into the bb.
227 * @param bb A {@code ByteBuffer} to get the tables.
228 */
229 protected void sortTables(int[] offsets, final ByteBuffer bb) {
230 Integer[] off = new Integer[offsets.length];
231 for (int i = 0; i < offsets.length; i++) off[i] = offsets[i];
232 java.util.Arrays.sort(off, new java.util.Comparator<Integer>() {
233 public int compare(Integer o1, Integer o2) {
234 return keysCompare(o1, o2, bb);
235 }
236 });
237 for (int i = 0; i < offsets.length; i++) offsets[i] = off[i];
238 }
239
240 /**
241 * Compare two tables by the key.
242 *
243 * @param o1 An 'Integer' index of the first key into the bb.
244 * @param o2 An 'Integer' index of the second key into the bb.
245 * @param bb A {@code ByteBuffer} to get the keys.
246 */
247 protected int keysCompare(Integer o1, Integer o2, ByteBuffer bb) { return 0; }
248
249 /**
250 * Compare two strings in the buffer.
251 *
252 * @param offset_1 An 'int' index of the first string into the bb.
253 * @param offset_2 An 'int' index of the second string into the bb.
254 * @param bb A {@code ByteBuffer} to get the strings.
255 */
256 protected static int compareStrings(int offset_1, int offset_2, ByteBuffer bb) {
257 offset_1 += bb.getInt(offset_1);
258 offset_2 += bb.getInt(offset_2);
259 int len_1 = bb.getInt(offset_1);
260 int len_2 = bb.getInt(offset_2);
261 int startPos_1 = offset_1 + SIZEOF_INT;
262 int startPos_2 = offset_2 + SIZEOF_INT;
263 int len = Math.min(len_1, len_2);
264 for(int i = 0; i < len; i++) {
265 if (bb.get(i + startPos_1) != bb.get(i + startPos_2))
266 return bb.get(i + startPos_1) - bb.get(i + startPos_2);
267 }
268 return len_1 - len_2;
269 }
270
271 /**
272 * Compare string from the buffer with the 'String' object.
273 *
274 * @param offset_1 An 'int' index of the first string into the bb.
275 * @param key Second string as a byte array.
276 * @param bb A {@code ByteBuffer} to get the first string.
277 */
278 protected static int compareStrings(int offset_1, byte[] key, ByteBuffer bb) {
279 offset_1 += bb.getInt(offset_1);
280 int len_1 = bb.getInt(offset_1);
281 int len_2 = key.length;
282 int startPos_1 = offset_1 + Constants.SIZEOF_INT;
283 int len = Math.min(len_1, len_2);
284 for (int i = 0; i < len; i++) {
285 if (bb.get(i + startPos_1) != key[i])
286 return bb.get(i + startPos_1) - key[i];
287 }
288 return len_1 - len_2;
289 }
290
291 /**
292 * Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within.
293 *
294 * This method exists primarily to allow recycling Table instances without risking memory leaks
295 * due to {@code ByteBuffer} references.
296 */
297 protected void __reset(int _i, ByteBuffer _bb) {
298 bb = _bb;
299 if (bb != null) {
300 bb_pos = _i;
301 vtable_start = bb_pos - bb.getInt(bb_pos);
302 vtable_size = bb.getShort(vtable_start);
303 } else {
304 bb_pos = 0;
305 vtable_start = 0;
306 vtable_size = 0;
307 }
308 }
309
310 /**
311 * Resets the internal state with a null {@code ByteBuffer} and a zero position.
312 *
313 * This method exists primarily to allow recycling Table instances without risking memory leaks
314 * due to {@code ByteBuffer} references. The instance will be unusable until it is assigned
315 * again to a {@code ByteBuffer}.
316 */
317 public void __reset() {
318 __reset(0, null);
319 }
320}
321
322/// @endcond