Sync from upstream

This commit is contained in:
吴凡
2016-07-01 11:03:25 +08:00
296 changed files with 16524 additions and 8059 deletions

View File

@@ -16,12 +16,27 @@
package com.google.flatbuffers;
// Class that holds shared constants.
/// @cond FLATBUFFERS_INTERNAL
/**
* Class that holds shared constants
*/
public class Constants {
// Java doesn't seem to have these.
/** The number of bytes in an `byte`. */
static final int SIZEOF_BYTE = 1;
/** The number of bytes in a `short`. */
static final int SIZEOF_SHORT = 2;
/** The number of bytes in an `int`. */
static final int SIZEOF_INT = 4;
/** The number of bytes in an `float`. */
static final int SIZEOF_FLOAT = 4;
/** The number of bytes in an `long`. */
static final int SIZEOF_LONG = 8;
/** The number of bytes in an `double`. */
static final int SIZEOF_DOUBLE = 8;
/** The number of bytes in a file identifier. */
static final int FILE_IDENTIFIER_LENGTH = 4;
}
/// @endcond

View File

@@ -17,17 +17,26 @@
package com.google.flatbuffers;
import static com.google.flatbuffers.Constants.*;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.Arrays;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
/// @file
/// @addtogroup flatbuffers_java_api
/// @{
/**
* Class that helps you build a FlatBuffer. See the section
* <a href="http://google.github.io/flatbuffers/md__java_usage.html">"Use in Java"</a> in the
* main FlatBuffers documentation.
* "Use in Java/C#" in the main FlatBuffers documentation.
*/
public class FlatBufferBuilder {
<<<<<<< HEAD
ByteBuffer bb; // Where we construct the FlatBuffer.
int space; // Remaining space in the ByteBuffer.
static final Charset utf8charset = Charset.forName("UTF-8");
@@ -41,11 +50,30 @@ public class FlatBufferBuilder {
int num_vtables = 0; // Number of entries in `vtables` in use.
int vector_num_elems = 0; // For the current vector being built.
boolean force_defaults = false; // False omits default values from the serialized data
=======
/// @cond FLATBUFFERS_INTERNAL
ByteBuffer bb; // Where we construct the FlatBuffer.
int space; // Remaining space in the ByteBuffer.
static final Charset utf8charset = Charset.forName("UTF-8"); // The UTF-8 character set used by FlatBuffers.
int minalign = 1; // Minimum alignment encountered so far.
int[] vtable = null; // The vtable for the current table.
int vtable_in_use = 0; // The amount of fields we're actually using.
boolean nested = false; // Whether we are currently serializing a table.
boolean finished = false; // Whether the buffer is finished.
int object_start; // Starting offset of the current struct/table.
int[] vtables = new int[16]; // List of offsets of all vtables.
int num_vtables = 0; // Number of entries in `vtables` in use.
int vector_num_elems = 0; // For the current vector being built.
boolean force_defaults = false; // False omits default values from the serialized data.
CharsetEncoder encoder = utf8charset.newEncoder();
ByteBuffer dst;
/// @endcond
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
/**
* Start with a buffer of size {@code initial_size}, then grow as required.
* Start with a buffer of size `initial_size`, then grow as required.
*
* @param initial_size The initial size of the internal buffer to use
* @param initial_size The initial size of the internal buffer to use.
*/
public FlatBufferBuilder(int initial_size) {
if (initial_size <= 0) initial_size = 1;
@@ -63,9 +91,9 @@ public class FlatBufferBuilder {
/**
* Alternative constructor allowing reuse of {@link ByteBuffer}s. The builder
* can still grow the buffer as necessary. User classes should make sure
* to call {@link #dataBuffer()} to obtain the resulting encoded message
* to call {@link #dataBuffer()} to obtain the resulting encoded message.
*
* @param existing_bb The byte buffer to reuse
* @param existing_bb The byte buffer to reuse.
*/
public FlatBufferBuilder(ByteBuffer existing_bb) {
init(existing_bb);
@@ -73,11 +101,11 @@ public class FlatBufferBuilder {
/**
* Alternative initializer that allows reusing this object on an existing
* ByteBuffer. This method resets the builder's internal state, but keeps
* `ByteBuffer`. This method resets the builder's internal state, but keeps
* objects that have been allocated for temporary storage.
*
* @param existing_bb The byte buffer to reuse
* @return this
* @param existing_bb The byte buffer to reuse.
* @return Returns `this`.
*/
public FlatBufferBuilder init(ByteBuffer existing_bb){
bb = existing_bb;
@@ -94,6 +122,13 @@ public class FlatBufferBuilder {
return this;
}
/// @cond FLATBUFFERS_INTERNAL
/**
* Create a `ByteBuffer` with a given capacity.
*
* @param capacity The size of the `ByteBuffer` to allocate.
* @return Returns the new `ByteBuffer` that was allocated.
*/
static ByteBuffer newByteBuffer(int capacity) {
ByteBuffer newbb = ByteBuffer.allocate(capacity);
newbb.order(ByteOrder.LITTLE_ENDIAN);
@@ -101,10 +136,10 @@ public class FlatBufferBuilder {
}
/**
* Doubles the size of the backing {link ByteBuffer} and copies the old data towards the
* Doubles the size of the backing {@link ByteBuffer} and copies the old data towards the
* end of the new buffer (since we build the buffer backwards).
*
* @param bb The current buffer with the existing data
* @param bb The current buffer with the existing data.
* @return A new byte buffer with the old data copied copied to it. The data is
* located at the end of the buffer.
*/
@@ -130,7 +165,7 @@ public class FlatBufferBuilder {
}
/**
* Add zero valued bytes to prepare a new entry to be added
* Add zero valued bytes to prepare a new entry to be added.
*
* @param byte_size Number of bytes to add.
*/
@@ -139,14 +174,14 @@ public class FlatBufferBuilder {
}
/**
* Prepare to write an element of {@code size} after {@code additional_bytes}
* Prepare to write an element of `size` after `additional_bytes`
* have been written, e.g. if you write a string, you need to align such
* the int length field is aligned to {@link com.google.flatbuffers.Constants#SIZEOF_INT}, and
* the string data follows it directly. If all you need to do is alignment, {@code additional_bytes}
* the string data follows it directly. If all you need to do is alignment, `additional_bytes`
* will be 0.
*
* @param size This is the of the new element to write
* @param additional_bytes The padding size
* @param size This is the of the new element to write.
* @param additional_bytes The padding size.
*/
public void prep(int size, int additional_bytes) {
// Track the biggest thing we've ever aligned to.
@@ -163,30 +198,116 @@ public class FlatBufferBuilder {
pad(align_size);
}
// Add a scalar to the buffer, backwards from the current location.
// Doesn't align nor check for space.
public void putBoolean(boolean x) { bb.put (space -= 1, (byte)(x ? 1 : 0)); }
public void putByte (byte x) { bb.put (space -= 1, x); }
public void putShort (short x) { bb.putShort (space -= 2, x); }
public void putInt (int x) { bb.putInt (space -= 4, x); }
public void putLong (long x) { bb.putLong (space -= 8, x); }
public void putFloat (float x) { bb.putFloat (space -= 4, x); }
public void putDouble (double x) { bb.putDouble(space -= 8, x); }
/**
* Add a `boolean` to the buffer, backwards from the current location. Doesn't align nor
* check for space.
*
* @param x A `boolean` to put into the buffer.
*/
public void putBoolean(boolean x) { bb.put (space -= Constants.SIZEOF_BYTE, (byte)(x ? 1 : 0)); }
// Adds a scalar to the buffer, properly aligned, and the buffer grown
// if needed.
public void addBoolean(boolean x) { prep(1, 0); putBoolean(x); }
public void addByte (byte x) { prep(1, 0); putByte (x); }
public void addShort (short x) { prep(2, 0); putShort (x); }
public void addInt (int x) { prep(4, 0); putInt (x); }
public void addLong (long x) { prep(8, 0); putLong (x); }
public void addFloat (float x) { prep(4, 0); putFloat (x); }
public void addDouble (double x) { prep(8, 0); putDouble (x); }
/**
* Add a `byte` to the buffer, backwards from the current location. Doesn't align nor
* check for space.
*
* @param x A `byte` to put into the buffer.
*/
public void putByte (byte x) { bb.put (space -= Constants.SIZEOF_BYTE, x); }
/**
* Add a `short` to the buffer, backwards from the current location. Doesn't align nor
* check for space.
*
* @param x A `short` to put into the buffer.
*/
public void putShort (short x) { bb.putShort (space -= Constants.SIZEOF_SHORT, x); }
/**
* Add an `int` to the buffer, backwards from the current location. Doesn't align nor
* check for space.
*
* @param x An `int` to put into the buffer.
*/
public void putInt (int x) { bb.putInt (space -= Constants.SIZEOF_INT, x); }
/**
* Add a `long` to the buffer, backwards from the current location. Doesn't align nor
* check for space.
*
* @param x A `long` to put into the buffer.
*/
public void putLong (long x) { bb.putLong (space -= Constants.SIZEOF_LONG, x); }
/**
* Add a `float` to the buffer, backwards from the current location. Doesn't align nor
* check for space.
*
* @param x A `float` to put into the buffer.
*/
public void putFloat (float x) { bb.putFloat (space -= Constants.SIZEOF_FLOAT, x); }
/**
* Add a `double` to the buffer, backwards from the current location. Doesn't align nor
* check for space.
*
* @param x A `double` to put into the buffer.
*/
public void putDouble (double x) { bb.putDouble(space -= Constants.SIZEOF_DOUBLE, x); }
/// @endcond
/**
* Add a `boolean` to the buffer, properly aligned, and grows the buffer (if necessary).
*
* @param x A `boolean` to put into the buffer.
*/
public void addBoolean(boolean x) { prep(Constants.SIZEOF_BYTE, 0); putBoolean(x); }
/**
* Add a `byte` to the buffer, properly aligned, and grows the buffer (if necessary).
*
* @param x A `byte` to put into the buffer.
*/
public void addByte (byte x) { prep(Constants.SIZEOF_BYTE, 0); putByte (x); }
/**
* Add a `short` to the buffer, properly aligned, and grows the buffer (if necessary).
*
* @param x A `short` to put into the buffer.
*/
public void addShort (short x) { prep(Constants.SIZEOF_SHORT, 0); putShort (x); }
/**
* Add an `int` to the buffer, properly aligned, and grows the buffer (if necessary).
*
* @param x An `int` to put into the buffer.
*/
public void addInt (int x) { prep(Constants.SIZEOF_INT, 0); putInt (x); }
/**
* Add a `long` to the buffer, properly aligned, and grows the buffer (if necessary).
*
* @param x A `long` to put into the buffer.
*/
public void addLong (long x) { prep(Constants.SIZEOF_LONG, 0); putLong (x); }
/**
* Add a `float` to the buffer, properly aligned, and grows the buffer (if necessary).
*
* @param x A `float` to put into the buffer.
*/
public void addFloat (float x) { prep(Constants.SIZEOF_FLOAT, 0); putFloat (x); }
/**
* Add a `double` to the buffer, properly aligned, and grows the buffer (if necessary).
*
* @param x A `double` to put into the buffer.
*/
public void addDouble (double x) { prep(Constants.SIZEOF_DOUBLE, 0); putDouble (x); }
/**
* Adds on offset, relative to where it will be written.
*
* @param off The offset to add
* @param off The offset to add.
*/
public void addOffset(int off) {
prep(SIZEOF_INT, 0); // Ensure alignment is already done.
@@ -195,15 +316,16 @@ public class FlatBufferBuilder {
putInt(off);
}
/// @cond FLATBUFFERS_INTERNAL
/**
* Start a new array/vector of objects. Users usually will not call
* this directly. The {@code FlatBuffers} compiler will create a start/end
* this directly. The `FlatBuffers` compiler will create a start/end
* method for vector types in generated code.
* <p>
* The expected sequence of calls is:
* <ol>
* <li>Start the array using this method.</li>
* <li>Call {@link #addOffset(int)} {@code num_elems} number of times to set
* <li>Call {@link #addOffset(int)} `num_elems` number of times to set
* the offset of each element in the array.</li>
* <li>Call {@link #endVector()} to retrieve the offset of the array.</li>
* </ol>
@@ -233,9 +355,9 @@ public class FlatBufferBuilder {
* int offsetOfTheVector = fbb.endVector();
* }</pre>
*
* @param elem_size The size of each element in the array
* @param num_elems The number of elements in the array
* @param alignment The alignment of the array
* @param elem_size The size of each element in the array.
* @param num_elems The number of elements in the array.
* @param alignment The alignment of the array.
*/
public void startVector(int elem_size, int num_elems, int alignment) {
notNested();
@@ -259,27 +381,44 @@ public class FlatBufferBuilder {
putInt(vector_num_elems);
return offset();
}
/// @endcond
/**
* Encode the string {@code s} in the buffer using UTF-8.
* Encode the string `s` in the buffer using UTF-8. If {@code s} is
* already a {@link CharBuffer}, this method is allocation free.
*
* @param s The string to encode
* @return The offset in the buffer where the encoded string starts
* @param s The string to encode.
* @return The offset in the buffer where the encoded string starts.
*/
public int createString(String s) {
byte[] utf8 = s.getBytes(utf8charset);
addByte((byte)0);
startVector(1, utf8.length, 1);
bb.position(space -= utf8.length);
bb.put(utf8, 0, utf8.length);
return endVector();
public int createString(CharSequence s) {
int length = s.length();
int estimatedDstCapacity = (int) (length * encoder.maxBytesPerChar());
if (dst == null || dst.capacity() < estimatedDstCapacity) {
dst = ByteBuffer.allocate(Math.max(128, estimatedDstCapacity));
}
dst.clear();
CharBuffer src = s instanceof CharBuffer ? (CharBuffer) s :
CharBuffer.wrap(s);
CoderResult result = encoder.encode(src, dst, true);
if (result.isError()) {
try {
result.throwException();
} catch (CharacterCodingException x) {
throw new Error(x);
}
}
dst.flip();
return createString(dst);
}
/**
* Encode the string {@code s} in the buffer using UTF-8.
* Create a string in the buffer from an already encoded UTF-8 string in a ByteBuffer.
*
* @param s An already encoded UTF-8 string
* @return The offset in the buffer where the encoded string starts
* @param s An already encoded UTF-8 string as a `ByteBuffer`.
* @return The offset in the buffer where the encoded string starts.
*/
public int createString(ByteBuffer s) {
int length = s.remaining();
@@ -290,6 +429,17 @@ public class FlatBufferBuilder {
return endVector();
}
/// @cond FLATBUFFERS_INTERNAL
/**
* Should not be accessing the final buffer before it is finished.
*/
public void finished() {
if (!finished)
throw new AssertionError(
"FlatBuffers: you can only access the serialized buffer after it has been" +
" finished by FlatBufferBuilder.finish().");
}
/**
* Should not be accessing the final buffer before it is finished.
*/
@@ -302,7 +452,7 @@ public class FlatBufferBuilder {
/**
* Should not be creating any other object, string or vector
* while an object is being constructed
* while an object is being constructed.
*/
public void notNested() {
if (nested)
@@ -314,7 +464,7 @@ public class FlatBufferBuilder {
* where they're used. You'll get this assertion failure if you
* created it elsewhere.
*
* @param obj The offset of the created object
* @param obj The offset of the created object.
*/
public void Nested(int obj) {
if (obj != offset())
@@ -323,12 +473,11 @@ public class FlatBufferBuilder {
/**
* Start encoding a new object in the buffer. Users will not usually need to
* call this directly. The {@code FlatBuffers} compiler will generate helper methods
* call this directly. The `FlatBuffers` compiler will generate helper methods
* that call this method internally.
* <p>
* For example, using the "Monster" code found on the
* <a href="http://google.github.io/flatbuffers/md__java_usage.html">landing page</a>. An
* object of type {@code Monster} can be created using the following code:
* For example, using the "Monster" code found on the "landing page". An
* object of type `Monster` can be created using the following code:
*
* <pre>{@code
* int testArrayOfString = Monster.createTestarrayofstringVector(fbb, new int[] {
@@ -351,14 +500,14 @@ public class FlatBufferBuilder {
* <p>
* Here:
* <ul>
* <li>The call to {@code Monster#startMonster(FlatBufferBuilder)} will call this
* <li>The call to `Monster#startMonster(FlatBufferBuilder)` will call this
* method with the right number of fields set.</li>
* <li>{@code Monster#endMonster(FlatBufferBuilder)} will ensure {@link #endObject()} is called.</li>
* <li>`Monster#endMonster(FlatBufferBuilder)` will ensure {@link #endObject()} is called.</li>
* </ul>
* <p>
* It's not recommended to call this method directly. If it's called manually, you must ensure
* to audit all calls to it whenever fields are added or removed from your schema. This is
* automatically done by the code generated by the {@code FlatBuffers} compiler.
* automatically done by the code generated by the `FlatBuffers` compiler.
*
* @param numfields The number of fields found in this object.
*/
@@ -371,17 +520,101 @@ public class FlatBufferBuilder {
object_start = offset();
}
// Add a scalar to a table at `o` into its vtable, with value `x` and default `d`
/**
* Add a `boolean` to a table at `o` into its vtable, with value `x` and default `d`.
*
* @param o The index into the vtable.
* @param x A `boolean` to put into the buffer, depending on how defaults are handled. If
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
* default value, it can be skipped.
* @param d A `boolean` default value to compare against when `force_defaults` is `false`.
*/
public void addBoolean(int o, boolean x, boolean d) { if(force_defaults || x != d) { addBoolean(x); slot(o); } }
/**
* Add a `byte` to a table at `o` into its vtable, with value `x` and default `d`.
*
* @param o The index into the vtable.
* @param x A `byte` to put into the buffer, depending on how defaults are handled. If
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
* default value, it can be skipped.
* @param d A `byte` default value to compare against when `force_defaults` is `false`.
*/
public void addByte (int o, byte x, int d) { if(force_defaults || x != d) { addByte (x); slot(o); } }
/**
* Add a `short` to a table at `o` into its vtable, with value `x` and default `d`.
*
* @param o The index into the vtable.
* @param x A `short` to put into the buffer, depending on how defaults are handled. If
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
* default value, it can be skipped.
* @param d A `short` default value to compare against when `force_defaults` is `false`.
*/
public void addShort (int o, short x, int d) { if(force_defaults || x != d) { addShort (x); slot(o); } }
/**
* Add an `int` to a table at `o` into its vtable, with value `x` and default `d`.
*
* @param o The index into the vtable.
* @param x An `int` to put into the buffer, depending on how defaults are handled. If
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
* default value, it can be skipped.
* @param d An `int` default value to compare against when `force_defaults` is `false`.
*/
public void addInt (int o, int x, int d) { if(force_defaults || x != d) { addInt (x); slot(o); } }
/**
* Add a `long` to a table at `o` into its vtable, with value `x` and default `d`.
*
* @param o The index into the vtable.
* @param x A `long` to put into the buffer, depending on how defaults are handled. If
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
* default value, it can be skipped.
* @param d A `long` default value to compare against when `force_defaults` is `false`.
*/
public void addLong (int o, long x, long d) { if(force_defaults || x != d) { addLong (x); slot(o); } }
/**
* Add a `float` to a table at `o` into its vtable, with value `x` and default `d`.
*
* @param o The index into the vtable.
* @param x A `float` to put into the buffer, depending on how defaults are handled. If
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
* default value, it can be skipped.
* @param d A `float` default value to compare against when `force_defaults` is `false`.
*/
public void addFloat (int o, float x, double d) { if(force_defaults || x != d) { addFloat (x); slot(o); } }
/**
* Add a `double` to a table at `o` into its vtable, with value `x` and default `d`.
*
* @param o The index into the vtable.
* @param x A `double` to put into the buffer, depending on how defaults are handled. If
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
* default value, it can be skipped.
* @param d A `double` default value to compare against when `force_defaults` is `false`.
*/
public void addDouble (int o, double x, double d) { if(force_defaults || x != d) { addDouble (x); slot(o); } }
/**
* Add an `offset` to a table at `o` into its vtable, with value `x` and default `d`.
*
* @param o The index into the vtable.
* @param x An `offset` to put into the buffer, depending on how defaults are handled. If
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
* default value, it can be skipped.
* @param d An `offset` default value to compare against when `force_defaults` is `false`.
*/
public void addOffset (int o, int x, int d) { if(force_defaults || x != d) { addOffset (x); slot(o); } }
// Structs are stored inline, so nothing additional is being added. `d` is always 0.
/**
* Add a struct to the table. Structs are stored inline, so nothing additional is being added.
*
* @param voffset The index into the vtable.
* @param x The offset of the created struct.
* @param d The default value is always `0`.
*/
public void addStruct(int voffset, int x, int d) {
if(x != d) {
Nested(x);
@@ -389,7 +622,12 @@ public class FlatBufferBuilder {
}
}
// Set the current vtable at `voffset` to the current location in the buffer.
/**
* Set the current vtable at `voffset` to the current location in the buffer.
*
* @param voffset The index into the vtable to store the offset relative to the end of the
* buffer.
*/
public void slot(int voffset) {
vtable[voffset] = offset();
}
@@ -397,7 +635,7 @@ public class FlatBufferBuilder {
/**
* Finish off writing the object that is under construction.
*
* @return The offset to the object inside {@link #dataBuffer()}
* @return The offset to the object inside {@link #dataBuffer()}.
* @see #startObject(int)
*/
public int endObject() {
@@ -453,8 +691,13 @@ public class FlatBufferBuilder {
return vtableloc;
}
// This checks a required field has been set in a given table that has
// just been constructed.
/**
* Checks that a required field has been set in a given table that has
* just been constructed.
*
* @param table The offset to the start of the table from the `ByteBuffer` capacity.
* @param field The offset to the field in the vtable.
*/
public void required(int table, int field) {
int table_start = bb.capacity() - table;
int vtable_start = table_start - bb.getInt(table_start);
@@ -463,7 +706,13 @@ public class FlatBufferBuilder {
if (!ok)
throw new AssertionError("FlatBuffers: field " + field + " must be set");
}
/// @endcond
/**
* Finalize a buffer, pointing to the given `root_table`.
*
* @param root_table An offset to be added to the buffer.
*/
public void finish(int root_table) {
prep(minalign, SIZEOF_INT);
addOffset(root_table);
@@ -471,6 +720,13 @@ public class FlatBufferBuilder {
finished = true;
}
/**
* Finalize a buffer, pointing to the given `root_table`.
*
* @param root_table An offset to be added to the buffer.
* @param file_identifier A FlatBuffer file identifier to be added to the buffer before
* `root_table`.
*/
public void finish(int root_table, String file_identifier) {
prep(minalign, SIZEOF_INT + FILE_IDENTIFIER_LENGTH);
if (file_identifier.length() != FILE_IDENTIFIER_LENGTH)
@@ -487,17 +743,27 @@ public class FlatBufferBuilder {
* don't get serialized into the buffer. Forcing defaults provides a
* way to manually disable this optimization.
*
* @param forceDefaults true always serializes default values
* @return this
* @param forceDefaults When set to `true`, always serializes default values.
* @return Returns `this`.
*/
public FlatBufferBuilder forceDefaults(boolean forceDefaults){
this.force_defaults = forceDefaults;
return this;
}
<<<<<<< HEAD
// Get the ByteBuffer representing the FlatBuffer. Only call this after you've
// called finish(). The actual data starts at the ByteBuffer's current position,
// not necessarily at 0.
=======
/**
* Get the ByteBuffer representing the FlatBuffer. Only call this after you've
* called `finish()`. The actual data starts at the ByteBuffer's current position,
* not necessarily at `0`.
*
* @return The {@link ByteBuffer} representing the FlatBuffer
*/
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
public ByteBuffer dataBuffer() {
finished();
return bb;
@@ -518,13 +784,13 @@ public class FlatBufferBuilder {
}
/**
* Utility function for copying a byte array from {@code start} to
* {@code start} + {@code length}
* A utility function to copy and return the ByteBuffer data from `start` to
* `start` + `length` as a `byte[]`.
*
* @param start Start copying at this offset
* @param length How many bytes to copy
* @return A range copy of the {@link #dataBuffer() data buffer}
* @throws IndexOutOfBoundsException If the range of bytes is ouf of bound
* @param start Start copying at this offset.
* @param length How many bytes to copy.
* @return A range copy of the {@link #dataBuffer() data buffer}.
* @throws IndexOutOfBoundsException If the range of bytes is ouf of bound.
*/
public byte[] sizedByteArray(int start, int length){
finished();
@@ -535,11 +801,13 @@ public class FlatBufferBuilder {
}
/**
* Utility function for copying a byte array that starts at 0.
* A utility function to copy and return the ByteBuffer data as a `byte[]`.
*
* @return A full copy of the {@link #dataBuffer() data buffer}
* @return A full copy of the {@link #dataBuffer() data buffer}.
*/
public byte[] sizedByteArray() {
return sizedByteArray(space, bb.capacity() - space);
}
}
/// @}

View File

@@ -18,8 +18,16 @@ package com.google.flatbuffers;
import java.nio.ByteBuffer;
// All structs in the generated code derive from this class, and add their own accessors.
/// @cond FLATBUFFERS_INTERNAL
/**
* All structs in the generated code derive from this class, and add their own accessors.
*/
public class Struct {
/** Used to hold the position of the `bb` buffer. */
protected int bb_pos;
/** The underlying ByteBuffer to hold the data of the Struct. */
protected ByteBuffer bb;
}
/// @endcond

View File

@@ -19,64 +19,134 @@ package com.google.flatbuffers;
import static com.google.flatbuffers.Constants.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
// All tables in the generated code derive from this class, and add their own accessors.
/// @cond FLATBUFFERS_INTERNAL
/**
* All tables in the generated code derive from this class, and add their own accessors.
*/
public class Table {
private final static ThreadLocal<CharsetDecoder> UTF8_DECODER = new ThreadLocal<CharsetDecoder>() {
@Override
protected CharsetDecoder initialValue() {
return Charset.forName("UTF-8").newDecoder();
}
};
private final static ThreadLocal<CharBuffer> CHAR_BUFFER = new ThreadLocal<CharBuffer>();
/** Used to hold the position of the `bb` buffer. */
protected int bb_pos;
/** The underlying ByteBuffer to hold the data of the Table. */
protected ByteBuffer bb;
/**
* Get the underlying ByteBuffer.
*
* @return Returns the Table's ByteBuffer.
*/
public ByteBuffer getByteBuffer() { return bb; }
// Look up a field in the vtable, return an offset into the object, or 0 if the field is not
// present.
/**
* Look up a field in the vtable.
*
* @param vtable_offset An `int` offset to the vtable in the Table's ByteBuffer.
* @return Returns an offset into the object, or `0` if the field is not present.
*/
protected int __offset(int vtable_offset) {
int vtable = bb_pos - bb.getInt(bb_pos);
return vtable_offset < bb.getShort(vtable) ? bb.getShort(vtable + vtable_offset) : 0;
}
// Retrieve the relative offset stored at "offset"
/**
* Retrieve a relative offset.
*
* @param offset An `int` index into the Table's ByteBuffer containing the relative offset.
* @return Returns the relative offset stored at `offset`.
*/
protected int __indirect(int offset) {
return offset + bb.getInt(offset);
}
// Create a java String from UTF-8 data stored inside the flatbuffer.
// This allocates a new string and converts to wide chars upon each access,
// which is not very efficient. Instead, each FlatBuffer string also comes with an
// accessor based on __vector_as_bytebuffer below, which is much more efficient,
// assuming your Java program can handle UTF-8 data directly.
/**
* Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
*
* This allocates a new string and converts to wide chars upon each access,
* which is not very efficient. Instead, each FlatBuffer string also comes with an
* accessor based on __vector_as_bytebuffer below, which is much more efficient,
* assuming your Java program can handle UTF-8 data directly.
*
* @param offset An `int` index into the Table's ByteBuffer.
* @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
*/
protected String __string(int offset) {
CharsetDecoder decoder = UTF8_DECODER.get();
decoder.reset();
offset += bb.getInt(offset);
if (bb.hasArray()) {
return new String(bb.array(), bb.arrayOffset() + offset + SIZEOF_INT, bb.getInt(offset), FlatBufferBuilder.utf8charset);
} else {
// We can't access .array(), since the ByteBuffer is read-only,
// off-heap or a memory map
ByteBuffer bb = this.bb.duplicate().order(ByteOrder.LITTLE_ENDIAN);
// We're forced to make an extra copy:
byte[] copy = new byte[bb.getInt(offset)];
bb.position(offset + SIZEOF_INT);
bb.get(copy);
return new String(copy, 0, copy.length, FlatBufferBuilder.utf8charset);
ByteBuffer src = bb.duplicate().order(ByteOrder.LITTLE_ENDIAN);
int length = src.getInt(offset);
src.position(offset + SIZEOF_INT);
src.limit(offset + SIZEOF_INT + length);
int required = (int)((float)length * decoder.maxCharsPerByte());
CharBuffer dst = CHAR_BUFFER.get();
if (dst == null || dst.capacity() < required) {
dst = CharBuffer.allocate(required);
CHAR_BUFFER.set(dst);
}
dst.clear();
try {
CoderResult cr = decoder.decode(src, dst, true);
if (!cr.isUnderflow()) {
cr.throwException();
}
} catch (CharacterCodingException x) {
throw new Error(x);
}
return dst.flip().toString();
}
// Get the length of a vector whose offset is stored at "offset" in this object.
/**
* Get the length of a vector.
*
* @param offset An `int` index into the Table's ByteBuffer.
* @return Returns the length of the vector whose offset is stored at `offset`.
*/
protected int __vector_len(int offset) {
offset += bb_pos;
offset += bb.getInt(offset);
return bb.getInt(offset);
}
// Get the start of data of a vector whose offset is stored at "offset" in this object.
/**
* Get the start data of a vector.
*
* @param offset An `int` index into the Table's ByteBuffer.
* @return Returns the start of the vector data whose offset is stored at `offset`.
*/
protected int __vector(int offset) {
offset += bb_pos;
return offset + bb.getInt(offset) + SIZEOF_INT; // data starts after the length
}
// Get a whole vector as a ByteBuffer. This is efficient, since it only allocates a new
// bytebuffer object, but does not actually copy the data, it still refers to the same
// bytes as the original ByteBuffer.
// Also useful with nested FlatBuffers etc.
/**
* Get a whole vector as a ByteBuffer.
*
* This is efficient, since it only allocates a new {@link ByteBuffer} object,
* but does not actually copy the data, it still refers to the same bytes
* as the original ByteBuffer. Also useful with nested FlatBuffers, etc.
*
* @param vector_offset The position of the vector in the byte buffer
* @param elem_size The size of each element in the array
* @return The {@link ByteBuffer} for the array
*/
protected ByteBuffer __vector_as_bytebuffer(int vector_offset, int elem_size) {
int o = __offset(vector_offset);
if (o == 0) return null;
@@ -87,7 +157,13 @@ public class Table {
return bb;
}
// Initialize any Table-derived type to point to the union at the given offset.
/**
* Initialize any Table-derived type to point to the union at the given `offset`.
*
* @param t A `Table`-derived type that should point to the union at `offset`.
* @param offset An `int` index into the Table's ByteBuffer.
* @return Returns the Table that points to the union at `offset`.
*/
protected Table __union(Table t, int offset) {
offset += bb_pos;
t.bb_pos = offset + bb.getInt(offset);
@@ -95,6 +171,14 @@ public class Table {
return t;
}
/**
* Check if a {@link ByteBuffer} contains a file identifier.
*
* @param bb A {@code ByteBuffer} to check if it contains the identifier
* `ident`.
* @param ident A `String` identifier of the FlatBuffer file.
* @return True if the buffer contains the file identifier
*/
protected static boolean __has_identifier(ByteBuffer bb, String ident) {
if (ident.length() != FILE_IDENTIFIER_LENGTH)
throw new AssertionError("FlatBuffers: file identifier must be length " +
@@ -105,3 +189,5 @@ public class Table {
return true;
}
}
/// @endcond

View File

@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId>
<version>1.2.0-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>FlatBuffers Java API</name>
<description>