diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/com/google/flatbuffers/FlexBuffers.java | 216 | ||||
-rw-r--r-- | java/com/google/flatbuffers/FlexBuffersBuilder.java | 134 |
2 files changed, 313 insertions, 37 deletions
diff --git a/java/com/google/flatbuffers/FlexBuffers.java b/java/com/google/flatbuffers/FlexBuffers.java index 07e162d9..6e7b0868 100644 --- a/java/com/google/flatbuffers/FlexBuffers.java +++ b/java/com/google/flatbuffers/FlexBuffers.java @@ -25,37 +25,61 @@ import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +/// @file +/// @addtogroup flatbuffers_java_api +/// @{ + /** * This class can be used to parse FlexBuffer messages. * <p> * For generating FlexBuffer messages, use {@link FlexBuffersBuilder}. * <p> * Example of usage: + * <pre> * ByteBuffer bb = ... // load message from file or network * FlexBuffers.Reference r = FlexBuffers.getRoot(bb); // Reads the root element * FlexBuffers.Map map = r.asMap(); // We assumed root object is a map * System.out.println(map.get("name").asString()); // prints element with key "name" + * </pre> */ public class FlexBuffers { // These are used as the upper 6 bits of a type field to indicate the actual // type. + /** Represent a null type */ public static final int FBT_NULL = 0; + /** Represent a signed integer type */ public static final int FBT_INT = 1; + /** Represent a unsigned type */ public static final int FBT_UINT = 2; + /** Represent a float type */ public static final int FBT_FLOAT = 3; // Types above stored inline, types below store an offset. + /** Represent a key to a map type */ public static final int FBT_KEY = 4; + /** Represent a string type */ public static final int FBT_STRING = 5; + /** Represent a indirect signed integer type */ public static final int FBT_INDIRECT_INT = 6; + /** Represent a indirect unsigned integer type */ public static final int FBT_INDIRECT_UINT = 7; + /** Represent a indirect float type */ public static final int FBT_INDIRECT_FLOAT = 8; + /** Represent a map type */ public static final int FBT_MAP = 9; + /** Represent a vector type */ public static final int FBT_VECTOR = 10; // Untyped. + /** Represent a vector of signed integers type */ public static final int FBT_VECTOR_INT = 11; // Typed any size = stores no type table). + /** Represent a vector of unsigned integers type */ public static final int FBT_VECTOR_UINT = 12; + /** Represent a vector of floats type */ public static final int FBT_VECTOR_FLOAT = 13; + /** Represent a vector of keys type */ public static final int FBT_VECTOR_KEY = 14; + /** Represent a vector of strings type */ public static final int FBT_VECTOR_STRING = 15; + + /// @cond FLATBUFFERS_INTERNAL public static final int FBT_VECTOR_INT2 = 16; // Typed tuple = no type table; no size field). public static final int FBT_VECTOR_UINT2 = 17; public static final int FBT_VECTOR_FLOAT2 = 18; @@ -65,9 +89,15 @@ public class FlexBuffers { public static final int FBT_VECTOR_INT4 = 22; // Typed quad = no type table; no size field). public static final int FBT_VECTOR_UINT4 = 23; public static final int FBT_VECTOR_FLOAT4 = 24; + /// @endcond FLATBUFFERS_INTERNAL + + /** Represent a blob type */ public static final int FBT_BLOB = 25; + /** Represent a boolean type */ public static final int FBT_BOOL = 26; + /** Represent a vector of booleans type */ public static final int FBT_VECTOR_BOOL = 36; // To Allow the same type of conversion of type to vector type + private static final ByteBuffer EMPTY_BB = ByteBuffer.allocate(0).asReadOnlyBuffer(); /** @@ -98,7 +128,7 @@ public class FlexBuffers { * Return a vector type our of a original element type * * @param type element type - * @param fixedLength size of elment + * @param fixedLength size of element * @return typed vector type */ static int toTypedVector(int type, int fixedLength) { @@ -120,7 +150,7 @@ public class FlexBuffers { // return position of the element that the offset is pointing to private static int indirect(ByteBuffer bb, int offset, int byteWidth) { - //TODO: we assume all offset fits on a int, since ByteBuffer operates with that assumption + // we assume all offset fits on a int, since ByteBuffer operates with that assumption return (int) (offset - readUInt(bb, offset, byteWidth)); } @@ -175,6 +205,9 @@ public class FlexBuffers { return new Reference(buffer, end, byteWidth, packetType); } + /** + * Represents an generic element in the buffer. + */ public static class Reference { private static final Reference NULL_REFERENCE = new Reference(EMPTY_BB, 0, 1, 0); @@ -196,63 +229,127 @@ public class FlexBuffers { this.type = type; } + /** + * Return element type + * @return element type as integer + */ public int getType() { return type; } + /** + * Checks whether the element is null type + * @return true if null type + */ public boolean isNull() { return type == FBT_NULL; } - + + /** + * Checks whether the element is boolean type + * @return true if boolean type + */ public boolean isBoolean() { return type == FBT_BOOL; } + /** + * Checks whether the element type is numeric (signed/unsigned integers and floats) + * @return true if numeric type + */ public boolean isNumeric() { return isIntOrUInt() || isFloat(); } + /** + * Checks whether the element type is signed or unsigned integers + * @return true if an integer type + */ public boolean isIntOrUInt() { return isInt() || isUInt(); } + /** + * Checks whether the element type is float + * @return true if a float type + */ public boolean isFloat() { return type == FBT_FLOAT || type == FBT_INDIRECT_FLOAT; } + /** + * Checks whether the element type is signed integer + * @return true if a signed integer type + */ public boolean isInt() { return type == FBT_INT || type == FBT_INDIRECT_INT; } + /** + * Checks whether the element type is signed integer + * @return true if a signed integer type + */ public boolean isUInt() { return type == FBT_UINT || type == FBT_INDIRECT_UINT; } + /** + * Checks whether the element type is string + * @return true if a string type + */ public boolean isString() { return type == FBT_STRING; } + /** + * Checks whether the element type is key + * @return true if a key type + */ public boolean isKey() { return type == FBT_KEY; } + /** + * Checks whether the element type is vector + * @return true if a vector type + */ public boolean isVector() { return type == FBT_VECTOR || type == FBT_MAP; } + /** + * Checks whether the element type is typed vector + * @return true if a typed vector type + */ public boolean isTypedVector() { return (type >= FBT_VECTOR_INT && type <= FBT_VECTOR_STRING) || type == FBT_VECTOR_BOOL; } + /** + * Checks whether the element type is a map + * @return true if a map type + */ public boolean isMap() { return type == FBT_MAP; } + /** + * Checks whether the element type is a blob + * @return true if a blob type + */ public boolean isBlob() { return type == FBT_BLOB; } + /** + * Returns element as 32-bit integer. + * <p> For vector element, it will return size of the vector</p> + * <p> For String element, it will type to be parsed as integer</p> + * <p> Unsigned elements will become negative</p> + * <p> Float elements will be casted to integer </p> + * @return 32-bit integer or 0 if fail to convert element to integer. + */ public int asInt() { if (type == FBT_INT) { // A fast path for the common case. @@ -274,6 +371,14 @@ public class FlexBuffers { } } + /** + * Returns element as unsigned 64-bit integer. + * <p> For vector element, it will return size of the vector</p> + * <p> For String element, it will type to be parsed as integer</p> + * <p> Negative signed elements will become unsigned counterpart</p> + * <p> Float elements will be casted to integer </p> + * @return 64-bit integer or 0 if fail to convert element to integer. + */ public long asUInt() { if (type == FBT_UINT) { // A fast path for the common case. @@ -295,6 +400,14 @@ public class FlexBuffers { } } + /** + * Returns element as 64-bit integer. + * <p> For vector element, it will return size of the vector</p> + * <p> For String element, it will type to be parsed as integer</p> + * <p> Unsigned elements will become negative</p> + * <p> Float elements will be casted to integer </p> + * @return 64-bit integer or 0 if fail to convert element to long. + */ public long asLong() { if (type == FBT_INT) { // A fast path for the common case. @@ -322,6 +435,12 @@ public class FlexBuffers { } } + /** + * Returns element as 64-bit integer. + * <p> For vector element, it will return size of the vector</p> + * <p> For String element, it will type to be parsed as integer</p> + * @return 64-bit integer or 0 if fail to convert element to long. + */ public double asFloat() { if (type == FBT_FLOAT) { // A fast path for the common case. @@ -344,6 +463,10 @@ public class FlexBuffers { } } + /** + * Returns element as a {@link Key} + * @return key or {@link Key#empty()} if element is not a key + */ public Key asKey() { if (isKey()) { return new Key(bb, indirect(bb, end, parentWidth), byteWidth); @@ -352,6 +475,10 @@ public class FlexBuffers { } } + /** + * Returns element as a `String` + * @return element as `String` or empty `String` if fail + */ public String asString() { if (isString()) { int start = indirect(bb, end, byteWidth); @@ -370,6 +497,10 @@ public class FlexBuffers { } } + /** + * Returns element as a {@link Map} + * @return element as {@link Map} or empty {@link Map} if fail + */ public Map asMap() { if (isMap()) { return new Map(bb, indirect(bb, end, parentWidth), byteWidth); @@ -378,6 +509,10 @@ public class FlexBuffers { } } + /** + * Returns element as a {@link Vector} + * @return element as {@link Vector} or empty {@link Vector} if fail + */ public Vector asVector() { if (isVector()) { return new Vector(bb, indirect(bb, end, parentWidth), byteWidth); @@ -388,6 +523,10 @@ public class FlexBuffers { } } + /** + * Returns element as a {@link Blob} + * @return element as {@link Blob} or empty {@link Blob} if fail + */ public Blob asBlob() { if (isBlob() || isString()) { return new Blob(bb, indirect(bb, end, parentWidth), byteWidth); @@ -396,6 +535,11 @@ public class FlexBuffers { } } + /** + * Returns element as a boolean + * <p>If element type is not boolean, it will be casted to integer and compared against 0</p> + * @return element as boolean + */ public boolean asBoolean() { if (isBoolean()) { return bb.get(end) != 0; @@ -403,11 +547,18 @@ public class FlexBuffers { return asUInt() != 0; } + /** + * Returns text representation of the element (JSON) + * @return String containing text representation of the element + */ @Override public String toString() { return toString(new StringBuilder(128)).toString(); } + /** + * Appends a text(JSON) representation to a `StringBuilder` + */ StringBuilder toString(StringBuilder sb) { //TODO: Original C++ implementation escape strings. // probably we should do it as well. @@ -493,6 +644,13 @@ public class FlexBuffers { } } + /** + * Represents a array of bytes element in the buffer + * + * <p>It can be converted to `ByteBuffer` using {@link data()}, + * copied into a byte[] using {@link getBytes()} or + * have individual bytes accessed individually using {@link get(int)}</p> + */ public static class Blob extends Sized { static final Blob EMPTY = new Blob(EMPTY_BB, 0, 1); @@ -500,12 +658,14 @@ public class FlexBuffers { super(buff, end, byteWidth); } + /** Return an empty {@link Blob} */ public static Blob empty() { return EMPTY; } /** - * @return blob as a {@link ByteBuffer} + * Return {@link Blob} as `ByteBuffer` + * @return blob as `ByteBuffer` */ public ByteBuffer data() { ByteBuffer dup = bb.duplicate(); @@ -515,7 +675,8 @@ public class FlexBuffers { } /** - * @return blob as a byte array + * Copy blob into a byte[] + * @return blob as a byte[] */ public byte[] getBytes() { int size = size(); @@ -526,16 +687,26 @@ public class FlexBuffers { return result; } + /** + * Return individual byte at a given position + * @param pos position of the byte to be read + */ public byte get(int pos) { assert pos >=0 && pos <= size(); return bb.get(end + pos); } + /** + * Returns a text(JSON) representation of the {@link Blob} + */ @Override public String toString() { return Utf8.getDefault().decodeUtf8(bb, end, size()); } + /** + * Append a text(JSON) representation of the {@link Blob} into a `StringBuilder` + */ @Override public StringBuilder toString(StringBuilder sb) { sb.append('"'); @@ -544,6 +715,10 @@ public class FlexBuffers { } } + /** + * Represents a key element in the buffer. Keys are + * used to reference objects in a {@link Map} + */ public static class Key extends Object { private static final Key EMPTY = new Key(EMPTY_BB, 0, 0); @@ -552,10 +727,17 @@ public class FlexBuffers { super(buff, end, byteWidth); } + /** + * Return an empty {@link Key} + * @return empty {@link Key} + * */ public static Key empty() { return Key.EMPTY; } + /** + * Appends a text(JSON) representation to a `StringBuilder` + */ @Override public StringBuilder toString(StringBuilder sb) { int size; @@ -590,6 +772,11 @@ public class FlexBuffers { return c1 - c2; } + /** + * Compare keys + * @param obj other key to compare + * @return true if keys are the same + */ @Override public boolean equals(java.lang.Object obj) { if (!(obj instanceof Key)) @@ -609,6 +796,10 @@ public class FlexBuffers { super(bb, end, byteWidth); } + /** + * Returns an empty {@link Map} + * @return an empty {@link Map} + */ public static Map empty() { return EMPTY_MAP; } @@ -710,14 +901,25 @@ public class FlexBuffers { super(bb, end, byteWidth); } + /** + * Returns an empty {@link Map} + * @return an empty {@link Map} + */ public static Vector empty() { return EMPTY_VECTOR; } + /** + * Checks if the vector is empty + * @return true if vector is empty + */ public boolean isEmpty() { return this == EMPTY_VECTOR; } + /** + * Appends a text(JSON) representation to a `StringBuilder` + */ @Override public StringBuilder toString(StringBuilder sb) { sb.append("[ "); @@ -833,6 +1035,9 @@ public class FlexBuffers { return vec.size(); } + /** + * Returns a text(JSON) representation + */ public String toString() { StringBuilder b = new StringBuilder(); b.append('['); @@ -867,3 +1072,4 @@ public class FlexBuffers { } } } +/// @} diff --git a/java/com/google/flatbuffers/FlexBuffersBuilder.java b/java/com/google/flatbuffers/FlexBuffersBuilder.java index 36e8544a..a58c7a30 100644 --- a/java/com/google/flatbuffers/FlexBuffersBuilder.java +++ b/java/com/google/flatbuffers/FlexBuffersBuilder.java @@ -30,34 +30,26 @@ import static com.google.flatbuffers.FlexBuffers.Unsigned.byteToUnsignedInt; import static com.google.flatbuffers.FlexBuffers.Unsigned.intToUnsignedLong; import static com.google.flatbuffers.FlexBuffers.Unsigned.shortToUnsignedInt; +/// @file +/// @addtogroup flatbuffers_java_api +/// @{ + /** - * A class that generates FlexBuffers - * <p> - * This class presents all necessary APIs to create FlexBuffers. The {@link ByteBuffer } buffer used to store the - * data can be created internally, or passed down in the constructor. - * <p> - * Because it uses {@link ByteBuffer} internally, this impose some limitations in generating FlexBuffers. Mostly noted, - * the maximum size limitation on FlexBuffer message, which is {@link Integer#MAX_VALUE}. + * Helper class that builds FlexBuffers + * <p> This class presents all necessary APIs to create FlexBuffers. A `ByteBuffer` will be used to store the + * data. It can be created internally, or passed down in the constructor.</p> * - * <p>There is also some differences from the original implementation in C++. It can changed in future updates. + * <p>There are some limitations when compared to original implementation in C++. Most notably: * <ul> - * - * <li><p>No support for mutations (might change in the future).</p></li> - * - * <li><p>Size of message limited to {@link Integer#MAX_VALUE}</p></li> - * - * <li><p>Since Java does not support unsigned type, all unsigned operations accepts a immediate higher representation - * of similar type. Unsigned long is not supported</p></li> + * <li><p> No support for mutations (might change in the future).</p></li> + * <li><p> Buffer size limited to {@link Integer#MAX_VALUE}</p></li> + * <li><p> Since Java does not support unsigned type, all unsigned operations accepts an immediate higher representation + * of similar type.</p></li> * </ul> * </p> */ public class FlexBuffersBuilder { - private static final int WIDTH_8 = 0; - private static final int WIDTH_16 = 1; - private static final int WIDTH_32 = 2; - private static final int WIDTH_64 = 3; - /** * No keys or strings will be shared */ @@ -86,6 +78,11 @@ public class FlexBuffersBuilder { */ public static final int BUILDER_FLAG_SHARE_ALL = 7; + /// @cond FLATBUFFERS_INTERNAL + private static final int WIDTH_8 = 0; + private static final int WIDTH_16 = 1; + private static final int WIDTH_32 = 2; + private static final int WIDTH_64 = 3; private final ByteBuffer bb; private final ArrayList<Value> stack = new ArrayList<>(); private final HashMap<String, Integer> keyPool = new HashMap<>(); @@ -93,7 +90,8 @@ public class FlexBuffersBuilder { private final int flags; private boolean finished = false; - private Comparator<Value> valueComparator = new Comparator<Value>() { + // A lambda to sort map keys + private Comparator<Value> keyComparator = new Comparator<Value>() { @Override public int compare(Value o1, Value o2) { int ia = o1.key; @@ -111,18 +109,27 @@ public class FlexBuffersBuilder { return c1 - c2; } }; + /// @endcond + + /** + * Constructs a newly allocated {@code FlexBuffersBuilder} with {@link #BUILDER_FLAG_SHARE_KEYS} set. + * @param bufSize size of buffer in bytes. + */ + public FlexBuffersBuilder(int bufSize) { + this(ByteBuffer.allocate(bufSize), BUILDER_FLAG_SHARE_KEYS); + } /** * Constructs a newly allocated {@code FlexBuffersBuilder} with {@link #BUILDER_FLAG_SHARE_KEYS} set. */ public FlexBuffersBuilder() { - this(ByteBuffer.allocate(256), BUILDER_FLAG_SHARE_KEYS); + this(256); } /** * Constructs a newly allocated {@code FlexBuffersBuilder}. * - * @param bb ByteBuffer that will hold the message + * @param bb `ByteBuffer` that will hold the message * @param flags Share flags */ public FlexBuffersBuilder(ByteBuffer bb, int flags) { @@ -134,18 +141,18 @@ public class FlexBuffersBuilder { /** * Constructs a newly allocated {@code FlexBuffersBuilder}. - * - * @param bb ByteBuffer that will hold the message + * By default same keys will be serialized only once + * @param bb `ByteBuffer` that will hold the message */ public FlexBuffersBuilder(ByteBuffer bb) { this(bb, BUILDER_FLAG_SHARE_KEYS); } /** - * Return {@code ByteBuffer} containing FlexBuffer message. {@code #finish()} must be called before calling this + * Return `ByteBuffer` containing FlexBuffer message. {@code #finish()} must be called before calling this * function otherwise an assert will trigger. * - * @return {@code ByteBuffer} with finished message + * @return `ByteBuffer` with finished message */ public ByteBuffer getBuffer() { assert (finished); @@ -160,6 +167,11 @@ public class FlexBuffersBuilder { putBoolean(null, val); } + /** + * Insert a single boolean into the buffer + * @param key key used to store element in map + * @param val true or false + */ public void putBoolean(String key, boolean val) { stack.add(Value.bool(putKey(key), val)); } @@ -193,10 +205,20 @@ public class FlexBuffersBuilder { putInt(null, val); } + /** + * Adds a integer into the buff + * @param key key used to store element in map + * @param val integer + */ public void putInt(String key, int val) { putInt(key, (long) val); } + /** + * Adds a integer into the buff + * @param key key used to store element in map + * @param val 64-bit integer + */ public void putInt(String key, long val) { int iKey = putKey(key); if (Byte.MIN_VALUE <= val && val <= Byte.MAX_VALUE) { @@ -273,6 +295,11 @@ public class FlexBuffersBuilder { putFloat(null, value); } + /** + * Adds a 32-bit float into the buff. + * @param key key used to store element in map + * @param value float representing value + */ public void putFloat(String key, float val) { stack.add(Value.float32(putKey(key), val)); } @@ -285,6 +312,11 @@ public class FlexBuffersBuilder { putFloat(null, value); } + /** + * Adds a 64-bit float into the buff. + * @param key key used to store element in map + * @param value float representing value + */ public void putFloat(String key, double val) { stack.add(Value.float64(putKey(key), val)); } @@ -298,6 +330,12 @@ public class FlexBuffersBuilder { return putString(null, value); } + /** + * Adds a String into the buffer + * @param key key used to store element in map + * @param value string + * @return start position of string in the buffer + */ public int putString(String key, String val) { int iKey = putKey(key); if ((flags & FlexBuffersBuilder.BUILDER_FLAG_SHARE_STRINGS) != 0) { @@ -371,6 +409,12 @@ public class FlexBuffersBuilder { return putBlob(null, value); } + /** + * Adds a byte array into the message + * @param key key used to store element in map + * @param value byte array + * @return position in buffer as the start of byte array + */ public int putBlob(String key, byte[] val) { int iKey = putKey(key); Value value = writeBlob(iKey, val, FBT_BLOB); @@ -378,10 +422,23 @@ public class FlexBuffersBuilder { return (int) value.iValue; } + /** + * Start a new vector in the buffer. + * @return a reference indicating position of the vector in buffer. This + * reference must be passed along when the vector is finished using endVector() + */ public int startVector() { return stack.size(); } + /** + * Finishes a vector, but writing the information in the buffer + * @param key key used to store element in map + * @param start reference for begining of the vector. Returned by {@link startVector()} + * @param typed boolean indicating wether vector is typed + * @param fixed boolean indicating wether vector is fixed + * @return Reference to the vector + */ public int endVector(String key, int start, boolean typed, boolean fixed) { int iKey = putKey(key); Value vec = createVector(iKey, start, stack.size() - start, typed, fixed, null); @@ -397,7 +454,7 @@ public class FlexBuffersBuilder { * Finish writing the message into the buffer. After that no other element must * be inserted into the buffer. Also, you must call this function before start using the * FlexBuffer message - * @return ByteBuffer containing the FlexBuffer message + * @return `ByteBuffer` containing the FlexBuffer message */ public ByteBuffer finish() { // If you hit this assert, you likely have objects that were never included @@ -420,12 +477,12 @@ public class FlexBuffersBuilder { /* * Create a vector based on the elements stored in the stack * - * @param key reference to its key + * @param key reference to its key * @param start element in the stack * @param length size of the vector * @param typed whether is TypedVector or not * @param fixed whether is Fixed vector or not - * @param keys Value representing key vector + * @param keys Value representing key vector * @return Value representing the created vector */ private Value createVector(int key, int start, int length, boolean typed, boolean fixed, Value keys) { @@ -514,14 +571,25 @@ public class FlexBuffersBuilder { } } + /** + * Start a new map in the buffer. + * @return a reference indicating position of the map in buffer. This + * reference must be passed along when the map is finished using endMap() + */ public int startMap() { return stack.size(); } + /** + * Finishes a map, but writing the information in the buffer + * @param key key used to store element in map + * @param start reference for begining of the map. Returned by {@link startMap()} + * @return Reference to the map + */ public int endMap(String key, int start) { int iKey = putKey(key); - Collections.sort(stack.subList(start, stack.size()), valueComparator); + Collections.sort(stack.subList(start, stack.size()), keyComparator); Value keys = createKeyVector(start, stack.size() - start); Value vec = createVector(iKey, start, stack.size() - start, false, false, keys); @@ -557,7 +625,7 @@ public class FlexBuffersBuilder { return new Value(-1, FlexBuffers.toTypedVector(FBT_KEY,0), bitWidth, vloc); } - public static class Value { + private static class Value { final int type; // for scalars, represents scalar size in bytes // for vectors, represents the size @@ -690,3 +758,5 @@ public class FlexBuffersBuilder { } } } + +/// @} |