summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulo Pinheiro <paulovictor.pinheiro@gmail.com>2020-07-02 21:40:56 +0200
committerGitHub <noreply@github.com>2020-07-02 12:40:56 -0700
commitb69fc8cc9584436c1bc48012e9c426843ec1a055 (patch)
treeee128004bb588c56829445c8bf3a25aaefd5ef08
parentab6af18d9feeee3e7b01cd6ee62c5bf190982cfc (diff)
downloadflatbuffers-b69fc8cc9584436c1bc48012e9c426843ec1a055.tar.gz
flatbuffers-b69fc8cc9584436c1bc48012e9c426843ec1a055.tar.bz2
flatbuffers-b69fc8cc9584436c1bc48012e9c426843ec1a055.zip
[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.
-rw-r--r--java/com/google/flatbuffers/FlatBufferBuilder.java69
-rw-r--r--tests/JavaTest.java13
-rw-r--r--tests/KotlinTest.kt13
3 files changed, 80 insertions, 15 deletions
diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java
index e5e3967a..939e1b0c 100644
--- a/java/com/google/flatbuffers/FlatBufferBuilder.java
+++ b/java/com/google/flatbuffers/FlatBufferBuilder.java
@@ -22,6 +22,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.*;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.lang.Integer;
/// @file
/// @addtogroup flatbuffers_java_api
@@ -33,20 +36,21 @@ import java.util.Arrays;
*/
public class FlatBufferBuilder {
/// @cond FLATBUFFERS_INTERNAL
- ByteBuffer bb; // Where we construct the FlatBuffer.
- int space; // Remaining space in the ByteBuffer.
- 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.
- ByteBufferFactory bb_factory; // Factory for allocating the internal buffer
- final Utf8 utf8; // UTF-8 encoder to use
+ ByteBuffer bb; // Where we construct the FlatBuffer.
+ int space; // Remaining space in the ByteBuffer.
+ 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.
+ ByteBufferFactory bb_factory; // Factory for allocating the internal buffer
+ final Utf8 utf8; // UTF-8 encoder to use
+ Map<String, Integer> string_pool; // map used to cache shared strings.
/// @endcond
/**
@@ -147,6 +151,9 @@ public class FlatBufferBuilder {
object_start = 0;
num_vtables = 0;
vector_num_elems = 0;
+ if (string_pool != null) {
+ string_pool.clear();
+ }
return this;
}
@@ -224,6 +231,9 @@ public class FlatBufferBuilder {
object_start = 0;
num_vtables = 0;
vector_num_elems = 0;
+ if (string_pool != null) {
+ string_pool.clear();
+ }
}
/**
@@ -527,6 +537,37 @@ public class FlatBufferBuilder {
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
* already a {@link CharBuffer}, this method is allocation free.
diff --git a/tests/JavaTest.java b/tests/JavaTest.java
index 39c77334..fef099ff 100644
--- a/tests/JavaTest.java
+++ b/tests/JavaTest.java
@@ -23,7 +23,9 @@ import java.io.*;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -101,6 +103,8 @@ class JavaTest {
TestVectorOfBytes();
+ TestSharedStringPool();
+
System.out.println("FlatBuffers test: completed successfully");
}
@@ -1216,6 +1220,15 @@ class JavaTest {
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) {
if (!a.equals(b)) {
System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
diff --git a/tests/KotlinTest.kt b/tests/KotlinTest.kt
index 2d64a386..538ab466 100644
--- a/tests/KotlinTest.kt
+++ b/tests/KotlinTest.kt
@@ -76,6 +76,8 @@ class KotlinTest {
TestVectorOfUnions()
+ TestSharedStringPool()
+
println("FlatBuffers test: completed successfully")
}
@@ -456,5 +458,14 @@ class KotlinTest {
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));
+ }
+ }
}
+}