forked from BigfootDev/flatbuffers
bulk code format fix (#8707)
This commit is contained in:
@@ -8,6 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "com.google.flatbuffers.jmh"
|
||||
|
||||
version = "2.0.0-SNAPSHOT"
|
||||
|
||||
// Reads latest version from Java's runtime pom.xml,
|
||||
@@ -15,10 +16,11 @@ version = "2.0.0-SNAPSHOT"
|
||||
// runtime
|
||||
fun readJavaFlatBufferVersion(): String {
|
||||
val pom = XmlParser().parse(File("../java/pom.xml"))
|
||||
val versionTag = pom.children().find {
|
||||
val node = it as groovy.util.Node
|
||||
node.name().toString().contains("version")
|
||||
} as groovy.util.Node
|
||||
val versionTag =
|
||||
pom.children().find {
|
||||
val node = it as groovy.util.Node
|
||||
node.name().toString().contains("version")
|
||||
} as groovy.util.Node
|
||||
return versionTag.value().toString()
|
||||
}
|
||||
|
||||
@@ -39,27 +41,26 @@ benchmark {
|
||||
iterationTime = 300
|
||||
iterationTimeUnit = "ms"
|
||||
// uncomment for benchmarking JSON op only
|
||||
include(".*FlatbufferBenchmark.*")
|
||||
include(".*FlatbufferBenchmark.*")
|
||||
}
|
||||
}
|
||||
targets {
|
||||
register("jvm")
|
||||
}
|
||||
targets { register("jvm") }
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvm {
|
||||
compilations {
|
||||
val main by getting { }
|
||||
val main by getting {}
|
||||
// custom benchmark compilation
|
||||
val benchmarks by compilations.creating {
|
||||
defaultSourceSet {
|
||||
dependencies {
|
||||
// Compile against the main compilation's compile classpath and outputs:
|
||||
implementation(main.compileDependencyFiles + main.output.classesDirs)
|
||||
val benchmarks by
|
||||
compilations.creating {
|
||||
defaultSourceSet {
|
||||
dependencies {
|
||||
// Compile against the main compilation's compile classpath and outputs:
|
||||
implementation(main.compileDependencyFiles + main.output.classesDirs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,17 +92,13 @@ tasks.register<de.undercouch.gradle.tasks.download.Download>("downloadMultipleFi
|
||||
}
|
||||
|
||||
abstract class GenerateFBTestClasses : DefaultTask() {
|
||||
@get:InputFiles
|
||||
abstract val inputFiles: ConfigurableFileCollection
|
||||
@get:InputFiles abstract val inputFiles: ConfigurableFileCollection
|
||||
|
||||
@get:Input
|
||||
abstract val includeFolder: Property<String>
|
||||
@get:Input abstract val includeFolder: Property<String>
|
||||
|
||||
@get:Input
|
||||
abstract val outputFolder: Property<String>
|
||||
@get:Input abstract val outputFolder: Property<String>
|
||||
|
||||
@get:Input
|
||||
abstract val variants: ListProperty<String>
|
||||
@get:Input abstract val variants: ListProperty<String>
|
||||
|
||||
@Inject
|
||||
protected open fun getExecActionFactory(): org.gradle.process.internal.ExecActionFactory? {
|
||||
@@ -117,7 +114,7 @@ abstract class GenerateFBTestClasses : DefaultTask() {
|
||||
val execAction = getExecActionFactory()!!.newExecAction()
|
||||
val sources = inputFiles.asPath.split(":")
|
||||
val langs = variants.get().map { "--$it" }
|
||||
val args = mutableListOf("flatc","-o", outputFolder.get(), *langs.toTypedArray())
|
||||
val args = mutableListOf("flatc", "-o", outputFolder.get(), *langs.toTypedArray())
|
||||
if (includeFolder.get().isNotEmpty()) {
|
||||
args.add("-I")
|
||||
args.add(includeFolder.get())
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
package com.google.flatbuffers.kotlin.benchmark
|
||||
|
||||
|
||||
import com.google.flatbuffers.kotlin.FlatBufferBuilder
|
||||
import java.util.concurrent.TimeUnit
|
||||
import jmonster.JAllMonsters
|
||||
import jmonster.JColor
|
||||
import jmonster.JMonster
|
||||
@@ -17,7 +17,6 @@ import monster.MonsterOffsetArray
|
||||
import monster.Vec3
|
||||
import org.openjdk.jmh.annotations.*
|
||||
import org.openjdk.jmh.infra.Blackhole
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@@ -32,48 +31,55 @@ open class FlatbufferBenchmark {
|
||||
val fbDeserializationJava = com.google.flatbuffers.FlatBufferBuilder(1024 * repetition)
|
||||
|
||||
init {
|
||||
populateMosterKotlin(fbDeserializationKotlin)
|
||||
populateMosterJava(fbDeserializationJava)
|
||||
populateMosterKotlin(fbDeserializationKotlin)
|
||||
populateMosterJava(fbDeserializationJava)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
private fun populateMosterKotlin(fb: FlatBufferBuilder) {
|
||||
fb.clear()
|
||||
val monsterName = fb.createString("MonsterName");
|
||||
val monsterName = fb.createString("MonsterName")
|
||||
val items = ubyteArrayOf(0u, 1u, 2u, 3u, 4u)
|
||||
val inv = createInventoryVector(fb, items)
|
||||
val monsterOffsets: MonsterOffsetArray = MonsterOffsetArray(repetition) {
|
||||
Monster.startMonster(fb)
|
||||
Monster.addName(fb, monsterName)
|
||||
Monster.addPos(fb, Vec3.createVec3(fb, 1.0f, 2.0f, 3.0f))
|
||||
Monster.addHp(fb, 80)
|
||||
Monster.addMana(fb, 150)
|
||||
Monster.addInventory(fb, inv)
|
||||
Monster.addColor(fb, monster.Color.Red)
|
||||
Monster.endMonster(fb)
|
||||
}
|
||||
val monsterOffsets: MonsterOffsetArray =
|
||||
MonsterOffsetArray(repetition) {
|
||||
Monster.startMonster(fb)
|
||||
Monster.addName(fb, monsterName)
|
||||
Monster.addPos(fb, Vec3.createVec3(fb, 1.0f, 2.0f, 3.0f))
|
||||
Monster.addHp(fb, 80)
|
||||
Monster.addMana(fb, 150)
|
||||
Monster.addInventory(fb, inv)
|
||||
Monster.addColor(fb, monster.Color.Red)
|
||||
Monster.endMonster(fb)
|
||||
}
|
||||
val monsters = createMonstersVector(fb, monsterOffsets)
|
||||
val allMonsters = createAllMonsters(fb, monsters)
|
||||
fb.finish(allMonsters)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
private fun populateMosterJava(fb: com.google.flatbuffers.FlatBufferBuilder){
|
||||
private fun populateMosterJava(fb: com.google.flatbuffers.FlatBufferBuilder) {
|
||||
fb.clear()
|
||||
val monsterName = fb.createString("MonsterName");
|
||||
val monsterName = fb.createString("MonsterName")
|
||||
val inv = JMonster.createInventoryVector(fb, ubyteArrayOf(0u, 1u, 2u, 3u, 4u))
|
||||
val monsters = JAllMonsters.createMonstersVector(fb, IntArray(repetition) {
|
||||
JMonster.startJMonster(fb)
|
||||
JMonster.addName(fb, monsterName)
|
||||
JMonster.addPos(fb, JVec3.createJVec3(fb, 1.0f, 2.0f, 3.0f))
|
||||
JMonster.addHp(fb, 80)
|
||||
JMonster.addMana(fb, 150)
|
||||
JMonster.addInventory(fb, inv)
|
||||
JMonster.addColor(fb, JColor.Red)
|
||||
JMonster.endJMonster(fb)
|
||||
})
|
||||
val monsters =
|
||||
JAllMonsters.createMonstersVector(
|
||||
fb,
|
||||
IntArray(repetition) {
|
||||
JMonster.startJMonster(fb)
|
||||
JMonster.addName(fb, monsterName)
|
||||
JMonster.addPos(fb, JVec3.createJVec3(fb, 1.0f, 2.0f, 3.0f))
|
||||
JMonster.addHp(fb, 80)
|
||||
JMonster.addMana(fb, 150)
|
||||
JMonster.addInventory(fb, inv)
|
||||
JMonster.addColor(fb, JColor.Red)
|
||||
JMonster.endJMonster(fb)
|
||||
},
|
||||
)
|
||||
val allMonsters = JAllMonsters.createJAllMonsters(fb, monsters)
|
||||
fb.finish(allMonsters)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun monstersSerializationKotlin() {
|
||||
populateMosterKotlin(fbKotlin)
|
||||
@@ -100,6 +106,7 @@ open class FlatbufferBenchmark {
|
||||
hole.consume(monster.inventory(3))
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun monstersSerializationJava() {
|
||||
populateMosterJava(fbJava)
|
||||
@@ -125,5 +132,4 @@ open class FlatbufferBenchmark {
|
||||
hole.consume(monster.inventory(3))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
@file:OptIn(ExperimentalUnsignedTypes::class)
|
||||
|
||||
package com.google.flatbuffers.kotlin.benchmark
|
||||
|
||||
import com.google.flatbuffers.ArrayReadWriteBuf
|
||||
import com.google.flatbuffers.FlexBuffers
|
||||
import com.google.flatbuffers.FlexBuffersBuilder.BUILDER_FLAG_SHARE_ALL
|
||||
import com.google.flatbuffers.kotlin.FlexBuffersBuilder
|
||||
import com.google.flatbuffers.kotlin.getRoot
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode
|
||||
@@ -30,7 +32,6 @@ import org.openjdk.jmh.annotations.OutputTimeUnit
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.Setup
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@@ -57,9 +58,7 @@ open class FlexBuffersBenchmark {
|
||||
this["int"] = 10
|
||||
this["float"] = 12.3
|
||||
this["intarray"] = bigIntArray
|
||||
this.putMap("myMap") {
|
||||
this["cool"] = "beans"
|
||||
}
|
||||
this.putMap("myMap") { this["cool"] = "beans" }
|
||||
}
|
||||
val ref = getRoot(kBuilder.finish())
|
||||
val map = ref.toMap()
|
||||
@@ -74,7 +73,11 @@ open class FlexBuffersBenchmark {
|
||||
|
||||
@Benchmark
|
||||
open fun mapJava(blackhole: Blackhole) {
|
||||
val jBuilder = com.google.flatbuffers.FlexBuffersBuilder(ArrayReadWriteBuf(initialCapacity), BUILDER_FLAG_SHARE_ALL)
|
||||
val jBuilder =
|
||||
com.google.flatbuffers.FlexBuffersBuilder(
|
||||
ArrayReadWriteBuf(initialCapacity),
|
||||
BUILDER_FLAG_SHARE_ALL,
|
||||
)
|
||||
val startMap = jBuilder.startMap()
|
||||
jBuilder.putString("hello", "world")
|
||||
jBuilder.putInt("int", 10)
|
||||
@@ -112,18 +115,18 @@ open class FlexBuffersBenchmark {
|
||||
|
||||
@Benchmark
|
||||
open fun intArrayJava(blackhole: Blackhole) {
|
||||
val jBuilder = com.google.flatbuffers.FlexBuffersBuilder(ArrayReadWriteBuf(initialCapacity), BUILDER_FLAG_SHARE_ALL)
|
||||
val jBuilder =
|
||||
com.google.flatbuffers.FlexBuffersBuilder(
|
||||
ArrayReadWriteBuf(initialCapacity),
|
||||
BUILDER_FLAG_SHARE_ALL,
|
||||
)
|
||||
val v = jBuilder.startVector()
|
||||
bigIntArray.forEach { jBuilder.putInt(it) }
|
||||
jBuilder.endVector(null, v, true, false)
|
||||
jBuilder.finish()
|
||||
val root = FlexBuffers.getRoot(jBuilder.buffer)
|
||||
val vec = root.asVector()
|
||||
blackhole.consume(
|
||||
IntArray(vec.size()) {
|
||||
vec[it].asInt()
|
||||
}
|
||||
)
|
||||
blackhole.consume(IntArray(vec.size()) { vec[it].asInt() })
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@@ -138,7 +141,11 @@ open class FlexBuffersBenchmark {
|
||||
|
||||
@Benchmark
|
||||
open fun stringArrayJava(blackhole: Blackhole) {
|
||||
val jBuilder = com.google.flatbuffers.FlexBuffersBuilder(ArrayReadWriteBuf(initialCapacity), BUILDER_FLAG_SHARE_ALL)
|
||||
val jBuilder =
|
||||
com.google.flatbuffers.FlexBuffersBuilder(
|
||||
ArrayReadWriteBuf(initialCapacity),
|
||||
BUILDER_FLAG_SHARE_ALL,
|
||||
)
|
||||
val v = jBuilder.startVector()
|
||||
stringValue.forEach { jBuilder.putString(it) }
|
||||
jBuilder.endVector(null, v, false, false)
|
||||
@@ -182,7 +189,11 @@ open class FlexBuffersBenchmark {
|
||||
|
||||
@Benchmark
|
||||
open fun stringMapJava(blackhole: Blackhole) {
|
||||
val jBuilder = com.google.flatbuffers.FlexBuffersBuilder(ArrayReadWriteBuf(initialCapacity), BUILDER_FLAG_SHARE_ALL)
|
||||
val jBuilder =
|
||||
com.google.flatbuffers.FlexBuffersBuilder(
|
||||
ArrayReadWriteBuf(initialCapacity),
|
||||
BUILDER_FLAG_SHARE_ALL,
|
||||
)
|
||||
val v = jBuilder.startMap()
|
||||
for (i in stringKey.indices) {
|
||||
jBuilder.putString(stringKey[i], stringValue[i])
|
||||
|
||||
@@ -24,6 +24,9 @@ import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import okio.Buffer
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
@@ -33,9 +36,6 @@ import org.openjdk.jmh.annotations.Mode
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@@ -43,9 +43,7 @@ import java.util.concurrent.TimeUnit
|
||||
@Measurement(iterations = 100, time = 1, timeUnit = TimeUnit.MICROSECONDS)
|
||||
open class JsonBenchmark {
|
||||
|
||||
final val moshi = Moshi.Builder()
|
||||
.addLast(KotlinJsonAdapterFactory())
|
||||
.build()
|
||||
final val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
|
||||
final val moshiAdapter = moshi.adapter(Map::class.java)
|
||||
|
||||
final val gson = Gson()
|
||||
@@ -77,46 +75,60 @@ open class JsonBenchmark {
|
||||
|
||||
// TWITTER
|
||||
@Benchmark
|
||||
open fun readTwitterFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(twitterData))
|
||||
@Benchmark
|
||||
open fun readTwitterMoshi(hole: Blackhole?) = hole?.consume(readMoshi(twitterData))
|
||||
@Benchmark
|
||||
open fun readTwitterGson(hole: Blackhole?) = hole?.consume(readGson(twitterData))
|
||||
open fun readTwitterFlexBuffers(hole: Blackhole? = null) =
|
||||
hole?.consume(readFlexBuffers(twitterData))
|
||||
|
||||
@Benchmark open fun readTwitterMoshi(hole: Blackhole?) = hole?.consume(readMoshi(twitterData))
|
||||
|
||||
@Benchmark open fun readTwitterGson(hole: Blackhole?) = hole?.consume(readGson(twitterData))
|
||||
|
||||
@Benchmark
|
||||
open fun roundTripTwitterFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(twitterData).toJson())
|
||||
open fun roundTripTwitterFlexBuffers(hole: Blackhole? = null) =
|
||||
hole?.consume(readFlexBuffers(twitterData).toJson())
|
||||
|
||||
@Benchmark
|
||||
open fun roundTripTwitterMoshi(hole: Blackhole?) = hole?.consume(moshiAdapter.toJson(readMoshi(twitterData)))
|
||||
open fun roundTripTwitterMoshi(hole: Blackhole?) =
|
||||
hole?.consume(moshiAdapter.toJson(readMoshi(twitterData)))
|
||||
|
||||
@Benchmark
|
||||
open fun roundTripTwitterGson(hole: Blackhole?) = hole?.consume(gson.toJson(readGson(twitterData)))
|
||||
open fun roundTripTwitterGson(hole: Blackhole?) =
|
||||
hole?.consume(gson.toJson(readGson(twitterData)))
|
||||
|
||||
// CITM
|
||||
@Benchmark
|
||||
open fun readCITMFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(citmData))
|
||||
|
||||
@Benchmark
|
||||
open fun readCITMMoshi(hole: Blackhole?) = hole?.consume(moshiAdapter.toJson(readMoshi(citmData)))
|
||||
|
||||
@Benchmark
|
||||
open fun readCITMGson(hole: Blackhole?) = hole?.consume(gson.toJson(readGson(citmData)))
|
||||
|
||||
@Benchmark
|
||||
open fun roundTripCITMFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(citmData).toJson())
|
||||
open fun roundTripCITMFlexBuffers(hole: Blackhole? = null) =
|
||||
hole?.consume(readFlexBuffers(citmData).toJson())
|
||||
|
||||
@Benchmark
|
||||
open fun roundTripCITMMoshi(hole: Blackhole?) = hole?.consume(moshiAdapter.toJson(readMoshi(citmData)))
|
||||
open fun roundTripCITMMoshi(hole: Blackhole?) =
|
||||
hole?.consume(moshiAdapter.toJson(readMoshi(citmData)))
|
||||
|
||||
@Benchmark
|
||||
open fun roundTripCITMGson(hole: Blackhole?) = hole?.consume(gson.toJson(readGson(citmData)))
|
||||
|
||||
@Benchmark
|
||||
open fun writeCITMFlexBuffers(hole: Blackhole? = null) = hole?.consume(fbCitmRef.toJson())
|
||||
|
||||
@Benchmark
|
||||
open fun writeCITMMoshi(hole: Blackhole?) = hole?.consume(moshiAdapter.toJson(moshiCitmRef))
|
||||
@Benchmark
|
||||
open fun writeCITMGson(hole: Blackhole?) = hole?.consume(gson.toJson(gsonCitmRef))
|
||||
|
||||
@Benchmark open fun writeCITMGson(hole: Blackhole?) = hole?.consume(gson.toJson(gsonCitmRef))
|
||||
|
||||
// CANADA
|
||||
@Benchmark
|
||||
open fun readCanadaFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(canadaData))
|
||||
@Benchmark
|
||||
open fun readCanadaMoshi(hole: Blackhole?) = hole?.consume(readMoshi(canadaData))
|
||||
@Benchmark
|
||||
open fun readCanadaGson(hole: Blackhole?) = hole?.consume(readGson(canadaData))
|
||||
open fun readCanadaFlexBuffers(hole: Blackhole? = null) =
|
||||
hole?.consume(readFlexBuffers(canadaData))
|
||||
|
||||
@Benchmark open fun readCanadaMoshi(hole: Blackhole?) = hole?.consume(readMoshi(canadaData))
|
||||
|
||||
@Benchmark open fun readCanadaGson(hole: Blackhole?) = hole?.consume(readGson(canadaData))
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ package com.google.flatbuffers.kotlin.benchmark
|
||||
import com.google.flatbuffers.kotlin.ArrayReadWriteBuffer
|
||||
import com.google.flatbuffers.kotlin.Key
|
||||
import com.google.flatbuffers.kotlin.Utf8
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.random.Random
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode
|
||||
@@ -27,9 +30,6 @@ import org.openjdk.jmh.annotations.OutputTimeUnit
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.Setup
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@@ -44,9 +44,7 @@ open class UTF8Benchmark {
|
||||
private var sampleSmallAscii = (0..sampleSize).map { populateAscii(stringSize) }.toList()
|
||||
private var sampleSmallAsciiDecoded = sampleSmallAscii.map { it.encodeToByteArray() }.toList()
|
||||
|
||||
@Setup
|
||||
fun setUp() {
|
||||
}
|
||||
@Setup fun setUp() {}
|
||||
|
||||
@Benchmark
|
||||
fun encodeUtf8KotlinStandard(blackhole: Blackhole) {
|
||||
@@ -54,6 +52,7 @@ open class UTF8Benchmark {
|
||||
blackhole.consume(i.encodeToByteArray())
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun encodeUtf8KotlinFlatbuffers(blackhole: Blackhole) {
|
||||
for (i in sampleSmallUtf8) {
|
||||
@@ -61,6 +60,7 @@ open class UTF8Benchmark {
|
||||
blackhole.consume(Utf8.encodeUtf8Array(i, byteArray, 0, byteArray.size))
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun encodeUtf8JavaFlatbuffers(blackhole: Blackhole) {
|
||||
val javaUtf8 = com.google.flatbuffers.Utf8.getDefault()
|
||||
@@ -101,6 +101,7 @@ open class UTF8Benchmark {
|
||||
blackhole.consume(i.encodeToByteArray())
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun encodeAsciiKotlinFlatbuffers(blackhole: Blackhole) {
|
||||
for (i in sampleSmallAscii) {
|
||||
@@ -108,6 +109,7 @@ open class UTF8Benchmark {
|
||||
blackhole.consume(Utf8.encodeUtf8Array(i, byteArray, 0, byteArray.size))
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun encodeAsciiJavaFlatbuffers(blackhole: Blackhole) {
|
||||
val javaUtf8 = com.google.flatbuffers.Utf8.getDefault()
|
||||
@@ -179,7 +181,8 @@ open class UTF8Benchmark {
|
||||
while (i < size) {
|
||||
val w = Random.nextInt() and 0xFF
|
||||
when {
|
||||
w < 0x80 -> data[i++] = 0x20; // w;
|
||||
w < 0x80 -> data[i++] = 0x20
|
||||
// w;
|
||||
w < 0xE0 -> {
|
||||
data[i++] = (0xC2 + Random.nextInt() % (0xDF - 0xC2 + 1)).toByte()
|
||||
data[i++] = (0x80 + Random.nextInt() % (0xBF - 0x80 + 1)).toByte()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import org.gradle.internal.impldep.org.testng.ITestResult.STARTED
|
||||
import java.nio.charset.StandardCharsets
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
@@ -26,7 +25,8 @@ allprojects {
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<KotlinCommonOptions>>().configureEach {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs += "-progressive" // https://kotlinlang.org/docs/whatsnew13.html#progressive-mode
|
||||
freeCompilerArgs +=
|
||||
"-progressive" // https://kotlinlang.org/docs/whatsnew13.html#progressive-mode
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
}
|
||||
plugins { `kotlin-dsl` }
|
||||
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
}
|
||||
repositories { gradlePluginPortal() }
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import java.util.*
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.kotlin.dsl.`maven-publish`
|
||||
import org.gradle.kotlin.dsl.signing
|
||||
import java.util.*
|
||||
|
||||
plugins {
|
||||
`maven-publish`
|
||||
@@ -11,21 +11,24 @@ plugins {
|
||||
|
||||
// Stub secrets to let the project sync and build without the publication values set up
|
||||
ext["signing.keyId"] = null
|
||||
|
||||
ext["signing.password"] = null
|
||||
|
||||
ext["signing.secretKeyRingFile"] = null
|
||||
|
||||
ext["ossrhUsername"] = null
|
||||
|
||||
ext["ossrhPassword"] = null
|
||||
|
||||
// Grabbing secrets from local.properties file or from environment variables, which could be used on CI
|
||||
// Grabbing secrets from local.properties file or from environment variables, which could be used on
|
||||
// CI
|
||||
val secretPropsFile = project.rootProject.file("local.properties")
|
||||
|
||||
if (secretPropsFile.exists()) {
|
||||
secretPropsFile.reader().use {
|
||||
Properties().apply {
|
||||
load(it)
|
||||
}
|
||||
}.onEach { (name, value) ->
|
||||
ext[name.toString()] = value
|
||||
}
|
||||
secretPropsFile
|
||||
.reader()
|
||||
.use { Properties().apply { load(it) } }
|
||||
.onEach { (name, value) -> ext[name.toString()] = value }
|
||||
} else {
|
||||
ext["signing.keyId"] = System.getenv("OSSRH_USERNAME")
|
||||
ext["signing.password"] = System.getenv("OSSRH_PASSWORD")
|
||||
@@ -34,9 +37,7 @@ if (secretPropsFile.exists()) {
|
||||
ext["ossrhPassword"] = System.getenv("OSSRH_PASSWORD")
|
||||
}
|
||||
|
||||
val javadocJar by tasks.registering(Jar::class) {
|
||||
archiveClassifier.set("javadoc")
|
||||
}
|
||||
val javadocJar by tasks.registering(Jar::class) { archiveClassifier.set("javadoc") }
|
||||
|
||||
fun getExtraString(name: String) = ext[name]?.toString()
|
||||
|
||||
@@ -82,14 +83,10 @@ publishing {
|
||||
email.set("dbaileychess@gmail.com")
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url.set("https://github.com/google/flatbuffers")
|
||||
}
|
||||
scm { url.set("https://github.com/google/flatbuffers") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Signing artifacts. Signing.* extra properties values will be used
|
||||
signing {
|
||||
sign(publishing.publications)
|
||||
}
|
||||
signing { sign(publishing.publications) }
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
import org.gradle.internal.impldep.org.fusesource.jansi.AnsiRenderer.test
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework
|
||||
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFrameworkConfig
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("convention.publication")
|
||||
}
|
||||
|
||||
|
||||
val libName = "Flatbuffers"
|
||||
|
||||
group = "com.google.flatbuffers.kotlin"
|
||||
|
||||
version = "2.0.0-SNAPSHOT"
|
||||
|
||||
kotlin {
|
||||
explicitApi()
|
||||
jvm()
|
||||
js(IR) {
|
||||
browser {
|
||||
testTask {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
browser { testTask { enabled = false } }
|
||||
binaries.executable()
|
||||
}
|
||||
macosX64()
|
||||
@@ -32,17 +22,10 @@ kotlin {
|
||||
iosSimulatorArm64()
|
||||
|
||||
sourceSets {
|
||||
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib-common"))
|
||||
}
|
||||
}
|
||||
val commonMain by getting { dependencies { implementation(kotlin("stdlib-common")) } }
|
||||
|
||||
val commonTest by getting {
|
||||
dependencies {
|
||||
implementation(kotlin("test"))
|
||||
}
|
||||
dependencies { implementation(kotlin("test")) }
|
||||
|
||||
kotlin.srcDir("src/commonTest/generated/kotlin/")
|
||||
}
|
||||
@@ -52,8 +35,7 @@ kotlin {
|
||||
implementation("com.google.flatbuffers:flatbuffers-java:2.0.3")
|
||||
}
|
||||
}
|
||||
val jvmMain by getting {
|
||||
}
|
||||
val jvmMain by getting {}
|
||||
|
||||
val macosX64Main by getting
|
||||
val macosArm64Main by getting
|
||||
@@ -69,53 +51,47 @@ kotlin {
|
||||
iosSimulatorArm64Main.dependsOn(this)
|
||||
}
|
||||
|
||||
all {
|
||||
languageSettings.optIn("kotlin.ExperimentalUnsignedTypes")
|
||||
}
|
||||
all { languageSettings.optIn("kotlin.ExperimentalUnsignedTypes") }
|
||||
}
|
||||
}
|
||||
|
||||
// Fixes JS issue: https://youtrack.jetbrains.com/issue/KT-49109
|
||||
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
|
||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().nodeVersion = "16.0.0"
|
||||
|
||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().nodeVersion =
|
||||
"16.0.0"
|
||||
}
|
||||
|
||||
// Use the default greeting
|
||||
tasks.register<GenerateFBTestClasses>("generateFBTestClassesKt") {
|
||||
inputFiles.setFrom("$rootDir/../tests/monster_test.fbs",
|
||||
inputFiles.setFrom(
|
||||
"$rootDir/../tests/monster_test.fbs",
|
||||
"$rootDir/../tests/dictionary_lookup.fbs",
|
||||
// @todo Seems like nesting code generation is broken for all generators.
|
||||
// disabling test for now.
|
||||
// "$rootDir/../tests/namespace_test/namespace_test1.fbs",
|
||||
// "$rootDir/../tests/namespace_test/namespace_test2.fbs",
|
||||
// @todo Seems like nesting code generation is broken for all generators.
|
||||
// disabling test for now.
|
||||
// "$rootDir/../tests/namespace_test/namespace_test1.fbs",
|
||||
// "$rootDir/../tests/namespace_test/namespace_test2.fbs",
|
||||
"$rootDir/../tests/union_vector/union_vector.fbs",
|
||||
"$rootDir/../tests/optional_scalars.fbs")
|
||||
"$rootDir/../tests/optional_scalars.fbs",
|
||||
)
|
||||
includeFolder.set("$rootDir/../tests/include_test")
|
||||
outputFolder.set("${projectDir}/src/commonTest/generated/kotlin/")
|
||||
variant.set("kotlin-kmp")
|
||||
}
|
||||
|
||||
|
||||
project.tasks.forEach {
|
||||
if (it.name.contains("compileKotlin"))
|
||||
it.dependsOn("generateFBTestClassesKt")
|
||||
if (it.name.contains("compileKotlin")) it.dependsOn("generateFBTestClassesKt")
|
||||
}
|
||||
|
||||
fun String.intProperty() = findProperty(this).toString().toInt()
|
||||
|
||||
abstract class GenerateFBTestClasses : DefaultTask() {
|
||||
@get:InputFiles
|
||||
abstract val inputFiles: ConfigurableFileCollection
|
||||
@get:InputFiles abstract val inputFiles: ConfigurableFileCollection
|
||||
|
||||
@get:Input
|
||||
abstract val includeFolder: Property<String>
|
||||
@get:Input abstract val includeFolder: Property<String>
|
||||
|
||||
@get:Input
|
||||
abstract val outputFolder: Property<String>
|
||||
@get:Input abstract val outputFolder: Property<String>
|
||||
|
||||
@get:Input
|
||||
abstract val variant: Property<String>
|
||||
@get:Input abstract val variant: Property<String>
|
||||
|
||||
@Inject
|
||||
protected open fun getExecActionFactory(): org.gradle.process.internal.ExecActionFactory? {
|
||||
@@ -130,7 +106,7 @@ abstract class GenerateFBTestClasses : DefaultTask() {
|
||||
fun compile() {
|
||||
val execAction = getExecActionFactory()!!.newExecAction()
|
||||
val sources = inputFiles.asPath.split(":")
|
||||
val args = mutableListOf("flatc","-o", outputFolder.get(), "--${variant.get()}")
|
||||
val args = mutableListOf("flatc", "-o", outputFolder.get(), "--${variant.get()}")
|
||||
if (includeFolder.get().isNotEmpty()) {
|
||||
args.add("-I")
|
||||
args.add(includeFolder.get())
|
||||
|
||||
@@ -18,13 +18,12 @@ package com.google.flatbuffers.kotlin
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Represent a chunk of data, where FlexBuffers will be read from.
|
||||
*/
|
||||
/** Represent a chunk of data, where FlexBuffers will be read from. */
|
||||
public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Scan through the buffer for first byte matching value.
|
||||
*
|
||||
* @param value to be match
|
||||
* @param start inclusive initial position to start searching
|
||||
* @param end exclusive final position of the search
|
||||
@@ -34,6 +33,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read boolean from the buffer. Booleans as stored as a single byte
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return [Boolean] element
|
||||
*/
|
||||
@@ -41,6 +41,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a [Byte] from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return a byte
|
||||
*/
|
||||
@@ -48,6 +49,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a [UByte] from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return a [UByte]
|
||||
*/
|
||||
@@ -55,6 +57,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a [Short] from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return a [Short]
|
||||
*/
|
||||
@@ -62,6 +65,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a [UShort] from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return a [UShort]
|
||||
*/
|
||||
@@ -69,6 +73,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a [Int] from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return an [Int]
|
||||
*/
|
||||
@@ -76,6 +81,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a [UInt] from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return an [UInt]
|
||||
*/
|
||||
@@ -83,6 +89,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a [Long] from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return a [Long]
|
||||
*/
|
||||
@@ -90,6 +97,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a [ULong] from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return a [ULong]
|
||||
*/
|
||||
@@ -97,6 +105,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a 32-bit float from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return a float
|
||||
*/
|
||||
@@ -104,6 +113,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a 64-bit float from the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
* @return a double
|
||||
*/
|
||||
@@ -111,6 +121,7 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a UTF-8 string from the buffer.
|
||||
*
|
||||
* @param start initial element of the string
|
||||
* @param size size of the string in bytes.
|
||||
* @return a `String`
|
||||
@@ -119,22 +130,25 @@ public interface ReadBuffer {
|
||||
|
||||
/**
|
||||
* Read a ByteArray from the buffer.
|
||||
*
|
||||
* @param start position from the [ReadBuffer] to be read
|
||||
* @param length maximum number of bytes to be written in the buffer
|
||||
*/
|
||||
public fun getBytes(array: ByteArray, start: Int, length: Int = array.size)
|
||||
|
||||
/**
|
||||
* Expose [ReadBuffer] as an array of bytes.
|
||||
* This method is meant to be as efficient as possible, so for an array-backed [ReadBuffer], it should
|
||||
* return its own internal data. In case access to internal data is not possible,
|
||||
* a copy of the data into an array of bytes might occur.
|
||||
* Expose [ReadBuffer] as an array of bytes. This method is meant to be as efficient as possible,
|
||||
* so for an array-backed [ReadBuffer], it should return its own internal data. In case access to
|
||||
* internal data is not possible, a copy of the data into an array of bytes might occur.
|
||||
*
|
||||
* @return [ReadBuffer] as an array of bytes
|
||||
*/
|
||||
public fun data(): ByteArray
|
||||
|
||||
/**
|
||||
* Creates a new [ReadBuffer] point to a region of the current buffer, starting at [start] with size [size].
|
||||
* Creates a new [ReadBuffer] point to a region of the current buffer, starting at [start] with
|
||||
* size [size].
|
||||
*
|
||||
* @param start starting position of the [ReadBuffer]
|
||||
* @param size in bytes of the [ReadBuffer]
|
||||
* @return [ReadBuffer] slice.
|
||||
@@ -142,15 +156,17 @@ public interface ReadBuffer {
|
||||
public fun slice(start: Int, size: Int): ReadBuffer
|
||||
|
||||
/**
|
||||
* Defines the size of the message in the buffer. It also determines last position that buffer
|
||||
* can be read. Last byte to be accessed is in position `limit() -1`.
|
||||
* Defines the size of the message in the buffer. It also determines last position that buffer can
|
||||
* be read. Last byte to be accessed is in position `limit() -1`.
|
||||
*
|
||||
* @return indicate last position
|
||||
*/
|
||||
public val limit: Int
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to represent a read-write buffers. This interface will be used to access and write FlexBuffer messages.
|
||||
* Interface to represent a read-write buffers. This interface will be used to access and write
|
||||
* FlexBuffer messages.
|
||||
*/
|
||||
public interface ReadWriteBuffer : ReadBuffer {
|
||||
/**
|
||||
@@ -160,9 +176,9 @@ public interface ReadWriteBuffer : ReadBuffer {
|
||||
|
||||
/**
|
||||
* Request capacity of the buffer relative to [writePosition]. In case buffer is already larger
|
||||
* than the requested, this method will just return true. Otherwise,
|
||||
* It might try to resize the buffer. In case of being unable to allocate
|
||||
* enough memory, an exception will be thrown.
|
||||
* than the requested, this method will just return true. Otherwise, It might try to resize the
|
||||
* buffer. In case of being unable to allocate enough memory, an exception will be thrown.
|
||||
*
|
||||
* @param additional capacity in bytes to be added on top of [writePosition]
|
||||
* @param copyAtEnd copy current data at the end of new underlying buffer
|
||||
* @return new capacity in bytes
|
||||
@@ -171,10 +187,10 @@ public interface ReadWriteBuffer : ReadBuffer {
|
||||
requestCapacity(writePosition + additional, copyAtEnd)
|
||||
|
||||
/**
|
||||
* Request capacity of the buffer in absolute values. In case buffer is already larger
|
||||
* than the requested the method is a no-op. Otherwise,
|
||||
* It might try to resize the buffer. In case of being unable to allocate
|
||||
* enough memory, an exception will be thrown.
|
||||
* Request capacity of the buffer in absolute values. In case buffer is already larger than the
|
||||
* requested the method is a no-op. Otherwise, It might try to resize the buffer. In case of being
|
||||
* unable to allocate enough memory, an exception will be thrown.
|
||||
*
|
||||
* @param capacity new capacity
|
||||
* @param copyAtEnd copy current data at the end of new underlying buffer
|
||||
* @return new capacity in bytes
|
||||
@@ -182,14 +198,16 @@ public interface ReadWriteBuffer : ReadBuffer {
|
||||
public fun requestCapacity(capacity: Int, copyAtEnd: Boolean = false): Int
|
||||
|
||||
/**
|
||||
* Put a [Boolean] into the buffer at [writePosition] . Booleans as stored as single byte.
|
||||
* Write position will be incremented.
|
||||
* Put a [Boolean] into the buffer at [writePosition] . Booleans as stored as single byte. Write
|
||||
* position will be incremented.
|
||||
*
|
||||
* @return [Boolean] element
|
||||
*/
|
||||
public fun put(value: Boolean)
|
||||
|
||||
/**
|
||||
* Put an array of bytes into the buffer at [writePosition]. Write position will be incremented.
|
||||
*
|
||||
* @param value the data to be copied
|
||||
* @param start initial position on value to be copied
|
||||
* @param length amount of bytes to be copied
|
||||
@@ -198,74 +216,58 @@ public interface ReadWriteBuffer : ReadBuffer {
|
||||
|
||||
/**
|
||||
* Put an array of bytes into the buffer at [writePosition]. Write position will be incremented.
|
||||
*
|
||||
* @param value [ReadBuffer] the data to be copied
|
||||
* @param start initial position on value to be copied
|
||||
* @param length amount of bytes to be copied
|
||||
*/
|
||||
public fun put(value: ReadBuffer, start: Int = 0, length: Int = value.limit - start)
|
||||
|
||||
/**
|
||||
* Write a [Byte] into the buffer at [writePosition]. Write position will be incremented.
|
||||
*/
|
||||
/** Write a [Byte] into the buffer at [writePosition]. Write position will be incremented. */
|
||||
public fun put(value: Byte)
|
||||
|
||||
/**
|
||||
* Write a [UByte] into the buffer at [writePosition]. Write position will be incremented.
|
||||
*/
|
||||
/** Write a [UByte] into the buffer at [writePosition]. Write position will be incremented. */
|
||||
public fun put(value: UByte)
|
||||
|
||||
/**
|
||||
* Write a [Short] into in the buffer at [writePosition]. Write position will be incremented.
|
||||
*/
|
||||
/** Write a [Short] into in the buffer at [writePosition]. Write position will be incremented. */
|
||||
public fun put(value: Short)
|
||||
|
||||
/**
|
||||
* Write a [UShort] into in the buffer at [writePosition]. Write position will be incremented.
|
||||
*/
|
||||
/** Write a [UShort] into in the buffer at [writePosition]. Write position will be incremented. */
|
||||
public fun put(value: UShort)
|
||||
|
||||
/**
|
||||
* Write a [Int] in the buffer at [writePosition]. Write position will be incremented.
|
||||
*/
|
||||
/** Write a [Int] in the buffer at [writePosition]. Write position will be incremented. */
|
||||
public fun put(value: Int)
|
||||
|
||||
/**
|
||||
* Write a [UInt] into in the buffer at [writePosition]. Write position will be incremented.
|
||||
*/
|
||||
/** Write a [UInt] into in the buffer at [writePosition]. Write position will be incremented. */
|
||||
public fun put(value: UInt)
|
||||
|
||||
/**
|
||||
* Write a [Long] into in the buffer at [writePosition]. Write position will be
|
||||
* incremented.
|
||||
*/
|
||||
/** Write a [Long] into in the buffer at [writePosition]. Write position will be incremented. */
|
||||
public fun put(value: Long)
|
||||
|
||||
/**
|
||||
* Write a [ULong] into in the buffer at [writePosition]. Write position will be
|
||||
* incremented.
|
||||
*/
|
||||
/** Write a [ULong] into in the buffer at [writePosition]. Write position will be incremented. */
|
||||
public fun put(value: ULong)
|
||||
|
||||
/**
|
||||
* Write a 32-bit [Float] into the buffer at [writePosition]. Write position will be
|
||||
* incremented.
|
||||
* Write a 32-bit [Float] into the buffer at [writePosition]. Write position will be incremented.
|
||||
*/
|
||||
public fun put(value: Float)
|
||||
|
||||
/**
|
||||
* Write a 64-bit [Double] into the buffer at [writePosition]. Write position will be
|
||||
* incremented.
|
||||
* Write a 64-bit [Double] into the buffer at [writePosition]. Write position will be incremented.
|
||||
*/
|
||||
public fun put(value: Double)
|
||||
|
||||
/**
|
||||
* Write a [String] encoded as UTF-8 into the buffer at [writePosition]. Write position will be incremented.
|
||||
* Write a [String] encoded as UTF-8 into the buffer at [writePosition]. Write position will be
|
||||
* incremented.
|
||||
*
|
||||
* @return size in bytes of the encoded string
|
||||
*/
|
||||
public fun put(value: CharSequence, encodedLength: Int = -1): Int
|
||||
|
||||
/**
|
||||
* Write an array of bytes into the buffer.
|
||||
*
|
||||
* @param dstIndex initial position where [src] will be copied into.
|
||||
* @param src the data to be copied.
|
||||
* @param srcStart initial position on [src] that will be copied.
|
||||
@@ -275,6 +277,7 @@ public interface ReadWriteBuffer : ReadBuffer {
|
||||
|
||||
/**
|
||||
* Write an array of bytes into the buffer.
|
||||
*
|
||||
* @param dstIndex initial position where [src] will be copied into.
|
||||
* @param src the data to be copied.
|
||||
* @param srcStart initial position on [src] that will be copied.
|
||||
@@ -284,66 +287,77 @@ public interface ReadWriteBuffer : ReadBuffer {
|
||||
|
||||
/**
|
||||
* Write [Boolean] into a given position [index] on the buffer. Booleans as stored as single byte.
|
||||
*
|
||||
* @param index position of the element in buffer
|
||||
*/
|
||||
public operator fun set(index: Int, value: Boolean)
|
||||
|
||||
/**
|
||||
* Write [Byte] into a given position [index] on the buffer.
|
||||
*
|
||||
* @param index position of the element in the buffer
|
||||
*/
|
||||
public operator fun set(index: Int, value: Byte)
|
||||
|
||||
/**
|
||||
* Write [UByte] into a given position [index] on the buffer.
|
||||
*
|
||||
* @param index position of the element in the buffer
|
||||
*/
|
||||
public operator fun set(index: Int, value: UByte)
|
||||
|
||||
/**
|
||||
Short
|
||||
* Short
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
*/
|
||||
public fun set(index: Int, value: Short)
|
||||
|
||||
/**
|
||||
* Write [UShort] into a given position [index] on the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
*/
|
||||
public fun set(index: Int, value: UShort)
|
||||
|
||||
/**
|
||||
* Write [Int] into a given position [index] on the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
*/
|
||||
public fun set(index: Int, value: Int)
|
||||
|
||||
/**
|
||||
* Write [UInt] into a given position [index] on the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
*/
|
||||
public fun set(index: Int, value: UInt)
|
||||
|
||||
/**
|
||||
* Write [Long] into a given position [index] on the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
*/
|
||||
public fun set(index: Int, value: Long)
|
||||
|
||||
/**
|
||||
* Write [ULong] into a given position [index] on the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
*/
|
||||
public fun set(index: Int, value: ULong)
|
||||
|
||||
/**
|
||||
* Write [Float] into a given position [index] on the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
*/
|
||||
public fun set(index: Int, value: Float)
|
||||
|
||||
/**
|
||||
* Write [Double] into a given position [index] on the buffer.
|
||||
*
|
||||
* @param index position of the element in [ReadBuffer]
|
||||
*/
|
||||
public fun set(index: Int, value: Double)
|
||||
@@ -351,12 +365,15 @@ public interface ReadWriteBuffer : ReadBuffer {
|
||||
public fun fill(value: Byte, start: Int, end: Int)
|
||||
|
||||
/**
|
||||
* Current position of the buffer to be written. It will be automatically updated on [put] operations.
|
||||
* Current position of the buffer to be written. It will be automatically updated on [put]
|
||||
* operations.
|
||||
*/
|
||||
public var writePosition: Int
|
||||
|
||||
/**
|
||||
* Creates a new [ReadWriteBuffer] point to a region of the current buffer, starting at [offset] with size [size].
|
||||
* Creates a new [ReadWriteBuffer] point to a region of the current buffer, starting at [offset]
|
||||
* with size [size].
|
||||
*
|
||||
* @param offset starting position of the [ReadWriteBuffer]
|
||||
* @param size in bytes of the [ReadWriteBuffer]
|
||||
* @return [ReadWriteBuffer] slice.
|
||||
@@ -364,35 +381,35 @@ public interface ReadWriteBuffer : ReadBuffer {
|
||||
public fun writeSlice(offset: Int, size: Int): ReadWriteBuffer
|
||||
|
||||
/**
|
||||
* Special operation where we increase the backed buffer size to [capacity]
|
||||
* and shift all already written data to the end of the buffer.
|
||||
* Special operation where we increase the backed buffer size to [capacity] and shift all already
|
||||
* written data to the end of the buffer.
|
||||
*
|
||||
* This function is mostly used when creating a Flatbuffer message, as data is written from the
|
||||
* end of the buffer towards index 0.
|
||||
*
|
||||
* This function is mostly used when creating a Flatbuffer message, as
|
||||
* data is written from the end of the buffer towards index 0.
|
||||
* @param capacity required in bytes
|
||||
* @return new capacity in bytes
|
||||
*/
|
||||
public fun moveWrittenDataToEnd(capacity: Int): Int
|
||||
|
||||
/**
|
||||
* Maximum size in bytes that the backed buffer supports.
|
||||
*/
|
||||
/** Maximum size in bytes that the backed buffer supports. */
|
||||
public val capacity: Int
|
||||
|
||||
/**
|
||||
* Defines last relative position of the backed buffer that can be written.
|
||||
* Any addition to the buffer that goes beyond will throw an exception
|
||||
* instead of regrow the buffer (default behavior).
|
||||
* Defines last relative position of the backed buffer that can be written. Any addition to the
|
||||
* buffer that goes beyond will throw an exception instead of regrow the buffer (default
|
||||
* behavior).
|
||||
*/
|
||||
public val writeLimit: Int
|
||||
}
|
||||
|
||||
public open class ArrayReadBuffer(protected var buffer: ByteArray,
|
||||
// offsets writePosition against backed buffer e.g. offset = 1, writePosition = 1
|
||||
// will write first byte at position 2 of the backed buffer
|
||||
internal val offset: Int = 0,
|
||||
override val limit: Int = buffer.size - offset) : ReadBuffer {
|
||||
|
||||
public open class ArrayReadBuffer(
|
||||
protected var buffer: ByteArray,
|
||||
// offsets writePosition against backed buffer e.g. offset = 1, writePosition = 1
|
||||
// will write first byte at position 2 of the backed buffer
|
||||
internal val offset: Int = 0,
|
||||
override val limit: Int = buffer.size - offset,
|
||||
) : ReadBuffer {
|
||||
|
||||
override fun findFirst(value: Byte, start: Int, end: Int): Int {
|
||||
val e = min(end, limit)
|
||||
@@ -423,8 +440,8 @@ public open class ArrayReadBuffer(protected var buffer: ByteArray,
|
||||
|
||||
override fun getDouble(index: Int): Double = buffer.getDouble(offset + index)
|
||||
|
||||
override fun getString(start: Int, size: Int): String = buffer.decodeToString(this.offset + start,
|
||||
this.offset + start + size)
|
||||
override fun getString(start: Int, size: Int): String =
|
||||
buffer.decodeToString(this.offset + start, this.offset + start + size)
|
||||
|
||||
override fun getBytes(array: ByteArray, start: Int, length: Int) {
|
||||
val end = min(this.offset + start + length, buffer.size)
|
||||
@@ -436,19 +453,19 @@ public open class ArrayReadBuffer(protected var buffer: ByteArray,
|
||||
|
||||
override fun data(): ByteArray = buffer
|
||||
|
||||
override fun slice(start: Int, size: Int): ReadBuffer = ArrayReadBuffer(buffer, this.offset + start, size)
|
||||
override fun slice(start: Int, size: Int): ReadBuffer =
|
||||
ArrayReadBuffer(buffer, this.offset + start, size)
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements `[ReadWriteBuffer]` using [ByteArray] as backing buffer. Using array of bytes are
|
||||
* usually faster than `ByteBuffer`.
|
||||
*
|
||||
* This class is not thread-safe, meaning that
|
||||
* it must operate on a single thread. Operating from
|
||||
* This class is not thread-safe, meaning that it must operate on a single thread. Operating from
|
||||
* multiple thread leads into an undefined behavior
|
||||
*
|
||||
* All operations assume Little Endian byte order.
|
||||
*/
|
||||
|
||||
public class ArrayReadWriteBuffer(
|
||||
buffer: ByteArray,
|
||||
offset: Int = 0,
|
||||
@@ -456,12 +473,13 @@ public class ArrayReadWriteBuffer(
|
||||
// Any addition to the buffer that goes beyond will throw an exception
|
||||
// instead of regrow the buffer (default behavior).
|
||||
public override val writeLimit: Int = -1,
|
||||
override var writePosition: Int = offset
|
||||
override var writePosition: Int = offset,
|
||||
) : ArrayReadBuffer(buffer, offset, writePosition), ReadWriteBuffer {
|
||||
|
||||
public constructor(initialCapacity: Int = 10) : this(ByteArray(initialCapacity))
|
||||
|
||||
override val limit: Int get() = writePosition
|
||||
override val limit: Int
|
||||
get() = writePosition
|
||||
|
||||
override fun clear(): Unit = run { writePosition = 0 }
|
||||
|
||||
@@ -545,35 +563,69 @@ public class ArrayReadWriteBuffer(
|
||||
}
|
||||
|
||||
override operator fun set(dstIndex: Int, src: ReadBuffer, srcStart: Int, srcLength: Int) {
|
||||
when(src) {
|
||||
is ArrayReadBuffer -> {
|
||||
src.data().copyInto(buffer, dstIndex, src.offset + srcStart, src.offset + srcStart + srcLength)
|
||||
}
|
||||
else -> {
|
||||
for (i in 0 until srcLength) {
|
||||
buffer[dstIndex + i] = src[srcStart + i]
|
||||
}
|
||||
when (src) {
|
||||
is ArrayReadBuffer -> {
|
||||
src
|
||||
.data()
|
||||
.copyInto(buffer, dstIndex, src.offset + srcStart, src.offset + srcStart + srcLength)
|
||||
}
|
||||
else -> {
|
||||
for (i in 0 until srcLength) {
|
||||
buffer[dstIndex + i] = src[srcStart + i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: Byte) { buffer[index] = value }
|
||||
override operator fun set(index: Int, value: UByte) { buffer.setUByte(index, value) }
|
||||
override operator fun set(index: Int, value: Short) { buffer.setShort(index, value) }
|
||||
override operator fun set(index: Int, value: UShort) { buffer.setUShort(index, value) }
|
||||
override operator fun set(index: Int, value: Int) { buffer.setInt(index, value) }
|
||||
override operator fun set(index: Int, value: UInt) { buffer.setUInt(index, value) }
|
||||
override operator fun set(index: Int, value: Long) { buffer.setLong(index, value) }
|
||||
override operator fun set(index: Int, value: ULong) { buffer.setULong(index, value) }
|
||||
override operator fun set(index: Int, value: Float) { buffer.setFloat(index, value) }
|
||||
override operator fun set(index: Int, value: Double) { buffer.setDouble(index, value) }
|
||||
override fun fill(value: Byte, start: Int, end: Int) { buffer.fill(value, start, end) }
|
||||
override operator fun set(index: Int, value: Byte) {
|
||||
buffer[index] = value
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: UByte) {
|
||||
buffer.setUByte(index, value)
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: Short) {
|
||||
buffer.setShort(index, value)
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: UShort) {
|
||||
buffer.setUShort(index, value)
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: Int) {
|
||||
buffer.setInt(index, value)
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: UInt) {
|
||||
buffer.setUInt(index, value)
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: Long) {
|
||||
buffer.setLong(index, value)
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: ULong) {
|
||||
buffer.setULong(index, value)
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: Float) {
|
||||
buffer.setFloat(index, value)
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, value: Double) {
|
||||
buffer.setDouble(index, value)
|
||||
}
|
||||
|
||||
override fun fill(value: Byte, start: Int, end: Int) {
|
||||
buffer.fill(value, start, end)
|
||||
}
|
||||
|
||||
/**
|
||||
* Request capacity of the buffer. In case buffer is already larger
|
||||
* than the requested, it is a no-op. Otherwise,
|
||||
* It might try to resize the buffer. In case of being unable to allocate
|
||||
* enough memory, an exception will be thrown.
|
||||
* Request capacity of the buffer. In case buffer is already larger than the requested, it is a
|
||||
* no-op. Otherwise, It might try to resize the buffer. In case of being unable to allocate enough
|
||||
* memory, an exception will be thrown.
|
||||
*
|
||||
* @param capacity new capacity
|
||||
* @param copyAtEnd copy current data at the end of new underlying buffer
|
||||
*/
|
||||
@@ -582,15 +634,18 @@ public class ArrayReadWriteBuffer(
|
||||
|
||||
if (buffer.size >= capacity) return buffer.size
|
||||
|
||||
if (writeLimit > 0 && writeLimit + offset >= buffer.size) error("Buffer in writeLimit mode. In writeLimit mode" +
|
||||
" the buffer does not grow automatically and any write beyond writeLimit will throw exception. " +
|
||||
"(writeLimit: $writeLimit, newCapacity: $capacity")
|
||||
if (writeLimit > 0 && writeLimit + offset >= buffer.size)
|
||||
error(
|
||||
"Buffer in writeLimit mode. In writeLimit mode" +
|
||||
" the buffer does not grow automatically and any write beyond writeLimit will throw exception. " +
|
||||
"(writeLimit: $writeLimit, newCapacity: $capacity"
|
||||
)
|
||||
// implemented in the same growing fashion as ArrayList
|
||||
val oldCapacity = buffer.size
|
||||
if (oldCapacity == Int.MAX_VALUE - 8) { // Ensure we don't grow beyond what fits in an int.
|
||||
error("FlatBuffers: cannot grow buffer beyond 2 gigabytes.")
|
||||
}
|
||||
//(old_buf_size & 0xC0000000) != 0 ? MAX_BUFFER_SIZE : old_buf_size << 1;
|
||||
// (old_buf_size & 0xC0000000) != 0 ? MAX_BUFFER_SIZE : old_buf_size << 1;
|
||||
var newCapacity = 8
|
||||
while (newCapacity < capacity) { // Note: this also catches newCapacity int overflow
|
||||
newCapacity = if (newCapacity and -0x40000000 != 0) Int.MAX_VALUE - 8 else newCapacity shl 1
|
||||
@@ -603,14 +658,13 @@ public class ArrayReadWriteBuffer(
|
||||
}
|
||||
|
||||
override fun writeSlice(offset: Int, size: Int): ReadWriteBuffer {
|
||||
return ArrayReadWriteBuffer(this.buffer, offset=offset, writeLimit=size)
|
||||
return ArrayReadWriteBuffer(this.buffer, offset = offset, writeLimit = size)
|
||||
}
|
||||
|
||||
override fun moveWrittenDataToEnd(capacity: Int): Int = requestCapacity(capacity, true)
|
||||
|
||||
override val capacity: Int
|
||||
get() = buffer.size
|
||||
|
||||
}
|
||||
|
||||
public val emptyBuffer: ReadWriteBuffer = ArrayReadWriteBuffer(ByteArray(1))
|
||||
|
||||
@@ -19,37 +19,53 @@ package com.google.flatbuffers.kotlin
|
||||
|
||||
import kotlin.experimental.and
|
||||
|
||||
internal fun ByteArray.getString(index: Int, size: Int): String = Utf8.decodeUtf8Array(this, index, size)
|
||||
internal fun ByteArray.getString(index: Int, size: Int): String =
|
||||
Utf8.decodeUtf8Array(this, index, size)
|
||||
|
||||
internal fun ByteArray.setCharSequence(index: Int, value: CharSequence): Int =
|
||||
Utf8.encodeUtf8Array(value, this, index, this.size - index)
|
||||
|
||||
// List of functions that needs to be implemented on all platforms.
|
||||
internal expect inline fun ByteArray.getUByte(index: Int): UByte
|
||||
|
||||
internal expect inline fun ByteArray.getShort(index: Int): Short
|
||||
|
||||
internal expect inline fun ByteArray.getUShort(index: Int): UShort
|
||||
|
||||
internal expect inline fun ByteArray.getInt(index: Int): Int
|
||||
|
||||
internal expect inline fun ByteArray.getUInt(index: Int): UInt
|
||||
|
||||
internal expect inline fun ByteArray.getLong(index: Int): Long
|
||||
|
||||
internal expect inline fun ByteArray.getULong(index: Int): ULong
|
||||
|
||||
internal expect inline fun ByteArray.getFloat(index: Int): Float
|
||||
|
||||
internal expect inline fun ByteArray.getDouble(index: Int): Double
|
||||
|
||||
internal expect inline fun ByteArray.setUByte(index: Int, value: UByte)
|
||||
|
||||
public expect inline fun ByteArray.setShort(index: Int, value: Short)
|
||||
|
||||
internal expect inline fun ByteArray.setUShort(index: Int, value: UShort)
|
||||
|
||||
internal expect inline fun ByteArray.setInt(index: Int, value: Int)
|
||||
|
||||
internal expect inline fun ByteArray.setUInt(index: Int, value: UInt)
|
||||
|
||||
internal expect inline fun ByteArray.setLong(index: Int, value: Long)
|
||||
|
||||
internal expect inline fun ByteArray.setULong(index: Int, value: ULong)
|
||||
|
||||
internal expect inline fun ByteArray.setFloat(index: Int, value: Float)
|
||||
|
||||
internal expect inline fun ByteArray.setDouble(index: Int, value: Double)
|
||||
|
||||
/**
|
||||
* This implementation uses Little Endian order.
|
||||
*/
|
||||
/** This implementation uses Little Endian order. */
|
||||
public object ByteArrayOps {
|
||||
public inline fun getUByte(ary: ByteArray, index: Int): UByte = ary[index].toUByte()
|
||||
|
||||
public inline fun getShort(ary: ByteArray, index: Int): Short {
|
||||
return (ary[index + 1].toInt() shl 8 or (ary[index].toInt() and 0xff)).toShort()
|
||||
}
|
||||
@@ -57,19 +73,18 @@ public object ByteArrayOps {
|
||||
public inline fun getUShort(ary: ByteArray, index: Int): UShort = getShort(ary, index).toUShort()
|
||||
|
||||
public inline fun getInt(ary: ByteArray, index: Int): Int {
|
||||
return (
|
||||
(ary[index + 3].toInt() shl 24) or
|
||||
((ary[index + 2].toInt() and 0xff) shl 16) or
|
||||
((ary[index + 1].toInt() and 0xff) shl 8) or
|
||||
((ary[index].toInt() and 0xff))
|
||||
)
|
||||
return ((ary[index + 3].toInt() shl 24) or
|
||||
((ary[index + 2].toInt() and 0xff) shl 16) or
|
||||
((ary[index + 1].toInt() and 0xff) shl 8) or
|
||||
((ary[index].toInt() and 0xff)))
|
||||
}
|
||||
|
||||
public inline fun getUInt(ary: ByteArray, index: Int): UInt = getInt(ary, index).toUInt()
|
||||
|
||||
public inline fun getLong(ary: ByteArray, index: Int): Long {
|
||||
var idx = index
|
||||
return ary[idx++].toLong() and 0xff or
|
||||
return ary[idx++].toLong() and
|
||||
0xff or
|
||||
(ary[idx++].toLong() and 0xff shl 8) or
|
||||
(ary[idx++].toLong() and 0xff shl 16) or
|
||||
(ary[idx++].toLong() and 0xff shl 24) or
|
||||
@@ -84,13 +99,15 @@ public object ByteArrayOps {
|
||||
public inline fun setUByte(ary: ByteArray, index: Int, value: UByte) {
|
||||
ary[index] = value.toByte()
|
||||
}
|
||||
|
||||
public inline fun setShort(ary: ByteArray, index: Int, value: Short) {
|
||||
var idx = index
|
||||
ary[idx++] = (value and 0xff).toByte()
|
||||
ary[idx] = (value.toInt() shr 8 and 0xff).toByte()
|
||||
}
|
||||
|
||||
public inline fun setUShort(ary: ByteArray, index: Int, value: UShort): Unit = setShort(ary, index, value.toShort())
|
||||
public inline fun setUShort(ary: ByteArray, index: Int, value: UShort): Unit =
|
||||
setShort(ary, index, value.toShort())
|
||||
|
||||
public inline fun setInt(ary: ByteArray, index: Int, value: Int) {
|
||||
var idx = index
|
||||
@@ -100,7 +117,8 @@ public object ByteArrayOps {
|
||||
ary[idx] = (value shr 24 and 0xff).toByte()
|
||||
}
|
||||
|
||||
public inline fun setUInt(ary: ByteArray, index: Int, value: UInt): Unit = setInt(ary, index, value.toInt())
|
||||
public inline fun setUInt(ary: ByteArray, index: Int, value: UInt): Unit =
|
||||
setInt(ary, index, value.toInt())
|
||||
|
||||
public inline fun setLong(ary: ByteArray, index: Int, value: Long) {
|
||||
var i = value.toInt()
|
||||
@@ -109,7 +127,8 @@ public object ByteArrayOps {
|
||||
setInt(ary, index + 4, i)
|
||||
}
|
||||
|
||||
public inline fun setULong(ary: ByteArray, index: Int, value: ULong): Unit = setLong(ary, index, value.toLong())
|
||||
public inline fun setULong(ary: ByteArray, index: Int, value: ULong): Unit =
|
||||
setLong(ary, index, value.toLong())
|
||||
|
||||
public inline fun setFloat(ary: ByteArray, index: Int, value: Float) {
|
||||
setInt(ary, index, value.toRawBits())
|
||||
@@ -120,5 +139,7 @@ public object ByteArrayOps {
|
||||
}
|
||||
|
||||
public inline fun getFloat(ary: ByteArray, index: Int): Float = Float.fromBits(getInt(ary, index))
|
||||
public inline fun getDouble(ary: ByteArray, index: Int): Double = Double.fromBits(getLong(ary, index))
|
||||
|
||||
public inline fun getDouble(ary: ByteArray, index: Int): Double =
|
||||
Double.fromBits(getLong(ary, index))
|
||||
}
|
||||
|
||||
@@ -17,14 +17,15 @@ package com.google.flatbuffers.kotlin
|
||||
|
||||
import kotlin.jvm.JvmOverloads
|
||||
|
||||
|
||||
/**
|
||||
* Class that helps you build a FlatBuffer. See the section
|
||||
* "Use in Kotlin" in the main FlatBuffers documentation.
|
||||
* Class that helps you build a FlatBuffer. See the section "Use in Kotlin" in the main FlatBuffers
|
||||
* documentation.
|
||||
*/
|
||||
public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
public class FlatBufferBuilder
|
||||
@JvmOverloads
|
||||
constructor(
|
||||
private val initialSize: Int = 1024,
|
||||
private var buffer: ReadWriteBuffer = ArrayReadWriteBuffer(initialSize)
|
||||
private var buffer: ReadWriteBuffer = ArrayReadWriteBuffer(initialSize),
|
||||
) {
|
||||
// Remaining space in the ByteBuffer.
|
||||
private var space: Int = buffer.capacity
|
||||
@@ -62,9 +63,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
// map used to cache shared strings.
|
||||
private var stringPool: MutableMap<CharSequence, Offset<String>>? = null
|
||||
|
||||
/**
|
||||
* Reset the FlatBufferBuilder by purging all data that it holds.
|
||||
*/
|
||||
/** Reset the FlatBufferBuilder by purging all data that it holds. */
|
||||
public fun clear() {
|
||||
space = buffer.capacity
|
||||
buffer.clear()
|
||||
@@ -96,11 +95,10 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare to write an element of `size` after `additional_bytes`
|
||||
* have been written, e.g. if you write a string, you need to align such
|
||||
* the int length field is aligned to [com.google.flatbuffers.Int.SIZE_BYTES], and
|
||||
* the string data follows it directly. If all you need to do is alignment, `additional_bytes`
|
||||
* will be 0.
|
||||
* Prepare to write an element of `size` after `additional_bytes` have been written, e.g. if you
|
||||
* write a string, you need to align such the int length field is aligned to
|
||||
* [com.google.flatbuffers.Int.SIZE_BYTES], and the string data follows it directly. If all you
|
||||
* need to do is alignment, `additional_bytes` will be 0.
|
||||
*
|
||||
* @param size This is the of the new element to write.
|
||||
* @param additionalBytes The padding size.
|
||||
@@ -124,8 +122,8 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a `boolean` to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add a `boolean` to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x A `boolean` to put into the buffer.
|
||||
*/
|
||||
@@ -135,16 +133,16 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [UByte] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add a [UByte] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x A [UByte] to put into the buffer.
|
||||
*/
|
||||
public fun put(x: UByte): Unit = put(x.toByte())
|
||||
|
||||
/**
|
||||
* Add a [Byte] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add a [Byte] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x A [Byte] to put into the buffer.
|
||||
*/
|
||||
@@ -154,16 +152,16 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [UShort] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add a [UShort] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x A [UShort] to put into the buffer.
|
||||
*/
|
||||
public fun put(x: UShort): Unit = put(x.toShort())
|
||||
|
||||
/**
|
||||
* Add a [Short] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add a [Short] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x A [Short] to put into the buffer.
|
||||
*/
|
||||
@@ -173,35 +171,35 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an [UInt] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add an [UInt] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x An [UInt] to put into the buffer.
|
||||
*/
|
||||
public fun put(x: UInt): Unit = put(x.toInt())
|
||||
|
||||
/**
|
||||
* Add an [Int] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add an [Int] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x An [Int] to put into the buffer.
|
||||
*/
|
||||
public fun put(x: Int){
|
||||
public fun put(x: Int) {
|
||||
space -= Int.SIZE_BYTES
|
||||
buffer.set(space, x)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [ULong] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add a [ULong] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x A [ULong] to put into the buffer.
|
||||
*/
|
||||
public fun put(x: ULong): Unit = put(x.toLong())
|
||||
|
||||
/**
|
||||
* Add a [Long] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add a [Long] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x A [Long] to put into the buffer.
|
||||
*/
|
||||
@@ -211,8 +209,8 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [Float] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add a [Float] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x A [Float] to put into the buffer.
|
||||
*/
|
||||
@@ -222,8 +220,8 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [Double] to the buffer, backwards from the current location. Doesn't align nor
|
||||
* check for space.
|
||||
* Add a [Double] to the buffer, backwards from the current location. Doesn't align nor check for
|
||||
* space.
|
||||
*
|
||||
* @param x A [Double] to put into the buffer.
|
||||
*/
|
||||
@@ -336,26 +334,23 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
* @param off The offset to add.
|
||||
*/
|
||||
public fun add(off: Offset<*>): Unit = addOffset(off.value)
|
||||
|
||||
public fun add(off: VectorOffset<*>): Unit = addOffset(off.value)
|
||||
|
||||
private fun addOffset(off: Int) {
|
||||
prep(Int.SIZE_BYTES, 0) // Ensure alignment is already done.
|
||||
put(buffer.capacity - space - off + Int.SIZE_BYTES)
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new array/vector of objects. Users usually will not call
|
||||
* this directly. The `FlatBuffers` compiler will create a start/end
|
||||
* method for vector types in generated code.
|
||||
*
|
||||
* Start a new array/vector of objects. Users usually will not call this directly. The
|
||||
* `FlatBuffers` compiler will create a start/end method for vector types in generated code.
|
||||
*
|
||||
* The expected sequence of calls is:
|
||||
*
|
||||
* 1. Start the array using this method.
|
||||
* 1. Call [.addOffset] `num_elems` number of times to set
|
||||
* the offset of each element in the array.
|
||||
* 1. Call [.endVector] to retrieve the offset of the array.
|
||||
*
|
||||
*
|
||||
* 1. Start the array using this method.
|
||||
* 1. Call [.addOffset] `num_elems` number of times to set the offset of each element in the
|
||||
* array.
|
||||
* 1. Call [.endVector] to retrieve the offset of the array.
|
||||
*
|
||||
* For example, to create an array of strings, do:
|
||||
* <pre>`// Need 10 strings
|
||||
@@ -379,7 +374,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
*
|
||||
* // Finish off the vector
|
||||
* int offsetOfTheVector = fbb.endVector();
|
||||
`</pre> *
|
||||
* `</pre> *
|
||||
*
|
||||
* @param elemSize The size of each element in the array.
|
||||
* @param numElems The number of elements in the array.
|
||||
@@ -392,11 +387,12 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
prep(alignment, elemSize * numElems) // Just in case alignment > int.
|
||||
nested = true
|
||||
}
|
||||
|
||||
public fun startString(numElems: Int): Unit = startVector(1, numElems, 1)
|
||||
|
||||
/**
|
||||
* Finish off the creation of an array and all its elements. The array
|
||||
* must be created with [.startVector].
|
||||
* Finish off the creation of an array and all its elements. The array must be created with
|
||||
* [.startVector].
|
||||
*
|
||||
* @return The offset at which the newly created array starts.
|
||||
* @see .startVector
|
||||
@@ -423,16 +419,19 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new array/vector and return a ByteBuffer to be filled later.
|
||||
* Call [endVector] after this method to get an offset to the beginning
|
||||
* of vector.
|
||||
* Create a new array/vector and return a ByteBuffer to be filled later. Call [endVector] after
|
||||
* this method to get an offset to the beginning of vector.
|
||||
*
|
||||
* @param elemSize the size of each element in bytes.
|
||||
* @param numElems number of elements in the vector.
|
||||
* @param alignment byte alignment.
|
||||
* @return ByteBuffer with position and limit set to the space allocated for the array.
|
||||
*/
|
||||
public fun createUnintializedVector(elemSize: Int, numElems: Int, alignment: Int): ReadWriteBuffer {
|
||||
public fun createUnintializedVector(
|
||||
elemSize: Int,
|
||||
numElems: Int,
|
||||
alignment: Int,
|
||||
): ReadWriteBuffer {
|
||||
val length = elemSize * numElems
|
||||
startVector(elemSize, numElems, alignment)
|
||||
space -= length
|
||||
@@ -460,19 +459,21 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
* @param offsets Offsets of the tables.
|
||||
* @return Returns offset of the sorted vector.
|
||||
*/
|
||||
public fun <T : Table> createSortedVectorOfTables(obj: T, offsets: Array<Offset<T>>): VectorOffset<T> {
|
||||
public fun <T : Table> createSortedVectorOfTables(
|
||||
obj: T,
|
||||
offsets: Array<Offset<T>>,
|
||||
): VectorOffset<T> {
|
||||
obj.sortTables(offsets, buffer)
|
||||
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.
|
||||
* 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.
|
||||
* 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.
|
||||
@@ -494,6 +495,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
|
||||
/**
|
||||
* Encode the [CharSequence] `s` in the buffer using UTF-8.
|
||||
*
|
||||
* @param s The [CharSequence] to encode.
|
||||
* @return The offset in the buffer where the encoded string starts.
|
||||
*/
|
||||
@@ -513,7 +515,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
* @param s An already encoded UTF-8 string as a `ByteBuffer`.
|
||||
* @return The offset in the buffer where the encoded string starts.
|
||||
*/
|
||||
public fun createString(s: ReadBuffer): Offset<String> {
|
||||
public fun createString(s: ReadBuffer): Offset<String> {
|
||||
val length: Int = s.limit
|
||||
add(0.toByte())
|
||||
startVector(1, length, 1)
|
||||
@@ -557,13 +559,16 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
/**
|
||||
* Create a byte array in the buffer.
|
||||
*
|
||||
* The source [ReadBuffer] position is advanced until [ReadBuffer.limit]
|
||||
* after this call.
|
||||
* The source [ReadBuffer] position is advanced until [ReadBuffer.limit] after this call.
|
||||
*
|
||||
* @param data A source [ReadBuffer] with data.
|
||||
* @return The offset in the buffer where the encoded array starts.
|
||||
*/
|
||||
public fun createByteVector(data: ReadBuffer, from: Int = 0, until: Int = data.limit): VectorOffset<Byte> {
|
||||
public fun createByteVector(
|
||||
data: ReadBuffer,
|
||||
from: Int = 0,
|
||||
until: Int = data.limit,
|
||||
): VectorOffset<Byte> {
|
||||
val length: Int = until - from
|
||||
startVector(1, length, 1)
|
||||
space -= length
|
||||
@@ -572,28 +577,25 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
return VectorOffset(endVector())
|
||||
}
|
||||
|
||||
/**
|
||||
* Should not be accessing the final buffer before it is finished.
|
||||
*/
|
||||
/** Should not be accessing the final buffer before it is finished. */
|
||||
public fun finished() {
|
||||
if (!finished) throw AssertionError(
|
||||
"FlatBuffers: you can only access the serialized buffer after it has been" +
|
||||
" finished by FlatBufferBuilder.finish()."
|
||||
)
|
||||
if (!finished)
|
||||
throw AssertionError(
|
||||
"FlatBuffers: you can only access the serialized buffer after it has been" +
|
||||
" finished by FlatBufferBuilder.finish()."
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Should not be creating any other object, string or vector
|
||||
* while an object is being constructed.
|
||||
* Should not be creating any other object, string or vector while an object is being constructed.
|
||||
*/
|
||||
public fun notNested() {
|
||||
if (nested) throw AssertionError("FlatBuffers: object serialization must not be nested.")
|
||||
}
|
||||
|
||||
/**
|
||||
* Structures are always stored inline, they need to be created right
|
||||
* where they're used. You'll get this assertion failure if you
|
||||
* created it elsewhere.
|
||||
* Structures are always stored inline, they need to be created right where they're used. You'll
|
||||
* get this assertion failure if you created it elsewhere.
|
||||
*
|
||||
* @param obj The offset of the created object.
|
||||
*/
|
||||
@@ -602,14 +604,11 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Start encoding a new object in the buffer. Users will not usually need to
|
||||
* call this directly. The `FlatBuffers` compiler will generate helper methods
|
||||
* that call this method internally.
|
||||
*
|
||||
*
|
||||
* For example, using the "Monster" code found on the "landing page". An
|
||||
* object of type `Monster` can be created using the following code:
|
||||
* Start encoding a new object in the buffer. Users will not usually need to call this directly.
|
||||
* The `FlatBuffers` compiler will generate helper methods that call this method internally.
|
||||
*
|
||||
* For example, using the "Monster" code found on the "landing page". An object of type `Monster`
|
||||
* can be created using the following code:
|
||||
* <pre>`int testArrayOfString = Monster.createTestarrayofstringVector(fbb, new int[] {
|
||||
* fbb.createString("test1"),
|
||||
* fbb.createString("test2")
|
||||
@@ -626,19 +625,15 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
* Monster.addTest4(fbb, test4);
|
||||
* Monster.addTestarrayofstring(fbb, testArrayOfString);
|
||||
* int mon = Monster.endMonster(fbb);
|
||||
`</pre> *
|
||||
*
|
||||
* `</pre> *
|
||||
*
|
||||
* Here:
|
||||
* * The call to `Monster#startMonster(FlatBufferBuilder)` will call this method with the right
|
||||
* number of fields set.
|
||||
* * `Monster#endMonster(FlatBufferBuilder)` will ensure [.endObject] is called.
|
||||
*
|
||||
* * The call to `Monster#startMonster(FlatBufferBuilder)` will call this
|
||||
* method with the right number of fields set.
|
||||
* * `Monster#endMonster(FlatBufferBuilder)` will ensure [.endObject] is called.
|
||||
*
|
||||
*
|
||||
*
|
||||
* It's not recommended to call this method directly. If it's called manually, you must ensure
|
||||
* to audit all calls to it whenever fields are added or removed from your schema. This is
|
||||
* It's not recommended to call this method directly. If it's called manually, you must ensure to
|
||||
* audit all calls to it whenever fields are added or removed from your schema. This is
|
||||
* automatically done by the code generated by the `FlatBuffers` compiler.
|
||||
*
|
||||
* @param numFields The number of fields found in this object.
|
||||
@@ -649,15 +644,14 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
vtable = IntArray(numFields)
|
||||
}
|
||||
vtableInUse = numFields
|
||||
for (i in 0 until vtableInUse)
|
||||
vtable[i] = 0
|
||||
for (i in 0 until vtableInUse) vtable[i] = 0
|
||||
nested = true
|
||||
objectStart = offset()
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [Boolean] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [Boolean] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: Boolean, d: Boolean?) {
|
||||
@@ -666,6 +660,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: Boolean, d: Boolean) {
|
||||
if (forceDefaults || x != d) {
|
||||
@@ -675,17 +670,18 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [UByte] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [UByte] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: UByte, d: UByte?): Unit = add(o, x.toByte(), d?.toByte())
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: UByte, d: UByte): Unit = add(o, x.toByte(), d.toByte())
|
||||
|
||||
/**
|
||||
* Add a [Byte] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [Byte] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: Byte, d: Byte?) {
|
||||
@@ -694,6 +690,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: Byte, d: Byte) {
|
||||
if (forceDefaults || x != d) {
|
||||
@@ -701,19 +698,20 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [UShort] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [UShort] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: UShort, d: UShort?): Unit = add(o, x.toShort(), d?.toShort())
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: UShort, d: UShort): Unit = add(o, x.toShort(), d.toShort())
|
||||
|
||||
|
||||
/**
|
||||
* Add a [Short] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [Short] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: Short, d: Short?) {
|
||||
@@ -722,6 +720,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: Short, d: Short) {
|
||||
if (forceDefaults || x != d) {
|
||||
@@ -731,17 +730,18 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [UInt] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [UInt] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: UInt, d: UInt?): Unit = add(o, x.toInt(), d?.toInt())
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: UInt, d: UInt): Unit = add(o, x.toInt(), d.toInt())
|
||||
|
||||
/**
|
||||
* Add a [Int] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [Int] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: Int, d: Int?) {
|
||||
@@ -750,6 +750,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: Int, d: Int) {
|
||||
if (forceDefaults || x != d) {
|
||||
@@ -757,17 +758,20 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [ULong] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [ULong] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: ULong, d: ULong?): Unit = add(o, x.toLong(), d?.toLong())
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: ULong, d: ULong): Unit = add(o, x.toLong(), d.toLong())
|
||||
|
||||
/**
|
||||
* Add a [Long] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [Long] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: Long, d: Long?) {
|
||||
@@ -776,6 +780,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: Long, d: Long) {
|
||||
if (forceDefaults || x != d) {
|
||||
@@ -785,8 +790,8 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [Float] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [Float] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: Float, d: Float?) {
|
||||
@@ -795,6 +800,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: Float, d: Float) {
|
||||
if (forceDefaults || x != d) {
|
||||
@@ -804,8 +810,8 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [Double] to a table at `o` into its vtable, with value `x` and default `d`.
|
||||
* If `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* Add a [Double] to a table at `o` into its vtable, with value `x` and default `d`. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
*/
|
||||
public fun add(o: Int, x: Double, d: Double?) {
|
||||
@@ -814,6 +820,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
// unboxed specialization
|
||||
public fun add(o: Int, x: Double, d: Double) {
|
||||
if (forceDefaults || x != d) {
|
||||
@@ -827,8 +834,8 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
*
|
||||
* @param o The index into the vtable.
|
||||
* @param x An `offset` to put into the buffer, depending on how defaults are handled. If
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
* `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
|
||||
* default value, it can be skipped.
|
||||
* @param d An `offset` default value to compare against when `force_defaults` is `false`.
|
||||
*/
|
||||
public fun add(o: Int, x: Offset<*>, d: Int) {
|
||||
@@ -837,6 +844,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
slot(o)
|
||||
}
|
||||
}
|
||||
|
||||
public fun add(o: Int, x: VectorOffset<*>, d: Int) {
|
||||
if (forceDefaults || x.value != d) {
|
||||
add(x)
|
||||
@@ -851,15 +859,20 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
* @param x The offset of the created struct.
|
||||
* @param d The default value is always `0`.
|
||||
*/
|
||||
public fun addStruct(vOffset: Int, x: Offset<*>, d: Offset<*>?): Unit = addStruct(vOffset, x.value, d?.value)
|
||||
public fun addStruct(vOffset: Int, x: Offset<*>, d: Offset<*>?): Unit =
|
||||
addStruct(vOffset, x.value, d?.value)
|
||||
|
||||
// unboxed specialization
|
||||
public fun addStruct(vOffset: Int, x: Offset<*>, d: Offset<*>): Unit = addStruct(vOffset, x.value, d.value)
|
||||
public fun addStruct(vOffset: Int, x: Offset<*>, d: Offset<*>): Unit =
|
||||
addStruct(vOffset, x.value, d.value)
|
||||
|
||||
public fun addStruct(vOffset: Int, x: Int, d: Int?) {
|
||||
if (x != d) {
|
||||
nested(x)
|
||||
slot(vOffset)
|
||||
}
|
||||
}
|
||||
|
||||
// unboxed specialization
|
||||
public fun addStruct(vOffset: Int, x: Int, d: Int) {
|
||||
if (x != d) {
|
||||
@@ -871,8 +884,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
/**
|
||||
* Set the current vtable at `voffset` to the current location in the buffer.
|
||||
*
|
||||
* @param vOffset The index into the vtable to store the offset relative to the end of the
|
||||
* buffer.
|
||||
* @param vOffset The index into the vtable to store the offset relative to the end of the buffer.
|
||||
*/
|
||||
public fun slot(vOffset: Int) {
|
||||
vtable[vOffset] = offset()
|
||||
@@ -947,8 +959,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a required field has been set in a given table that has
|
||||
* just been constructed.
|
||||
* Checks that a required field has been set in a given table that has just been constructed.
|
||||
*
|
||||
* @param table The offset to the start of the table from the `ByteBuffer` capacity.
|
||||
* @param field The offset to the field in the vtable.
|
||||
@@ -1000,16 +1011,14 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
*
|
||||
* @param rootTable An offset to be added to the buffer.
|
||||
* @param fileIdentifier A FlatBuffer file identifier to be added to the buffer before
|
||||
* `root_table`.
|
||||
* `root_table`.
|
||||
* @param sizePrefix Whether to prefix the size to the buffer.
|
||||
*/
|
||||
protected fun finish(rootTable: Offset<*>, fileIdentifier: String, sizePrefix: Boolean) {
|
||||
val identifierSize = 4
|
||||
prep(minalign, Int.SIZE_BYTES + identifierSize + if (sizePrefix) Int.SIZE_BYTES else 0)
|
||||
if (fileIdentifier.length != identifierSize) throw AssertionError(
|
||||
"FlatBuffers: file identifier must be length " +
|
||||
identifierSize
|
||||
)
|
||||
if (fileIdentifier.length != identifierSize)
|
||||
throw AssertionError("FlatBuffers: file identifier must be length " + identifierSize)
|
||||
for (i in identifierSize - 1 downTo 0) {
|
||||
add(fileIdentifier[i].code.toByte())
|
||||
}
|
||||
@@ -1021,7 +1030,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
*
|
||||
* @param rootTable An offset to be added to the buffer.
|
||||
* @param fileIdentifier A FlatBuffer file identifier to be added to the buffer before
|
||||
* `root_table`.
|
||||
* `root_table`.
|
||||
*/
|
||||
public fun finish(rootTable: Offset<*>, fileIdentifier: String) {
|
||||
finish(rootTable, fileIdentifier, false)
|
||||
@@ -1032,16 +1041,15 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
*
|
||||
* @param rootTable An offset to be added to the buffer.
|
||||
* @param fileIdentifier A FlatBuffer file identifier to be added to the buffer before
|
||||
* `root_table`.
|
||||
* `root_table`.
|
||||
*/
|
||||
public fun finishSizePrefixed(rootTable: Offset<*>, fileIdentifier: String) {
|
||||
finish(rootTable, fileIdentifier, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* In order to save space, fields that are set to their default value
|
||||
* don't get serialized into the buffer. Forcing defaults provides a
|
||||
* way to manually disable this optimization.
|
||||
* In order to save space, fields that are set to their default value don't get serialized into
|
||||
* the buffer. Forcing defaults provides a way to manually disable this optimization.
|
||||
*
|
||||
* @param forceDefaults When set to `true`, always serializes default values.
|
||||
* @return Returns `this`.
|
||||
@@ -1052,9 +1060,8 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ByteBuffer representing the FlatBuffer. Only call this after you've
|
||||
* called `finish()`. The actual data starts at the ByteBuffer's current position,
|
||||
* not necessarily at `0`.
|
||||
* Get the ByteBuffer representing the FlatBuffer. Only call this after you've called `finish()`.
|
||||
* The actual data starts at the ByteBuffer's current position, not necessarily at `0`.
|
||||
*
|
||||
* @return The [ReadBuffer] representing the FlatBuffer
|
||||
*/
|
||||
@@ -1068,7 +1075,7 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
*
|
||||
* @return A full copy of the [data buffer][.dataBuffer].
|
||||
*/
|
||||
public fun sizedByteArray(start: Int = space, length: Int = buffer.capacity - space): ByteArray {
|
||||
public fun sizedByteArray(start: Int = space, length: Int = buffer.capacity - space): ByteArray {
|
||||
finished()
|
||||
val array = ByteArray(length)
|
||||
buffer.getBytes(array, start)
|
||||
@@ -1080,26 +1087,29 @@ public class FlatBufferBuilder @JvmOverloads constructor(
|
||||
*
|
||||
* @param offset virtual table offset
|
||||
* @return true if the filed is present
|
||||
*/
|
||||
*/
|
||||
public fun Table.isFieldPresent(offset: Int): Boolean = this.offset(offset) != 0
|
||||
}
|
||||
|
||||
public fun Double.sign(): Double = when {
|
||||
this.isNaN() -> Double.NaN
|
||||
this > 0 -> 1.0
|
||||
this < 0 -> -1.0
|
||||
else -> this
|
||||
}
|
||||
public fun Double.sign(): Double =
|
||||
when {
|
||||
this.isNaN() -> Double.NaN
|
||||
this > 0 -> 1.0
|
||||
this < 0 -> -1.0
|
||||
else -> this
|
||||
}
|
||||
|
||||
public fun Float.sign(): Float = when {
|
||||
this.isNaN() -> Float.NaN
|
||||
this > 0 -> 1.0f
|
||||
this < 0 -> -1.0f
|
||||
else -> this
|
||||
}
|
||||
public fun Float.sign(): Float =
|
||||
when {
|
||||
this.isNaN() -> Float.NaN
|
||||
this > 0 -> 1.0f
|
||||
this < 0 -> -1.0f
|
||||
else -> this
|
||||
}
|
||||
|
||||
public fun Int.sign(): Int = when {
|
||||
this > 0 -> 1
|
||||
this < 0 -> -1
|
||||
else -> this
|
||||
}
|
||||
public fun Int.sign(): Int =
|
||||
when {
|
||||
this > 0 -> 1
|
||||
this < 0 -> -1
|
||||
else -> this
|
||||
}
|
||||
|
||||
@@ -20,29 +20,33 @@ import kotlin.math.min
|
||||
|
||||
// For now a typealias to guarantee type safety.
|
||||
public typealias UnionOffset = Offset<Any>
|
||||
|
||||
public typealias UnionOffsetArray = OffsetArray<Any>
|
||||
|
||||
public typealias StringOffsetArray = OffsetArray<String>
|
||||
|
||||
public inline fun UnionOffsetArray(size: Int, crossinline call: (Int) -> Offset<Any>): UnionOffsetArray =
|
||||
UnionOffsetArray(IntArray(size) { call(it).value })
|
||||
public inline fun StringOffsetArray(size: Int, crossinline call: (Int) -> Offset<String>): StringOffsetArray =
|
||||
StringOffsetArray(IntArray(size) { call(it).value })
|
||||
/**
|
||||
* Represents a "pointer" to a pointer types (table, string, struct) within the buffer
|
||||
*/
|
||||
public inline fun UnionOffsetArray(
|
||||
size: Int,
|
||||
crossinline call: (Int) -> Offset<Any>,
|
||||
): UnionOffsetArray = UnionOffsetArray(IntArray(size) { call(it).value })
|
||||
|
||||
public inline fun StringOffsetArray(
|
||||
size: Int,
|
||||
crossinline call: (Int) -> Offset<String>,
|
||||
): StringOffsetArray = StringOffsetArray(IntArray(size) { call(it).value })
|
||||
|
||||
/** Represents a "pointer" to a pointer types (table, string, struct) within the buffer */
|
||||
@JvmInline
|
||||
public value class Offset<T>(public val value: Int) {
|
||||
public fun toUnion(): UnionOffset = UnionOffset(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an array of offsets. Used to avoid boxing
|
||||
* offset types.
|
||||
*/
|
||||
/** Represents an array of offsets. Used to avoid boxing offset types. */
|
||||
@JvmInline
|
||||
public value class OffsetArray<T>(public val value: IntArray) {
|
||||
public inline val size: Int
|
||||
get() = value.size
|
||||
|
||||
public inline operator fun get(index: Int): Offset<T> = Offset(value[index])
|
||||
}
|
||||
|
||||
@@ -50,12 +54,8 @@ public inline fun <T> OffsetArray(size: Int, crossinline call: (Int) -> Offset<T
|
||||
return OffsetArray(IntArray(size) { call(it).value })
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents a "pointer" to a vector type with elements T
|
||||
*/
|
||||
@JvmInline
|
||||
public value class VectorOffset<T>(public val value: Int)
|
||||
/** Represents a "pointer" to a vector type with elements T */
|
||||
@JvmInline public value class VectorOffset<T>(public val value: Int)
|
||||
|
||||
public fun <T> Int.toOffset(): Offset<T> = Offset(this)
|
||||
|
||||
@@ -64,28 +64,30 @@ public operator fun <T> Offset<T>.minus(other: Int): Offset<T> = Offset(this.val
|
||||
public operator fun <T> Int.minus(other: Offset<T>): Int {
|
||||
return this - other.value
|
||||
}
|
||||
/**
|
||||
* All tables in the generated code derive from this class, and add their own accessors.
|
||||
*/
|
||||
|
||||
/** All tables in the generated code derive from this class, and add their own accessors. */
|
||||
public open class Table {
|
||||
|
||||
/** Used to hold the position of the `bb` buffer. */
|
||||
/** Used to hold the position of the `bb` buffer. */
|
||||
public var bufferPos: Int = 0
|
||||
|
||||
/** The underlying ReadWriteBuffer to hold the data of the Table. */
|
||||
/** The underlying ReadWriteBuffer to hold the data of the Table. */
|
||||
public var bb: ReadWriteBuffer = emptyBuffer
|
||||
|
||||
/** Used to hold the vtable position. */
|
||||
/** Used to hold the vtable position. */
|
||||
public var vtableStart: Int = 0
|
||||
|
||||
/** Used to hold the vtable size. */
|
||||
/** Used to hold the vtable size. */
|
||||
public var vtableSize: Int = 0
|
||||
|
||||
protected inline fun <reified T> Int.invalid(default: T, crossinline valid: (Int) -> T) : T =
|
||||
protected inline fun <reified T> Int.invalid(default: T, crossinline valid: (Int) -> T): T =
|
||||
if (this != 0) valid(this) else default
|
||||
|
||||
protected inline fun <reified T> lookupField(i: Int, default: T, crossinline found: (Int) -> T) : T =
|
||||
offset(i).invalid(default) { found(it) }
|
||||
protected inline fun <reified T> lookupField(
|
||||
i: Int,
|
||||
default: T,
|
||||
crossinline found: (Int) -> T,
|
||||
): T = offset(i).invalid(default) { found(it) }
|
||||
|
||||
/**
|
||||
* Look up a field in the vtable.
|
||||
@@ -107,10 +109,10 @@ public open class Table {
|
||||
/**
|
||||
* Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
|
||||
*
|
||||
* This allocates a new string and converts to wide chars upon each access,
|
||||
* which is not very efficient. Instead, each FlatBuffer string also comes with an
|
||||
* accessor based on __vector_as_ReadWriteBuffer below, which is much more efficient,
|
||||
* assuming your Java program can handle UTF-8 data directly.
|
||||
* This allocates a new string and converts to wide chars upon each access, which is not very
|
||||
* efficient. Instead, each FlatBuffer string also comes with an accessor based on
|
||||
* __vector_as_ReadWriteBuffer below, which is much more efficient, assuming your Java program can
|
||||
* handle UTF-8 data directly.
|
||||
*
|
||||
* @param offset An `int` index into the Table's ReadWriteBuffer.
|
||||
* @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
|
||||
@@ -141,23 +143,24 @@ public open class Table {
|
||||
newOffset += bufferPos
|
||||
return newOffset + bb.getInt(newOffset) + Int.SIZE_BYTES // data starts after the length
|
||||
}
|
||||
/**
|
||||
* Initialize vector as a ReadWriteBuffer.
|
||||
*
|
||||
* This is more efficient than using duplicate, since it doesn't copy the data
|
||||
* nor allocates a new [ReadBuffer], creating no garbage to be collected.
|
||||
*
|
||||
* @param buffer The [ReadBuffer] for the array
|
||||
* @param vectorOffset The position of the vector in the byte buffer
|
||||
* @param elemSize The size of each element in the array
|
||||
* @return The [ReadBuffer] for the array
|
||||
*/
|
||||
public fun vectorAsBuffer(buffer: ReadWriteBuffer, vectorOffset: Int, elemSize: Int): ReadBuffer {
|
||||
val o = offset(vectorOffset)
|
||||
if (o == 0) return emptyBuffer
|
||||
val vectorStart = vector(o)
|
||||
return buffer.slice(vectorStart, vectorLength(o) * elemSize)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize vector as a ReadWriteBuffer.
|
||||
*
|
||||
* This is more efficient than using duplicate, since it doesn't copy the data nor allocates a new
|
||||
* [ReadBuffer], creating no garbage to be collected.
|
||||
*
|
||||
* @param buffer The [ReadBuffer] for the array
|
||||
* @param vectorOffset The position of the vector in the byte buffer
|
||||
* @param elemSize The size of each element in the array
|
||||
* @return The [ReadBuffer] for the array
|
||||
*/
|
||||
public fun vectorAsBuffer(buffer: ReadWriteBuffer, vectorOffset: Int, elemSize: Int): ReadBuffer {
|
||||
val o = offset(vectorOffset)
|
||||
if (o == 0) return emptyBuffer
|
||||
val vectorStart = vector(o)
|
||||
return buffer.slice(vectorStart, vectorLength(o) * elemSize)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize any Table-derived type to point to the union at the given `offset`.
|
||||
@@ -194,7 +197,7 @@ public open class Table {
|
||||
* This method exists primarily to allow recycling Table instances without risking memory leaks
|
||||
* due to `ReadWriteBuffer` references.
|
||||
*/
|
||||
public inline fun <reified T: Table> reset(i: Int, reuseBuffer: ReadWriteBuffer): T {
|
||||
public inline fun <reified T : Table> reset(i: Int, reuseBuffer: ReadWriteBuffer): T {
|
||||
bb = reuseBuffer
|
||||
if (bb != emptyBuffer) {
|
||||
bufferPos = i
|
||||
@@ -212,10 +215,10 @@ public open class Table {
|
||||
* Resets the internal state with a null `ReadWriteBuffer` and a zero position.
|
||||
*
|
||||
* This method exists primarily to allow recycling Table instances without risking memory leaks
|
||||
* due to `ReadWriteBuffer` references. The instance will be unusable until it is assigned
|
||||
* again to a `ReadWriteBuffer`.
|
||||
* due to `ReadWriteBuffer` references. The instance will be unusable until it is assigned again
|
||||
* to a `ReadWriteBuffer`.
|
||||
*/
|
||||
public inline fun <reified T: Table> reset(): T = reset(0, emptyBuffer)
|
||||
public inline fun <reified T : Table> reset(): T = reset(0, emptyBuffer)
|
||||
|
||||
public companion object {
|
||||
|
||||
@@ -238,10 +241,10 @@ public open class Table {
|
||||
/**
|
||||
* Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
|
||||
*
|
||||
* This allocates a new string and converts to wide chars upon each access,
|
||||
* which is not very efficient. Instead, each FlatBuffer string also comes with an
|
||||
* accessor based on __vector_as_ReadWriteBuffer below, which is much more efficient,
|
||||
* assuming your Java program can handle UTF-8 data directly.
|
||||
* This allocates a new string and converts to wide chars upon each access, which is not very
|
||||
* efficient. Instead, each FlatBuffer string also comes with an accessor based on
|
||||
* __vector_as_ReadWriteBuffer below, which is much more efficient, assuming your Java program
|
||||
* can handle UTF-8 data directly.
|
||||
*
|
||||
* @param offset An `int` index into the Table's ReadWriteBuffer.
|
||||
* @param bb Table ReadWriteBuffer used to read a string at given offset.
|
||||
@@ -268,8 +271,7 @@ public open class Table {
|
||||
/**
|
||||
* Check if a [ReadWriteBuffer] contains a file identifier.
|
||||
*
|
||||
* @param bb A `ReadWriteBuffer` to check if it contains the identifier
|
||||
* `ident`.
|
||||
* @param bb A `ReadWriteBuffer` to check if it contains the identifier `ident`.
|
||||
* @param ident A `String` identifier of the FlatBuffer file.
|
||||
* @return True if the buffer contains the file identifier
|
||||
*/
|
||||
@@ -330,14 +332,12 @@ public open class Table {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All structs in the generated code derive from this class, and add their own accessors.
|
||||
*/
|
||||
/** All structs in the generated code derive from this class, and add their own accessors. */
|
||||
public open class Struct {
|
||||
/** Used to hold the position of the `bb` buffer. */
|
||||
/** Used to hold the position of the `bb` buffer. */
|
||||
protected var bufferPos: Int = 0
|
||||
|
||||
/** The underlying ByteBuffer to hold the data of the Struct. */
|
||||
/** The underlying ByteBuffer to hold the data of the Struct. */
|
||||
protected var bb: ReadWriteBuffer = emptyBuffer
|
||||
|
||||
/**
|
||||
@@ -346,7 +346,7 @@ public open class Struct {
|
||||
* This method exists primarily to allow recycling Table instances without risking memory leaks
|
||||
* due to `ByteBuffer` references.
|
||||
*/
|
||||
protected inline fun <reified T: Struct> reset(i: Int, reuseBuffer: ReadWriteBuffer): T {
|
||||
protected inline fun <reified T : Struct> reset(i: Int, reuseBuffer: ReadWriteBuffer): T {
|
||||
bb = reuseBuffer
|
||||
bufferPos = if (bb != emptyBuffer) i else 0
|
||||
return this as T
|
||||
@@ -356,12 +356,13 @@ public open class Struct {
|
||||
* Resets internal state with a null `ByteBuffer` and a zero position.
|
||||
*
|
||||
* This method exists primarily to allow recycling Struct instances without risking memory leaks
|
||||
* due to `ByteBuffer` references. The instance will be unusable until it is assigned
|
||||
* again to a `ByteBuffer`.
|
||||
* due to `ByteBuffer` references. The instance will be unusable until it is assigned again to a
|
||||
* `ByteBuffer`.
|
||||
*/
|
||||
private inline fun <reified T: Struct> reset(): T = reset(0, emptyBuffer)
|
||||
private inline fun <reified T : Struct> reset(): T = reset(0, emptyBuffer)
|
||||
}
|
||||
|
||||
public inline val <T> T.value: T get() = this
|
||||
public inline val <T> T.value: T
|
||||
get() = this
|
||||
|
||||
public const val VERSION_2_0_8: Int = 1
|
||||
|
||||
@@ -15,13 +15,14 @@
|
||||
*/
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
@file:JvmName("FlexBuffers")
|
||||
|
||||
package com.google.flatbuffers.kotlin
|
||||
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
/**
|
||||
* Reads a FlexBuffer message in ReadBuf and returns [Reference] to
|
||||
* the root element.
|
||||
* Reads a FlexBuffer message in ReadBuf and returns [Reference] to the root element.
|
||||
*
|
||||
* @param buffer ReadBuf containing FlexBuffer message
|
||||
* @return [Reference] to the root object
|
||||
*/
|
||||
@@ -34,199 +35,231 @@ public fun getRoot(buffer: ReadBuffer): Reference {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an generic element in the buffer. It can be specialized into scalar types, using for example,
|
||||
* [Reference.toInt], or casted into Flexbuffer object types, like [Reference.toMap] or [Reference.toBlob].
|
||||
* Represents an generic element in the buffer. It can be specialized into scalar types, using for
|
||||
* example, [Reference.toInt], or casted into Flexbuffer object types, like [Reference.toMap] or
|
||||
* [Reference.toBlob].
|
||||
*/
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
public class Reference internal constructor(
|
||||
public class Reference
|
||||
internal constructor(
|
||||
internal val buffer: ReadBuffer,
|
||||
internal val end: Int,
|
||||
internal val parentWidth: ByteWidth,
|
||||
internal val byteWidth: ByteWidth,
|
||||
public val type: FlexBufferType
|
||||
public val type: FlexBufferType,
|
||||
) {
|
||||
|
||||
internal constructor(bb: ReadBuffer, end: Int, parentWidth: ByteWidth, packedType: Int) :
|
||||
this(bb, end, parentWidth, ByteWidth(1 shl (packedType and 3)), FlexBufferType((packedType shr 2)))
|
||||
internal constructor(
|
||||
bb: ReadBuffer,
|
||||
end: Int,
|
||||
parentWidth: ByteWidth,
|
||||
packedType: Int,
|
||||
) : this(
|
||||
bb,
|
||||
end,
|
||||
parentWidth,
|
||||
ByteWidth(1 shl (packedType and 3)),
|
||||
FlexBufferType((packedType shr 2)),
|
||||
)
|
||||
|
||||
/**
|
||||
* Checks whether the element is null type
|
||||
*
|
||||
* @return true if null type
|
||||
*/
|
||||
public val isNull: Boolean get() = type == T_NULL
|
||||
public val isNull: Boolean
|
||||
get() = type == T_NULL
|
||||
|
||||
/**
|
||||
* Checks whether the element is boolean type
|
||||
*
|
||||
* @return true if boolean type
|
||||
*/
|
||||
public val isBoolean: Boolean get() = type == T_BOOL
|
||||
public val isBoolean: Boolean
|
||||
get() = type == T_BOOL
|
||||
|
||||
/**
|
||||
* Checks whether the element type is numeric (signed/unsigned integers and floats)
|
||||
*
|
||||
* @return true if numeric type
|
||||
*/
|
||||
public val isNumeric: Boolean get() = isIntOrUInt || isFloat
|
||||
public val isNumeric: Boolean
|
||||
get() = isIntOrUInt || isFloat
|
||||
|
||||
/**
|
||||
* Checks whether the element type is signed or unsigned integers
|
||||
*
|
||||
* @return true if an integer type
|
||||
*/
|
||||
public val isIntOrUInt: Boolean get() = isInt || isUInt
|
||||
public val isIntOrUInt: Boolean
|
||||
get() = isInt || isUInt
|
||||
|
||||
/**
|
||||
* Checks whether the element type is float
|
||||
*
|
||||
* @return true if a float type
|
||||
*/
|
||||
public val isFloat: Boolean get() = type == T_FLOAT || type == T_INDIRECT_FLOAT
|
||||
public val isFloat: Boolean
|
||||
get() = type == T_FLOAT || type == T_INDIRECT_FLOAT
|
||||
|
||||
/**
|
||||
* Checks whether the element type is signed integer
|
||||
*
|
||||
* @return true if a signed integer type
|
||||
*/
|
||||
public val isInt: Boolean get() = type == T_INT || type == T_INDIRECT_INT
|
||||
public val isInt: Boolean
|
||||
get() = type == T_INT || type == T_INDIRECT_INT
|
||||
|
||||
/**
|
||||
* Checks whether the element type is signed integer
|
||||
*
|
||||
* @return true if a signed integer type
|
||||
*/
|
||||
public val isUInt: Boolean get() = type == T_UINT || type == T_INDIRECT_UINT
|
||||
public val isUInt: Boolean
|
||||
get() = type == T_UINT || type == T_INDIRECT_UINT
|
||||
|
||||
/**
|
||||
* Checks whether the element type is string
|
||||
*
|
||||
* @return true if a string type
|
||||
*/
|
||||
public val isString: Boolean get() = type == T_STRING
|
||||
public val isString: Boolean
|
||||
get() = type == T_STRING
|
||||
|
||||
/**
|
||||
* Checks whether the element type is key
|
||||
*
|
||||
* @return true if a key type
|
||||
*/
|
||||
public val isKey: Boolean get() = type == T_KEY
|
||||
public val isKey: Boolean
|
||||
get() = type == T_KEY
|
||||
|
||||
/**
|
||||
* Checks whether the element type is vector or a map. [TypedVector] are considered different types and will return
|
||||
* false.
|
||||
* Checks whether the element type is vector or a map. [TypedVector] are considered different
|
||||
* types and will return false.
|
||||
*
|
||||
* @return true if a vector type
|
||||
*/
|
||||
public val isVector: Boolean get() = type == T_VECTOR || type == T_MAP
|
||||
public val isVector: Boolean
|
||||
get() = type == T_VECTOR || type == T_MAP
|
||||
|
||||
/**
|
||||
* Checks whether the element type is typed vector
|
||||
*
|
||||
* @return true if a typed vector type
|
||||
*/
|
||||
public val isTypedVector: Boolean get() = type.isTypedVector()
|
||||
public val isTypedVector: Boolean
|
||||
get() = type.isTypedVector()
|
||||
|
||||
/**
|
||||
* Checks whether the element type is a map
|
||||
*
|
||||
* @return true if a map type
|
||||
*/
|
||||
public val isMap: Boolean get() = type == T_MAP
|
||||
public val isMap: Boolean
|
||||
get() = type == T_MAP
|
||||
|
||||
/**
|
||||
* Checks whether the element type is a blob
|
||||
*
|
||||
* @return true if a blob type
|
||||
*/
|
||||
public val isBlob: Boolean get() = type == T_BLOB
|
||||
public val isBlob: Boolean
|
||||
get() = type == T_BLOB
|
||||
|
||||
/**
|
||||
* Assumes [Reference] as a [Vector] and returns a [Reference] at index [index].
|
||||
*/
|
||||
/** Assumes [Reference] as a [Vector] and returns a [Reference] at index [index]. */
|
||||
public operator fun get(index: Int): Reference = toVector()[index]
|
||||
|
||||
/**
|
||||
* Assumes [Reference] as a [Map] and returns a [Reference] for the value at key [key].
|
||||
*/
|
||||
/** Assumes [Reference] as a [Map] and returns a [Reference] for the value at key [key]. */
|
||||
public operator fun get(key: String): Reference = toMap()[key]
|
||||
|
||||
/**
|
||||
* Returns element as a [Boolean].
|
||||
* If element type is not boolean, it will be casted to integer and compared against 0
|
||||
* Returns element as a [Boolean]. If element type is not boolean, it will be casted to integer
|
||||
* and compared against 0
|
||||
*
|
||||
* @return element as [Boolean]
|
||||
*/
|
||||
public fun toBoolean(): Boolean = if (isBoolean) buffer.getBoolean(end) else toUInt() != 0u
|
||||
|
||||
/**
|
||||
* Returns element as [Byte].
|
||||
* For vector types, it will return size of the vector.
|
||||
* For String type, it will be parsed as integer.
|
||||
* Unsigned elements will become signed (with possible overflow).
|
||||
* Float elements will be casted to [Byte].
|
||||
* Returns element as [Byte]. For vector types, it will return size of the vector. For String
|
||||
* type, it will be parsed as integer. Unsigned elements will become signed (with possible
|
||||
* overflow). Float elements will be casted to [Byte].
|
||||
*
|
||||
* @return [Byte] or 0 if fail to convert element to integer.
|
||||
*/
|
||||
public fun toByte(): Byte = toULong().toByte()
|
||||
|
||||
/**
|
||||
* Returns element as [Short].
|
||||
* For vector types, it will return size of the vector.
|
||||
* For String type, it will type to be parsed as integer.
|
||||
* Unsigned elements will become signed (with possible overflow).
|
||||
* Float elements will be casted to [Short]
|
||||
* Returns element as [Short]. For vector types, it will return size of the vector. For String
|
||||
* type, it will type to be parsed as integer. Unsigned elements will become signed (with possible
|
||||
* overflow). Float elements will be casted to [Short]
|
||||
*
|
||||
* @return [Short] or 0 if fail to convert element to integer.
|
||||
*/
|
||||
public fun toShort(): Short = toULong().toShort()
|
||||
|
||||
/**
|
||||
* Returns element as [Int].
|
||||
* For vector types, it will return size of the vector.
|
||||
* For String type, it will type to be parsed as integer.
|
||||
* Unsigned elements will become signed (with possible overflow).
|
||||
* Float elements will be casted to [Int]
|
||||
* Returns element as [Int]. For vector types, it will return size of the vector. For String type,
|
||||
* it will type to be parsed as integer. Unsigned elements will become signed (with possible
|
||||
* overflow). Float elements will be casted to [Int]
|
||||
*
|
||||
* @return [Int] or 0 if fail to convert element to integer.
|
||||
*/
|
||||
public fun toInt(): Int = toULong().toInt()
|
||||
|
||||
/**
|
||||
* Returns element as [Long].
|
||||
* For vector types, it will return size of the vector
|
||||
* For String type, it will type to be parsed as integer
|
||||
* Unsigned elements will become negative
|
||||
* Float elements will be casted to integer
|
||||
* Returns element as [Long]. For vector types, it will return size of the vector For String type,
|
||||
* it will type to be parsed as integer Unsigned elements will become negative Float elements will
|
||||
* be casted to integer
|
||||
*
|
||||
* @return [Long] integer or 0 if fail to convert element to long.
|
||||
*/
|
||||
public fun toLong(): Long = toULong().toLong()
|
||||
|
||||
/**
|
||||
* Returns element as [UByte].
|
||||
* For vector types, it will return size of the vector.
|
||||
* For String type, it will type to be parsed as integer.
|
||||
* Negative elements will become unsigned counterpart.
|
||||
* Float elements will be casted to [UByte]
|
||||
* Returns element as [UByte]. For vector types, it will return size of the vector. For String
|
||||
* type, it will type to be parsed as integer. Negative elements will become unsigned counterpart.
|
||||
* Float elements will be casted to [UByte]
|
||||
*
|
||||
* @return [UByte] or 0 if fail to convert element to integer.
|
||||
*/
|
||||
public fun toUByte(): UByte = toULong().toUByte()
|
||||
|
||||
/**
|
||||
* Returns element as [UShort].
|
||||
* For vector types, it will return size of the vector.
|
||||
* For String type, it will type to be parsed as integer.
|
||||
* Negative elements will become unsigned counterpart.
|
||||
* Float elements will be casted to [UShort]
|
||||
* Returns element as [UShort]. For vector types, it will return size of the vector. For String
|
||||
* type, it will type to be parsed as integer. Negative elements will become unsigned counterpart.
|
||||
* Float elements will be casted to [UShort]
|
||||
*
|
||||
* @return [UShort] or 0 if fail to convert element to integer.
|
||||
*/
|
||||
public fun toUShort(): UShort = toULong().toUShort()
|
||||
|
||||
/**
|
||||
* Returns element as [UInt].
|
||||
* For vector types, it will return size of the vector.
|
||||
* For String type, it will type to be parsed as integer.
|
||||
* Negative elements will become unsigned counterpart.
|
||||
* Float elements will be casted to [UInt]
|
||||
* Returns element as [UInt]. For vector types, it will return size of the vector. For String
|
||||
* type, it will type to be parsed as integer. Negative elements will become unsigned counterpart.
|
||||
* Float elements will be casted to [UInt]
|
||||
*
|
||||
* @return [UInt] or 0 if fail to convert element to integer.
|
||||
*/
|
||||
public fun toUInt(): UInt = toULong().toUInt()
|
||||
|
||||
/**
|
||||
* Returns element as [ULong] integer.
|
||||
* For vector types, it will return size of the vector
|
||||
* For String type, it will type to be parsed as integer
|
||||
* Negative elements will become unsigned counterpart.
|
||||
* Float elements will be casted to integer
|
||||
* Returns element as [ULong] integer. For vector types, it will return size of the vector For
|
||||
* String type, it will type to be parsed as integer Negative elements will become unsigned
|
||||
* counterpart. Float elements will be casted to integer
|
||||
*
|
||||
* @return [ULong] integer or 0 if fail to convert element to long.
|
||||
*/
|
||||
public fun toULong(): ULong = resolve { pos: Int, width: ByteWidth ->
|
||||
when (type) {
|
||||
T_INDIRECT_INT, T_INDIRECT_UINT, T_INT, T_BOOL, T_UINT -> buffer.readULong(pos, width)
|
||||
T_FLOAT, T_INDIRECT_FLOAT -> buffer.readFloat(pos, width).toULong()
|
||||
T_INDIRECT_INT,
|
||||
T_INDIRECT_UINT,
|
||||
T_INT,
|
||||
T_BOOL,
|
||||
T_UINT -> buffer.readULong(pos, width)
|
||||
T_FLOAT,
|
||||
T_INDIRECT_FLOAT -> buffer.readFloat(pos, width).toULong()
|
||||
T_STRING -> toString().toULong()
|
||||
T_VECTOR -> toVector().size.toULong()
|
||||
else -> 0UL
|
||||
@@ -234,17 +267,18 @@ public class Reference internal constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element as [Float].
|
||||
* For vector types, it will return size of the vector
|
||||
* For String type, it will type to be parsed as [Float]
|
||||
* Float elements will be casted to integer
|
||||
* Returns element as [Float]. For vector types, it will return size of the vector For String
|
||||
* type, it will type to be parsed as [Float] Float elements will be casted to integer
|
||||
*
|
||||
* @return [Float] integer or 0 if fail to convert element to long.
|
||||
*/
|
||||
public fun toFloat(): Float = resolve { pos: Int, width: ByteWidth ->
|
||||
when (type) {
|
||||
T_INDIRECT_FLOAT, T_FLOAT -> buffer.readFloat(pos, width).toFloat()
|
||||
T_INDIRECT_FLOAT,
|
||||
T_FLOAT -> buffer.readFloat(pos, width).toFloat()
|
||||
T_INT -> buffer.readInt(end, parentWidth).toFloat()
|
||||
T_UINT, T_BOOL -> buffer.readUInt(end, parentWidth).toFloat()
|
||||
T_UINT,
|
||||
T_BOOL -> buffer.readUInt(end, parentWidth).toFloat()
|
||||
T_INDIRECT_INT -> buffer.readInt(pos, width).toFloat()
|
||||
T_INDIRECT_UINT -> buffer.readUInt(pos, width).toFloat()
|
||||
T_NULL -> 0.0f
|
||||
@@ -255,16 +289,18 @@ public class Reference internal constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element as [Double].
|
||||
* For vector types, it will return size of the vector
|
||||
* For String type, it will type to be parsed as [Double]
|
||||
* Returns element as [Double]. For vector types, it will return size of the vector For String
|
||||
* type, it will type to be parsed as [Double]
|
||||
*
|
||||
* @return [Float] integer or 0 if fail to convert element to long.
|
||||
*/
|
||||
public fun toDouble(): Double = resolve { pos: Int, width: ByteWidth ->
|
||||
when (type) {
|
||||
T_INDIRECT_FLOAT, T_FLOAT -> buffer.readFloat(pos, width)
|
||||
T_INDIRECT_FLOAT,
|
||||
T_FLOAT -> buffer.readFloat(pos, width)
|
||||
T_INT -> buffer.readInt(pos, width).toDouble()
|
||||
T_UINT, T_BOOL -> buffer.readUInt(pos, width).toDouble()
|
||||
T_UINT,
|
||||
T_BOOL -> buffer.readUInt(pos, width).toDouble()
|
||||
T_INDIRECT_INT -> buffer.readInt(pos, width).toDouble()
|
||||
T_INDIRECT_UINT -> buffer.readUInt(pos, width).toDouble()
|
||||
T_NULL -> 0.0
|
||||
@@ -274,40 +310,48 @@ public class Reference internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element as [Key] or invalid key.
|
||||
*/
|
||||
public fun toKey(): Key = when (type) {
|
||||
T_KEY -> Key(buffer, buffer.indirect(end, parentWidth))
|
||||
else -> nullKey()
|
||||
}
|
||||
/** Returns element as [Key] or invalid key. */
|
||||
public fun toKey(): Key =
|
||||
when (type) {
|
||||
T_KEY -> Key(buffer, buffer.indirect(end, parentWidth))
|
||||
else -> nullKey()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element as a [String]
|
||||
*
|
||||
* @return element as [String] or empty [String] if fail
|
||||
*/
|
||||
override fun toString(): String = when (type) {
|
||||
T_STRING -> {
|
||||
val start = buffer.indirect(end, parentWidth)
|
||||
val size = buffer.readULong(start - byteWidth, byteWidth).toInt()
|
||||
buffer.getString(start, size)
|
||||
override fun toString(): String =
|
||||
when (type) {
|
||||
T_STRING -> {
|
||||
val start = buffer.indirect(end, parentWidth)
|
||||
val size = buffer.readULong(start - byteWidth, byteWidth).toInt()
|
||||
buffer.getString(start, size)
|
||||
}
|
||||
T_KEY -> buffer.getKeyString(buffer.indirect(end, parentWidth))
|
||||
T_MAP -> "{ ${toMap().entries.joinToString(", ") { "${it.key}: ${it.value}"}} }"
|
||||
T_VECTOR,
|
||||
T_VECTOR_BOOL,
|
||||
T_VECTOR_FLOAT,
|
||||
T_VECTOR_INT,
|
||||
T_VECTOR_UINT,
|
||||
T_VECTOR_KEY,
|
||||
T_VECTOR_STRING_DEPRECATED -> "[ ${toVector().joinToString(", ") { it.toString() }} ]"
|
||||
T_INT -> toLong().toString()
|
||||
T_UINT -> toULong().toString()
|
||||
T_FLOAT -> toDouble().toString()
|
||||
else -> "${type.typeToString()}(end=$end)"
|
||||
}
|
||||
T_KEY -> buffer.getKeyString(buffer.indirect(end, parentWidth))
|
||||
T_MAP -> "{ ${toMap().entries.joinToString(", ") { "${it.key}: ${it.value}"}} }"
|
||||
T_VECTOR, T_VECTOR_BOOL, T_VECTOR_FLOAT, T_VECTOR_INT,
|
||||
T_VECTOR_UINT, T_VECTOR_KEY, T_VECTOR_STRING_DEPRECATED ->
|
||||
"[ ${toVector().joinToString(", ") { it.toString() }} ]"
|
||||
T_INT -> toLong().toString()
|
||||
T_UINT -> toULong().toString()
|
||||
T_FLOAT -> toDouble().toString()
|
||||
else -> "${type.typeToString()}(end=$end)"
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element as a [ByteArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [ByteArray] or empty [ByteArray] if fail.
|
||||
*/
|
||||
public fun toByteArray(): ByteArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_INT -> ByteArray(vec.size) { vec.getInt(it).toByte() }
|
||||
T_VECTOR_UINT -> ByteArray(vec.size) { vec.getUInt(it).toByte() }
|
||||
@@ -319,10 +363,12 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [ByteArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [ByteArray] or empty [ByteArray] if fail.
|
||||
*/
|
||||
public fun toShortArray(): ShortArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_INT -> ShortArray(vec.size) { vec.getInt(it).toShort() }
|
||||
T_VECTOR_UINT -> ShortArray(vec.size) { vec.getUInt(it).toShort() }
|
||||
@@ -334,10 +380,12 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [IntArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [IntArray] or empty [IntArray] if fail.
|
||||
*/
|
||||
public fun toIntArray(): IntArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_INT -> IntArray(vec.size) { vec.getInt(it).toInt() }
|
||||
T_VECTOR_UINT -> IntArray(vec.size) { vec.getUInt(it).toInt() }
|
||||
@@ -349,10 +397,12 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [LongArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [LongArray] or empty [LongArray] if fail.
|
||||
*/
|
||||
public fun toLongArray(): LongArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_INT -> LongArray(vec.size) { vec.getInt(it) }
|
||||
T_VECTOR_UINT -> LongArray(vec.size) { vec.getInt(it) }
|
||||
@@ -364,10 +414,12 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [UByteArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [UByteArray] or empty [UByteArray] if fail.
|
||||
*/
|
||||
public fun toUByteArray(): UByteArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_INT -> UByteArray(vec.size) { vec.getInt(it).toUByte() }
|
||||
T_VECTOR_UINT -> UByteArray(vec.size) { vec.getUInt(it).toUByte() }
|
||||
@@ -379,10 +431,12 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [UIntArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [UIntArray] or empty [UIntArray] if fail.
|
||||
*/
|
||||
public fun toUShortArray(): UShortArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_INT -> UShortArray(vec.size) { vec.getInt(it).toUShort() }
|
||||
T_VECTOR_UINT -> UShortArray(vec.size) { vec.getUInt(it).toUShort() }
|
||||
@@ -394,10 +448,12 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [UIntArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [UIntArray] or empty [UIntArray] if fail.
|
||||
*/
|
||||
public fun toUIntArray(): UIntArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_INT -> UIntArray(vec.size) { vec.getInt(it).toUInt() }
|
||||
T_VECTOR_UINT -> UIntArray(vec.size) { vec.getUInt(it).toUInt() }
|
||||
@@ -409,10 +465,12 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [ULongArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [ULongArray] or empty [ULongArray] if fail.
|
||||
*/
|
||||
public fun toULongArray(): ULongArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_INT -> ULongArray(vec.size) { vec.getUInt(it) }
|
||||
T_VECTOR_UINT -> ULongArray(vec.size) { vec.getUInt(it) }
|
||||
@@ -424,10 +482,12 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [FloatArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [FloatArray] or empty [FloatArray] if fail.
|
||||
*/
|
||||
public fun toFloatArray(): FloatArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_FLOAT -> FloatArray(vec.size) { vec.getFloat(it).toFloat() }
|
||||
T_VECTOR_INT -> FloatArray(vec.size) { vec.getInt(it).toFloat() }
|
||||
@@ -439,10 +499,12 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [DoubleArray], converting scalar types when possible.
|
||||
*
|
||||
* @return element as [DoubleArray] or empty [DoubleArray] if fail.
|
||||
*/
|
||||
public fun toDoubleArray(): DoubleArray {
|
||||
val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
val vec =
|
||||
TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
return when (type) {
|
||||
T_VECTOR_FLOAT -> DoubleArray(vec.size) { vec[it].toDouble() }
|
||||
T_VECTOR_INT -> DoubleArray(vec.size) { vec[it].toDouble() }
|
||||
@@ -454,35 +516,46 @@ public class Reference internal constructor(
|
||||
|
||||
/**
|
||||
* Returns element as a [Vector]
|
||||
*
|
||||
* @return element as [Vector] or empty [Vector] if fail
|
||||
*/
|
||||
public fun toVector(): Vector {
|
||||
return when {
|
||||
isVector -> Vector(buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
isTypedVector -> TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
isTypedVector ->
|
||||
TypedVector(
|
||||
type.toElementTypedVector(),
|
||||
buffer,
|
||||
buffer.indirect(end, parentWidth),
|
||||
byteWidth,
|
||||
)
|
||||
else -> emptyVector()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element as a [Blob]
|
||||
*
|
||||
* @return element as [Blob] or empty [Blob] if fail
|
||||
*/
|
||||
public fun toBlob(): Blob {
|
||||
return when (type) {
|
||||
T_BLOB, T_STRING -> Blob(buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
T_BLOB,
|
||||
T_STRING -> Blob(buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
else -> emptyBlob()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element as a [Map].
|
||||
*
|
||||
* @return element as [Map] or empty [Map] if fail
|
||||
*/
|
||||
public fun toMap(): Map = when (type) {
|
||||
T_MAP -> Map(buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
else -> emptyMap()
|
||||
}
|
||||
public fun toMap(): Map =
|
||||
when (type) {
|
||||
T_MAP -> Map(buffer, buffer.indirect(end, parentWidth), byteWidth)
|
||||
else -> emptyMap()
|
||||
}
|
||||
|
||||
private inline fun <T> resolve(crossinline block: (pos: Int, width: ByteWidth) -> T): T {
|
||||
return if (type.isIndirectScalar()) {
|
||||
@@ -496,12 +569,14 @@ public class Reference internal constructor(
|
||||
if (this === other) return true
|
||||
if (other == null || this::class != other::class) return false
|
||||
other as Reference
|
||||
if (buffer != other.buffer ||
|
||||
end != other.end ||
|
||||
parentWidth != other.parentWidth ||
|
||||
byteWidth != other.byteWidth ||
|
||||
type != other.type
|
||||
) return false
|
||||
if (
|
||||
buffer != other.buffer ||
|
||||
end != other.end ||
|
||||
parentWidth != other.parentWidth ||
|
||||
byteWidth != other.byteWidth ||
|
||||
type != other.type
|
||||
)
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -518,30 +593,28 @@ public class Reference internal constructor(
|
||||
/**
|
||||
* Represents any element that has a size property to it, like: [Map], [Vector] and [TypedVector].
|
||||
*/
|
||||
public open class Sized internal constructor(
|
||||
public open class Sized
|
||||
internal constructor(
|
||||
public val buffer: ReadBuffer,
|
||||
public val end: Int,
|
||||
public val byteWidth: ByteWidth
|
||||
public val byteWidth: ByteWidth,
|
||||
) {
|
||||
public open val size: Int = buffer.readSize(end, byteWidth)
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent an array of bytes in the buffer.
|
||||
*/
|
||||
public open class Blob internal constructor(
|
||||
buffer: ReadBuffer,
|
||||
end: Int,
|
||||
byteWidth: ByteWidth
|
||||
) : Sized(buffer, end, byteWidth) {
|
||||
/** Represent an array of bytes in the buffer. */
|
||||
public open class Blob internal constructor(buffer: ReadBuffer, end: Int, byteWidth: ByteWidth) :
|
||||
Sized(buffer, end, byteWidth) {
|
||||
/**
|
||||
* Return [Blob] as [ReadBuffer]
|
||||
*
|
||||
* @return blob as [ReadBuffer]
|
||||
*/
|
||||
public fun data(): ReadBuffer = buffer.slice(end, size)
|
||||
|
||||
/**
|
||||
* Copy [Blob] into a [ByteArray]
|
||||
*
|
||||
* @return A [ByteArray] containing the blob data.
|
||||
*/
|
||||
public fun toByteArray(): ByteArray {
|
||||
@@ -554,6 +627,7 @@ public open class Blob internal constructor(
|
||||
|
||||
/**
|
||||
* Return individual byte at a given position
|
||||
*
|
||||
* @param pos position of the byte to be read
|
||||
*/
|
||||
public operator fun get(pos: Int): Byte {
|
||||
@@ -564,18 +638,13 @@ public open class Blob internal constructor(
|
||||
override fun toString(): String = buffer.getString(end, size)
|
||||
}
|
||||
|
||||
/**
|
||||
* [Vector] represents an array of elements in the buffer. The element can be of any type.
|
||||
*/
|
||||
public open class Vector internal constructor(
|
||||
buffer: ReadBuffer,
|
||||
end: Int,
|
||||
byteWidth: ByteWidth
|
||||
) : Collection<Reference>,
|
||||
Sized(buffer, end, byteWidth) {
|
||||
/** [Vector] represents an array of elements in the buffer. The element can be of any type. */
|
||||
public open class Vector internal constructor(buffer: ReadBuffer, end: Int, byteWidth: ByteWidth) :
|
||||
Collection<Reference>, Sized(buffer, end, byteWidth) {
|
||||
|
||||
/**
|
||||
* Returns a [Reference] from the [Vector] at position [index]. Returns a null reference
|
||||
*
|
||||
* @param index position in the vector.
|
||||
* @return [Reference] for a key or a null [Reference] if not found.
|
||||
*/
|
||||
@@ -597,25 +666,27 @@ public open class Vector internal constructor(
|
||||
|
||||
override fun isEmpty(): Boolean = size == 0
|
||||
|
||||
override fun iterator(): Iterator<Reference> = object : Iterator<Reference> {
|
||||
var position = 0
|
||||
override fun hasNext(): Boolean = position != size
|
||||
override fun next(): Reference = get(position++)
|
||||
}
|
||||
override fun iterator(): Iterator<Reference> =
|
||||
object : Iterator<Reference> {
|
||||
var position = 0
|
||||
|
||||
override fun hasNext(): Boolean = position != size
|
||||
|
||||
override fun next(): Reference = get(position++)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [TypedVector] represents an array of scalar elements of the same type in the buffer.
|
||||
*/
|
||||
/** [TypedVector] represents an array of scalar elements of the same type in the buffer. */
|
||||
public open class TypedVector(
|
||||
private val elementType: FlexBufferType,
|
||||
buffer: ReadBuffer,
|
||||
end: Int,
|
||||
byteWidth: ByteWidth
|
||||
byteWidth: ByteWidth,
|
||||
) : Vector(buffer, end, byteWidth) {
|
||||
|
||||
/**
|
||||
* Returns a [Reference] from the [TypedVector] at position [index]. Returns a null reference
|
||||
*
|
||||
* @param index position in the vector.
|
||||
* @return [Reference] for a key or a null [Reference] if not found.
|
||||
*/
|
||||
@@ -630,28 +701,24 @@ public open class TypedVector(
|
||||
return block(childPos, byteWidth)
|
||||
}
|
||||
|
||||
internal fun getBoolean(index: Int): Boolean = resolveAt(index) {
|
||||
pos: Int, _: ByteWidth -> buffer.getBoolean(pos)
|
||||
}
|
||||
internal fun getInt(index: Int): Long = resolveAt(index) {
|
||||
pos: Int, width: ByteWidth -> buffer.readLong(pos, width)
|
||||
}
|
||||
internal fun getUInt(index: Int): ULong = resolveAt(index) {
|
||||
pos: Int, width: ByteWidth -> buffer.readULong(pos, width)
|
||||
}
|
||||
internal fun getFloat(index: Int): Double = resolveAt(index) {
|
||||
pos: Int, width: ByteWidth -> buffer.readFloat(pos, width)
|
||||
}
|
||||
internal fun getBoolean(index: Int): Boolean =
|
||||
resolveAt(index) { pos: Int, _: ByteWidth -> buffer.getBoolean(pos) }
|
||||
|
||||
internal fun getInt(index: Int): Long =
|
||||
resolveAt(index) { pos: Int, width: ByteWidth -> buffer.readLong(pos, width) }
|
||||
|
||||
internal fun getUInt(index: Int): ULong =
|
||||
resolveAt(index) { pos: Int, width: ByteWidth -> buffer.readULong(pos, width) }
|
||||
|
||||
internal fun getFloat(index: Int): Double =
|
||||
resolveAt(index) { pos: Int, width: ByteWidth -> buffer.readFloat(pos, width) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a key element in the buffer. Keys are
|
||||
* used to reference objects in a [Map]
|
||||
*/
|
||||
/** Represents a key element in the buffer. Keys are used to reference objects in a [Map] */
|
||||
public data class Key(
|
||||
public val buffer: ReadBuffer,
|
||||
public val start: Int,
|
||||
public val end: Int = buffer.findFirst(ZeroByte, start)
|
||||
public val end: Int = buffer.findFirst(ZeroByte, start),
|
||||
) {
|
||||
|
||||
val sizeInBytes: Int = end - start
|
||||
@@ -704,25 +771,21 @@ public data class Key(
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = if (sizeInBytes > 0) buffer.getString(start, sizeInBytes) else ""
|
||||
override fun toString(): String =
|
||||
if (sizeInBytes > 0) buffer.getString(start, sizeInBytes) else ""
|
||||
|
||||
/**
|
||||
* Checks whether Key is invalid or not.
|
||||
*/
|
||||
/** Checks whether Key is invalid or not. */
|
||||
public fun isInvalid(): Boolean = sizeInBytes <= 0
|
||||
}
|
||||
|
||||
/**
|
||||
* A Map class that provide support to access Key-Value data from Flexbuffers.
|
||||
*/
|
||||
public class Map
|
||||
internal constructor(buffer: ReadBuffer, end: Int, byteWidth: ByteWidth):
|
||||
Sized(buffer, end, byteWidth),
|
||||
kotlin.collections.Map<Key, Reference> {
|
||||
/** A Map class that provide support to access Key-Value data from Flexbuffers. */
|
||||
public class Map internal constructor(buffer: ReadBuffer, end: Int, byteWidth: ByteWidth) :
|
||||
Sized(buffer, end, byteWidth), kotlin.collections.Map<Key, Reference> {
|
||||
|
||||
// used for accessing the key vector elements
|
||||
private var keyVectorEnd: Int
|
||||
private var keyVectorByteWidth: ByteWidth
|
||||
|
||||
init {
|
||||
val keysOffset = end - (3 * byteWidth) // 3 is number of prefixed fields
|
||||
keyVectorEnd = buffer.indirect(keysOffset, byteWidth)
|
||||
@@ -731,6 +794,7 @@ public class Map
|
||||
|
||||
/**
|
||||
* Returns a [Reference] from the [Map] at position [index]. Returns a null reference
|
||||
*
|
||||
* @param index position in the map
|
||||
* @return [Reference] for a key or a null [Reference] if not found.
|
||||
*/
|
||||
@@ -744,6 +808,7 @@ public class Map
|
||||
|
||||
/**
|
||||
* Returns a [Reference] from the [Map] for a given [String] [key].
|
||||
*
|
||||
* @param key access key to element on map
|
||||
* @return [Reference] for a key or a null [Reference] if not found.
|
||||
*/
|
||||
@@ -756,6 +821,7 @@ public class Map
|
||||
|
||||
/**
|
||||
* Returns a [Reference] from the [Map] for a given [Key] [key].
|
||||
*
|
||||
* @param key access key to element on map
|
||||
* @return [Reference] for a key or a null [Reference] if not found.
|
||||
*/
|
||||
@@ -768,6 +834,7 @@ public class Map
|
||||
|
||||
/**
|
||||
* Checks whether the map contains a [key].
|
||||
*
|
||||
* @param key [String]
|
||||
* @return true if key is found in the map, otherwise false.
|
||||
*/
|
||||
@@ -775,6 +842,7 @@ public class Map
|
||||
|
||||
/**
|
||||
* Returns a [Key] for a given position [index] in the [Map].
|
||||
*
|
||||
* @param index of the key in the map
|
||||
* @return a Key for the given index. Out of bounds indexes returns invalid keys.
|
||||
*/
|
||||
@@ -785,6 +853,7 @@ public class Map
|
||||
|
||||
/**
|
||||
* Returns a [Key] as [String] for a given position [index] in the [Map].
|
||||
*
|
||||
* @param index of the key in the map
|
||||
* @return a Key for the given index. Out of bounds indexes returns empty string.
|
||||
*/
|
||||
@@ -815,6 +884,7 @@ public class Map
|
||||
|
||||
/**
|
||||
* Returns a [Vector] for accessing all values in the [Map].
|
||||
*
|
||||
* @return [Vector] of values.
|
||||
*/
|
||||
override val values: Collection<Reference>
|
||||
@@ -822,8 +892,7 @@ public class Map
|
||||
|
||||
override fun containsKey(key: Key): Boolean {
|
||||
for (i in 0 until size) {
|
||||
if (key == keyAt(i))
|
||||
return true
|
||||
if (key == keyAt(i)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -833,7 +902,10 @@ public class Map
|
||||
override fun isEmpty(): Boolean = size == 0
|
||||
|
||||
// Performs a binary search on a key vector and return index of the key in key vector
|
||||
private fun binarySearch(searchedKey: String) = binarySearch { compareCharSequence(it, searchedKey) }
|
||||
private fun binarySearch(searchedKey: String) = binarySearch {
|
||||
compareCharSequence(it, searchedKey)
|
||||
}
|
||||
|
||||
// Performs a binary search on a key vector and return index of the key in key vector
|
||||
private fun binarySearch(key: Key): Int = binarySearch { compareKeys(it, key.start) }
|
||||
|
||||
@@ -891,8 +963,7 @@ public class Map
|
||||
++bufferPos
|
||||
++otherPos
|
||||
}
|
||||
if (bufferPos < limit)
|
||||
return 0
|
||||
if (bufferPos < limit) return 0
|
||||
|
||||
val comparisonBuffer = ByteArray(4)
|
||||
while (bufferPos < limit) {
|
||||
|
||||
@@ -20,11 +20,13 @@ package com.google.flatbuffers.kotlin
|
||||
@ExperimentalUnsignedTypes
|
||||
public class FlexBuffersBuilder(
|
||||
public val buffer: ReadWriteBuffer,
|
||||
private val shareFlag: Int = SHARE_KEYS
|
||||
private val shareFlag: Int = SHARE_KEYS,
|
||||
) {
|
||||
|
||||
public constructor(initialCapacity: Int = 1024, shareFlag: Int = SHARE_KEYS) :
|
||||
this(ArrayReadWriteBuffer(initialCapacity), shareFlag)
|
||||
public constructor(
|
||||
initialCapacity: Int = 1024,
|
||||
shareFlag: Int = SHARE_KEYS,
|
||||
) : this(ArrayReadWriteBuffer(initialCapacity), shareFlag)
|
||||
|
||||
private val stringValuePool: HashMap<String, Value> = HashMap()
|
||||
private val stringKeyPool: HashMap<String, Int> = HashMap()
|
||||
@@ -32,8 +34,8 @@ public class FlexBuffersBuilder(
|
||||
private var finished: Boolean = false
|
||||
|
||||
/**
|
||||
* Reset the FlexBuffersBuilder by purging all data that it holds. Buffer might
|
||||
* keep its capacity after a reset.
|
||||
* Reset the FlexBuffersBuilder by purging all data that it holds. Buffer might keep its capacity
|
||||
* after a reset.
|
||||
*/
|
||||
public fun clear() {
|
||||
buffer.clear()
|
||||
@@ -44,9 +46,9 @@ 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
|
||||
* 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 [ReadBuffer] containing the FlexBuffer message
|
||||
*/
|
||||
public fun finish(): ReadBuffer {
|
||||
@@ -69,45 +71,46 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Insert a single [Boolean] into the buffer
|
||||
*
|
||||
* @param value true or false
|
||||
*/
|
||||
public fun put(value: Boolean): Unit = run { this[null] = value }
|
||||
|
||||
/**
|
||||
* Insert a null reference into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a null reference into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public fun putNull(key: String? = null): Unit =
|
||||
run { stack.add(Value(T_NULL, putKey(key), W_8, 0UL)) }
|
||||
public fun putNull(key: String? = null): Unit = run {
|
||||
stack.add(Value(T_NULL, putKey(key), W_8, 0UL))
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single [Boolean] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [Boolean] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public operator fun set(key: String? = null, value: Boolean): Unit =
|
||||
run { stack.add(Value(T_BOOL, putKey(key), W_8, if (value) 1UL else 0UL)) }
|
||||
public operator fun set(key: String? = null, value: Boolean): Unit = run {
|
||||
stack.add(Value(T_BOOL, putKey(key), W_8, if (value) 1UL else 0UL))
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single [Byte] into the buffer
|
||||
*/
|
||||
/** Insert a single [Byte] into the buffer */
|
||||
public fun put(value: Byte): Unit = set(null, value.toLong())
|
||||
|
||||
/**
|
||||
* Insert a single [Byte] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [Byte] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public operator fun set(key: String? = null, value: Byte): Unit = set(key, value.toLong())
|
||||
|
||||
/**
|
||||
* Insert a single [Short] into the buffer.
|
||||
*/
|
||||
/** Insert a single [Short] into the buffer. */
|
||||
public fun put(value: Short): Unit = set(null, value.toLong())
|
||||
|
||||
/**
|
||||
* Insert a single [Short] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [Short] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public inline operator fun set(key: String? = null, value: Short): Unit = set(key, value.toLong())
|
||||
|
||||
/**
|
||||
* Insert a single [Int] into the buffer.
|
||||
*/
|
||||
/** Insert a single [Int] into the buffer. */
|
||||
public fun put(value: Int): Unit = set(null, value.toLong())
|
||||
|
||||
/**
|
||||
@@ -115,110 +118,113 @@ public class FlexBuffersBuilder(
|
||||
*/
|
||||
public inline operator fun set(key: String? = null, value: Int): Unit = set(key, value.toLong())
|
||||
|
||||
/**
|
||||
* Insert a single [Long] into the buffer.
|
||||
*/
|
||||
/** Insert a single [Long] into the buffer. */
|
||||
public fun put(value: Long): Unit = set(null, value)
|
||||
|
||||
/**
|
||||
* Insert a single [Long] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [Long] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public operator fun set(key: String? = null, value: Long): Unit =
|
||||
run { stack.add(Value(T_INT, putKey(key), value.toULong().widthInUBits(), value.toULong())) }
|
||||
public operator fun set(key: String? = null, value: Long): Unit = run {
|
||||
stack.add(Value(T_INT, putKey(key), value.toULong().widthInUBits(), value.toULong()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single [UByte] into the buffer
|
||||
*/
|
||||
/** Insert a single [UByte] into the buffer */
|
||||
public fun put(value: UByte): Unit = set(null, value.toULong())
|
||||
|
||||
/**
|
||||
* Insert a single [UByte] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [UByte] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public inline operator fun set(key: String? = null, value: UByte): Unit = set(key, value.toULong())
|
||||
public inline operator fun set(key: String? = null, value: UByte): Unit =
|
||||
set(key, value.toULong())
|
||||
|
||||
/**
|
||||
* Insert a single [UShort] into the buffer.
|
||||
*/
|
||||
/** Insert a single [UShort] into the buffer. */
|
||||
public fun put(value: UShort): Unit = set(null, value.toULong())
|
||||
|
||||
/**
|
||||
* Insert a single [UShort] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [UShort] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
private inline operator fun set(key: String? = null, value: UShort): Unit = set(key, value.toULong())
|
||||
private inline operator fun set(key: String? = null, value: UShort): Unit =
|
||||
set(key, value.toULong())
|
||||
|
||||
/**
|
||||
* Insert a single [UInt] into the buffer.
|
||||
*/
|
||||
/** Insert a single [UInt] into the buffer. */
|
||||
public fun put(value: UInt): Unit = set(null, value.toULong())
|
||||
|
||||
/**
|
||||
* Insert a single [UInt] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [UInt] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
private inline operator fun set(key: String? = null, value: UInt): Unit = set(key, value.toULong())
|
||||
private inline operator fun set(key: String? = null, value: UInt): Unit =
|
||||
set(key, value.toULong())
|
||||
|
||||
/**
|
||||
* Insert a single [ULong] into the buffer.
|
||||
*/
|
||||
/** Insert a single [ULong] into the buffer. */
|
||||
public fun put(value: ULong): Unit = set(null, value)
|
||||
|
||||
/**
|
||||
* Insert a single [ULong] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [ULong] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public operator fun set(key: String? = null, value: ULong): Unit =
|
||||
run { stack.add(Value(T_UINT, putKey(key), value.widthInUBits(), value)) }
|
||||
public operator fun set(key: String? = null, value: ULong): Unit = run {
|
||||
stack.add(Value(T_UINT, putKey(key), value.widthInUBits(), value))
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single [Float] into the buffer.
|
||||
*/
|
||||
/** Insert a single [Float] into the buffer. */
|
||||
public fun put(value: Float): Unit = run { this[null] = value }
|
||||
|
||||
/**
|
||||
* Insert a single [Float] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [Float] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public operator fun set(key: String? = null, value: Float): Unit =
|
||||
run { stack.add(Value(T_FLOAT, putKey(key), W_32, dValue = value.toDouble())) }
|
||||
public operator fun set(key: String? = null, value: Float): Unit = run {
|
||||
stack.add(Value(T_FLOAT, putKey(key), W_32, dValue = value.toDouble()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single [Double] into the buffer.
|
||||
*/
|
||||
/** Insert a single [Double] into the buffer. */
|
||||
public fun put(value: Double): Unit = run { this[null] = value }
|
||||
|
||||
/**
|
||||
* Insert a single [Double] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [Double] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public operator fun set(key: String? = null, value: Double): Unit =
|
||||
run { stack.add(Value(T_FLOAT, putKey(key), W_64, dValue = value)) }
|
||||
public operator fun set(key: String? = null, value: Double): Unit = run {
|
||||
stack.add(Value(T_FLOAT, putKey(key), W_64, dValue = value))
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single [String] into the buffer.
|
||||
*/
|
||||
/** Insert a single [String] into the buffer. */
|
||||
public fun put(value: String): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Insert a single [String] into the buffer. A key must be present if element is inserted into a map.
|
||||
* Insert a single [String] into the buffer. A key must be present if element is inserted into a
|
||||
* map.
|
||||
*/
|
||||
public operator fun set(key: String? = null, value: String): Int {
|
||||
val iKey = putKey(key)
|
||||
val holder = if (shareFlag and SHARE_STRINGS != 0) {
|
||||
stringValuePool.getOrPut(value) {
|
||||
writeString(iKey, value).also { stringValuePool[value] = it }
|
||||
}.copy(key = iKey)
|
||||
} else {
|
||||
writeString(iKey, value)
|
||||
}
|
||||
val holder =
|
||||
if (shareFlag and SHARE_STRINGS != 0) {
|
||||
stringValuePool
|
||||
.getOrPut(value) { writeString(iKey, value).also { stringValuePool[value] = it } }
|
||||
.copy(key = iKey)
|
||||
} else {
|
||||
writeString(iKey, value)
|
||||
}
|
||||
stack.add(holder)
|
||||
return holder.iValue.toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a [ByteArray] into the message as a [Blob].
|
||||
*
|
||||
* @param value byte array
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: ByteArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [ByteArray] into the message as a [Blob]. A key must be present if element is inserted into a map.
|
||||
* Adds a [ByteArray] into the message as a [Blob]. A key must be present if element is inserted
|
||||
* into a map.
|
||||
*
|
||||
* @param value byte array
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -230,14 +236,16 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Adds a [IntArray] into the message as a typed vector of fixed size.
|
||||
*
|
||||
* @param value [IntArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: IntArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [IntArray] into the message as a typed vector of fixed size.
|
||||
* A key must be present if element is inserted into a map.
|
||||
* Adds a [IntArray] into the message as a typed vector of fixed size. A key must be present if
|
||||
* element is inserted into a map.
|
||||
*
|
||||
* @param value [IntArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -246,14 +254,16 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Adds a [ShortArray] into the message as a typed vector of fixed size.
|
||||
*
|
||||
* @param value [ShortArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: ShortArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [ShortArray] into the message as a typed vector of fixed size.
|
||||
* A key must be present if element is inserted into a map.
|
||||
* Adds a [ShortArray] into the message as a typed vector of fixed size. A key must be present if
|
||||
* element is inserted into a map.
|
||||
*
|
||||
* @param value [ShortArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -262,14 +272,16 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Adds a [LongArray] into the message as a typed vector of fixed size.
|
||||
*
|
||||
* @param value [LongArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: LongArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [LongArray] into the message as a typed vector of fixed size.
|
||||
* A key must be present if element is inserted into a map.
|
||||
* Adds a [LongArray] into the message as a typed vector of fixed size. A key must be present if
|
||||
* element is inserted into a map.
|
||||
*
|
||||
* @param value [LongArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -278,14 +290,16 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Adds a [FloatArray] into the message as a typed vector of fixed size.
|
||||
*
|
||||
* @param value [FloatArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: FloatArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [FloatArray] into the message as a typed vector of fixed size.
|
||||
* A key must be present if element is inserted into a map.
|
||||
* Adds a [FloatArray] into the message as a typed vector of fixed size. A key must be present if
|
||||
* element is inserted into a map.
|
||||
*
|
||||
* @param value [FloatArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -294,14 +308,16 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Adds a [DoubleArray] into the message as a typed vector of fixed size.
|
||||
*
|
||||
* @param value [DoubleArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: DoubleArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [DoubleArray] into the message as a typed vector of fixed size.
|
||||
* A key must be present if element is inserted into a map.
|
||||
* Adds a [DoubleArray] into the message as a typed vector of fixed size. A key must be present if
|
||||
* element is inserted into a map.
|
||||
*
|
||||
* @param value [DoubleArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -310,14 +326,16 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Adds a [UByteArray] into the message as a typed vector of fixed size.
|
||||
*
|
||||
* @param value [UByteArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: UByteArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [UByteArray] into the message as a typed vector of fixed size.
|
||||
* A key must be present if element is inserted into a map.
|
||||
* Adds a [UByteArray] into the message as a typed vector of fixed size. A key must be present if
|
||||
* element is inserted into a map.
|
||||
*
|
||||
* @param value [UByteArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -326,14 +344,16 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Adds a [UShortArray] into the message as a typed vector of fixed size.
|
||||
*
|
||||
* @param value [UShortArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: UShortArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [UShortArray] into the message as a typed vector of fixed size.
|
||||
* A key must be present if element is inserted into a map.
|
||||
* Adds a [UShortArray] into the message as a typed vector of fixed size. A key must be present if
|
||||
* element is inserted into a map.
|
||||
*
|
||||
* @param value [UShortArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -342,14 +362,16 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Adds a [UIntArray] into the message as a typed vector of fixed size.
|
||||
*
|
||||
* @param value [UIntArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: UIntArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [UIntArray] into the message as a typed vector of fixed size.
|
||||
* A key must be present if element is inserted into a map.
|
||||
* Adds a [UIntArray] into the message as a typed vector of fixed size. A key must be present if
|
||||
* element is inserted into a map.
|
||||
*
|
||||
* @param value [UIntArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -358,14 +380,16 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Adds a [ULongArray] into the message as a typed vector of fixed size.
|
||||
*
|
||||
* @param value [ULongArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public fun put(value: ULongArray): Int = set(null, value)
|
||||
|
||||
/**
|
||||
* Adds a [ULongArray] into the message as a typed vector of fixed size.
|
||||
* A key must be present if element is inserted into a map.
|
||||
* Adds a [ULongArray] into the message as a typed vector of fixed size. A key must be present if
|
||||
* element is inserted into a map.
|
||||
*
|
||||
* @param value [ULongArray]
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -374,6 +398,7 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Creates a new vector will all elements inserted in [block].
|
||||
*
|
||||
* @param block where elements will be inserted
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -385,6 +410,7 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Creates a new typed vector will all elements inserted in [block].
|
||||
*
|
||||
* @param block where elements will be inserted
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
@@ -394,40 +420,44 @@ public class FlexBuffersBuilder(
|
||||
return endTypedVector(pos)
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return position for starting a new vector.
|
||||
*/
|
||||
/** Helper function to return position for starting a new vector. */
|
||||
public fun startVector(): Int = stack.size
|
||||
|
||||
/**
|
||||
* Finishes a vector element. The initial position of the vector must be passed
|
||||
*
|
||||
* @param position position at the start of the vector
|
||||
*/
|
||||
public fun endVector(position: Int): Int = endVector(null, position)
|
||||
|
||||
/**
|
||||
* Finishes a vector element. The initial position of the vector must be passed
|
||||
*
|
||||
* @param position position at the start of the vector
|
||||
*/
|
||||
public fun endVector(key: String? = null, position: Int): Int =
|
||||
endAnyVector(position) { createVector(putKey(key), position, stack.size - position) }
|
||||
|
||||
/**
|
||||
* Finishes a typed vector element. The initial position of the vector must be passed
|
||||
*
|
||||
* @param position position at the start of the vector
|
||||
*/
|
||||
public fun endTypedVector(position: Int): Int = endTypedVector(position, null)
|
||||
|
||||
/**
|
||||
* Helper function to return position for starting a new vector.
|
||||
*/
|
||||
/** Helper function to return position for starting a new vector. */
|
||||
public fun startMap(): Int = stack.size
|
||||
|
||||
/**
|
||||
* Creates a new map will all elements inserted in [block].
|
||||
*
|
||||
* @param block where elements will be inserted
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public inline fun putMap(key: String? = null, crossinline block: FlexBuffersBuilder.() -> Unit): Int {
|
||||
public inline fun putMap(
|
||||
key: String? = null,
|
||||
crossinline block: FlexBuffersBuilder.() -> Unit,
|
||||
): Int {
|
||||
val pos = startMap()
|
||||
this.block()
|
||||
return endMap(pos, key)
|
||||
@@ -435,7 +465,8 @@ public class FlexBuffersBuilder(
|
||||
|
||||
/**
|
||||
* Finishes a map, but writing the information in the buffer
|
||||
* @param key key used to store element in map
|
||||
*
|
||||
* @param key key used to store element in map
|
||||
* @return Reference to the map
|
||||
*/
|
||||
public fun endMap(start: Int, key: String? = null): Int {
|
||||
@@ -456,7 +487,7 @@ public class FlexBuffersBuilder(
|
||||
length: Int,
|
||||
vecType: FlexBufferType,
|
||||
bitWidth: BitWidth,
|
||||
crossinline writeBlock: (ByteWidth) -> Unit
|
||||
crossinline writeBlock: (ByteWidth) -> Unit,
|
||||
): Int {
|
||||
val keyPos = putKey(key)
|
||||
val byteWidth = align(bitWidth)
|
||||
@@ -471,7 +502,10 @@ public class FlexBuffersBuilder(
|
||||
return vloc
|
||||
}
|
||||
|
||||
private inline fun setTypedVec(key: String? = null, crossinline block: FlexBuffersBuilder.() -> Unit): Int {
|
||||
private inline fun setTypedVec(
|
||||
key: String? = null,
|
||||
crossinline block: FlexBuffersBuilder.() -> Unit,
|
||||
): Int {
|
||||
val pos = startVector()
|
||||
this.block()
|
||||
return endTypedVector(pos, key)
|
||||
@@ -511,11 +545,15 @@ public class FlexBuffersBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeAny(toWrite: Value, byteWidth: ByteWidth) = when (toWrite.type) {
|
||||
T_NULL, T_BOOL, T_INT, T_UINT -> writeInt(toWrite.iValue, byteWidth)
|
||||
T_FLOAT -> writeDouble(toWrite.dValue, byteWidth)
|
||||
else -> writeOffset(toWrite.iValue.toInt(), byteWidth)
|
||||
}
|
||||
private fun writeAny(toWrite: Value, byteWidth: ByteWidth) =
|
||||
when (toWrite.type) {
|
||||
T_NULL,
|
||||
T_BOOL,
|
||||
T_INT,
|
||||
T_UINT -> writeInt(toWrite.iValue, byteWidth)
|
||||
T_FLOAT -> writeDouble(toWrite.dValue, byteWidth)
|
||||
else -> writeOffset(toWrite.iValue.toInt(), byteWidth)
|
||||
}
|
||||
|
||||
private fun writeString(key: Int, s: String): Value {
|
||||
val encodedSize = Utf8.encodedLength(s)
|
||||
@@ -526,8 +564,7 @@ public class FlexBuffersBuilder(
|
||||
|
||||
buffer.requestAdditionalCapacity(encodedSize + 1)
|
||||
val sloc: Int = buffer.writePosition
|
||||
if (encodedSize > 0)
|
||||
buffer.put(s, encodedSize)
|
||||
if (encodedSize > 0) buffer.put(s, encodedSize)
|
||||
buffer.put(ZeroByte)
|
||||
return Value(T_STRING, key, bitWidth, sloc.toULong())
|
||||
}
|
||||
@@ -544,11 +581,17 @@ public class FlexBuffersBuilder(
|
||||
private fun writeOffset(toWrite: Int, byteWidth: ByteWidth) {
|
||||
buffer.requestAdditionalCapacity(byteWidth.value)
|
||||
val relativeOffset = (buffer.writePosition - toWrite)
|
||||
if (byteWidth.value != 8 && relativeOffset >= 1L shl byteWidth.value * 8) error("invalid offset $relativeOffset, writer pos ${buffer.writePosition}")
|
||||
if (byteWidth.value != 8 && relativeOffset >= 1L shl byteWidth.value * 8)
|
||||
error("invalid offset $relativeOffset, writer pos ${buffer.writePosition}")
|
||||
writeInt(relativeOffset, byteWidth)
|
||||
}
|
||||
|
||||
private inline fun writeBlob(key: Int, blob: ByteArray, type: FlexBufferType, trailing: Boolean): Value {
|
||||
private inline fun writeBlob(
|
||||
key: Int,
|
||||
blob: ByteArray,
|
||||
type: FlexBufferType,
|
||||
trailing: Boolean,
|
||||
): Value {
|
||||
val bitWidth = blob.size.toULong().widthInUBits()
|
||||
val byteWidth = align(bitWidth)
|
||||
|
||||
@@ -586,22 +629,26 @@ public class FlexBuffersBuilder(
|
||||
start: Int,
|
||||
size: Int,
|
||||
byteWidth: ByteWidth,
|
||||
crossinline valueBlock: (Int) -> ULong
|
||||
crossinline valueBlock: (Int) -> ULong,
|
||||
) {
|
||||
buffer.requestAdditionalCapacity(size * byteWidth.value)
|
||||
return when (byteWidth.value) {
|
||||
1 -> for (i in start until start + size) {
|
||||
buffer.put(valueBlock(i).toUByte())
|
||||
}
|
||||
2 -> for (i in start until start + size) {
|
||||
buffer.put(valueBlock(i).toUShort())
|
||||
}
|
||||
4 -> for (i in start until start + size) {
|
||||
buffer.put(valueBlock(i).toUInt())
|
||||
}
|
||||
8 -> for (i in start until start + size) {
|
||||
buffer.put(valueBlock(i))
|
||||
}
|
||||
1 ->
|
||||
for (i in start until start + size) {
|
||||
buffer.put(valueBlock(i).toUByte())
|
||||
}
|
||||
2 ->
|
||||
for (i in start until start + size) {
|
||||
buffer.put(valueBlock(i).toUShort())
|
||||
}
|
||||
4 ->
|
||||
for (i in start until start + size) {
|
||||
buffer.put(valueBlock(i).toUInt())
|
||||
}
|
||||
8 ->
|
||||
for (i in start until start + size) {
|
||||
buffer.put(valueBlock(i))
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
@@ -619,7 +666,7 @@ public class FlexBuffersBuilder(
|
||||
|
||||
private fun writeInt(value: ULong, byteWidth: ByteWidth) {
|
||||
buffer.requestAdditionalCapacity(byteWidth.value)
|
||||
when(byteWidth.value) {
|
||||
when (byteWidth.value) {
|
||||
1 -> buffer.put(value.toUByte())
|
||||
2 -> buffer.put(value.toUShort())
|
||||
4 -> buffer.put(value.toUInt())
|
||||
@@ -646,7 +693,8 @@ public class FlexBuffersBuilder(
|
||||
val prefixElems = 1
|
||||
// Check bit widths and types for all elements.
|
||||
for (i in start until stack.size) {
|
||||
val elemWidth = elemWidth(T_KEY, W_8, stack[i].key.toLong(), buffer.writePosition, i + prefixElems)
|
||||
val elemWidth =
|
||||
elemWidth(T_KEY, W_8, stack[i].key.toLong(), buffer.writePosition, i + prefixElems)
|
||||
width = width.max(elemWidth)
|
||||
}
|
||||
return width
|
||||
@@ -689,13 +737,20 @@ public class FlexBuffersBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun createTypedVector(key: Int, start: Int, length: Int, keys: Value? = null): Value {
|
||||
private inline fun createTypedVector(
|
||||
key: Int,
|
||||
start: Int,
|
||||
length: Int,
|
||||
keys: Value? = null,
|
||||
): Value {
|
||||
// We assume the callers of this method guarantees all elements are of the same type.
|
||||
val elementType: FlexBufferType = stack[start].type
|
||||
for (i in start + 1 until length) {
|
||||
if (elementType != stack[i].type) error("TypedVector does not support array of different element types")
|
||||
if (elementType != stack[i].type)
|
||||
error("TypedVector does not support array of different element types")
|
||||
}
|
||||
if (!elementType.isTypedVectorElementType()) error("TypedVector does not support this element type")
|
||||
if (!elementType.isTypedVectorElementType())
|
||||
error("TypedVector does not support this element type")
|
||||
return createAnyVector(key, start, length, elementType.toTypedVector(), keys)
|
||||
}
|
||||
|
||||
@@ -705,7 +760,7 @@ public class FlexBuffersBuilder(
|
||||
length: Int,
|
||||
type: FlexBufferType,
|
||||
keys: Value? = null,
|
||||
crossinline typeBlock: (BitWidth) -> Unit = {}
|
||||
crossinline typeBlock: (BitWidth) -> Unit = {},
|
||||
): Value {
|
||||
// Figure out the smallest bit width we can store this vector with.
|
||||
var bitWidth = W_8.max(length.toULong().widthInUBits())
|
||||
@@ -742,45 +797,43 @@ public class FlexBuffersBuilder(
|
||||
}
|
||||
|
||||
// A lambda to sort map keys
|
||||
internal val keyComparator = object : Comparator<Value> {
|
||||
override fun compare(a: Value, b: Value): Int {
|
||||
var ia: Int = a.key
|
||||
var io: Int = b.key
|
||||
var c1: Byte
|
||||
var c2: Byte
|
||||
do {
|
||||
c1 = buffer[ia]
|
||||
c2 = buffer[io]
|
||||
if (c1.toInt() == 0) return c1 - c2
|
||||
ia++
|
||||
io++
|
||||
} while (c1 == c2)
|
||||
return c1 - c2
|
||||
internal val keyComparator =
|
||||
object : Comparator<Value> {
|
||||
override fun compare(a: Value, b: Value): Int {
|
||||
var ia: Int = a.key
|
||||
var io: Int = b.key
|
||||
var c1: Byte
|
||||
var c2: Byte
|
||||
do {
|
||||
c1 = buffer[ia]
|
||||
c2 = buffer[io]
|
||||
if (c1.toInt() == 0) return c1 - c2
|
||||
ia++
|
||||
io++
|
||||
} while (c1 == c2)
|
||||
return c1 - c2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* No keys or strings will be shared
|
||||
*/
|
||||
/** No keys or strings will be shared */
|
||||
public const val SHARE_NONE: Int = 0
|
||||
|
||||
/**
|
||||
* Keys will be shared between elements. Identical keys will only be serialized once, thus possibly saving space.
|
||||
* But serialization performance might be slower and consumes more memory.
|
||||
* Keys will be shared between elements. Identical keys will only be serialized once, thus
|
||||
* possibly saving space. But serialization performance might be slower and consumes more
|
||||
* memory.
|
||||
*/
|
||||
public const val SHARE_KEYS: Int = 1
|
||||
|
||||
/**
|
||||
* Strings will be shared between elements. Identical strings will only be serialized once, thus possibly saving space.
|
||||
* But serialization performance might be slower and consumes more memory. This is ideal if you expect many repeated
|
||||
* strings on the message.
|
||||
* Strings will be shared between elements. Identical strings will only be serialized once, thus
|
||||
* possibly saving space. But serialization performance might be slower and consumes more
|
||||
* memory. This is ideal if you expect many repeated strings on the message.
|
||||
*/
|
||||
public const val SHARE_STRINGS: Int = 2
|
||||
|
||||
/**
|
||||
* Strings and keys will be shared between elements.
|
||||
*/
|
||||
/** Strings and keys will be shared between elements. */
|
||||
public const val SHARE_KEYS_AND_STRINGS: Int = 3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,19 +24,25 @@ public value class BitWidth(public val value: Int) {
|
||||
public inline fun max(other: BitWidth): BitWidth = if (this.value >= other.value) this else other
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
public value class ByteWidth(public val value: Int)
|
||||
@JvmInline public value class ByteWidth(public val value: Int)
|
||||
|
||||
@JvmInline
|
||||
public value class FlexBufferType(public val value: Int) {
|
||||
public operator fun minus(other: FlexBufferType): FlexBufferType = FlexBufferType(this.value - other.value)
|
||||
public operator fun plus(other: FlexBufferType): FlexBufferType = FlexBufferType(this.value + other.value)
|
||||
public operator fun minus(other: FlexBufferType): FlexBufferType =
|
||||
FlexBufferType(this.value - other.value)
|
||||
|
||||
public operator fun plus(other: FlexBufferType): FlexBufferType =
|
||||
FlexBufferType(this.value + other.value)
|
||||
|
||||
public operator fun compareTo(other: FlexBufferType): Int = this.value - other.value
|
||||
}
|
||||
|
||||
internal operator fun Int.times(width: ByteWidth): Int = this * width.value
|
||||
|
||||
internal operator fun Int.minus(width: ByteWidth): Int = this - width.value
|
||||
|
||||
internal operator fun Int.plus(width: ByteWidth): Int = this + width.value
|
||||
|
||||
internal operator fun Int.minus(type: FlexBufferType): Int = this - type.value
|
||||
|
||||
// Returns a Key string from the buffer starting at index [start]. Key Strings are stored as
|
||||
@@ -61,23 +67,42 @@ internal inline fun ReadBuffer.readFloat(end: Int, byteWidth: ByteWidth): Double
|
||||
return when (byteWidth.value) {
|
||||
4 -> this.getFloat(end).toDouble()
|
||||
8 -> this.getDouble(end)
|
||||
else -> error("invalid byte width $byteWidth for floating point scalar") // we should never reach here
|
||||
else ->
|
||||
error("invalid byte width $byteWidth for floating point scalar") // we should never reach here
|
||||
}
|
||||
}
|
||||
|
||||
// return position on the [ReadBuffer] of the element that the offset is pointing to
|
||||
// we assume all offset fits on a int, since ReadBuffer operates with that assumption
|
||||
internal inline fun ReadBuffer.indirect(offset: Int, byteWidth: ByteWidth): Int = offset - readInt(offset, byteWidth)
|
||||
internal inline fun ReadBuffer.indirect(offset: Int, byteWidth: ByteWidth): Int =
|
||||
offset - readInt(offset, byteWidth)
|
||||
|
||||
// returns the size of an array-like element from [ReadBuffer].
|
||||
internal inline fun ReadBuffer.readSize(end: Int, byteWidth: ByteWidth) = readInt(end - byteWidth, byteWidth)
|
||||
internal inline fun ReadBuffer.readUInt(end: Int, byteWidth: ByteWidth): UInt = readULong(end, byteWidth).toUInt()
|
||||
internal inline fun ReadBuffer.readInt(end: Int, byteWidth: ByteWidth): Int = readULong(end, byteWidth).toInt()
|
||||
internal inline fun ReadBuffer.readLong(end: Int, byteWidth: ByteWidth): Long = readULong(end, byteWidth).toLong()
|
||||
internal inline fun ReadBuffer.readSize(end: Int, byteWidth: ByteWidth) =
|
||||
readInt(end - byteWidth, byteWidth)
|
||||
|
||||
internal fun IntArray.widthInUBits(): BitWidth = arrayWidthInUBits(this.size) { this[it].toULong().widthInUBits() }
|
||||
internal fun ShortArray.widthInUBits(): BitWidth = arrayWidthInUBits(this.size) { this[it].toULong().widthInUBits() }
|
||||
internal fun LongArray.widthInUBits(): BitWidth = arrayWidthInUBits(this.size) { this[it].toULong().widthInUBits() }
|
||||
internal inline fun ReadBuffer.readUInt(end: Int, byteWidth: ByteWidth): UInt =
|
||||
readULong(end, byteWidth).toUInt()
|
||||
|
||||
private inline fun arrayWidthInUBits(size: Int, crossinline elemWidthBlock: (Int) -> BitWidth): BitWidth {
|
||||
internal inline fun ReadBuffer.readInt(end: Int, byteWidth: ByteWidth): Int =
|
||||
readULong(end, byteWidth).toInt()
|
||||
|
||||
internal inline fun ReadBuffer.readLong(end: Int, byteWidth: ByteWidth): Long =
|
||||
readULong(end, byteWidth).toLong()
|
||||
|
||||
internal fun IntArray.widthInUBits(): BitWidth =
|
||||
arrayWidthInUBits(this.size) { this[it].toULong().widthInUBits() }
|
||||
|
||||
internal fun ShortArray.widthInUBits(): BitWidth =
|
||||
arrayWidthInUBits(this.size) { this[it].toULong().widthInUBits() }
|
||||
|
||||
internal fun LongArray.widthInUBits(): BitWidth =
|
||||
arrayWidthInUBits(this.size) { this[it].toULong().widthInUBits() }
|
||||
|
||||
private inline fun arrayWidthInUBits(
|
||||
size: Int,
|
||||
crossinline elemWidthBlock: (Int) -> BitWidth,
|
||||
): BitWidth {
|
||||
// Figure out smallest bit width we can store this vector with.
|
||||
var bitWidth = W_8.max(size.toULong().widthInUBits())
|
||||
// Check bit widths and types for all elements.
|
||||
@@ -88,27 +113,37 @@ private inline fun arrayWidthInUBits(size: Int, crossinline elemWidthBlock: (Int
|
||||
return bitWidth
|
||||
}
|
||||
|
||||
internal fun ULong.widthInUBits(): BitWidth = when {
|
||||
this <= MAX_UBYTE_ULONG -> W_8
|
||||
this <= UShort.MAX_VALUE -> W_16
|
||||
this <= UInt.MAX_VALUE -> W_32
|
||||
else -> W_64
|
||||
}
|
||||
internal fun ULong.widthInUBits(): BitWidth =
|
||||
when {
|
||||
this <= MAX_UBYTE_ULONG -> W_8
|
||||
this <= UShort.MAX_VALUE -> W_16
|
||||
this <= UInt.MAX_VALUE -> W_32
|
||||
else -> W_64
|
||||
}
|
||||
|
||||
// returns the number of bytes needed for padding the scalar of size scalarSize.
|
||||
internal inline fun paddingBytes(bufSize: Int, scalarSize: Int): Int = bufSize.inv() + 1 and scalarSize - 1
|
||||
internal inline fun paddingBytes(bufSize: Int, scalarSize: Int): Int =
|
||||
bufSize.inv() + 1 and scalarSize - 1
|
||||
|
||||
internal inline fun FlexBufferType.isInline(): Boolean = this.value <= T_FLOAT.value || this == T_BOOL
|
||||
internal inline fun FlexBufferType.isInline(): Boolean =
|
||||
this.value <= T_FLOAT.value || this == T_BOOL
|
||||
|
||||
internal fun FlexBufferType.isScalar(): Boolean = when (this) {
|
||||
T_INT, T_UINT, T_FLOAT, T_BOOL -> true
|
||||
else -> false
|
||||
}
|
||||
internal fun FlexBufferType.isScalar(): Boolean =
|
||||
when (this) {
|
||||
T_INT,
|
||||
T_UINT,
|
||||
T_FLOAT,
|
||||
T_BOOL -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
internal fun FlexBufferType.isIndirectScalar(): Boolean = when (this) {
|
||||
T_INDIRECT_INT, T_INDIRECT_UINT, T_INDIRECT_FLOAT -> true
|
||||
else -> false
|
||||
}
|
||||
internal fun FlexBufferType.isIndirectScalar(): Boolean =
|
||||
when (this) {
|
||||
T_INDIRECT_INT,
|
||||
T_INDIRECT_UINT,
|
||||
T_INDIRECT_FLOAT -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
internal fun FlexBufferType.isTypedVector(): Boolean =
|
||||
this >= T_VECTOR_INT && this <= T_VECTOR_STRING_DEPRECATED || this == T_VECTOR_BOOL
|
||||
@@ -118,6 +153,7 @@ internal fun FlexBufferType.isTypedVectorElementType(): Boolean =
|
||||
|
||||
// returns the typed vector of a given scalar type.
|
||||
internal fun FlexBufferType.toTypedVector(): FlexBufferType = (this - T_INT) + T_VECTOR_INT
|
||||
|
||||
// returns the element type of given typed vector.
|
||||
internal fun FlexBufferType.toElementTypedVector(): FlexBufferType = this - T_VECTOR_INT + T_INT
|
||||
|
||||
@@ -127,10 +163,11 @@ internal data class Value(
|
||||
var key: Int = -1,
|
||||
var minBitWidth: BitWidth = W_8,
|
||||
var iValue: ULong = 0UL, // integer value
|
||||
var dValue: Double = 0.0 // TODO(paulovap): maybe we can keep floating type on iValue as well.
|
||||
var dValue: Double = 0.0, // TODO(paulovap): maybe we can keep floating type on iValue as well.
|
||||
) { // float value
|
||||
|
||||
inline fun storedPackedType(parentBitWidth: BitWidth = W_8): Byte = packedType(storedWidth(parentBitWidth), type)
|
||||
inline fun storedPackedType(parentBitWidth: BitWidth = W_8): Byte =
|
||||
packedType(storedWidth(parentBitWidth), type)
|
||||
|
||||
private inline fun packedType(bitWidth: BitWidth, type: FlexBufferType): Byte =
|
||||
(bitWidth.value or (type.value shl 2)).toByte()
|
||||
@@ -147,7 +184,7 @@ internal fun elemWidth(
|
||||
minBitWidth: BitWidth,
|
||||
iValue: Long,
|
||||
bufSize: Int,
|
||||
elemIndex: Int
|
||||
elemIndex: Int,
|
||||
): BitWidth {
|
||||
if (type.isInline()) return minBitWidth
|
||||
|
||||
@@ -173,43 +210,48 @@ internal fun elemWidth(
|
||||
}
|
||||
|
||||
// For debugging purposes, convert type to a human-readable string.
|
||||
internal fun FlexBufferType.typeToString(): String = when (this) {
|
||||
T_NULL -> "Null"
|
||||
T_INT -> "Int"
|
||||
T_UINT -> "UInt"
|
||||
T_FLOAT -> "Float"
|
||||
T_KEY -> "Key"
|
||||
T_STRING -> "String"
|
||||
T_INDIRECT_INT -> "IndirectInt"
|
||||
T_INDIRECT_UINT -> "IndirectUInt"
|
||||
T_INDIRECT_FLOAT -> "IndirectFloat"
|
||||
T_MAP -> "Map"
|
||||
T_VECTOR -> "Vector"
|
||||
T_VECTOR_INT -> "IntVector"
|
||||
T_VECTOR_UINT -> "UIntVector"
|
||||
T_VECTOR_FLOAT -> "FloatVector"
|
||||
T_VECTOR_KEY -> "KeyVector"
|
||||
T_VECTOR_STRING_DEPRECATED -> "StringVectorDeprecated"
|
||||
T_VECTOR_INT2 -> "Int2Vector"
|
||||
T_VECTOR_UINT2 -> "UInt2Vector"
|
||||
T_VECTOR_FLOAT2 -> "Float2Vector"
|
||||
T_VECTOR_INT3 -> "Int3Vector"
|
||||
T_VECTOR_UINT3 -> "UInt3Vector"
|
||||
T_VECTOR_FLOAT3 -> "Float3Vector"
|
||||
T_VECTOR_INT4 -> "Int4Vector"
|
||||
T_VECTOR_UINT4 -> "UInt4Vector"
|
||||
T_VECTOR_FLOAT4 -> "Float4Vector"
|
||||
T_BLOB -> "BlobVector"
|
||||
T_BOOL -> "BoolVector"
|
||||
T_VECTOR_BOOL -> "BoolVector"
|
||||
else -> "UnknownType"
|
||||
}
|
||||
internal fun FlexBufferType.typeToString(): String =
|
||||
when (this) {
|
||||
T_NULL -> "Null"
|
||||
T_INT -> "Int"
|
||||
T_UINT -> "UInt"
|
||||
T_FLOAT -> "Float"
|
||||
T_KEY -> "Key"
|
||||
T_STRING -> "String"
|
||||
T_INDIRECT_INT -> "IndirectInt"
|
||||
T_INDIRECT_UINT -> "IndirectUInt"
|
||||
T_INDIRECT_FLOAT -> "IndirectFloat"
|
||||
T_MAP -> "Map"
|
||||
T_VECTOR -> "Vector"
|
||||
T_VECTOR_INT -> "IntVector"
|
||||
T_VECTOR_UINT -> "UIntVector"
|
||||
T_VECTOR_FLOAT -> "FloatVector"
|
||||
T_VECTOR_KEY -> "KeyVector"
|
||||
T_VECTOR_STRING_DEPRECATED -> "StringVectorDeprecated"
|
||||
T_VECTOR_INT2 -> "Int2Vector"
|
||||
T_VECTOR_UINT2 -> "UInt2Vector"
|
||||
T_VECTOR_FLOAT2 -> "Float2Vector"
|
||||
T_VECTOR_INT3 -> "Int3Vector"
|
||||
T_VECTOR_UINT3 -> "UInt3Vector"
|
||||
T_VECTOR_FLOAT3 -> "Float3Vector"
|
||||
T_VECTOR_INT4 -> "Int4Vector"
|
||||
T_VECTOR_UINT4 -> "UInt4Vector"
|
||||
T_VECTOR_FLOAT4 -> "Float4Vector"
|
||||
T_BLOB -> "BlobVector"
|
||||
T_BOOL -> "BoolVector"
|
||||
T_VECTOR_BOOL -> "BoolVector"
|
||||
else -> "UnknownType"
|
||||
}
|
||||
|
||||
// Few repeated values used in hot path is cached here
|
||||
internal fun emptyBlob() = Blob(emptyBuffer, 1, ByteWidth(1))
|
||||
|
||||
internal fun emptyVector() = Vector(emptyBuffer, 1, ByteWidth(1))
|
||||
|
||||
internal fun emptyMap() = Map(ArrayReadWriteBuffer(3), 3, ByteWidth(1))
|
||||
|
||||
internal fun nullReference() = Reference(emptyBuffer, 1, ByteWidth(0), T_NULL.value)
|
||||
|
||||
internal fun nullKey() = Key(emptyBuffer, 1)
|
||||
|
||||
internal const val ZeroByte = 0.toByte()
|
||||
@@ -228,7 +270,8 @@ internal val T_INVALID = FlexBufferType(-1)
|
||||
internal val T_NULL = FlexBufferType(0)
|
||||
internal val T_INT = FlexBufferType(1)
|
||||
internal val T_UINT = FlexBufferType(2)
|
||||
internal val T_FLOAT = FlexBufferType(3) // Types above stored inline, types below are stored in an offset.
|
||||
internal val T_FLOAT =
|
||||
FlexBufferType(3) // Types above stored inline, types below are stored in an offset.
|
||||
internal val T_KEY = FlexBufferType(4)
|
||||
internal val T_STRING = FlexBufferType(5)
|
||||
internal val T_INDIRECT_INT = FlexBufferType(6)
|
||||
@@ -254,4 +297,5 @@ internal val T_VECTOR_UINT4 = FlexBufferType(23)
|
||||
internal val T_VECTOR_FLOAT4 = FlexBufferType(24)
|
||||
internal val T_BLOB = FlexBufferType(25)
|
||||
internal val T_BOOL = FlexBufferType(26)
|
||||
internal val T_VECTOR_BOOL = FlexBufferType(36) // To Allow the same type of conversion of type to vector type
|
||||
internal val T_VECTOR_BOOL =
|
||||
FlexBufferType(36) // To Allow the same type of conversion of type to vector type
|
||||
|
||||
@@ -19,12 +19,10 @@ package com.google.flatbuffers.kotlin
|
||||
|
||||
public object Utf8 {
|
||||
/**
|
||||
* Returns the number of bytes in the UTF-8-encoded form of `sequence`. For a string,
|
||||
* this method is equivalent to `string.getBytes(UTF_8).length`, but is more efficient in
|
||||
* both time and space.
|
||||
* Returns the number of bytes in the UTF-8-encoded form of `sequence`. For a string, this method
|
||||
* is equivalent to `string.getBytes(UTF_8).length`, but is more efficient in both time and space.
|
||||
*
|
||||
* @throws IllegalArgumentException if `sequence` contains ill-formed UTF-16 (unpaired
|
||||
* surrogates)
|
||||
* @throws IllegalArgumentException if `sequence` contains ill-formed UTF-16 (unpaired surrogates)
|
||||
*/
|
||||
private fun computeEncodedLength(sequence: CharSequence): Int {
|
||||
// Warning to maintainers: this implementation is highly optimized.
|
||||
@@ -80,45 +78,30 @@ public object Utf8 {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes in the UTF-8-encoded form of `sequence`. For a string,
|
||||
* this method is equivalent to `string.getBytes(UTF_8).length`, but is more efficient in
|
||||
* both time and space.
|
||||
* Returns the number of bytes in the UTF-8-encoded form of `sequence`. For a string, this method
|
||||
* is equivalent to `string.getBytes(UTF_8).length`, but is more efficient in both time and space.
|
||||
*
|
||||
* @throws IllegalArgumentException if `sequence` contains ill-formed UTF-16 (unpaired
|
||||
* surrogates)
|
||||
* @throws IllegalArgumentException if `sequence` contains ill-formed UTF-16 (unpaired surrogates)
|
||||
*/
|
||||
public fun encodedLength(sequence: CharSequence): Int = computeEncodedLength(sequence)
|
||||
|
||||
/**
|
||||
* Returns whether this is a single-byte codepoint (i.e., ASCII) with the form '0XXXXXXX'.
|
||||
*/
|
||||
/** Returns whether this is a single-byte codepoint (i.e., ASCII) with the form '0XXXXXXX'. */
|
||||
public inline fun isOneByte(b: Byte): Boolean = b >= 0
|
||||
|
||||
/**
|
||||
* Returns whether this is a two-byte codepoint with the form 110xxxxx 0xC0..0xDF.
|
||||
*/
|
||||
/** Returns whether this is a two-byte codepoint with the form 110xxxxx 0xC0..0xDF. */
|
||||
public inline fun isTwoBytes(b: Byte): Boolean = b < 0xE0.toByte()
|
||||
|
||||
/**
|
||||
* Returns whether this is a three-byte codepoint with the form 1110xxxx 0xE0..0xEF.
|
||||
*/
|
||||
/** Returns whether this is a three-byte codepoint with the form 1110xxxx 0xE0..0xEF. */
|
||||
public inline fun isThreeBytes(b: Byte): Boolean = b < 0xF0.toByte()
|
||||
|
||||
/**
|
||||
* Returns whether this is a four-byte codepoint with the form 11110xxx 0xF0..0xF4.
|
||||
*/
|
||||
/** Returns whether this is a four-byte codepoint with the form 11110xxx 0xF0..0xF4. */
|
||||
public inline fun isFourByte(b: Byte): Boolean = b < 0xF8.toByte()
|
||||
|
||||
public fun handleOneByte(byte1: Byte, resultArr: CharArray, resultPos: Int) {
|
||||
resultArr[resultPos] = byte1.toInt().toChar()
|
||||
}
|
||||
|
||||
public fun handleTwoBytes(
|
||||
byte1: Byte,
|
||||
byte2: Byte,
|
||||
resultArr: CharArray,
|
||||
resultPos: Int
|
||||
) {
|
||||
public fun handleTwoBytes(byte1: Byte, byte2: Byte, resultArr: CharArray, resultPos: Int) {
|
||||
// Simultaneously checks for illegal trailing-byte in leading position (<= '11000000') and
|
||||
// overlong 2-byte, '11000001'.
|
||||
if (byte1 < 0xC2.toByte()) {
|
||||
@@ -135,17 +118,23 @@ public object Utf8 {
|
||||
byte2: Byte,
|
||||
byte3: Byte,
|
||||
resultArr: CharArray,
|
||||
resultPos: Int
|
||||
resultPos: Int,
|
||||
) {
|
||||
if (isNotTrailingByte(byte2) || // overlong? 5 most significant bits must not all be zero
|
||||
byte1 == 0xE0.toByte() && byte2 < 0xA0.toByte() || // check for illegal surrogate codepoints
|
||||
byte1 == 0xED.toByte() && byte2 >= 0xA0.toByte() ||
|
||||
isNotTrailingByte(byte3)
|
||||
if (
|
||||
isNotTrailingByte(byte2) || // overlong? 5 most significant bits must not all be zero
|
||||
byte1 == 0xE0.toByte() && byte2 < 0xA0.toByte() || // check for illegal surrogate codepoints
|
||||
byte1 == 0xED.toByte() && byte2 >= 0xA0.toByte() ||
|
||||
isNotTrailingByte(byte3)
|
||||
) {
|
||||
error("Invalid UTF-8")
|
||||
}
|
||||
resultArr[resultPos] =
|
||||
(byte1.toInt() and 0x0F shl 12 or (trailingByteValue(byte2) shl 6) or trailingByteValue(byte3)).toChar()
|
||||
(byte1.toInt() and
|
||||
0x0F shl
|
||||
12 or
|
||||
(trailingByteValue(byte2) shl 6) or
|
||||
trailingByteValue(byte3))
|
||||
.toChar()
|
||||
}
|
||||
|
||||
public fun handleFourBytes(
|
||||
@@ -154,50 +143,47 @@ public object Utf8 {
|
||||
byte3: Byte,
|
||||
byte4: Byte,
|
||||
resultArr: CharArray,
|
||||
resultPos: Int
|
||||
resultPos: Int,
|
||||
) {
|
||||
if (isNotTrailingByte(byte2) || // Check that 1 <= plane <= 16. Tricky optimized form of:
|
||||
// valid 4-byte leading byte?
|
||||
// if (byte1 > (byte) 0xF4 ||
|
||||
// overlong? 4 most significant bits must not all be zero
|
||||
// byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
|
||||
// codepoint larger than the highest code point (U+10FFFF)?
|
||||
// byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
|
||||
(byte1.toInt() shl 28) + (byte2 - 0x90.toByte()) shr 30 != 0 || isNotTrailingByte(byte3) ||
|
||||
isNotTrailingByte(byte4)
|
||||
if (
|
||||
isNotTrailingByte(byte2) || // Check that 1 <= plane <= 16. Tricky optimized form of:
|
||||
// valid 4-byte leading byte?
|
||||
// if (byte1 > (byte) 0xF4 ||
|
||||
// overlong? 4 most significant bits must not all be zero
|
||||
// byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
|
||||
// codepoint larger than the highest code point (U+10FFFF)?
|
||||
// byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
|
||||
(byte1.toInt() shl 28) + (byte2 - 0x90.toByte()) shr 30 != 0 ||
|
||||
isNotTrailingByte(byte3) ||
|
||||
isNotTrailingByte(byte4)
|
||||
) {
|
||||
error("Invalid UTF-8")
|
||||
}
|
||||
val codepoint: Int = (
|
||||
byte1.toInt() and 0x07 shl 18
|
||||
or (trailingByteValue(byte2) shl 12)
|
||||
or (trailingByteValue(byte3) shl 6)
|
||||
or trailingByteValue(byte4)
|
||||
)
|
||||
val codepoint: Int =
|
||||
(byte1.toInt() and
|
||||
0x07 shl
|
||||
18 or
|
||||
(trailingByteValue(byte2) shl 12) or
|
||||
(trailingByteValue(byte3) shl 6) or
|
||||
trailingByteValue(byte4))
|
||||
resultArr[resultPos] = highSurrogate(codepoint)
|
||||
resultArr[resultPos + 1] = lowSurrogate(codepoint)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the byte is not a valid continuation of the form '10XXXXXX'.
|
||||
*/
|
||||
/** Returns whether the byte is not a valid continuation of the form '10XXXXXX'. */
|
||||
private fun isNotTrailingByte(b: Byte): Boolean = b > 0xBF.toByte()
|
||||
|
||||
/**
|
||||
* Returns the actual value of the trailing byte (removes the prefix '10') for composition.
|
||||
*/
|
||||
/** Returns the actual value of the trailing byte (removes the prefix '10') for composition. */
|
||||
private fun trailingByteValue(b: Byte): Int = b.toInt() and 0x3F
|
||||
|
||||
private fun highSurrogate(codePoint: Int): Char =
|
||||
(
|
||||
Char.MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT ushr 10) +
|
||||
(codePoint ushr 10)
|
||||
)
|
||||
(Char.MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT ushr 10) + (codePoint ushr 10))
|
||||
|
||||
private fun lowSurrogate(codePoint: Int): Char = (Char.MIN_LOW_SURROGATE + (codePoint and 0x3ff))
|
||||
|
||||
/**
|
||||
* Encode a [CharSequence] UTF8 codepoint into a byte array.
|
||||
*
|
||||
* @param `in` CharSequence to be encoded
|
||||
* @param start start position of the first char in the codepoint
|
||||
* @param out byte array of 4 bytes to be filled
|
||||
@@ -297,10 +283,7 @@ public object Utf8 {
|
||||
if (offset >= limit) {
|
||||
error("Invalid UTF-8")
|
||||
}
|
||||
handleTwoBytes(
|
||||
byte1, /* byte2 */
|
||||
bytes[offset++], resultArr, resultPos++
|
||||
)
|
||||
handleTwoBytes(byte1, /* byte2 */ bytes[offset++], resultArr, resultPos++)
|
||||
} else if (isThreeBytes(byte1)) {
|
||||
if (offset >= limit - 1) {
|
||||
error("Invalid UTF-8")
|
||||
@@ -310,7 +293,7 @@ public object Utf8 {
|
||||
bytes[offset++], /* byte3 */
|
||||
bytes[offset++],
|
||||
resultArr,
|
||||
resultPos++
|
||||
resultPos++,
|
||||
)
|
||||
} else {
|
||||
if (offset >= limit - 2) {
|
||||
@@ -322,7 +305,7 @@ public object Utf8 {
|
||||
bytes[offset++], /* byte4 */
|
||||
bytes[offset++],
|
||||
resultArr,
|
||||
resultPos++
|
||||
resultPos++,
|
||||
)
|
||||
// 4-byte case requires two chars.
|
||||
resultPos++
|
||||
@@ -331,10 +314,12 @@ public object Utf8 {
|
||||
return resultArr.concatToString(0, resultPos)
|
||||
}
|
||||
|
||||
public fun encodeUtf8Array(input: CharSequence,
|
||||
out: ByteArray,
|
||||
offset: Int = 0,
|
||||
length: Int = out.size - offset): Int {
|
||||
public fun encodeUtf8Array(
|
||||
input: CharSequence,
|
||||
out: ByteArray,
|
||||
offset: Int = 0,
|
||||
length: Int = out.size - offset,
|
||||
): Int {
|
||||
val utf16Length = input.length
|
||||
var j = offset
|
||||
var i = 0
|
||||
@@ -342,8 +327,7 @@ public object Utf8 {
|
||||
// Designed to take advantage of
|
||||
// https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
|
||||
|
||||
if (utf16Length == 0)
|
||||
return 0
|
||||
if (utf16Length == 0) return 0
|
||||
var cc: Char = input[i]
|
||||
while (i < utf16Length && i + j < limit && input[i].also { cc = it }.code < 0x80) {
|
||||
out[j + i] = cc.code.toByte()
|
||||
@@ -370,9 +354,7 @@ public object Utf8 {
|
||||
// Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
|
||||
// four UTF-8 bytes
|
||||
var low: Char = Char.MIN_VALUE
|
||||
if (i + 1 == input.length ||
|
||||
!isSurrogatePair(c, input[++i].also { low = it })
|
||||
) {
|
||||
if (i + 1 == input.length || !isSurrogatePair(c, input[++i].also { low = it })) {
|
||||
errorSurrogate(i - 1, utf16Length)
|
||||
}
|
||||
val codePoint: Int = toCodePoint(c, low)
|
||||
@@ -383,8 +365,10 @@ public object Utf8 {
|
||||
} else {
|
||||
// If we are surrogates and we're not a surrogate pair, always throw an
|
||||
// UnpairedSurrogateException instead of an ArrayOutOfBoundsException.
|
||||
if (Char.MIN_SURROGATE <= c && c <= Char.MAX_SURROGATE &&
|
||||
(i + 1 == input.length || !isSurrogatePair(c, input[i + 1]))
|
||||
if (
|
||||
Char.MIN_SURROGATE <= c &&
|
||||
c <= Char.MAX_SURROGATE &&
|
||||
(i + 1 == input.length || !isSurrogatePair(c, input[i + 1]))
|
||||
) {
|
||||
errorSurrogate(i, utf16Length)
|
||||
}
|
||||
@@ -407,10 +391,15 @@ public object Utf8 {
|
||||
return c1.code
|
||||
}
|
||||
|
||||
private fun isSurrogatePair(high: Char, low: Char) = high.isHighSurrogate() and low.isLowSurrogate()
|
||||
private fun isSurrogatePair(high: Char, low: Char) =
|
||||
high.isHighSurrogate() and low.isLowSurrogate()
|
||||
|
||||
private fun toCodePoint(high: Char, low: Char): Int = (high.code shl 10) + low.code +
|
||||
(MIN_SUPPLEMENTARY_CODE_POINT - (Char.MIN_HIGH_SURROGATE.code shl 10) - Char.MIN_LOW_SURROGATE.code)
|
||||
private fun toCodePoint(high: Char, low: Char): Int =
|
||||
(high.code shl 10) +
|
||||
low.code +
|
||||
(MIN_SUPPLEMENTARY_CODE_POINT -
|
||||
(Char.MIN_HIGH_SURROGATE.code shl 10) -
|
||||
Char.MIN_LOW_SURROGATE.code)
|
||||
|
||||
private fun errorSurrogate(i: Int, utf16Length: Int): Unit =
|
||||
error("Unpaired surrogate at index $i of $utf16Length length")
|
||||
|
||||
@@ -22,17 +22,17 @@ import kotlin.experimental.and
|
||||
import kotlin.jvm.JvmInline
|
||||
import kotlin.math.pow
|
||||
|
||||
/**
|
||||
* Returns a minified version of this FlexBuffer as a JSON.
|
||||
*/
|
||||
public fun Reference.toJson(): String = ArrayReadWriteBuffer(1024).let {
|
||||
toJson(it)
|
||||
val data = it.data() // it.getString(0, it.writePosition)
|
||||
return data.decodeToString(0, it.writePosition)
|
||||
}
|
||||
/** Returns a minified version of this FlexBuffer as a JSON. */
|
||||
public fun Reference.toJson(): String =
|
||||
ArrayReadWriteBuffer(1024).let {
|
||||
toJson(it)
|
||||
val data = it.data() // it.getString(0, it.writePosition)
|
||||
return data.decodeToString(0, it.writePosition)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a minified version of this FlexBuffer as a JSON.
|
||||
*
|
||||
* @param out [ReadWriteBuffer] the JSON will be written.
|
||||
*/
|
||||
public fun Reference.toJson(out: ReadWriteBuffer) {
|
||||
@@ -57,19 +57,27 @@ public fun Reference.toJson(out: ReadWriteBuffer) {
|
||||
T_NULL -> out.put("null")
|
||||
T_BOOL -> out.put(toBoolean().toString())
|
||||
T_MAP -> toMap().toJson(out)
|
||||
T_VECTOR, T_VECTOR_BOOL, T_VECTOR_FLOAT, T_VECTOR_INT,
|
||||
T_VECTOR_UINT, T_VECTOR_KEY, T_VECTOR_STRING_DEPRECATED -> toVector().toJson(out)
|
||||
T_VECTOR,
|
||||
T_VECTOR_BOOL,
|
||||
T_VECTOR_FLOAT,
|
||||
T_VECTOR_INT,
|
||||
T_VECTOR_UINT,
|
||||
T_VECTOR_KEY,
|
||||
T_VECTOR_STRING_DEPRECATED -> toVector().toJson(out)
|
||||
else -> error("Unable to convert type ${type.typeToString()} to JSON")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a minified version of this FlexBuffer as a JSON.
|
||||
*/
|
||||
public fun Map.toJson(): String = ArrayReadWriteBuffer(1024).let { toJson(it); it.toString() }
|
||||
/** Returns a minified version of this FlexBuffer as a JSON. */
|
||||
public fun Map.toJson(): String =
|
||||
ArrayReadWriteBuffer(1024).let {
|
||||
toJson(it)
|
||||
it.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a minified version of this FlexBuffer as a JSON.
|
||||
*
|
||||
* @param out [ReadWriteBuffer] the JSON will be written.
|
||||
*/
|
||||
public fun Map.toJson(out: ReadWriteBuffer) {
|
||||
@@ -88,13 +96,16 @@ public fun Map.toJson(out: ReadWriteBuffer) {
|
||||
out.put('}'.code.toByte())
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a minified version of this FlexBuffer as a JSON.
|
||||
*/
|
||||
public fun Vector.toJson(): String = ArrayReadWriteBuffer(1024).let { toJson(it); it.toString() }
|
||||
/** Returns a minified version of this FlexBuffer as a JSON. */
|
||||
public fun Vector.toJson(): String =
|
||||
ArrayReadWriteBuffer(1024).let {
|
||||
toJson(it)
|
||||
it.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a minified version of this FlexBuffer as a JSON.
|
||||
*
|
||||
* @param out that the JSON is being concatenated.
|
||||
*/
|
||||
public fun Vector.toJson(out: ReadWriteBuffer) {
|
||||
@@ -109,27 +120,23 @@ public fun Vector.toJson(out: ReadWriteBuffer) {
|
||||
}
|
||||
|
||||
/**
|
||||
* JSONParser class is used to parse a JSON as FlexBuffers. Calling [JSONParser.parse] fiils [output]
|
||||
* and returns a [Reference] ready to be used.
|
||||
* JSONParser class is used to parse a JSON as FlexBuffers. Calling [JSONParser.parse] fiils
|
||||
* [output] and returns a [Reference] ready to be used.
|
||||
*/
|
||||
@ExperimentalUnsignedTypes
|
||||
public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuilder(1024, SHARE_KEYS_AND_STRINGS)) {
|
||||
public class JSONParser(
|
||||
public var output: FlexBuffersBuilder = FlexBuffersBuilder(1024, SHARE_KEYS_AND_STRINGS)
|
||||
) {
|
||||
private var readPos = 0
|
||||
private var scopes = ScopeStack()
|
||||
|
||||
/**
|
||||
* Parse a json as [String] and returns a [Reference] to a FlexBuffer.
|
||||
*/
|
||||
/** Parse a json as [String] and returns a [Reference] to a FlexBuffer. */
|
||||
public fun parse(data: String): Reference = parse(ArrayReadBuffer(data.encodeToByteArray()))
|
||||
|
||||
/**
|
||||
* Parse a json as [ByteArray] and returns a [Reference] to a FlexBuffer.
|
||||
*/
|
||||
/** Parse a json as [ByteArray] and returns a [Reference] to a FlexBuffer. */
|
||||
public fun parse(data: ByteArray): Reference = parse(ArrayReadBuffer(data))
|
||||
|
||||
/**
|
||||
* Parse a json as [ReadBuffer] and returns a [Reference] to a FlexBuffer.
|
||||
*/
|
||||
/** Parse a json as [ReadBuffer] and returns a [Reference] to a FlexBuffer. */
|
||||
public fun parse(data: ReadBuffer): Reference {
|
||||
reset()
|
||||
parseValue(data, nextToken(data), null)
|
||||
@@ -165,7 +172,8 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
when (val tok = nextToken(data)) {
|
||||
TOK_END_OBJECT -> {
|
||||
this.scopes.pop()
|
||||
output.endMap(fPos, key); return T_MAP
|
||||
output.endMap(fPos, key)
|
||||
return T_MAP
|
||||
}
|
||||
TOK_BEGIN_QUOTE -> {
|
||||
val childKey = readString(data)
|
||||
@@ -347,7 +355,11 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
return readString(data, limit) { data[it] }
|
||||
}
|
||||
|
||||
private inline fun readString(data: ReadBuffer, limit: Int, crossinline fetch: (Int) -> Byte): String {
|
||||
private inline fun readString(
|
||||
data: ReadBuffer,
|
||||
limit: Int,
|
||||
crossinline fetch: (Int) -> Byte,
|
||||
): String {
|
||||
var cursorPos = readPos
|
||||
var foundEscape = false
|
||||
var currentChar: Byte = 0
|
||||
@@ -420,7 +432,8 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
endOfString = pos + 1
|
||||
}
|
||||
else -> {
|
||||
endOfString = pos; break
|
||||
endOfString = pos
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -478,7 +491,8 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
else -> makeError(data, "Unfinished Array", c)
|
||||
}
|
||||
}
|
||||
SCOPE_OBJ_EMPTY, SCOPE_OBJ_FILLED -> {
|
||||
SCOPE_OBJ_EMPTY,
|
||||
SCOPE_OBJ_FILLED -> {
|
||||
this.scopes.last = SCOPE_OBJ_KEY
|
||||
// Look for a comma before the next element.
|
||||
if (scope == SCOPE_OBJ_FILLED) {
|
||||
@@ -490,11 +504,12 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
}
|
||||
return when (val c = skipWhitespace(data)) {
|
||||
CHAR_DOUBLE_QUOTE -> TOK_BEGIN_QUOTE
|
||||
CHAR_CLOSE_OBJECT -> if (scope != SCOPE_OBJ_FILLED) {
|
||||
TOK_END_OBJECT
|
||||
} else {
|
||||
makeError(data, "Expected Key", c)
|
||||
}
|
||||
CHAR_CLOSE_OBJECT ->
|
||||
if (scope != SCOPE_OBJ_FILLED) {
|
||||
TOK_END_OBJECT
|
||||
} else {
|
||||
makeError(data, "Expected Key", c)
|
||||
}
|
||||
else -> {
|
||||
makeError(data, "Expected Key/Value", c)
|
||||
}
|
||||
@@ -510,8 +525,7 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
SCOPE_DOC_EMPTY -> this.scopes.last = SCOPE_DOC_FILLED
|
||||
SCOPE_DOC_FILLED -> {
|
||||
val c = skipWhitespace(data)
|
||||
if (c != CHAR_EOF)
|
||||
makeError(data, "Root object already finished", c)
|
||||
if (c != CHAR_EOF) makeError(data, "Root object already finished", c)
|
||||
return TOK_EOF
|
||||
}
|
||||
}
|
||||
@@ -550,10 +564,20 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
readPos += 4
|
||||
return TOK_FALSE
|
||||
}
|
||||
CHAR_0, CHAR_1, CHAR_2, CHAR_3, CHAR_4, CHAR_5,
|
||||
CHAR_6, CHAR_7, CHAR_8, CHAR_9, CHAR_MINUS -> return TOK_NUMBER.also {
|
||||
readPos-- // rewind one position so we don't lose first digit
|
||||
}
|
||||
CHAR_0,
|
||||
CHAR_1,
|
||||
CHAR_2,
|
||||
CHAR_3,
|
||||
CHAR_4,
|
||||
CHAR_5,
|
||||
CHAR_6,
|
||||
CHAR_7,
|
||||
CHAR_8,
|
||||
CHAR_9,
|
||||
CHAR_MINUS ->
|
||||
return TOK_NUMBER.also {
|
||||
readPos-- // rewind one position so we don't lose first digit
|
||||
}
|
||||
}
|
||||
makeError(data, "Expecting element", c)
|
||||
}
|
||||
@@ -593,12 +617,13 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
while (i < end) {
|
||||
val part: Byte = data[i]
|
||||
result = (result.code shl 4).toChar()
|
||||
result += when (part) {
|
||||
in CHAR_0..CHAR_9 -> part - CHAR_0
|
||||
in CHAR_a..CHAR_f -> part - CHAR_a + 10
|
||||
in CHAR_A..CHAR_F -> part - CHAR_A + 10
|
||||
else -> makeError(data, "Invalid utf8 escaped character", -1)
|
||||
}
|
||||
result +=
|
||||
when (part) {
|
||||
in CHAR_0..CHAR_9 -> part - CHAR_0
|
||||
in CHAR_a..CHAR_f -> part - CHAR_a + 10
|
||||
in CHAR_A..CHAR_F -> part - CHAR_A + 10
|
||||
else -> makeError(data, "Invalid utf8 escaped character", -1)
|
||||
}
|
||||
i++
|
||||
}
|
||||
result
|
||||
@@ -608,16 +633,19 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
CHAR_r -> '\r'
|
||||
CHAR_n -> '\n'
|
||||
CHAR_f -> 12.toChar() // '\f'
|
||||
CHAR_DOUBLE_QUOTE, CHAR_BACKSLASH, CHAR_FORWARDSLASH -> byte1.toInt().toChar()
|
||||
CHAR_DOUBLE_QUOTE,
|
||||
CHAR_BACKSLASH,
|
||||
CHAR_FORWARDSLASH -> byte1.toInt().toChar()
|
||||
else -> makeError(data, "Invalid escape sequence.", byte1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Byte.print(): String = when (this) {
|
||||
in 0x21..0x7E -> "'${this.toInt().toChar()}'" // visible ascii chars
|
||||
CHAR_EOF -> "EOF"
|
||||
else -> "'0x${this.toString(16)}'"
|
||||
}
|
||||
private fun Byte.print(): String =
|
||||
when (this) {
|
||||
in 0x21..0x7E -> "'${this.toInt().toChar()}'" // visible ascii chars
|
||||
CHAR_EOF -> "EOF"
|
||||
else -> "'0x${this.toString(16)}'"
|
||||
}
|
||||
|
||||
private inline fun makeError(data: ReadBuffer, msg: String, tok: Byte? = null): Nothing {
|
||||
val (line, column) = calculateErrorPosition(data, readPos)
|
||||
@@ -634,8 +662,7 @@ public class JSONParser(public var output: FlexBuffersBuilder = FlexBuffersBuild
|
||||
}
|
||||
|
||||
private inline fun checkEOF(data: ReadBuffer, pos: Int) {
|
||||
if (pos >= data.limit)
|
||||
makeError(data, "Unexpected end of file", -1)
|
||||
if (pos >= data.limit) makeError(data, "Unexpected end of file", -1)
|
||||
}
|
||||
|
||||
private fun calculateErrorPosition(data: ReadBuffer, endPos: Int): Pair<Int, Int> {
|
||||
@@ -686,22 +713,23 @@ private inline fun ReadWriteBuffer.jsonEscape(data: ReadBuffer, start: Int, size
|
||||
}
|
||||
|
||||
// Following escape strategy defined in RFC7159.
|
||||
private val JSON_ESCAPE_CHARS: Array<ByteArray?> = arrayOfNulls<ByteArray>(128).apply {
|
||||
this['\n'.code] = "\\n".encodeToByteArray()
|
||||
this['\t'.code] = "\\t".encodeToByteArray()
|
||||
this['\r'.code] = "\\r".encodeToByteArray()
|
||||
this['\b'.code] = "\\b".encodeToByteArray()
|
||||
this[0x0c] = "\\f".encodeToByteArray()
|
||||
this['"'.code] = "\\\"".encodeToByteArray()
|
||||
this['\\'.code] = "\\\\".encodeToByteArray()
|
||||
for (i in 0..0x1f) {
|
||||
this[i] = "\\u${i.toPaddedHex()}".encodeToByteArray()
|
||||
private val JSON_ESCAPE_CHARS: Array<ByteArray?> =
|
||||
arrayOfNulls<ByteArray>(128).apply {
|
||||
this['\n'.code] = "\\n".encodeToByteArray()
|
||||
this['\t'.code] = "\\t".encodeToByteArray()
|
||||
this['\r'.code] = "\\r".encodeToByteArray()
|
||||
this['\b'.code] = "\\b".encodeToByteArray()
|
||||
this[0x0c] = "\\f".encodeToByteArray()
|
||||
this['"'.code] = "\\\"".encodeToByteArray()
|
||||
this['\\'.code] = "\\\\".encodeToByteArray()
|
||||
for (i in 0..0x1f) {
|
||||
this[i] = "\\u${i.toPaddedHex()}".encodeToByteArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scope is used to the define current space that the scanner is operating.
|
||||
@JvmInline
|
||||
private value class Scope(val id: Int)
|
||||
@JvmInline private value class Scope(val id: Int)
|
||||
|
||||
private val SCOPE_DOC_EMPTY = Scope(0)
|
||||
private val SCOPE_DOC_FILLED = Scope(1)
|
||||
private val SCOPE_OBJ_EMPTY = Scope(2)
|
||||
@@ -714,7 +742,7 @@ private val SCOPE_ARRAY_FILLED = Scope(6)
|
||||
// max stack size of 22, as per tests cases defined in http://json.org/JSON_checker/
|
||||
private class ScopeStack(
|
||||
private val ary: IntArray = IntArray(22) { SCOPE_DOC_EMPTY.id },
|
||||
var lastPos: Int = 0
|
||||
var lastPos: Int = 0,
|
||||
) {
|
||||
var last: Scope
|
||||
get() = Scope(ary[lastPos])
|
||||
@@ -743,20 +771,21 @@ private class ScopeStack(
|
||||
|
||||
@JvmInline
|
||||
private value class Token(val id: Int) {
|
||||
fun print(): String = when (this) {
|
||||
TOK_EOF -> "TOK_EOF"
|
||||
TOK_NONE -> "TOK_NONE"
|
||||
TOK_BEGIN_OBJECT -> "TOK_BEGIN_OBJECT"
|
||||
TOK_END_OBJECT -> "TOK_END_OBJECT"
|
||||
TOK_BEGIN_ARRAY -> "TOK_BEGIN_ARRAY"
|
||||
TOK_END_ARRAY -> "TOK_END_ARRAY"
|
||||
TOK_NUMBER -> "TOK_NUMBER"
|
||||
TOK_TRUE -> "TOK_TRUE"
|
||||
TOK_FALSE -> "TOK_FALSE"
|
||||
TOK_NULL -> "TOK_NULL"
|
||||
TOK_BEGIN_QUOTE -> "TOK_BEGIN_QUOTE"
|
||||
else -> this.toString()
|
||||
}
|
||||
fun print(): String =
|
||||
when (this) {
|
||||
TOK_EOF -> "TOK_EOF"
|
||||
TOK_NONE -> "TOK_NONE"
|
||||
TOK_BEGIN_OBJECT -> "TOK_BEGIN_OBJECT"
|
||||
TOK_END_OBJECT -> "TOK_END_OBJECT"
|
||||
TOK_BEGIN_ARRAY -> "TOK_BEGIN_ARRAY"
|
||||
TOK_END_ARRAY -> "TOK_END_ARRAY"
|
||||
TOK_NUMBER -> "TOK_NUMBER"
|
||||
TOK_TRUE -> "TOK_TRUE"
|
||||
TOK_FALSE -> "TOK_FALSE"
|
||||
TOK_NULL -> "TOK_NULL"
|
||||
TOK_BEGIN_QUOTE -> "TOK_BEGIN_QUOTE"
|
||||
else -> this.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private val TOK_EOF = Token(-1)
|
||||
@@ -813,20 +842,265 @@ private const val CHAR_DOT = '.'.code.toByte()
|
||||
// bit 0 (1) - set if: plain ASCII string character
|
||||
// bit 1 (2) - set if: whitespace
|
||||
// bit 4 (0x10) - set if: 0-9 e E .
|
||||
private val parseFlags = byteArrayOf(
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
||||
3, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x11, 1, // 2
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 1, 1, 1, 1, 1, 1, // 3
|
||||
1, 1, 1, 1, 1, 0x11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 5
|
||||
1, 1, 1, 1, 1, 0x11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
|
||||
private val parseFlags =
|
||||
byteArrayOf(
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0, // 0
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 1
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0x11,
|
||||
1, // 2
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 3
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0x11,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 4
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1, // 5
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0x11,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 6
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 7
|
||||
|
||||
// 128-255
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
)
|
||||
// 128-255
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
|
||||
@@ -35,8 +35,7 @@ fun arrayFailMessage(expected: ShortArray, actual: ShortArray): String =
|
||||
fun arrayFailMessage(expected: LongArray, actual: LongArray): String =
|
||||
failMessage(expected.contentToString(), actual.contentToString())
|
||||
|
||||
fun failMessage(expected: String, actual: String): String =
|
||||
"Expected: $expected\nActual: $actual"
|
||||
fun failMessage(expected: String, actual: String): String = "Expected: $expected\nActual: $actual"
|
||||
|
||||
fun arrayFailMessage(expected: FloatArray, actual: FloatArray): String {
|
||||
return "Expected: ${expected.contentToString()}\nActual: ${actual.contentToString()}"
|
||||
|
||||
@@ -16,10 +16,10 @@ class BuffersTest {
|
||||
|
||||
assertEquals(bytes.size, fullRead.limit)
|
||||
assertEquals(text, fullRead.getString(0, fullRead.limit))
|
||||
assertEquals("Hello" , helloRead.getString(0, helloRead.limit))
|
||||
assertEquals("world!" , worldRead.getString())
|
||||
assertEquals(fullRead.getString(0, 5) , helloRead.getString(0, helloRead.limit))
|
||||
assertEquals(fullRead.getString(6, 6) , worldRead.getString(0, worldRead.limit))
|
||||
assertEquals("Hello", helloRead.getString(0, helloRead.limit))
|
||||
assertEquals("world!", worldRead.getString())
|
||||
assertEquals(fullRead.getString(0, 5), helloRead.getString(0, helloRead.limit))
|
||||
assertEquals(fullRead.getString(6, 6), worldRead.getString(0, worldRead.limit))
|
||||
|
||||
for (i in 0 until helloRead.limit) {
|
||||
assertEquals(fullRead[i], helloRead[i])
|
||||
|
||||
@@ -17,18 +17,18 @@ package com.google.flatbuffers.kotlin
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ByteArrayTest {
|
||||
|
||||
@Test
|
||||
fun testByte() {
|
||||
val testSet = arrayOf(
|
||||
67.toByte() to byteArrayOf(67),
|
||||
Byte.MIN_VALUE to byteArrayOf(-128),
|
||||
Byte.MAX_VALUE to byteArrayOf(127),
|
||||
0.toByte() to byteArrayOf(0)
|
||||
)
|
||||
val testSet =
|
||||
arrayOf(
|
||||
67.toByte() to byteArrayOf(67),
|
||||
Byte.MIN_VALUE to byteArrayOf(-128),
|
||||
Byte.MAX_VALUE to byteArrayOf(127),
|
||||
0.toByte() to byteArrayOf(0),
|
||||
)
|
||||
val data = ByteArray(1)
|
||||
testSet.forEach {
|
||||
data[0] = it.first
|
||||
@@ -39,12 +39,13 @@ class ByteArrayTest {
|
||||
|
||||
@Test
|
||||
fun testShort() {
|
||||
val testSet = arrayOf(
|
||||
6712.toShort() to byteArrayOf(56, 26),
|
||||
Short.MIN_VALUE to byteArrayOf(0, -128),
|
||||
Short.MAX_VALUE to byteArrayOf(-1, 127),
|
||||
0.toShort() to byteArrayOf(0, 0,)
|
||||
)
|
||||
val testSet =
|
||||
arrayOf(
|
||||
6712.toShort() to byteArrayOf(56, 26),
|
||||
Short.MIN_VALUE to byteArrayOf(0, -128),
|
||||
Short.MAX_VALUE to byteArrayOf(-1, 127),
|
||||
0.toShort() to byteArrayOf(0, 0),
|
||||
)
|
||||
|
||||
val data = ByteArray(Short.SIZE_BYTES)
|
||||
testSet.forEach {
|
||||
@@ -56,12 +57,13 @@ class ByteArrayTest {
|
||||
|
||||
@Test
|
||||
fun testInt() {
|
||||
val testSet = arrayOf(
|
||||
33333500 to byteArrayOf(-4, -96, -4, 1),
|
||||
Int.MIN_VALUE to byteArrayOf(0, 0, 0, -128),
|
||||
Int.MAX_VALUE to byteArrayOf(-1, -1, -1, 127),
|
||||
0 to byteArrayOf(0, 0, 0, 0)
|
||||
)
|
||||
val testSet =
|
||||
arrayOf(
|
||||
33333500 to byteArrayOf(-4, -96, -4, 1),
|
||||
Int.MIN_VALUE to byteArrayOf(0, 0, 0, -128),
|
||||
Int.MAX_VALUE to byteArrayOf(-1, -1, -1, 127),
|
||||
0 to byteArrayOf(0, 0, 0, 0),
|
||||
)
|
||||
val data = ByteArray(Int.SIZE_BYTES)
|
||||
testSet.forEach {
|
||||
data.setInt(0, it.first)
|
||||
@@ -72,13 +74,14 @@ class ByteArrayTest {
|
||||
|
||||
@Test
|
||||
fun testLong() {
|
||||
val testSet = arrayOf(
|
||||
1234567123122890123L to byteArrayOf(-117, -91, 29, -23, 65, 16, 34, 17),
|
||||
-1L to byteArrayOf(-1, -1, -1, -1, -1, -1, -1, -1),
|
||||
Long.MIN_VALUE to byteArrayOf(0, 0, 0, 0, 0, 0, 0, -128),
|
||||
Long.MAX_VALUE to byteArrayOf(-1, -1, -1, -1, -1, -1, -1, 127),
|
||||
0L to byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0)
|
||||
)
|
||||
val testSet =
|
||||
arrayOf(
|
||||
1234567123122890123L to byteArrayOf(-117, -91, 29, -23, 65, 16, 34, 17),
|
||||
-1L to byteArrayOf(-1, -1, -1, -1, -1, -1, -1, -1),
|
||||
Long.MIN_VALUE to byteArrayOf(0, 0, 0, 0, 0, 0, 0, -128),
|
||||
Long.MAX_VALUE to byteArrayOf(-1, -1, -1, -1, -1, -1, -1, 127),
|
||||
0L to byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0),
|
||||
)
|
||||
val data = ByteArray(Long.SIZE_BYTES)
|
||||
testSet.forEach {
|
||||
data.setLong(0, it.first)
|
||||
@@ -89,12 +92,13 @@ class ByteArrayTest {
|
||||
|
||||
@Test
|
||||
fun testULong() {
|
||||
val testSet = arrayOf(
|
||||
1234567123122890123UL to byteArrayOf(-117, -91, 29, -23, 65, 16, 34, 17),
|
||||
ULong.MIN_VALUE to byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0),
|
||||
(-1L).toULong() to byteArrayOf(-1, -1, -1, -1, -1, -1, -1, -1),
|
||||
0UL to byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0)
|
||||
)
|
||||
val testSet =
|
||||
arrayOf(
|
||||
1234567123122890123UL to byteArrayOf(-117, -91, 29, -23, 65, 16, 34, 17),
|
||||
ULong.MIN_VALUE to byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0),
|
||||
(-1L).toULong() to byteArrayOf(-1, -1, -1, -1, -1, -1, -1, -1),
|
||||
0UL to byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0),
|
||||
)
|
||||
val data = ByteArray(ULong.SIZE_BYTES)
|
||||
testSet.forEach {
|
||||
data.setULong(0, it.first)
|
||||
@@ -105,12 +109,13 @@ class ByteArrayTest {
|
||||
|
||||
@Test
|
||||
fun testFloat() {
|
||||
val testSet = arrayOf(
|
||||
3545.56337f to byteArrayOf(4, -103, 93, 69),
|
||||
Float.MIN_VALUE to byteArrayOf(1, 0, 0, 0),
|
||||
Float.MAX_VALUE to byteArrayOf(-1, -1, 127, 127),
|
||||
0f to byteArrayOf(0, 0, 0, 0)
|
||||
)
|
||||
val testSet =
|
||||
arrayOf(
|
||||
3545.56337f to byteArrayOf(4, -103, 93, 69),
|
||||
Float.MIN_VALUE to byteArrayOf(1, 0, 0, 0),
|
||||
Float.MAX_VALUE to byteArrayOf(-1, -1, 127, 127),
|
||||
0f to byteArrayOf(0, 0, 0, 0),
|
||||
)
|
||||
val data = ByteArray(Float.SIZE_BYTES)
|
||||
testSet.forEach {
|
||||
data.setFloat(0, it.first)
|
||||
@@ -120,12 +125,13 @@ class ByteArrayTest {
|
||||
|
||||
@Test
|
||||
fun testDouble() {
|
||||
val testSet = arrayOf(
|
||||
123456.523423423412 to byteArrayOf(88, 61, -15, 95, 8, 36, -2, 64),
|
||||
Double.MIN_VALUE to byteArrayOf(1, 0, 0, 0, 0, 0, 0, 0),
|
||||
Double.MAX_VALUE to byteArrayOf(-1, -1, -1, -1, -1, -1, -17, 127),
|
||||
0.0 to byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0)
|
||||
)
|
||||
val testSet =
|
||||
arrayOf(
|
||||
123456.523423423412 to byteArrayOf(88, 61, -15, 95, 8, 36, -2, 64),
|
||||
Double.MIN_VALUE to byteArrayOf(1, 0, 0, 0, 0, 0, 0, 0),
|
||||
Double.MAX_VALUE to byteArrayOf(-1, -1, -1, -1, -1, -1, -17, 127),
|
||||
0.0 to byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0),
|
||||
)
|
||||
val data = ByteArray(Long.SIZE_BYTES)
|
||||
testSet.forEach {
|
||||
data.setDouble(0, it.first)
|
||||
@@ -144,4 +150,3 @@ class ByteArrayTest {
|
||||
assertEquals(testSet, data.getString(0, encoded.size))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,19 +18,17 @@
|
||||
package com.google.flatbuffers.kotlin
|
||||
|
||||
import Attacker
|
||||
import AttackerOffsetArray
|
||||
import CharacterEArray
|
||||
import dictionaryLookup.LongFloatEntry
|
||||
import dictionaryLookup.LongFloatMap
|
||||
import Movie
|
||||
import dictionaryLookup.LongFloatEntry
|
||||
import dictionaryLookup.LongFloatEntryOffsetArray
|
||||
import dictionaryLookup.LongFloatMap
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import myGame.example.*
|
||||
import myGame.example.Test.Companion.createTest
|
||||
import optionalScalars.OptionalByte
|
||||
import optionalScalars.ScalarStuff
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
class FlatBufferBuilderTest {
|
||||
@@ -43,10 +41,8 @@ class FlatBufferBuilderTest {
|
||||
val inv = Monster.createInventoryVector(fbb, invValues)
|
||||
Monster.startMonster(fbb)
|
||||
Monster.addPos(
|
||||
fbb, Vec3.createVec3(
|
||||
fbb, 1.0f, 2.0f, 3.0f, 3.0,
|
||||
Color.Green, 5.toShort(), 6.toByte()
|
||||
)
|
||||
fbb,
|
||||
Vec3.createVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0, Color.Green, 5.toShort(), 6.toByte()),
|
||||
)
|
||||
Monster.addHp(fbb, 80.toShort())
|
||||
Monster.addName(fbb, name)
|
||||
@@ -86,12 +82,14 @@ class FlatBufferBuilderTest {
|
||||
@Test
|
||||
fun testSortedVector() {
|
||||
val fbb = FlatBufferBuilder()
|
||||
val names = arrayOf(fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma"))
|
||||
val monsters = MonsterOffsetArray(3) {
|
||||
Monster.startMonster(fbb)
|
||||
Monster.addName(fbb, names[it])
|
||||
Monster.endMonster(fbb)
|
||||
}
|
||||
val names =
|
||||
arrayOf(fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma"))
|
||||
val monsters =
|
||||
MonsterOffsetArray(3) {
|
||||
Monster.startMonster(fbb)
|
||||
Monster.addName(fbb, names[it])
|
||||
Monster.endMonster(fbb)
|
||||
}
|
||||
val ary = Monster.createTestarrayoftablesVector(fbb, monsters)
|
||||
Monster.startMonster(fbb)
|
||||
Monster.addName(fbb, names[0])
|
||||
@@ -161,7 +159,8 @@ class FlatBufferBuilderTest {
|
||||
@Test
|
||||
fun testBuilderBasics() {
|
||||
val fbb = FlatBufferBuilder()
|
||||
val names = arrayOf(fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma"))
|
||||
val names =
|
||||
arrayOf(fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma"))
|
||||
val off = Array<Offset<Monster>>(3) { Offset(0) }
|
||||
Monster.startMonster(fbb)
|
||||
Monster.addName(fbb, names[0])
|
||||
@@ -176,7 +175,7 @@ class FlatBufferBuilderTest {
|
||||
|
||||
// We set up the same values as monsterdata.json:
|
||||
|
||||
val inv = Monster.createInventoryVector(fbb, byteArrayOf(0,1,2,3,4).toUByteArray())
|
||||
val inv = Monster.createInventoryVector(fbb, byteArrayOf(0, 1, 2, 3, 4).toUByteArray())
|
||||
|
||||
val fred = fbb.createString("Fred")
|
||||
Monster.startMonster(fbb)
|
||||
@@ -189,15 +188,14 @@ class FlatBufferBuilderTest {
|
||||
val test4 = fbb.endVector<myGame.example.Test>()
|
||||
|
||||
val strings = StringOffsetArray(2) { fbb.createString("test$it") }
|
||||
val testArrayOfString =
|
||||
Monster.createTestarrayofstringVector(fbb, strings)
|
||||
val testArrayOfString = Monster.createTestarrayofstringVector(fbb, strings)
|
||||
|
||||
Monster.startMonster(fbb)
|
||||
Monster.addName(fbb, names[0])
|
||||
Monster.addPos(fbb, Vec3.createVec3(
|
||||
fbb, 1.0f, 2.0f, 3.0f, 3.0,
|
||||
Color.Green, 5.toShort(), 6.toByte()
|
||||
))
|
||||
Monster.addPos(
|
||||
fbb,
|
||||
Vec3.createVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0, Color.Green, 5.toShort(), 6.toByte()),
|
||||
)
|
||||
Monster.addHp(fbb, 80)
|
||||
Monster.addMana(fbb, 150)
|
||||
Monster.addInventory(fbb, inv)
|
||||
@@ -210,7 +208,7 @@ class FlatBufferBuilderTest {
|
||||
Monster.addTestarrayoftables(fbb, sortMons)
|
||||
val mon = Monster.endMonster(fbb)
|
||||
Monster.finishMonsterBuffer(fbb, mon)
|
||||
//Attempt to mutate Monster fields and check whether the buffer has been mutated properly
|
||||
// Attempt to mutate Monster fields and check whether the buffer has been mutated properly
|
||||
// revert to original values after testing
|
||||
val monster = Monster.asRoot(fbb.dataBuffer())
|
||||
|
||||
@@ -255,14 +253,12 @@ class FlatBufferBuilderTest {
|
||||
CharacterE.MuLan,
|
||||
attacker,
|
||||
Movie.createCharactersTypeVector(fbb, characters),
|
||||
Movie.createCharactersVector(fbb, attackers)
|
||||
)
|
||||
Movie.createCharactersVector(fbb, attackers),
|
||||
),
|
||||
)
|
||||
|
||||
val movie: Movie = Movie.asRoot(fbb.dataBuffer())
|
||||
|
||||
|
||||
|
||||
assertEquals(movie.charactersTypeLength, 1)
|
||||
assertEquals(movie.charactersLength, 1)
|
||||
|
||||
@@ -326,7 +322,7 @@ class FlatBufferBuilderTest {
|
||||
fbb.clear()
|
||||
|
||||
val largeData = ByteArray(1024)
|
||||
offset = fbb.createByteVector(largeData) as VectorOffset<UByte> //TODO: fix me
|
||||
offset = fbb.createByteVector(largeData) as VectorOffset<UByte> // TODO: fix me
|
||||
str = fbb.createString("ByteMonster")
|
||||
Monster.startMonster(fbb)
|
||||
Monster.addName(fbb, str)
|
||||
@@ -340,7 +336,7 @@ class FlatBufferBuilderTest {
|
||||
fbb.clear()
|
||||
|
||||
var bb = ArrayReadBuffer(largeData, 512)
|
||||
offset = fbb.createByteVector(bb) as VectorOffset<UByte> //TODO: fix me
|
||||
offset = fbb.createByteVector(bb) as VectorOffset<UByte> // TODO: fix me
|
||||
str = fbb.createString("ByteMonster")
|
||||
Monster.startMonster(fbb)
|
||||
Monster.addName(fbb, str)
|
||||
@@ -354,7 +350,7 @@ class FlatBufferBuilderTest {
|
||||
|
||||
bb = ArrayReadBuffer(largeData, largeData.size - 216)
|
||||
val stringBuffer = ArrayReadBuffer("AlreadyBufferedString".encodeToByteArray())
|
||||
offset = fbb.createByteVector(bb) as VectorOffset<UByte> //TODO: fix me
|
||||
offset = fbb.createByteVector(bb) as VectorOffset<UByte> // TODO: fix me
|
||||
str = fbb.createString(stringBuffer)
|
||||
Monster.startMonster(fbb)
|
||||
Monster.addName(fbb, str)
|
||||
@@ -507,19 +503,19 @@ class FlatBufferBuilderTest {
|
||||
assertEquals(scalarStuff.defaultEnum, OptionalByte.Two)
|
||||
}
|
||||
|
||||
// @todo Seems like nesting code generation is broken for all generators.
|
||||
// disabling test for now.
|
||||
// @Test
|
||||
// fun testNamespaceNesting() {
|
||||
// // reference / manipulate these to verify compilation
|
||||
// val fbb = FlatBufferBuilder(1)
|
||||
// TableInNestedNS.startTableInNestedNS(fbb)
|
||||
// TableInNestedNS.addFoo(fbb, 1234)
|
||||
// val nestedTableOff = TableInNestedNS.endTableInNestedNs(fbb)
|
||||
// TableInFirstNS.startTableInFirstNS(fbb)
|
||||
// TableInFirstNS.addFooTable(fbb, nestedTableOff)
|
||||
// TableInFirstNS.endTableInFirstNs(fbb)
|
||||
// }
|
||||
// @todo Seems like nesting code generation is broken for all generators.
|
||||
// disabling test for now.
|
||||
// @Test
|
||||
// fun testNamespaceNesting() {
|
||||
// // reference / manipulate these to verify compilation
|
||||
// val fbb = FlatBufferBuilder(1)
|
||||
// TableInNestedNS.startTableInNestedNS(fbb)
|
||||
// TableInNestedNS.addFoo(fbb, 1234)
|
||||
// val nestedTableOff = TableInNestedNS.endTableInNestedNs(fbb)
|
||||
// TableInFirstNS.startTableInFirstNS(fbb)
|
||||
// TableInFirstNS.addFooTable(fbb, nestedTableOff)
|
||||
// TableInFirstNS.endTableInFirstNs(fbb)
|
||||
// }
|
||||
|
||||
@Test
|
||||
fun testNestedFlatBuffer() {
|
||||
@@ -558,7 +554,8 @@ class FlatBufferBuilderTest {
|
||||
fun testDictionaryLookup() {
|
||||
val fbb = FlatBufferBuilder(16)
|
||||
val lfIndex = LongFloatEntry.createLongFloatEntry(fbb, 0, 99.0f)
|
||||
val vectorEntriesIdx = LongFloatMap.createEntriesVector(fbb, LongFloatEntryOffsetArray(1) { lfIndex })
|
||||
val vectorEntriesIdx =
|
||||
LongFloatMap.createEntriesVector(fbb, LongFloatEntryOffsetArray(1) { lfIndex })
|
||||
val rootIdx = LongFloatMap.createLongFloatMap(fbb, vectorEntriesIdx)
|
||||
LongFloatMap.finishLongFloatMapBuffer(fbb, rootIdx)
|
||||
val map: LongFloatMap = LongFloatMap.asRoot(fbb.dataBuffer())
|
||||
|
||||
@@ -24,12 +24,13 @@ class FlexBuffersTest {
|
||||
|
||||
@Test
|
||||
fun testWriteInt() {
|
||||
val values = listOf(
|
||||
Byte.MAX_VALUE.toLong() to 3,
|
||||
Short.MAX_VALUE.toLong() to 4,
|
||||
Int.MAX_VALUE.toLong() to 6,
|
||||
Long.MAX_VALUE to 10
|
||||
)
|
||||
val values =
|
||||
listOf(
|
||||
Byte.MAX_VALUE.toLong() to 3,
|
||||
Short.MAX_VALUE.toLong() to 4,
|
||||
Int.MAX_VALUE.toLong() to 6,
|
||||
Long.MAX_VALUE to 10,
|
||||
)
|
||||
val builder = FlexBuffersBuilder()
|
||||
values.forEach {
|
||||
builder.clear()
|
||||
@@ -44,12 +45,13 @@ class FlexBuffersTest {
|
||||
|
||||
@Test
|
||||
fun testWriteUInt() {
|
||||
val values = listOf(
|
||||
UByte.MAX_VALUE.toULong() to 3,
|
||||
UShort.MAX_VALUE.toULong() to 4,
|
||||
UInt.MAX_VALUE.toULong() to 6,
|
||||
ULong.MAX_VALUE to 10
|
||||
)
|
||||
val values =
|
||||
listOf(
|
||||
UByte.MAX_VALUE.toULong() to 3,
|
||||
UShort.MAX_VALUE.toULong() to 4,
|
||||
UInt.MAX_VALUE.toULong() to 6,
|
||||
ULong.MAX_VALUE to 10,
|
||||
)
|
||||
val builder = FlexBuffersBuilder()
|
||||
values.forEach {
|
||||
builder.clear()
|
||||
@@ -126,7 +128,8 @@ class FlexBuffersTest {
|
||||
|
||||
@Test
|
||||
fun testLongArray() {
|
||||
val ary: LongArray = longArrayOf(0, Short.MIN_VALUE.toLong(), Int.MAX_VALUE.toLong(), Long.MAX_VALUE)
|
||||
val ary: LongArray =
|
||||
longArrayOf(0, Short.MIN_VALUE.toLong(), Int.MAX_VALUE.toLong(), Long.MAX_VALUE)
|
||||
val builder = FlexBuffersBuilder()
|
||||
builder.put(ary)
|
||||
val data = builder.finish()
|
||||
@@ -139,9 +142,7 @@ class FlexBuffersTest {
|
||||
fun testStringArray() {
|
||||
val ary = Array(5) { "Hello world number: $it" }
|
||||
val builder = FlexBuffersBuilder(ArrayReadWriteBuffer(20), SHARE_NONE)
|
||||
builder.putVector {
|
||||
ary.forEach { put(it) }
|
||||
}
|
||||
builder.putVector { ary.forEach { put(it) } }
|
||||
val data = builder.finish()
|
||||
val vec = getRoot(data).toVector()
|
||||
// although we put a long, it is shrink to a byte
|
||||
@@ -237,9 +238,7 @@ class FlexBuffersTest {
|
||||
this["int"] = 10
|
||||
this["float"] = 12.3
|
||||
this["intarray"] = intArrayOf(1, 2, 3, 4, 5)
|
||||
this.putMap("myMap") {
|
||||
this["cool"] = "beans"
|
||||
}
|
||||
this.putMap("myMap") { this["cool"] = "beans" }
|
||||
}
|
||||
|
||||
val ref = getRoot(builder.finish())
|
||||
@@ -257,7 +256,9 @@ class FlexBuffersTest {
|
||||
assertEquals(true, ref["invalid_key"].isNull)
|
||||
|
||||
val keys = map.keys.toTypedArray()
|
||||
arrayOf("hello", "int", "float", "intarray", "myMap").sortedArray().forEachIndexed { i: Int, it: String ->
|
||||
arrayOf("hello", "int", "float", "intarray", "myMap").sortedArray().forEachIndexed {
|
||||
i: Int,
|
||||
it: String ->
|
||||
assertEquals(it, keys[i].toString())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,11 @@ class JSONTest {
|
||||
|
||||
@Test
|
||||
fun parse2Test() {
|
||||
val dataStr = """
|
||||
{ "myKey" : [1, "yay"] }
|
||||
""".trimIndent()
|
||||
val dataStr =
|
||||
"""
|
||||
{ "myKey" : [1, "yay"] }
|
||||
"""
|
||||
.trimIndent()
|
||||
val data = dataStr.encodeToByteArray()
|
||||
val buffer = ArrayReadWriteBuffer(data, writePosition = data.size)
|
||||
val parser = JSONParser()
|
||||
@@ -35,7 +37,8 @@ class JSONTest {
|
||||
|
||||
@Test
|
||||
fun parseSample() {
|
||||
val dataStr = """
|
||||
val dataStr =
|
||||
"""
|
||||
{
|
||||
"ary" : [1, 2, 3],
|
||||
"boolean_false": false,
|
||||
@@ -69,26 +72,29 @@ class JSONTest {
|
||||
val obj = map["object"]
|
||||
assertEquals(true, obj.isMap)
|
||||
assertEquals("{\"field1\":\"hello\"}", obj.toJson())
|
||||
// TODO: Kotlin Double.toString() produce different strings dependending on the platform, so on JVM
|
||||
// TODO: Kotlin Double.toString() produce different strings dependending on the platform, so on
|
||||
// JVM
|
||||
// is 1.2E33, while on js is 1.2e+33. For now we are disabling this test.
|
||||
//
|
||||
// val minified = data.filterNot { it == ' '.toByte() || it == '\n'.toByte() }.toByteArray().decodeToString()
|
||||
// val minified = data.filterNot { it == ' '.toByte() || it == '\n'.toByte()
|
||||
// }.toByteArray().decodeToString()
|
||||
// assertEquals(minified, root.toJson())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDoubles() {
|
||||
val values = arrayOf(
|
||||
"-0.0",
|
||||
"1.0",
|
||||
"1.7976931348613157",
|
||||
"0.0",
|
||||
"-0.5",
|
||||
"3.141592653589793",
|
||||
"2.718281828459045E-3",
|
||||
"2.2250738585072014E-308",
|
||||
"4.9E-15",
|
||||
)
|
||||
val values =
|
||||
arrayOf(
|
||||
"-0.0",
|
||||
"1.0",
|
||||
"1.7976931348613157",
|
||||
"0.0",
|
||||
"-0.5",
|
||||
"3.141592653589793",
|
||||
"2.718281828459045E-3",
|
||||
"2.2250738585072014E-308",
|
||||
"4.9E-15",
|
||||
)
|
||||
val parser = JSONParser()
|
||||
assertEquals(-0.0, parser.parse(values[0]).toDouble())
|
||||
assertEquals(1.0, parser.parse(values[1]).toDouble())
|
||||
@@ -103,15 +109,16 @@ class JSONTest {
|
||||
|
||||
@Test
|
||||
fun testInts() {
|
||||
val values = arrayOf(
|
||||
"-0",
|
||||
"0",
|
||||
"-1",
|
||||
"${Int.MAX_VALUE}",
|
||||
"${Int.MIN_VALUE}",
|
||||
"${Long.MAX_VALUE}",
|
||||
"${Long.MIN_VALUE}",
|
||||
)
|
||||
val values =
|
||||
arrayOf(
|
||||
"-0",
|
||||
"0",
|
||||
"-1",
|
||||
"${Int.MAX_VALUE}",
|
||||
"${Int.MIN_VALUE}",
|
||||
"${Long.MAX_VALUE}",
|
||||
"${Long.MIN_VALUE}",
|
||||
)
|
||||
val parser = JSONParser()
|
||||
|
||||
assertEquals(parser.parse(values[0]).toInt(), 0)
|
||||
@@ -125,11 +132,7 @@ class JSONTest {
|
||||
|
||||
@Test
|
||||
fun testBooleansAndNull() {
|
||||
val values = arrayOf(
|
||||
"true",
|
||||
"false",
|
||||
"null"
|
||||
)
|
||||
val values = arrayOf("true", "false", "null")
|
||||
val parser = JSONParser()
|
||||
|
||||
assertEquals(true, parser.parse(values[0]).toBoolean())
|
||||
@@ -139,16 +142,17 @@ class JSONTest {
|
||||
|
||||
@Test
|
||||
fun testStrings() {
|
||||
val values = arrayOf(
|
||||
"\"\"",
|
||||
"\"a\"",
|
||||
"\"hello world\"",
|
||||
"\"\\\"\\\\\\/\\b\\f\\n\\r\\t cool\"",
|
||||
"\"\\u0000\"",
|
||||
"\"\\u0021\"",
|
||||
"\"hell\\u24AC\\n\\ro wor \\u0021 ld\"",
|
||||
"\"\\/_\\\\_\\\"_\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\n\\r\\t`1~!@#\$%^&*()_+-=[]{}|;:',./<>?\"",
|
||||
)
|
||||
val values =
|
||||
arrayOf(
|
||||
"\"\"",
|
||||
"\"a\"",
|
||||
"\"hello world\"",
|
||||
"\"\\\"\\\\\\/\\b\\f\\n\\r\\t cool\"",
|
||||
"\"\\u0000\"",
|
||||
"\"\\u0021\"",
|
||||
"\"hell\\u24AC\\n\\ro wor \\u0021 ld\"",
|
||||
"\"\\/_\\\\_\\\"_\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\n\\r\\t`1~!@#\$%^&*()_+-=[]{}|;:',./<>?\"",
|
||||
)
|
||||
val parser = JSONParser()
|
||||
|
||||
// empty
|
||||
@@ -189,39 +193,41 @@ class JSONTest {
|
||||
@Test
|
||||
fun testUnicode() {
|
||||
// took from test/unicode_test.json
|
||||
val data = """
|
||||
{
|
||||
"name": "unicode_test",
|
||||
"testarrayofstring": [
|
||||
"Цлїςσδε",
|
||||
"フムアムカモケモ",
|
||||
"フムヤムカモケモ",
|
||||
"㊀㊁㊂㊃㊄",
|
||||
"☳☶☲",
|
||||
"𡇙𝌆"
|
||||
],
|
||||
"testarrayoftables": [
|
||||
{
|
||||
"name": "Цлїςσδε"
|
||||
},
|
||||
{
|
||||
"name": "☳☶☲"
|
||||
},
|
||||
{
|
||||
"name": "フムヤムカモケモ"
|
||||
},
|
||||
{
|
||||
"name": "㊀㊁㊂㊃㊄"
|
||||
},
|
||||
{
|
||||
"name": "フムアムカモケモ"
|
||||
},
|
||||
{
|
||||
"name": "𡇙𝌆"
|
||||
}
|
||||
]
|
||||
}
|
||||
""".trimIndent()
|
||||
val data =
|
||||
"""
|
||||
{
|
||||
"name": "unicode_test",
|
||||
"testarrayofstring": [
|
||||
"Цлїςσδε",
|
||||
"フムアムカモケモ",
|
||||
"フムヤムカモケモ",
|
||||
"㊀㊁㊂㊃㊄",
|
||||
"☳☶☲",
|
||||
"𡇙𝌆"
|
||||
],
|
||||
"testarrayoftables": [
|
||||
{
|
||||
"name": "Цлїςσδε"
|
||||
},
|
||||
{
|
||||
"name": "☳☶☲"
|
||||
},
|
||||
{
|
||||
"name": "フムヤムカモケモ"
|
||||
},
|
||||
{
|
||||
"name": "㊀㊁㊂㊃㊄"
|
||||
},
|
||||
{
|
||||
"name": "フムアムカモケモ"
|
||||
},
|
||||
{
|
||||
"name": "𡇙𝌆"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
.trimIndent()
|
||||
val parser = JSONParser()
|
||||
val ref = parser.parse(data)
|
||||
|
||||
@@ -248,15 +254,16 @@ class JSONTest {
|
||||
|
||||
@Test
|
||||
fun testArrays() {
|
||||
val values = arrayOf(
|
||||
"[]",
|
||||
"[1]",
|
||||
"[0,1, 2,3 , 4 ]",
|
||||
"[1.0, 2.2250738585072014E-308, 4.9E-320]",
|
||||
"[1.0, 2, \"hello world\"] ",
|
||||
"[ 1.1, 2, [ \"hello\" ] ]",
|
||||
"[[[1]]]"
|
||||
)
|
||||
val values =
|
||||
arrayOf(
|
||||
"[]",
|
||||
"[1]",
|
||||
"[0,1, 2,3 , 4 ]",
|
||||
"[1.0, 2.2250738585072014E-308, 4.9E-320]",
|
||||
"[1.0, 2, \"hello world\"] ",
|
||||
"[ 1.1, 2, [ \"hello\" ] ]",
|
||||
"[[[1]]]",
|
||||
)
|
||||
val parser = JSONParser()
|
||||
|
||||
// empty
|
||||
@@ -300,47 +307,47 @@ class JSONTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Several test cases provided by json.org
|
||||
* For more details, see: http://json.org/JSON_checker/, with only
|
||||
* one exception. Single strings are considered accepted, whereas on
|
||||
* the test suit is should fail.
|
||||
* Several test cases provided by json.org For more details, see: http://json.org/JSON_checker/,
|
||||
* with only one exception. Single strings are considered accepted, whereas on the test suit is
|
||||
* should fail.
|
||||
*/
|
||||
@Test
|
||||
fun testParseMustFail() {
|
||||
val failList = listOf(
|
||||
"[\"Unclosed array\"",
|
||||
"{unquoted_key: \"keys must be quoted\"}",
|
||||
"[\"extra comma\",]",
|
||||
"[\"double extra comma\",,]",
|
||||
"[ , \"<-- missing value\"]",
|
||||
"[\"Comma after the close\"],",
|
||||
"[\"Extra close\"]]",
|
||||
"{\"Extra comma\": true,}",
|
||||
"{\"Extra value after close\": true} \"misplaced quoted value\"",
|
||||
"{\"Illegal expression\": 1 + 2}",
|
||||
"{\"Illegal invocation\": alert()}",
|
||||
"{\"Numbers cannot have leading zeroes\": 013}",
|
||||
"{\"Numbers cannot be hex\": 0x14}",
|
||||
"[\"Illegal backslash escape: \\x15\"]",
|
||||
"[\\naked]",
|
||||
"[\"Illegal backslash escape: \\017\"]",
|
||||
"[[[[[[[[[[[[[[[[[[[[[[[\"Too deep\"]]]]]]]]]]]]]]]]]]]]]]]",
|
||||
"{\"Missing colon\" null}",
|
||||
"{\"Double colon\":: null}",
|
||||
"{\"Comma instead of colon\", null}",
|
||||
"[\"Colon instead of comma\": false]",
|
||||
"[\"Bad value\", truth]",
|
||||
"['single quote']",
|
||||
"[\"\ttab\tcharacter\tin\tstring\t\"]",
|
||||
"[\"tab\\ character\\ in\\ string\\ \"]",
|
||||
"[\"line\nbreak\"]",
|
||||
"[\"line\\\nbreak\"]",
|
||||
"[0e]",
|
||||
"[0e+]",
|
||||
"[0e+-1]",
|
||||
"{\"Comma instead if closing brace\": true,",
|
||||
"[\"mismatch\"}"
|
||||
)
|
||||
val failList =
|
||||
listOf(
|
||||
"[\"Unclosed array\"",
|
||||
"{unquoted_key: \"keys must be quoted\"}",
|
||||
"[\"extra comma\",]",
|
||||
"[\"double extra comma\",,]",
|
||||
"[ , \"<-- missing value\"]",
|
||||
"[\"Comma after the close\"],",
|
||||
"[\"Extra close\"]]",
|
||||
"{\"Extra comma\": true,}",
|
||||
"{\"Extra value after close\": true} \"misplaced quoted value\"",
|
||||
"{\"Illegal expression\": 1 + 2}",
|
||||
"{\"Illegal invocation\": alert()}",
|
||||
"{\"Numbers cannot have leading zeroes\": 013}",
|
||||
"{\"Numbers cannot be hex\": 0x14}",
|
||||
"[\"Illegal backslash escape: \\x15\"]",
|
||||
"[\\naked]",
|
||||
"[\"Illegal backslash escape: \\017\"]",
|
||||
"[[[[[[[[[[[[[[[[[[[[[[[\"Too deep\"]]]]]]]]]]]]]]]]]]]]]]]",
|
||||
"{\"Missing colon\" null}",
|
||||
"{\"Double colon\":: null}",
|
||||
"{\"Comma instead of colon\", null}",
|
||||
"[\"Colon instead of comma\": false]",
|
||||
"[\"Bad value\", truth]",
|
||||
"['single quote']",
|
||||
"[\"\ttab\tcharacter\tin\tstring\t\"]",
|
||||
"[\"tab\\ character\\ in\\ string\\ \"]",
|
||||
"[\"line\nbreak\"]",
|
||||
"[\"line\\\nbreak\"]",
|
||||
"[0e]",
|
||||
"[0e+]",
|
||||
"[0e+-1]",
|
||||
"{\"Comma instead if closing brace\": true,",
|
||||
"[\"mismatch\"}",
|
||||
)
|
||||
for (data in failList) {
|
||||
try {
|
||||
JSONParser().parse(ArrayReadBuffer(data.encodeToByteArray()))
|
||||
@@ -353,73 +360,74 @@ class JSONTest {
|
||||
|
||||
@Test
|
||||
fun testParseMustPass() {
|
||||
val passList = listOf(
|
||||
"[\n" +
|
||||
" \"JSON Test Pattern pass1\",\n" +
|
||||
" {\"object with 1 member\":[\"array with 1 element\"]},\n" +
|
||||
" {},\n" +
|
||||
" [],\n" +
|
||||
" -42,\n" +
|
||||
" true,\n" +
|
||||
" false,\n" +
|
||||
" null,\n" +
|
||||
" {\n" +
|
||||
" \"integer\": 1234567890,\n" +
|
||||
" \"real\": -9876.543210,\n" +
|
||||
" \"e\": 0.123456789e-12,\n" +
|
||||
" \"E\": 1.234567890E+34,\n" +
|
||||
" \"\": 23456789012E66,\n" +
|
||||
" \"zero\": 0,\n" +
|
||||
" \"one\": 1,\n" +
|
||||
" \"space\": \" \",\n" +
|
||||
" \"quote\": \"\\\"\",\n" +
|
||||
" \"backslash\": \"\\\\\",\n" +
|
||||
" \"controls\": \"\\b\\f\\n\\r\\t\",\n" +
|
||||
" \"slash\": \"/ & \\/\",\n" +
|
||||
" \"alpha\": \"abcdefghijklmnopqrstuvwyz\",\n" +
|
||||
" \"ALPHA\": \"ABCDEFGHIJKLMNOPQRSTUVWYZ\",\n" +
|
||||
" \"digit\": \"0123456789\",\n" +
|
||||
" \"0123456789\": \"digit\",\n" +
|
||||
" \"special\": \"`1~!@#\$%^&*()_+-={':[,]}|;.</>?\",\n" +
|
||||
" \"hex\": \"\\u0123\\u4567\\u89AB\\uCDEF\\uabcd\\uef4A\",\n" +
|
||||
" \"true\": true,\n" +
|
||||
" \"false\": false,\n" +
|
||||
" \"null\": null,\n" +
|
||||
" \"array\":[ ],\n" +
|
||||
" \"object\":{ },\n" +
|
||||
" \"address\": \"50 St. James Street\",\n" +
|
||||
" \"url\": \"http://www.JSON.org/\",\n" +
|
||||
" \"comment\": \"// /* <!-- --\",\n" +
|
||||
" \"# -- --> */\": \" \",\n" +
|
||||
" \" s p a c e d \" :[1,2 , 3\n" +
|
||||
"\n" +
|
||||
",\n" +
|
||||
"\n" +
|
||||
"4 , 5 , 6 ,7 ],\"compact\":[1,2,3,4,5,6,7],\n" +
|
||||
" \"jsontext\": \"{\\\"object with 1 member\\\":[\\\"array with 1 element\\\"]}\",\n" +
|
||||
" \"quotes\": \"" \\u0022 %22 0x22 034 "\",\n" +
|
||||
" \"\\/\\\\\\\"\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\f\\n\\r\\t`1~!@#\$%^&*()_+-=[]{}|;:',./<>?\"\n" +
|
||||
": \"A key can be any string\"\n" +
|
||||
" },\n" +
|
||||
" 0.5 ,98.6\n" +
|
||||
",\n" +
|
||||
"99.44\n" +
|
||||
",\n" +
|
||||
"\n" +
|
||||
"1066,\n" +
|
||||
"1e1,\n" +
|
||||
"0.1e1,\n" +
|
||||
"1e-1,\n" +
|
||||
"1e00,2e+00,2e-00\n" +
|
||||
",\"rosebud\"]",
|
||||
"{\n" +
|
||||
" \"JSON Test Pattern pass3\": {\n" +
|
||||
" \"The outermost value\": \"must be an object or array.\",\n" +
|
||||
" \"In this test\": \"It is an object.\"\n" +
|
||||
" }\n" +
|
||||
"}",
|
||||
"[[[[[[[[[[[[[[[[[[[\"Not too deep\"]]]]]]]]]]]]]]]]]]]",
|
||||
)
|
||||
val passList =
|
||||
listOf(
|
||||
"[\n" +
|
||||
" \"JSON Test Pattern pass1\",\n" +
|
||||
" {\"object with 1 member\":[\"array with 1 element\"]},\n" +
|
||||
" {},\n" +
|
||||
" [],\n" +
|
||||
" -42,\n" +
|
||||
" true,\n" +
|
||||
" false,\n" +
|
||||
" null,\n" +
|
||||
" {\n" +
|
||||
" \"integer\": 1234567890,\n" +
|
||||
" \"real\": -9876.543210,\n" +
|
||||
" \"e\": 0.123456789e-12,\n" +
|
||||
" \"E\": 1.234567890E+34,\n" +
|
||||
" \"\": 23456789012E66,\n" +
|
||||
" \"zero\": 0,\n" +
|
||||
" \"one\": 1,\n" +
|
||||
" \"space\": \" \",\n" +
|
||||
" \"quote\": \"\\\"\",\n" +
|
||||
" \"backslash\": \"\\\\\",\n" +
|
||||
" \"controls\": \"\\b\\f\\n\\r\\t\",\n" +
|
||||
" \"slash\": \"/ & \\/\",\n" +
|
||||
" \"alpha\": \"abcdefghijklmnopqrstuvwyz\",\n" +
|
||||
" \"ALPHA\": \"ABCDEFGHIJKLMNOPQRSTUVWYZ\",\n" +
|
||||
" \"digit\": \"0123456789\",\n" +
|
||||
" \"0123456789\": \"digit\",\n" +
|
||||
" \"special\": \"`1~!@#\$%^&*()_+-={':[,]}|;.</>?\",\n" +
|
||||
" \"hex\": \"\\u0123\\u4567\\u89AB\\uCDEF\\uabcd\\uef4A\",\n" +
|
||||
" \"true\": true,\n" +
|
||||
" \"false\": false,\n" +
|
||||
" \"null\": null,\n" +
|
||||
" \"array\":[ ],\n" +
|
||||
" \"object\":{ },\n" +
|
||||
" \"address\": \"50 St. James Street\",\n" +
|
||||
" \"url\": \"http://www.JSON.org/\",\n" +
|
||||
" \"comment\": \"// /* <!-- --\",\n" +
|
||||
" \"# -- --> */\": \" \",\n" +
|
||||
" \" s p a c e d \" :[1,2 , 3\n" +
|
||||
"\n" +
|
||||
",\n" +
|
||||
"\n" +
|
||||
"4 , 5 , 6 ,7 ],\"compact\":[1,2,3,4,5,6,7],\n" +
|
||||
" \"jsontext\": \"{\\\"object with 1 member\\\":[\\\"array with 1 element\\\"]}\",\n" +
|
||||
" \"quotes\": \"" \\u0022 %22 0x22 034 "\",\n" +
|
||||
" \"\\/\\\\\\\"\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\f\\n\\r\\t`1~!@#\$%^&*()_+-=[]{}|;:',./<>?\"\n" +
|
||||
": \"A key can be any string\"\n" +
|
||||
" },\n" +
|
||||
" 0.5 ,98.6\n" +
|
||||
",\n" +
|
||||
"99.44\n" +
|
||||
",\n" +
|
||||
"\n" +
|
||||
"1066,\n" +
|
||||
"1e1,\n" +
|
||||
"0.1e1,\n" +
|
||||
"1e-1,\n" +
|
||||
"1e00,2e+00,2e-00\n" +
|
||||
",\"rosebud\"]",
|
||||
"{\n" +
|
||||
" \"JSON Test Pattern pass3\": {\n" +
|
||||
" \"The outermost value\": \"must be an object or array.\",\n" +
|
||||
" \"In this test\": \"It is an object.\"\n" +
|
||||
" }\n" +
|
||||
"}",
|
||||
"[[[[[[[[[[[[[[[[[[[\"Not too deep\"]]]]]]]]]]]]]]]]]]]",
|
||||
)
|
||||
for (data in passList) {
|
||||
JSONParser().parse(ArrayReadBuffer(data.encodeToByteArray()))
|
||||
}
|
||||
|
||||
@@ -17,25 +17,50 @@
|
||||
|
||||
package com.google.flatbuffers.kotlin
|
||||
|
||||
/**
|
||||
* This implementation uses Little Endian order.
|
||||
*/
|
||||
/** This implementation uses Little Endian order. */
|
||||
public actual inline fun ByteArray.getUByte(index: Int): UByte = ByteArrayOps.getUByte(this, index)
|
||||
public actual inline fun ByteArray.getShort(index: Int): Short = ByteArrayOps.getShort(this, index)
|
||||
public actual inline fun ByteArray.getUShort(index: Int): UShort = ByteArrayOps.getUShort(this, index)
|
||||
public actual inline fun ByteArray.getInt(index: Int): Int = ByteArrayOps.getInt(this, index)
|
||||
public actual inline fun ByteArray.getUInt(index: Int): UInt = ByteArrayOps.getUInt(this, index)
|
||||
public actual inline fun ByteArray.getLong(index: Int): Long = ByteArrayOps.getLong(this, index)
|
||||
public actual inline fun ByteArray.getULong(index: Int): ULong = ByteArrayOps.getULong(this, index)
|
||||
public actual inline fun ByteArray.getFloat(index: Int): Float = ByteArrayOps.getFloat(this, index)
|
||||
public actual inline fun ByteArray.getDouble(index: Int): Double = ByteArrayOps.getDouble(this, index)
|
||||
|
||||
public actual inline fun ByteArray.setUByte(index: Int, value: UByte): Unit = ByteArrayOps.setUByte(this, index, value)
|
||||
public actual inline fun ByteArray.setShort(index: Int, value: Short): Unit = ByteArrayOps.setShort(this, index, value)
|
||||
public actual inline fun ByteArray.setUShort(index: Int, value: UShort): Unit = ByteArrayOps.setUShort(this, index, value)
|
||||
public actual inline fun ByteArray.setInt(index: Int, value: Int): Unit = ByteArrayOps.setInt(this, index, value)
|
||||
public actual inline fun ByteArray.setUInt(index: Int, value: UInt): Unit = ByteArrayOps.setUInt(this, index, value)
|
||||
public actual inline fun ByteArray.setLong(index: Int, value: Long): Unit = ByteArrayOps.setLong(this, index, value)
|
||||
public actual inline fun ByteArray.setULong(index: Int, value: ULong): Unit = ByteArrayOps.setULong(this, index, value)
|
||||
public actual inline fun ByteArray.setFloat(index: Int, value: Float): Unit = ByteArrayOps.setFloat(this, index, value)
|
||||
public actual inline fun ByteArray.setDouble(index: Int, value: Double): Unit = ByteArrayOps.setDouble(this, index, value)
|
||||
public actual inline fun ByteArray.getShort(index: Int): Short = ByteArrayOps.getShort(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getUShort(index: Int): UShort =
|
||||
ByteArrayOps.getUShort(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getInt(index: Int): Int = ByteArrayOps.getInt(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getUInt(index: Int): UInt = ByteArrayOps.getUInt(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getLong(index: Int): Long = ByteArrayOps.getLong(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getULong(index: Int): ULong = ByteArrayOps.getULong(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getFloat(index: Int): Float = ByteArrayOps.getFloat(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getDouble(index: Int): Double =
|
||||
ByteArrayOps.getDouble(this, index)
|
||||
|
||||
public actual inline fun ByteArray.setUByte(index: Int, value: UByte): Unit =
|
||||
ByteArrayOps.setUByte(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setShort(index: Int, value: Short): Unit =
|
||||
ByteArrayOps.setShort(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setUShort(index: Int, value: UShort): Unit =
|
||||
ByteArrayOps.setUShort(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setInt(index: Int, value: Int): Unit =
|
||||
ByteArrayOps.setInt(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setUInt(index: Int, value: UInt): Unit =
|
||||
ByteArrayOps.setUInt(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setLong(index: Int, value: Long): Unit =
|
||||
ByteArrayOps.setLong(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setULong(index: Int, value: ULong): Unit =
|
||||
ByteArrayOps.setULong(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setFloat(index: Int, value: Float): Unit =
|
||||
ByteArrayOps.setFloat(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setDouble(index: Int, value: Double): Unit =
|
||||
ByteArrayOps.setDouble(this, index, value)
|
||||
|
||||
@@ -19,25 +19,50 @@
|
||||
|
||||
package com.google.flatbuffers.kotlin
|
||||
|
||||
/**
|
||||
* This implementation uses Little Endian order.
|
||||
*/
|
||||
/** This implementation uses Little Endian order. */
|
||||
public actual inline fun ByteArray.getUByte(index: Int): UByte = ByteArrayOps.getUByte(this, index)
|
||||
public actual inline fun ByteArray.getShort(index: Int): Short = ByteArrayOps.getShort(this, index)
|
||||
public actual inline fun ByteArray.getUShort(index: Int): UShort = ByteArrayOps.getUShort(this, index)
|
||||
public actual inline fun ByteArray.getInt(index: Int): Int = ByteArrayOps.getInt(this, index)
|
||||
public actual inline fun ByteArray.getUInt(index: Int): UInt = ByteArrayOps.getUInt(this, index)
|
||||
public actual inline fun ByteArray.getLong(index: Int): Long = ByteArrayOps.getLong(this, index)
|
||||
public actual inline fun ByteArray.getULong(index: Int): ULong = ByteArrayOps.getULong(this, index)
|
||||
public actual inline fun ByteArray.getFloat(index: Int): Float = ByteArrayOps.getFloat(this, index)
|
||||
public actual inline fun ByteArray.getDouble(index: Int): Double = ByteArrayOps.getDouble(this, index)
|
||||
|
||||
public actual inline fun ByteArray.setUByte(index: Int, value: UByte): Unit = ByteArrayOps.setUByte(this, index, value)
|
||||
public actual inline fun ByteArray.setShort(index: Int, value: Short): Unit = ByteArrayOps.setShort(this, index, value)
|
||||
public actual inline fun ByteArray.setUShort(index: Int, value: UShort): Unit = ByteArrayOps.setUShort(this, index, value)
|
||||
public actual inline fun ByteArray.setInt(index: Int, value: Int): Unit = ByteArrayOps.setInt(this, index, value)
|
||||
public actual inline fun ByteArray.setUInt(index: Int, value: UInt): Unit = ByteArrayOps.setUInt(this, index, value)
|
||||
public actual inline fun ByteArray.setLong(index: Int, value: Long): Unit = ByteArrayOps.setLong(this, index, value)
|
||||
public actual inline fun ByteArray.setULong(index: Int, value: ULong): Unit = ByteArrayOps.setULong(this, index, value)
|
||||
public actual inline fun ByteArray.setFloat(index: Int, value: Float): Unit = ByteArrayOps.setFloat(this, index, value)
|
||||
public actual inline fun ByteArray.setDouble(index: Int, value: Double): Unit = ByteArrayOps.setDouble(this, index, value)
|
||||
public actual inline fun ByteArray.getShort(index: Int): Short = ByteArrayOps.getShort(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getUShort(index: Int): UShort =
|
||||
ByteArrayOps.getUShort(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getInt(index: Int): Int = ByteArrayOps.getInt(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getUInt(index: Int): UInt = ByteArrayOps.getUInt(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getLong(index: Int): Long = ByteArrayOps.getLong(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getULong(index: Int): ULong = ByteArrayOps.getULong(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getFloat(index: Int): Float = ByteArrayOps.getFloat(this, index)
|
||||
|
||||
public actual inline fun ByteArray.getDouble(index: Int): Double =
|
||||
ByteArrayOps.getDouble(this, index)
|
||||
|
||||
public actual inline fun ByteArray.setUByte(index: Int, value: UByte): Unit =
|
||||
ByteArrayOps.setUByte(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setShort(index: Int, value: Short): Unit =
|
||||
ByteArrayOps.setShort(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setUShort(index: Int, value: UShort): Unit =
|
||||
ByteArrayOps.setUShort(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setInt(index: Int, value: Int): Unit =
|
||||
ByteArrayOps.setInt(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setUInt(index: Int, value: UInt): Unit =
|
||||
ByteArrayOps.setUInt(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setLong(index: Int, value: Long): Unit =
|
||||
ByteArrayOps.setLong(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setULong(index: Int, value: ULong): Unit =
|
||||
ByteArrayOps.setULong(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setFloat(index: Int, value: Float): Unit =
|
||||
ByteArrayOps.setFloat(this, index, value)
|
||||
|
||||
public actual inline fun ByteArray.setDouble(index: Int, value: Double): Unit =
|
||||
ByteArrayOps.setDouble(this, index, value)
|
||||
|
||||
@@ -15,23 +15,21 @@
|
||||
*/
|
||||
package com.google.flatbuffers.kotlin
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class Utf8Test {
|
||||
|
||||
@Test
|
||||
fun testUtf8EncodingDecoding() {
|
||||
val classLoader = this.javaClass.classLoader
|
||||
val utf8Lines = String(classLoader.getResourceAsStream("utf8_sample.txt")!!.readBytes())
|
||||
.split("\n")
|
||||
.filter { it.trim().isNotEmpty() }
|
||||
val utf8Lines =
|
||||
String(classLoader.getResourceAsStream("utf8_sample.txt")!!.readBytes()).split("\n").filter {
|
||||
it.trim().isNotEmpty()
|
||||
}
|
||||
|
||||
val utf8Bytes = utf8Lines.map {
|
||||
s -> ByteArray(Utf8.encodedLength(s)).also {
|
||||
Utf8.encodeUtf8Array(s, it)
|
||||
}
|
||||
}
|
||||
val utf8Bytes =
|
||||
utf8Lines.map { s -> ByteArray(Utf8.encodedLength(s)).also { Utf8.encodeUtf8Array(s, it) } }
|
||||
utf8Bytes.indices.forEach {
|
||||
assertArrayEquals(utf8Lines[it].encodeToByteArray(), utf8Bytes[it])
|
||||
assertEquals(utf8Lines[it], Utf8.decodeUtf8Array(utf8Bytes[it]))
|
||||
|
||||
@@ -18,25 +18,47 @@
|
||||
package com.google.flatbuffers.kotlin
|
||||
|
||||
/**
|
||||
* This implementation assumes that of native macOSX64 the byte order of the implementation is Little Endian.
|
||||
* This implementation assumes that of native macOSX64 the byte order of the implementation is
|
||||
* Little Endian.
|
||||
*/
|
||||
|
||||
public actual inline fun ByteArray.getUByte(index: Int): UByte = getUByteAt(index)
|
||||
|
||||
public actual inline fun ByteArray.getShort(index: Int): Short = getShortAt(index)
|
||||
|
||||
public actual inline fun ByteArray.getUShort(index: Int): UShort = getUShortAt(index)
|
||||
|
||||
public actual inline fun ByteArray.getInt(index: Int): Int = getIntAt(index)
|
||||
|
||||
public actual inline fun ByteArray.getUInt(index: Int): UInt = getUIntAt(index)
|
||||
|
||||
public actual inline fun ByteArray.getLong(index: Int): Long = getLongAt(index)
|
||||
|
||||
public actual inline fun ByteArray.getULong(index: Int): ULong = getULongAt(index)
|
||||
|
||||
public actual inline fun ByteArray.setUByte(index: Int, value: UByte): Unit = setUByteAt(index, value)
|
||||
public actual inline fun ByteArray.setShort(index: Int, value: Short): Unit = setShortAt(index, value)
|
||||
public actual inline fun ByteArray.setUShort(index: Int, value: UShort): Unit = setUShortAt(index, value)
|
||||
public actual inline fun ByteArray.setUByte(index: Int, value: UByte): Unit =
|
||||
setUByteAt(index, value)
|
||||
|
||||
public actual inline fun ByteArray.setShort(index: Int, value: Short): Unit =
|
||||
setShortAt(index, value)
|
||||
|
||||
public actual inline fun ByteArray.setUShort(index: Int, value: UShort): Unit =
|
||||
setUShortAt(index, value)
|
||||
|
||||
public actual inline fun ByteArray.setInt(index: Int, value: Int): Unit = setIntAt(index, value)
|
||||
|
||||
public actual inline fun ByteArray.setUInt(index: Int, value: UInt): Unit = setUIntAt(index, value)
|
||||
|
||||
public actual inline fun ByteArray.setLong(index: Int, value: Long): Unit = setLongAt(index, value)
|
||||
public actual inline fun ByteArray.setULong(index: Int, value: ULong): Unit = setULongAt(index, value)
|
||||
public actual inline fun ByteArray.setFloat(index: Int, value: Float): Unit = setFloatAt(index, value)
|
||||
public actual inline fun ByteArray.setDouble(index: Int, value: Double): Unit = setDoubleAt(index, value)
|
||||
|
||||
public actual inline fun ByteArray.setULong(index: Int, value: ULong): Unit =
|
||||
setULongAt(index, value)
|
||||
|
||||
public actual inline fun ByteArray.setFloat(index: Int, value: Float): Unit =
|
||||
setFloatAt(index, value)
|
||||
|
||||
public actual inline fun ByteArray.setDouble(index: Int, value: Double): Unit =
|
||||
setDoubleAt(index, value)
|
||||
|
||||
public actual inline fun ByteArray.getFloat(index: Int): Float = Float.fromBits(getIntAt(index))
|
||||
|
||||
public actual inline fun ByteArray.getDouble(index: Int): Double = Double.fromBits(getLongAt(index))
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
rootProject.name = "flatbuffers-kotlin"
|
||||
|
||||
includeBuild("convention-plugins")
|
||||
|
||||
include("flatbuffers-kotlin")
|
||||
|
||||
include("benchmark")
|
||||
|
||||
Reference in New Issue
Block a user