diff --git a/java/com/google/flatbuffers/FlexBuffers.java b/java/com/google/flatbuffers/FlexBuffers.java index 0605c1b24..ff8ea8d83 100644 --- a/java/com/google/flatbuffers/FlexBuffers.java +++ b/java/com/google/flatbuffers/FlexBuffers.java @@ -77,7 +77,9 @@ public class FlexBuffers { /** 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; + // DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead. + // more info on thttps://github.com/google/flatbuffers/issues/5627. + public static final int FBT_VECTOR_STRING_DEPRECATED = 15; /// @cond FLATBUFFERS_INTERNAL public static final int FBT_VECTOR_INT2 = 16; // Typed tuple = no type table; no size field). @@ -107,7 +109,7 @@ public class FlexBuffers { * @return true if typed vector */ static boolean isTypedVector(int type) { - return (type >= FBT_VECTOR_INT && type <= FBT_VECTOR_STRING) || type == FBT_VECTOR_BOOL; + return (type >= FBT_VECTOR_INT && type <= FBT_VECTOR_STRING_DEPRECATED) || type == FBT_VECTOR_BOOL; } /** @@ -145,7 +147,7 @@ public class FlexBuffers { } static boolean isTypedVectorElementType(int type) { - return (type >= FBT_INT && type <= FBT_STRING) || type == FBT_BOOL; + return (type >= FBT_INT && type <= FBT_KEY) || type == FBT_BOOL; } // return position of the element that the offset is pointing to @@ -322,8 +324,7 @@ public class FlexBuffers { * @return true if a typed vector type */ public boolean isTypedVector() { - return (type >= FBT_VECTOR_INT && type <= FBT_VECTOR_STRING) || - type == FBT_VECTOR_BOOL; + return FlexBuffers.isTypedVector(type); } /** @@ -482,7 +483,7 @@ public class FlexBuffers { public String asString() { if (isString()) { int start = indirect(bb, end, parentWidth); - int size = readInt(bb, start - byteWidth, byteWidth); + int size = (int) readUInt(bb, start - byteWidth, byteWidth); return Utf8.getDefault().decodeUtf8(bb, start, size); } else if (isKey()){ @@ -516,6 +517,9 @@ public class FlexBuffers { public Vector asVector() { if (isVector()) { return new Vector(bb, indirect(bb, end, parentWidth), byteWidth); + } else if(type == FlexBuffers.FBT_VECTOR_STRING_DEPRECATED) { + // deprecated. Should be treated as key vector + return new TypedVector(bb, indirect(bb, end, parentWidth), byteWidth, FlexBuffers.FBT_KEY); } else if (FlexBuffers.isTypedVector(type)) { return new TypedVector(bb, indirect(bb, end, parentWidth), byteWidth, FlexBuffers.toTypedVectorElementType(type)); } else { @@ -590,7 +594,7 @@ public class FlexBuffers { case FBT_VECTOR_UINT: case FBT_VECTOR_FLOAT: case FBT_VECTOR_KEY: - case FBT_VECTOR_STRING: + case FBT_VECTOR_STRING_DEPRECATED: case FBT_VECTOR_BOOL: return sb.append(asVector()); case FBT_VECTOR_INT2: diff --git a/java/com/google/flatbuffers/FlexBuffersBuilder.java b/java/com/google/flatbuffers/FlexBuffersBuilder.java index 64db751f3..c8438bba9 100644 --- a/java/com/google/flatbuffers/FlexBuffersBuilder.java +++ b/java/com/google/flatbuffers/FlexBuffersBuilder.java @@ -358,24 +358,24 @@ public class FlexBuffersBuilder { } private Value writeString(int key, String s) { - return writeBlob(key, s.getBytes(StandardCharsets.UTF_8), FBT_STRING); + return writeBlob(key, s.getBytes(StandardCharsets.UTF_8), FBT_STRING, true); } // in bits to fit a unsigned int - private static int widthUInBits(long len) { + static int widthUInBits(long len) { if (len <= byteToUnsignedInt((byte)0xff)) return WIDTH_8; if (len <= shortToUnsignedInt((short)0xffff)) return WIDTH_16; if (len <= intToUnsignedLong(0xffff_ffff)) return WIDTH_32; return WIDTH_64; } - private Value writeBlob(int key, byte[] blob, int type) { + private Value writeBlob(int key, byte[] blob, int type, boolean trailing) { int bitWidth = widthUInBits(blob.length); int byteWidth = align(bitWidth); writeInt(blob.length, byteWidth); int sloc = bb.position(); bb.put(blob); - if (type == FBT_STRING) { + if (trailing) { bb.put((byte) 0); } return Value.blob(key, sloc, type, bitWidth); @@ -384,7 +384,7 @@ public class FlexBuffersBuilder { // Align to prepare for writing a scalar with a certain size. private int align(int alignment) { int byteWidth = 1 << alignment; - int padBytes = Value.paddingBytes(bb.capacity(), byteWidth); + int padBytes = Value.paddingBytes(bb.position(), byteWidth); while (padBytes-- != 0) { bb.put((byte) 0); } @@ -417,7 +417,7 @@ public class FlexBuffersBuilder { */ public int putBlob(String key, byte[] val) { int iKey = putKey(key); - Value value = writeBlob(iKey, val, FBT_BLOB); + Value value = writeBlob(iKey, val, FBT_BLOB, false); stack.add(value); return (int) value.iValue; } @@ -504,6 +504,9 @@ public class FlexBuffersBuilder { if (typed) { if (i == start) { vectorType = stack.get(i).type; + if (!FlexBuffers.isTypedVectorElementType(vectorType)) { + throw new FlexBufferException("TypedVector does not support this element type"); + } } else { // If you get this assert, you are writing a typed vector with // elements that are not all the same type. @@ -659,7 +662,7 @@ public class FlexBuffersBuilder { } static Value blob(int key, int position, int type, int bitWidth) { - return new Value(key, type, WIDTH_8, position); + return new Value(key, type, bitWidth, position); } static Value int8(int key, int value) { diff --git a/tests/JavaTest.java b/tests/JavaTest.java index 1443b779b..766d35255 100644 --- a/tests/JavaTest.java +++ b/tests/JavaTest.java @@ -12,6 +12,10 @@ import com.google.flatbuffers.FlexBuffers; import com.google.flatbuffers.FlexBuffersBuilder; import com.google.flatbuffers.StringVector; import com.google.flatbuffers.UnionVector; +import com.google.flatbuffers.FlexBuffers.FlexBufferException; +import com.google.flatbuffers.FlexBuffers.Reference; +import com.google.flatbuffers.FlexBuffers.Vector; + import java.io.*; import java.math.BigInteger; import java.nio.ByteBuffer; @@ -694,6 +698,60 @@ class JavaTest { TestEq(mymap.get("blob").toString(), "\"AC\""); } + public static void testFlexBufferVectorStrings() { + FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(10000000)); + + int size = 3000; + StringBuilder sb = new StringBuilder(); + for (int i=0; i< size; i++) { + sb.append("a"); + } + + String text = sb.toString(); + TestEq(text.length(), size); + + int pos = builder.startVector(); + + for (int i=0; i