Java: Pulling in protobuf's faster UTF-8 encoder. (#5035)

* Pulling in protobuf's faster UTF-8 encoder.

* Remove Utf8 unsafe code.
This commit is contained in:
Owen O'Malley
2018-12-17 13:53:49 -08:00
committed by Wouter van Oortmerssen
parent 9ad73bf5a7
commit cb99116aca
6 changed files with 781 additions and 70 deletions

View File

@@ -21,11 +21,7 @@ import static com.google.flatbuffers.Constants.*;
import java.io.IOException;
import java.io.InputStream;
import java.nio.*;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.Arrays;
import java.nio.charset.Charset;
/// @file
/// @addtogroup flatbuffers_java_api
@@ -39,7 +35,6 @@ public class FlatBufferBuilder {
/// @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.
@@ -50,9 +45,8 @@ 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.
CharsetEncoder encoder = utf8charset.newEncoder();
ByteBuffer dst;
ByteBufferFactory bb_factory; // Factory for allocating the internal buffer
final Utf8 utf8; // UTF-8 encoder to use
/// @endcond
/**
@@ -62,10 +56,31 @@ public class FlatBufferBuilder {
* @param bb_factory The factory to be used for allocating the internal buffer
*/
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory) {
if (initial_size <= 0) initial_size = 1;
this(initial_size, bb_factory, null, Utf8.getDefault());
}
/**
* 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 bb_factory The factory to be used for allocating the internal buffer
* @param existing_bb The byte buffer to reuse.
*/
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory,
ByteBuffer existing_bb, Utf8 utf8) {
if (initial_size <= 0) {
initial_size = 1;
}
space = initial_size;
this.bb_factory = bb_factory;
bb = bb_factory.newByteBuffer(initial_size);
if (existing_bb != null) {
bb = existing_bb;
bb.clear();
} else {
bb = bb_factory.newByteBuffer(initial_size);
}
bb.order(ByteOrder.LITTLE_ENDIAN);
this.utf8 = utf8;
}
/**
@@ -74,7 +89,7 @@ public class FlatBufferBuilder {
* @param initial_size The initial size of the internal buffer to use.
*/
public FlatBufferBuilder(int initial_size) {
this(initial_size, new HeapByteBufferFactory());
this(initial_size, new HeapByteBufferFactory(), null, Utf8.getDefault());
}
/**
@@ -94,7 +109,7 @@ public class FlatBufferBuilder {
* the existing buffer needs to grow
*/
public FlatBufferBuilder(ByteBuffer existing_bb, ByteBufferFactory bb_factory) {
init(existing_bb, bb_factory);
this(existing_bb.capacity(), bb_factory, existing_bb, Utf8.getDefault());
}
/**
@@ -105,7 +120,7 @@ public class FlatBufferBuilder {
* @param existing_bb The byte buffer to reuse.
*/
public FlatBufferBuilder(ByteBuffer existing_bb) {
init(existing_bb, new HeapByteBufferFactory());
this(existing_bb, new HeapByteBufferFactory());
}
/**
@@ -503,27 +518,12 @@ public class FlatBufferBuilder {
* @return The offset in the buffer where the encoded string starts.
*/
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);
int length = utf8.encodedLength(s);
addByte((byte)0);
startVector(1, length, 1);
bb.position(space -= length);
utf8.encodeUtf8(s, bb);
return endVector();
}
/**