[Java] Add support for shared strings on FlatBufferBuilder. (#6012)
Added a method FlatBufferBuilder::createSharedString that enable string sharing for building messages on java. The shared pool will only contains strings inserted by this methods.
This commit is contained in:
parent
ab6af18d9f
commit
b69fc8cc95
|
@ -22,6 +22,9 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
/// @file
|
/// @file
|
||||||
/// @addtogroup flatbuffers_java_api
|
/// @addtogroup flatbuffers_java_api
|
||||||
|
@ -33,20 +36,21 @@ import java.util.Arrays;
|
||||||
*/
|
*/
|
||||||
public class FlatBufferBuilder {
|
public class FlatBufferBuilder {
|
||||||
/// @cond FLATBUFFERS_INTERNAL
|
/// @cond FLATBUFFERS_INTERNAL
|
||||||
ByteBuffer bb; // Where we construct the FlatBuffer.
|
ByteBuffer bb; // Where we construct the FlatBuffer.
|
||||||
int space; // Remaining space in the ByteBuffer.
|
int space; // Remaining space in the ByteBuffer.
|
||||||
int minalign = 1; // Minimum alignment encountered so far.
|
int minalign = 1; // Minimum alignment encountered so far.
|
||||||
int[] vtable = null; // The vtable for the current table.
|
int[] vtable = null; // The vtable for the current table.
|
||||||
int vtable_in_use = 0; // The amount of fields we're actually using.
|
int vtable_in_use = 0; // The amount of fields we're actually using.
|
||||||
boolean nested = false; // Whether we are currently serializing a table.
|
boolean nested = false; // Whether we are currently serializing a table.
|
||||||
boolean finished = false; // Whether the buffer is finished.
|
boolean finished = false; // Whether the buffer is finished.
|
||||||
int object_start; // Starting offset of the current struct/table.
|
int object_start; // Starting offset of the current struct/table.
|
||||||
int[] vtables = new int[16]; // List of offsets of all vtables.
|
int[] vtables = new int[16]; // List of offsets of all vtables.
|
||||||
int num_vtables = 0; // Number of entries in `vtables` in use.
|
int num_vtables = 0; // Number of entries in `vtables` in use.
|
||||||
int vector_num_elems = 0; // For the current vector being built.
|
int vector_num_elems = 0; // For the current vector being built.
|
||||||
boolean force_defaults = false; // False omits default values from the serialized data.
|
boolean force_defaults = false; // False omits default values from the serialized data.
|
||||||
ByteBufferFactory bb_factory; // Factory for allocating the internal buffer
|
ByteBufferFactory bb_factory; // Factory for allocating the internal buffer
|
||||||
final Utf8 utf8; // UTF-8 encoder to use
|
final Utf8 utf8; // UTF-8 encoder to use
|
||||||
|
Map<String, Integer> string_pool; // map used to cache shared strings.
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,6 +151,9 @@ public class FlatBufferBuilder {
|
||||||
object_start = 0;
|
object_start = 0;
|
||||||
num_vtables = 0;
|
num_vtables = 0;
|
||||||
vector_num_elems = 0;
|
vector_num_elems = 0;
|
||||||
|
if (string_pool != null) {
|
||||||
|
string_pool.clear();
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +231,9 @@ public class FlatBufferBuilder {
|
||||||
object_start = 0;
|
object_start = 0;
|
||||||
num_vtables = 0;
|
num_vtables = 0;
|
||||||
vector_num_elems = 0;
|
vector_num_elems = 0;
|
||||||
|
if (string_pool != null) {
|
||||||
|
string_pool.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -527,6 +537,37 @@ public class FlatBufferBuilder {
|
||||||
return createVectorOfTables(offsets);
|
return createVectorOfTables(offsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode the String `s` in the buffer using UTF-8. If a String with
|
||||||
|
* this exact contents has already been serialized using this method,
|
||||||
|
* instead simply returns the offset of the existing String.
|
||||||
|
*
|
||||||
|
* Usage of the method will incur into additional allocations,
|
||||||
|
* so it is advisable to use it only when it is known upfront that
|
||||||
|
* your message will have several repeated strings.
|
||||||
|
*
|
||||||
|
* @param s The String to encode.
|
||||||
|
* @return The offset in the buffer where the encoded String starts.
|
||||||
|
*/
|
||||||
|
public int createSharedString(String s) {
|
||||||
|
|
||||||
|
if (string_pool == null) {
|
||||||
|
string_pool = new HashMap<>();
|
||||||
|
int offset = createString(s);
|
||||||
|
string_pool.put(s, offset);
|
||||||
|
return offset;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer offset = string_pool.get(s);
|
||||||
|
|
||||||
|
if(offset == null) {
|
||||||
|
offset = createString(s);
|
||||||
|
string_pool.put(s, offset);
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the string `s` in the buffer using UTF-8. If {@code s} is
|
* Encode the string `s` in the buffer using UTF-8. If {@code s} is
|
||||||
* already a {@link CharBuffer}, this method is allocation free.
|
* already a {@link CharBuffer}, this method is allocation free.
|
||||||
|
|
|
@ -23,7 +23,9 @@ import java.io.*;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.CharBuffer;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -101,6 +103,8 @@ class JavaTest {
|
||||||
|
|
||||||
TestVectorOfBytes();
|
TestVectorOfBytes();
|
||||||
|
|
||||||
|
TestSharedStringPool();
|
||||||
|
|
||||||
System.out.println("FlatBuffers test: completed successfully");
|
System.out.println("FlatBuffers test: completed successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1216,6 +1220,15 @@ class JavaTest {
|
||||||
TestEq(monsterObject8.inventoryLength(), 2048);
|
TestEq(monsterObject8.inventoryLength(), 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TestSharedStringPool() {
|
||||||
|
FlatBufferBuilder fb = new FlatBufferBuilder(1);
|
||||||
|
String testString = "My string";
|
||||||
|
int offset = fb.createSharedString(testString);
|
||||||
|
for (int i=0; i< 10; i++) {
|
||||||
|
TestEq(offset, fb.createSharedString(testString));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static <T> void TestEq(T a, T b) {
|
static <T> void TestEq(T a, T b) {
|
||||||
if (!a.equals(b)) {
|
if (!a.equals(b)) {
|
||||||
System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
|
System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
|
||||||
|
|
|
@ -76,6 +76,8 @@ class KotlinTest {
|
||||||
|
|
||||||
TestVectorOfUnions()
|
TestVectorOfUnions()
|
||||||
|
|
||||||
|
TestSharedStringPool()
|
||||||
|
|
||||||
println("FlatBuffers test: completed successfully")
|
println("FlatBuffers test: completed successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,5 +458,14 @@ class KotlinTest {
|
||||||
|
|
||||||
assert((movie.characters(Attacker(), 0) as Attacker).swordAttackDamage == swordAttackDamage)
|
assert((movie.characters(Attacker(), 0) as Attacker).swordAttackDamage == swordAttackDamage)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
fun TestSharedStringPool() {
|
||||||
|
val fb = FlatBufferBuilder(1);
|
||||||
|
val testString = "My string";
|
||||||
|
val offset = fb.createSharedString(testString);
|
||||||
|
for (i in 0..10) {
|
||||||
|
assert(offset == fb.createSharedString(testString));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue