Remove some unused fbs files
22
third_party/flatbuffers/android/.project
vendored
@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>FlatBufferTest</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
</natures>
|
|
||||||
<filteredResources>
|
|
||||||
<filter>
|
|
||||||
<id>1672434305228</id>
|
|
||||||
<name></name>
|
|
||||||
<type>30</type>
|
|
||||||
<matcher>
|
|
||||||
<id>org.eclipse.core.resources.regexFilterMatcher</id>
|
|
||||||
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
|
|
||||||
</matcher>
|
|
||||||
</filter>
|
|
||||||
</filteredResources>
|
|
||||||
</projectDescription>
|
|
@ -1,31 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- BEGIN_INCLUDE(manifest) -->
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="com.example.FlatBufferTest">
|
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="14"/>
|
|
||||||
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
|
|
||||||
|
|
||||||
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
|
||||||
<application android:name="android.support.multidex.MultiDexApplication"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:hasCode="false"
|
|
||||||
android:allowBackup="false">
|
|
||||||
<!-- Our activity is the built-in NativeActivity framework class.
|
|
||||||
This will take care of integrating with our NDK code. -->
|
|
||||||
<activity android:name="android.app.NativeActivity"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:configChanges="orientation|keyboardHidden"
|
|
||||||
android:screenOrientation="landscape">
|
|
||||||
<!-- Tell NativeActivity the name of or .so -->
|
|
||||||
<meta-data android:name="android.app.lib_name"
|
|
||||||
android:value="FlatBufferTest" />
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
||||||
<!-- END_INCLUDE(manifest) -->
|
|
@ -1 +0,0 @@
|
|||||||
/build
|
|
125
third_party/flatbuffers/android/app/build.gradle
vendored
@ -1,125 +0,0 @@
|
|||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdk 33
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId "com.flatbuffers.app"
|
|
||||||
minSdkVersion 26
|
|
||||||
targetSdkVersion 33
|
|
||||||
versionCode 1
|
|
||||||
versionName "1.0"
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main {
|
|
||||||
java {
|
|
||||||
srcDir '../../java/src/main/java/'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ndk {
|
|
||||||
abiFilters 'arm64-v8a', 'armeabi-v7a'
|
|
||||||
}
|
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
||||||
externalNativeBuild {
|
|
||||||
cmake {
|
|
||||||
arguments "-DFLATBUFFERS_SRC=${rootProject.projectDir}/.."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
externalNativeBuild {
|
|
||||||
cmake {
|
|
||||||
path "src/main/cpp/CMakeLists.txt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task generateFbsCpp(type: Exec) {
|
|
||||||
def inputDir = file("$projectDir/src/main/fbs")
|
|
||||||
def outputCppDir = file("$projectDir/src/main/cpp/generated/")
|
|
||||||
def fbsFiles = layout.files { file(inputDir).listFiles() }.filter { File f -> f.name.endsWith(".fbs") }.toList()
|
|
||||||
ignoreExitValue(true)
|
|
||||||
|
|
||||||
standardOutput = new ByteArrayOutputStream()
|
|
||||||
errorOutput = new ByteArrayOutputStream()
|
|
||||||
def commandLineArgs = ['flatc', '-o', outputCppDir, '--cpp']
|
|
||||||
fbsFiles.forEach{
|
|
||||||
commandLineArgs.add(it.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
commandLine commandLineArgs
|
|
||||||
|
|
||||||
doFirst {
|
|
||||||
delete "$outputCppDir/"
|
|
||||||
mkdir "$outputCppDir/"
|
|
||||||
}
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
if (executionResult.get().exitValue != 0) {
|
|
||||||
throw new GradleException("flatc failed with: ${executionResult.get().toString()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task generateFbsKotlin(type: Exec) {
|
|
||||||
def inputDir = file("$projectDir/src/main/fbs")
|
|
||||||
def outputKotlinDir = file("$projectDir/src/main/java/generated/")
|
|
||||||
def fbsFiles = layout.files { file(inputDir).listFiles() }.filter { File f -> f.name.endsWith(".fbs") }.toList()
|
|
||||||
ignoreExitValue(true)
|
|
||||||
|
|
||||||
standardOutput = new ByteArrayOutputStream()
|
|
||||||
errorOutput = new ByteArrayOutputStream()
|
|
||||||
|
|
||||||
setErrorOutput(errorOutput)
|
|
||||||
setStandardOutput(standardOutput)
|
|
||||||
|
|
||||||
def commandLineArgs = ['flatc', '-o', outputKotlinDir, '--kotlin']
|
|
||||||
fbsFiles.forEach{
|
|
||||||
commandLineArgs.add(it.path)
|
|
||||||
}
|
|
||||||
commandLine commandLineArgs
|
|
||||||
|
|
||||||
doFirst {
|
|
||||||
delete "$outputKotlinDir/"
|
|
||||||
mkdir "$outputKotlinDir/"
|
|
||||||
}
|
|
||||||
doLast {
|
|
||||||
if (executionResult.get().exitValue != 0) {
|
|
||||||
throw new GradleException("flatc failed with: ${executionResult.get().toString()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
tasks.named("preBuild") {
|
|
||||||
dependsOn(generateFbsKotlin)
|
|
||||||
dependsOn(generateFbsCpp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
namespace 'com.flatbuffers.app'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
||||||
|
|
||||||
// If you using java runtime you can add its dependency as the example below
|
|
||||||
// implementation 'com.google.flatbuffers:flatbuffers-java:$latest_version'
|
|
||||||
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
|
||||||
# class:
|
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for
|
|
||||||
# debugging stack traces.
|
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
|
||||||
# hide the original source file name.
|
|
||||||
#-renamesourcefileattribute SourceFile
|
|
@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<application
|
|
||||||
android:allowBackup="true"
|
|
||||||
android:icon="@mipmap/ic_launcher"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:supportsRtl="true"
|
|
||||||
android:theme="@style/AppTheme">
|
|
||||||
<activity android:name=".MainActivity"
|
|
||||||
android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
@ -1,53 +0,0 @@
|
|||||||
# For more information about using CMake with Android Studio, read the
|
|
||||||
# documentation: https://d.android.com/studio/projects/add-native-code.html
|
|
||||||
|
|
||||||
# Sets the minimum version of CMake required to build the native library.
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.4.1)
|
|
||||||
|
|
||||||
# Creates and names a library, sets it as either STATIC
|
|
||||||
# or SHARED, and provides the relative paths to its source code.
|
|
||||||
# You can define multiple libraries, and CMake builds them for you.
|
|
||||||
# Gradle automatically packages shared libraries with your APK.
|
|
||||||
|
|
||||||
include_directories(${FLATBUFFERS_SRC}/include)
|
|
||||||
|
|
||||||
add_subdirectory(flatbuffers)
|
|
||||||
|
|
||||||
FILE(GLOB Generated_SRCS generated/*.h)
|
|
||||||
|
|
||||||
add_library( # Sets the name of the library.
|
|
||||||
native-lib
|
|
||||||
|
|
||||||
# Sets the library as a shared library.
|
|
||||||
SHARED
|
|
||||||
|
|
||||||
# Provides a relative path to your source file(s).
|
|
||||||
animals.cpp
|
|
||||||
${Generated_SRCS}
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
# Searches for a specified prebuilt library and stores the path as a
|
|
||||||
# variable. Because CMake includes system libraries in the search path by
|
|
||||||
# default, you only need to specify the name of the public NDK library
|
|
||||||
# you want to add. CMake verifies that the library exists before
|
|
||||||
# completing its build.
|
|
||||||
|
|
||||||
find_library( # Sets the name of the path variable.
|
|
||||||
log-lib
|
|
||||||
|
|
||||||
# Specifies the name of the NDK library that
|
|
||||||
# you want CMake to locate.
|
|
||||||
log )
|
|
||||||
|
|
||||||
# Specifies libraries CMake should link to your target library. You
|
|
||||||
# can link multiple libraries, such as libraries you define in this
|
|
||||||
# build script, prebuilt third-party libraries, or system libraries.
|
|
||||||
|
|
||||||
target_link_libraries( # Specifies the target library.
|
|
||||||
native-lib
|
|
||||||
flatbuffers
|
|
||||||
# Links the target library to the log library
|
|
||||||
# included in the NDK.
|
|
||||||
${log-lib} )
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
#include <string>
|
|
||||||
#include <search.h>
|
|
||||||
#include "generated/animal_generated.h"
|
|
||||||
|
|
||||||
using namespace com::fbs::app;
|
|
||||||
using namespace flatbuffers;
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT jbyteArray JNICALL Java_com_flatbuffers_app_MainActivity_createAnimalFromJNI(
|
|
||||||
JNIEnv* env,
|
|
||||||
jobject /* this */) {
|
|
||||||
// create a new animal flatbuffers
|
|
||||||
auto fb = FlatBufferBuilder(1024);
|
|
||||||
auto tiger = CreateAnimalDirect(fb, "Tiger", "Roar", 300);
|
|
||||||
fb.Finish(tiger);
|
|
||||||
|
|
||||||
// copies it to a Java byte array.
|
|
||||||
auto buf = reinterpret_cast<jbyte*>(fb.GetBufferPointer());
|
|
||||||
int size = fb.GetSize();
|
|
||||||
auto ret = env->NewByteArray(size);
|
|
||||||
env->SetByteArrayRegion (ret, 0, fb.GetSize(), buf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
# For more information about using CMake with Android Studio, read the
|
|
||||||
# documentation: https://d.android.com/studio/projects/add-native-code.html
|
|
||||||
|
|
||||||
# Sets the minimum version of CMake required to build the native library.
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.4.1)
|
|
||||||
|
|
||||||
include_directories(${FLATBUFFERS_SRC}/include)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -fexceptions -Wall -DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE")
|
|
||||||
|
|
||||||
# Certain platforms such as ARM do not use signed chars by default
|
|
||||||
# which causes issues with certain bounds checks.
|
|
||||||
set(CMAKE_CXX_FLAGS
|
|
||||||
"${CMAKE_CXX_FLAGS} -fsigned-char")
|
|
||||||
|
|
||||||
set(FlatBuffers_Library_SRCS
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/allocator.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/array.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/base.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/buffer.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/buffer_ref.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/default_allocator.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/detached_buffer.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/flatbuffer_builder.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/flatbuffers.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/flexbuffers.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/flex_flat_util.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/hash.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/idl.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/minireflect.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/reflection.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/reflection_generated.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/registry.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/stl_emulation.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/string.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/struct.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/table.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/util.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/vector.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/vector_downward.h
|
|
||||||
${FLATBUFFERS_SRC}/include/flatbuffers/verifier.h
|
|
||||||
${FLATBUFFERS_SRC}/src/idl_parser.cpp
|
|
||||||
${FLATBUFFERS_SRC}/src/idl_gen_text.cpp
|
|
||||||
${FLATBUFFERS_SRC}/src/reflection.cpp
|
|
||||||
${FLATBUFFERS_SRC}/src/util.cpp
|
|
||||||
${FLATBUFFERS_SRC}/src/idl_gen_fbs.cpp
|
|
||||||
${FLATBUFFERS_SRC}/src/code_generators.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library( # Sets the name of the library.
|
|
||||||
flatbuffers
|
|
||||||
|
|
||||||
${FlatBuffers_Library_SRCS}
|
|
||||||
${Generated_SRCS}
|
|
||||||
)
|
|
@ -1,134 +0,0 @@
|
|||||||
// automatically generated by the FlatBuffers compiler, do not modify
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_
|
|
||||||
#define FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
|
|
||||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
|
||||||
// generated, otherwise it may not be compatible.
|
|
||||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
|
|
||||||
FLATBUFFERS_VERSION_MINOR == 1 &&
|
|
||||||
FLATBUFFERS_VERSION_REVISION == 21,
|
|
||||||
"Non-compatible flatbuffers version included");
|
|
||||||
|
|
||||||
namespace com {
|
|
||||||
namespace fbs {
|
|
||||||
namespace app {
|
|
||||||
|
|
||||||
struct Animal;
|
|
||||||
struct AnimalBuilder;
|
|
||||||
|
|
||||||
struct Animal FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|
||||||
typedef AnimalBuilder Builder;
|
|
||||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
|
||||||
VT_NAME = 4,
|
|
||||||
VT_SOUND = 6,
|
|
||||||
VT_WEIGHT = 8
|
|
||||||
};
|
|
||||||
const ::flatbuffers::String *name() const {
|
|
||||||
return GetPointer<const ::flatbuffers::String *>(VT_NAME);
|
|
||||||
}
|
|
||||||
const ::flatbuffers::String *sound() const {
|
|
||||||
return GetPointer<const ::flatbuffers::String *>(VT_SOUND);
|
|
||||||
}
|
|
||||||
uint16_t weight() const {
|
|
||||||
return GetField<uint16_t>(VT_WEIGHT, 0);
|
|
||||||
}
|
|
||||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
|
||||||
return VerifyTableStart(verifier) &&
|
|
||||||
VerifyOffset(verifier, VT_NAME) &&
|
|
||||||
verifier.VerifyString(name()) &&
|
|
||||||
VerifyOffset(verifier, VT_SOUND) &&
|
|
||||||
verifier.VerifyString(sound()) &&
|
|
||||||
VerifyField<uint16_t>(verifier, VT_WEIGHT, 2) &&
|
|
||||||
verifier.EndTable();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AnimalBuilder {
|
|
||||||
typedef Animal Table;
|
|
||||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
|
||||||
::flatbuffers::uoffset_t start_;
|
|
||||||
void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
|
|
||||||
fbb_.AddOffset(Animal::VT_NAME, name);
|
|
||||||
}
|
|
||||||
void add_sound(::flatbuffers::Offset<::flatbuffers::String> sound) {
|
|
||||||
fbb_.AddOffset(Animal::VT_SOUND, sound);
|
|
||||||
}
|
|
||||||
void add_weight(uint16_t weight) {
|
|
||||||
fbb_.AddElement<uint16_t>(Animal::VT_WEIGHT, weight, 0);
|
|
||||||
}
|
|
||||||
explicit AnimalBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
|
||||||
: fbb_(_fbb) {
|
|
||||||
start_ = fbb_.StartTable();
|
|
||||||
}
|
|
||||||
::flatbuffers::Offset<Animal> Finish() {
|
|
||||||
const auto end = fbb_.EndTable(start_);
|
|
||||||
auto o = ::flatbuffers::Offset<Animal>(end);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<Animal> CreateAnimal(
|
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
|
||||||
::flatbuffers::Offset<::flatbuffers::String> name = 0,
|
|
||||||
::flatbuffers::Offset<::flatbuffers::String> sound = 0,
|
|
||||||
uint16_t weight = 0) {
|
|
||||||
AnimalBuilder builder_(_fbb);
|
|
||||||
builder_.add_sound(sound);
|
|
||||||
builder_.add_name(name);
|
|
||||||
builder_.add_weight(weight);
|
|
||||||
return builder_.Finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<Animal> CreateAnimalDirect(
|
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
|
||||||
const char *name = nullptr,
|
|
||||||
const char *sound = nullptr,
|
|
||||||
uint16_t weight = 0) {
|
|
||||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
|
||||||
auto sound__ = sound ? _fbb.CreateString(sound) : 0;
|
|
||||||
return com::fbs::app::CreateAnimal(
|
|
||||||
_fbb,
|
|
||||||
name__,
|
|
||||||
sound__,
|
|
||||||
weight);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const com::fbs::app::Animal *GetAnimal(const void *buf) {
|
|
||||||
return ::flatbuffers::GetRoot<com::fbs::app::Animal>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const com::fbs::app::Animal *GetSizePrefixedAnimal(const void *buf) {
|
|
||||||
return ::flatbuffers::GetSizePrefixedRoot<com::fbs::app::Animal>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VerifyAnimalBuffer(
|
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifyBuffer<com::fbs::app::Animal>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VerifySizePrefixedAnimalBuffer(
|
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifySizePrefixedBuffer<com::fbs::app::Animal>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FinishAnimalBuffer(
|
|
||||||
::flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
::flatbuffers::Offset<com::fbs::app::Animal> root) {
|
|
||||||
fbb.Finish(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FinishSizePrefixedAnimalBuffer(
|
|
||||||
::flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
::flatbuffers::Offset<com::fbs::app::Animal> root) {
|
|
||||||
fbb.FinishSizePrefixed(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace app
|
|
||||||
} // namespace fbs
|
|
||||||
} // namespace com
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_
|
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2015 Google Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
namespace com.fbs.app;
|
|
||||||
|
|
||||||
table Animal {
|
|
||||||
name:string;
|
|
||||||
sound:string;
|
|
||||||
weight: uint16;
|
|
||||||
}
|
|
||||||
|
|
||||||
root_type Animal;
|
|
@ -1,51 +0,0 @@
|
|||||||
package com.flatbuffers.app
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.widget.TextView
|
|
||||||
import com.fbs.app.Animal
|
|
||||||
import com.google.flatbuffers.FlatBufferBuilder
|
|
||||||
import java.nio.ByteBuffer
|
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
|
||||||
class MainActivity : AppCompatActivity() {
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_main)
|
|
||||||
|
|
||||||
val tiger = Animal.getRootAsAnimal(ByteBuffer.wrap(createAnimalFromJNI()))
|
|
||||||
findViewById<TextView>(R.id.tv_animal_one).text = animalInfo(tiger)
|
|
||||||
|
|
||||||
findViewById<TextView>(R.id.tv_animal_two).text = animalInfo(createAnimalFromKotlin())
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is a sample of communicating FlatBuffers between JNI (native C++) and Java.
|
|
||||||
// Implementation can be found on animals.cpp file.
|
|
||||||
private external fun createAnimalFromJNI(): ByteArray
|
|
||||||
|
|
||||||
// Create a "Cow" Animal flatbuffers from Kotlin
|
|
||||||
private fun createAnimalFromKotlin():Animal {
|
|
||||||
val fb = FlatBufferBuilder(100)
|
|
||||||
val cowOffset = Animal.createAnimal(
|
|
||||||
builder = fb,
|
|
||||||
nameOffset = fb.createString("Cow"),
|
|
||||||
soundOffset = fb.createString("Moo"),
|
|
||||||
weight = 720u
|
|
||||||
)
|
|
||||||
fb.finish(cowOffset)
|
|
||||||
return Animal.getRootAsAnimal(fb.dataBuffer())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun animalInfo(animal: Animal): String =
|
|
||||||
"The ${animal.name} sound is ${animal.sound} and it weights ${animal.weight}kg."
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
// Used to load the 'native-lib' library on application startup.
|
|
||||||
init {
|
|
||||||
System.loadLibrary("native-lib")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
// automatically generated by the FlatBuffers compiler, do not modify
|
|
||||||
|
|
||||||
package com.fbs.app
|
|
||||||
|
|
||||||
import com.google.flatbuffers.BaseVector
|
|
||||||
import com.google.flatbuffers.BooleanVector
|
|
||||||
import com.google.flatbuffers.ByteVector
|
|
||||||
import com.google.flatbuffers.Constants
|
|
||||||
import com.google.flatbuffers.DoubleVector
|
|
||||||
import com.google.flatbuffers.FlatBufferBuilder
|
|
||||||
import com.google.flatbuffers.FloatVector
|
|
||||||
import com.google.flatbuffers.LongVector
|
|
||||||
import com.google.flatbuffers.StringVector
|
|
||||||
import com.google.flatbuffers.Struct
|
|
||||||
import com.google.flatbuffers.Table
|
|
||||||
import com.google.flatbuffers.UnionVector
|
|
||||||
import java.nio.ByteBuffer
|
|
||||||
import java.nio.ByteOrder
|
|
||||||
import kotlin.math.sign
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
@kotlin.ExperimentalUnsignedTypes
|
|
||||||
class Animal : Table() {
|
|
||||||
|
|
||||||
fun __init(_i: Int, _bb: ByteBuffer) {
|
|
||||||
__reset(_i, _bb)
|
|
||||||
}
|
|
||||||
fun __assign(_i: Int, _bb: ByteBuffer) : Animal {
|
|
||||||
__init(_i, _bb)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
val name : String?
|
|
||||||
get() {
|
|
||||||
val o = __offset(4)
|
|
||||||
return if (o != 0) {
|
|
||||||
__string(o + bb_pos)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val nameAsByteBuffer : ByteBuffer get() = __vector_as_bytebuffer(4, 1)
|
|
||||||
fun nameInByteBuffer(_bb: ByteBuffer) : ByteBuffer = __vector_in_bytebuffer(_bb, 4, 1)
|
|
||||||
val sound : String?
|
|
||||||
get() {
|
|
||||||
val o = __offset(6)
|
|
||||||
return if (o != 0) {
|
|
||||||
__string(o + bb_pos)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val soundAsByteBuffer : ByteBuffer get() = __vector_as_bytebuffer(6, 1)
|
|
||||||
fun soundInByteBuffer(_bb: ByteBuffer) : ByteBuffer = __vector_in_bytebuffer(_bb, 6, 1)
|
|
||||||
val weight : UShort
|
|
||||||
get() {
|
|
||||||
val o = __offset(8)
|
|
||||||
return if(o != 0) bb.getShort(o + bb_pos).toUShort() else 0u
|
|
||||||
}
|
|
||||||
companion object {
|
|
||||||
fun validateVersion() = Constants.FLATBUFFERS_24_3_25()
|
|
||||||
fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal())
|
|
||||||
fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal {
|
|
||||||
_bb.order(ByteOrder.LITTLE_ENDIAN)
|
|
||||||
return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb))
|
|
||||||
}
|
|
||||||
fun createAnimal(builder: FlatBufferBuilder, nameOffset: Int, soundOffset: Int, weight: UShort) : Int {
|
|
||||||
builder.startTable(3)
|
|
||||||
addSound(builder, soundOffset)
|
|
||||||
addName(builder, nameOffset)
|
|
||||||
addWeight(builder, weight)
|
|
||||||
return endAnimal(builder)
|
|
||||||
}
|
|
||||||
fun startAnimal(builder: FlatBufferBuilder) = builder.startTable(3)
|
|
||||||
fun addName(builder: FlatBufferBuilder, name: Int) = builder.addOffset(0, name, 0)
|
|
||||||
fun addSound(builder: FlatBufferBuilder, sound: Int) = builder.addOffset(1, sound, 0)
|
|
||||||
fun addWeight(builder: FlatBufferBuilder, weight: UShort) = builder.addShort(2, weight.toShort(), 0)
|
|
||||||
fun endAnimal(builder: FlatBufferBuilder) : Int {
|
|
||||||
val o = builder.endTable()
|
|
||||||
return o
|
|
||||||
}
|
|
||||||
fun finishAnimalBuffer(builder: FlatBufferBuilder, offset: Int) = builder.finish(offset)
|
|
||||||
fun finishSizePrefixedAnimalBuffer(builder: FlatBufferBuilder, offset: Int) = builder.finishSizePrefixed(offset)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="85.84757"
|
|
||||||
android:endY="92.4963"
|
|
||||||
android:startX="42.9492"
|
|
||||||
android:startY="49.59793"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#44000000"
|
|
||||||
android:offset="0.0" />
|
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:fillType="nonZero"
|
|
||||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
|
||||||
android:strokeWidth="1"
|
|
||||||
android:strokeColor="#00000000" />
|
|
||||||
</vector>
|
|
@ -1,170 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path
|
|
||||||
android:fillColor="#3DDC84"
|
|
||||||
android:pathData="M0,0h108v108h-108z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M9,0L9,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,0L19,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,0L29,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,0L39,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,0L49,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,0L59,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,0L69,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,0L79,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M89,0L89,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M99,0L99,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,9L108,9"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,19L108,19"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,29L108,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,39L108,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,49L108,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,59L108,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,69L108,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,79L108,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,89L108,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,99L108,99"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,29L89,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,39L89,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,49L89,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,59L89,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,69L89,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,79L89,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,19L29,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,19L39,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,19L49,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,19L59,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,19L69,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,19L79,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
</vector>
|
|
@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center"
|
|
||||||
tools:context=".MainActivity">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_animal_one"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
tools:text="Text Sample"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_animal_two"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
tools:text="Text Sample 2"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 16 KiB |
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="colorPrimary">#6200EE</color>
|
|
||||||
<color name="colorPrimaryDark">#3700B3</color>
|
|
||||||
<color name="colorAccent">#03DAC5</color>
|
|
||||||
</resources>
|
|
@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<string name="app_name">FlatbuffersTestApp</string>
|
|
||||||
</resources>
|
|
@ -1,10 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<!-- Base application theme. -->
|
|
||||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
|
||||||
<!-- Customize your theme here. -->
|
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</resources>
|
|
35
third_party/flatbuffers/android/build.gradle
vendored
@ -1,35 +0,0 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
|
||||||
buildscript {
|
|
||||||
ext.kotlin_version = "1.7.21"
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.android.tools.build:gradle:7.4.1'
|
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
|
||||||
// in the individual module build.gradle files
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
|
|
||||||
compileKotlin {
|
|
||||||
dependsOn flatbuffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task clean(type: Delete) {
|
|
||||||
delete rootProject.buildDir
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
# Project-wide Gradle settings.
|
|
||||||
# IDE (e.g. Android Studio) users:
|
|
||||||
# Gradle settings configured through the IDE *will override*
|
|
||||||
# any settings specified in this file.
|
|
||||||
# For more details on how to configure your build environment visit
|
|
||||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
|
||||||
# Specifies the JVM arguments used for the daemon process.
|
|
||||||
# The setting is particularly useful for tweaking memory settings.
|
|
||||||
org.gradle.jvmargs=-Xmx2048m
|
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
|
||||||
# org.gradle.parallel=true
|
|
||||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
|
||||||
# Android operating system, and which are packaged with your app"s APK
|
|
||||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
|
||||||
android.useAndroidX=true
|
|
||||||
# Automatically convert third-party libraries to use AndroidX
|
|
||||||
android.enableJetifier=true
|
|
||||||
# Kotlin code style for this project: "official" or "obsolete":
|
|
||||||
kotlin.code.style=official
|
|
||||||
# Use parallel builds
|
|
||||||
org.gradle.parallel=true
|
|
@ -1,5 +0,0 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
|
||||||
distributionPath=wrapper/dists
|
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
|
||||||
zipStorePath=wrapper/dists
|
|
172
third_party/flatbuffers/android/gradlew
vendored
@ -1,172 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
##
|
|
||||||
## Gradle start up script for UN*X
|
|
||||||
##
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
|
||||||
# Resolve links: $0 may be a link
|
|
||||||
PRG="$0"
|
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
|
||||||
ls=`ls -ld "$PRG"`
|
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
|
||||||
PRG="$link"
|
|
||||||
else
|
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >/dev/null
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=`basename "$0"`
|
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
DEFAULT_JVM_OPTS=""
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
||||||
MAX_FD="maximum"
|
|
||||||
|
|
||||||
warn () {
|
|
||||||
echo "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
die () {
|
|
||||||
echo
|
|
||||||
echo "$*"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
|
||||||
cygwin=false
|
|
||||||
msys=false
|
|
||||||
darwin=false
|
|
||||||
nonstop=false
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN* )
|
|
||||||
cygwin=true
|
|
||||||
;;
|
|
||||||
Darwin* )
|
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
NONSTOP* )
|
|
||||||
nonstop=true
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
|
||||||
else
|
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
|
||||||
fi
|
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
location of your Java installation."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
JAVACMD="java"
|
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
location of your Java installation."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
|
||||||
if [ $? -eq 0 ] ; then
|
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
|
||||||
MAX_FD="$MAX_FD_LIMIT"
|
|
||||||
fi
|
|
||||||
ulimit -n $MAX_FD
|
|
||||||
if [ $? -ne 0 ] ; then
|
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Darwin, add options to specify how the application appears in the dock
|
|
||||||
if $darwin; then
|
|
||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
|
||||||
if $cygwin ; then
|
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
|
||||||
SEP=""
|
|
||||||
for dir in $ROOTDIRSRAW ; do
|
|
||||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
||||||
SEP="|"
|
|
||||||
done
|
|
||||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
||||||
# Add a user-defined pattern to the cygpath arguments
|
|
||||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
||||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
||||||
fi
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
i=0
|
|
||||||
for arg in "$@" ; do
|
|
||||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
|
||||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
|
||||||
|
|
||||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
|
||||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
|
||||||
else
|
|
||||||
eval `echo args$i`="\"$arg\""
|
|
||||||
fi
|
|
||||||
i=$((i+1))
|
|
||||||
done
|
|
||||||
case $i in
|
|
||||||
(0) set -- ;;
|
|
||||||
(1) set -- "$args0" ;;
|
|
||||||
(2) set -- "$args0" "$args1" ;;
|
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Escape application args
|
|
||||||
save () {
|
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
|
||||||
echo " "
|
|
||||||
}
|
|
||||||
APP_ARGS=$(save "$@")
|
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
|
||||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
|
84
third_party/flatbuffers/android/gradlew.bat
vendored
@ -1,84 +0,0 @@
|
|||||||
@if "%DEBUG%" == "" @echo off
|
|
||||||
@rem ##########################################################################
|
|
||||||
@rem
|
|
||||||
@rem Gradle startup script for Windows
|
|
||||||
@rem
|
|
||||||
@rem ##########################################################################
|
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
|
||||||
set APP_BASE_NAME=%~n0
|
|
||||||
set APP_HOME=%DIRNAME%
|
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS=
|
|
||||||
|
|
||||||
@rem Find java.exe
|
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
echo.
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
echo location of your Java installation.
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
|
||||||
echo.
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
echo location of your Java installation.
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:init
|
|
||||||
@rem Get command-line arguments, handling Windows variants
|
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
||||||
|
|
||||||
:win9xME_args
|
|
||||||
@rem Slurp the command line arguments.
|
|
||||||
set CMD_LINE_ARGS=
|
|
||||||
set _SKIP=2
|
|
||||||
|
|
||||||
:win9xME_args_slurp
|
|
||||||
if "x%~1" == "x" goto execute
|
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
:execute
|
|
||||||
@rem Setup the command line
|
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
|
||||||
|
|
||||||
:end
|
|
||||||
@rem End local scope for the variables with windows NT shell
|
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
|
||||||
|
|
||||||
:fail
|
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
|
||||||
rem the _cmd.exe /c_ return code!
|
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:mainEnd
|
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
|
||||||
|
|
||||||
:omega
|
|
@ -1,2 +0,0 @@
|
|||||||
include ':app'
|
|
||||||
rootProject.name = "FlatbuffersTest"
|
|
@ -1,88 +0,0 @@
|
|||||||
# Setup for running Google Benchmarks (https://github.com/google/benchmark) on
|
|
||||||
# flatbuffers. This requires both that benchmark library and its dependency gtest
|
|
||||||
# to build. Instead of including them here or doing a submodule, this uses
|
|
||||||
# FetchContent (https://cmake.org/cmake/help/latest/module/FetchContent.html) to
|
|
||||||
# grab the dependencies at config time. This requires CMake 3.14 or higher.
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.14)
|
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
# No particular reason for the specific GIT_TAGs for the following repos, they
|
|
||||||
# were just the latest releases when this was added.
|
|
||||||
FetchContent_Declare(
|
|
||||||
googletest
|
|
||||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
|
||||||
GIT_TAG e2239ee6043f73722e7aa812a459f54a28552929 # release-1.11.0
|
|
||||||
)
|
|
||||||
FetchContent_Declare(
|
|
||||||
googlebenchmark
|
|
||||||
GIT_REPOSITORY https://github.com/google/benchmark.git
|
|
||||||
GIT_TAG 0d98dba29d66e93259db7daa53a9327df767a415 # v1.6.1
|
|
||||||
)
|
|
||||||
|
|
||||||
# For Windows: Prevent overriding the parent project's compiler/linker
|
|
||||||
# settings.
|
|
||||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
|
||||||
FetchContent_MakeAvailable(
|
|
||||||
googletest
|
|
||||||
googlebenchmark
|
|
||||||
)
|
|
||||||
|
|
||||||
set(CPP_BENCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cpp)
|
|
||||||
set(CPP_FB_BENCH_DIR ${CPP_BENCH_DIR}/flatbuffers)
|
|
||||||
set(CPP_RAW_BENCH_DIR ${CPP_BENCH_DIR}/raw)
|
|
||||||
set(CPP_BENCH_FBS ${CPP_FB_BENCH_DIR}/bench.fbs)
|
|
||||||
set(CPP_BENCH_FB_GEN ${CPP_FB_BENCH_DIR}/bench_generated.h)
|
|
||||||
|
|
||||||
set(FlatBenchmark_SRCS
|
|
||||||
${CPP_BENCH_DIR}/benchmark_main.cpp
|
|
||||||
${CPP_FB_BENCH_DIR}/fb_bench.cpp
|
|
||||||
${CPP_RAW_BENCH_DIR}/raw_bench.cpp
|
|
||||||
${CPP_BENCH_FB_GEN}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Generate the flatbuffers benchmark code from the flatbuffers schema using
|
|
||||||
# flatc itself, thus it depends on flatc. This also depends on the C++ runtime
|
|
||||||
# flatbuffers and the schema file itself, so it should auto-generated at the
|
|
||||||
# correct times.
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${CPP_BENCH_FB_GEN}
|
|
||||||
COMMAND
|
|
||||||
"${FLATBUFFERS_FLATC_EXECUTABLE}"
|
|
||||||
--cpp
|
|
||||||
-o ${CPP_FB_BENCH_DIR}
|
|
||||||
${CPP_BENCH_FBS}
|
|
||||||
DEPENDS
|
|
||||||
flatc
|
|
||||||
flatbuffers
|
|
||||||
${CPP_BENCH_FBS}
|
|
||||||
COMMENT "Run Flatbuffers Benchmark Codegen: ${CPP_BENCH_FB_GEN}"
|
|
||||||
VERBATIM)
|
|
||||||
|
|
||||||
# The main flatbuffers benchmark executable
|
|
||||||
add_executable(flatbenchmark ${FlatBenchmark_SRCS})
|
|
||||||
|
|
||||||
# Benchmark requires C++11
|
|
||||||
target_compile_features(flatbenchmark PRIVATE
|
|
||||||
cxx_std_11 # requires cmake 3.8
|
|
||||||
)
|
|
||||||
|
|
||||||
target_compile_options(flatbenchmark
|
|
||||||
PRIVATE
|
|
||||||
-fno-aligned-new
|
|
||||||
-Wno-deprecated-declarations
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set the output directory to the root binary directory
|
|
||||||
set_target_properties(flatbenchmark
|
|
||||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY
|
|
||||||
"${CMAKE_BINARY_DIR}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# The includes of the benchmark files are fully qualified from flatbuffers root.
|
|
||||||
target_include_directories(flatbenchmark PUBLIC ${CMAKE_SOURCE_DIR})
|
|
||||||
|
|
||||||
target_link_libraries(flatbenchmark PRIVATE
|
|
||||||
benchmark::benchmark_main # _main to use their entry point
|
|
||||||
gtest # Link to gtest so we can also assert in the benchmarks
|
|
||||||
)
|
|
19
third_party/flatbuffers/benchmarks/cpp/bench.h
vendored
@ -1,19 +0,0 @@
|
|||||||
#ifndef BENCHMARKS_CPP_BENCH_H_
|
|
||||||
#define BENCHMARKS_CPP_BENCH_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
struct Bench {
|
|
||||||
virtual ~Bench() {}
|
|
||||||
|
|
||||||
inline void Add(int64_t value) { sum += value; }
|
|
||||||
|
|
||||||
virtual uint8_t *Encode(void *buf, int64_t &len) = 0;
|
|
||||||
virtual void *Decode(void *buf, int64_t len) = 0;
|
|
||||||
virtual int64_t Use(void *decoded) = 0;
|
|
||||||
virtual void Dealloc(void *decoded) = 0;
|
|
||||||
|
|
||||||
int64_t sum = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BENCHMARKS_CPP_BENCH_H_
|
|
@ -1,96 +0,0 @@
|
|||||||
#include <benchmark/benchmark.h>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#include "benchmarks/cpp/bench.h"
|
|
||||||
#include "benchmarks/cpp/flatbuffers/fb_bench.h"
|
|
||||||
#include "benchmarks/cpp/raw/raw_bench.h"
|
|
||||||
|
|
||||||
static inline void Encode(benchmark::State &state,
|
|
||||||
std::unique_ptr<Bench> &bench, uint8_t *buffer) {
|
|
||||||
int64_t length;
|
|
||||||
for (auto _ : state) {
|
|
||||||
bench->Encode(buffer, length);
|
|
||||||
benchmark::DoNotOptimize(length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void Decode(benchmark::State &state,
|
|
||||||
std::unique_ptr<Bench> &bench, uint8_t *buffer) {
|
|
||||||
int64_t length;
|
|
||||||
uint8_t *encoded = bench->Encode(buffer, length);
|
|
||||||
|
|
||||||
for (auto _ : state) {
|
|
||||||
void *decoded = bench->Decode(encoded, length);
|
|
||||||
benchmark::DoNotOptimize(decoded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void Use(benchmark::State &state, std::unique_ptr<Bench> &bench,
|
|
||||||
uint8_t *buffer, int64_t check_sum) {
|
|
||||||
int64_t length;
|
|
||||||
uint8_t *encoded = bench->Encode(buffer, length);
|
|
||||||
void *decoded = bench->Decode(encoded, length);
|
|
||||||
|
|
||||||
int64_t sum = 0;
|
|
||||||
|
|
||||||
for (auto _ : state) { sum = bench->Use(decoded); }
|
|
||||||
|
|
||||||
EXPECT_EQ(sum, check_sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BM_Flatbuffers_Encode(benchmark::State &state) {
|
|
||||||
const int64_t kBufferLength = 1024;
|
|
||||||
uint8_t buffer[kBufferLength];
|
|
||||||
|
|
||||||
StaticAllocator allocator(&buffer[0]);
|
|
||||||
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
|
||||||
Encode(state, bench, buffer);
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_Flatbuffers_Encode);
|
|
||||||
|
|
||||||
static void BM_Flatbuffers_Decode(benchmark::State &state) {
|
|
||||||
const int64_t kBufferLength = 1024;
|
|
||||||
uint8_t buffer[kBufferLength];
|
|
||||||
|
|
||||||
StaticAllocator allocator(&buffer[0]);
|
|
||||||
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
|
||||||
Decode(state, bench, buffer);
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_Flatbuffers_Decode);
|
|
||||||
|
|
||||||
static void BM_Flatbuffers_Use(benchmark::State &state) {
|
|
||||||
const int64_t kBufferLength = 1024;
|
|
||||||
uint8_t buffer[kBufferLength];
|
|
||||||
|
|
||||||
StaticAllocator allocator(&buffer[0]);
|
|
||||||
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
|
||||||
Use(state, bench, buffer, 218812692406581874);
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_Flatbuffers_Use);
|
|
||||||
|
|
||||||
static void BM_Raw_Encode(benchmark::State &state) {
|
|
||||||
const int64_t kBufferLength = 1024;
|
|
||||||
uint8_t buffer[kBufferLength];
|
|
||||||
|
|
||||||
std::unique_ptr<Bench> bench = NewRawBench();
|
|
||||||
Encode(state, bench, buffer);
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_Raw_Encode);
|
|
||||||
|
|
||||||
static void BM_Raw_Decode(benchmark::State &state) {
|
|
||||||
const int64_t kBufferLength = 1024;
|
|
||||||
uint8_t buffer[kBufferLength];
|
|
||||||
|
|
||||||
std::unique_ptr<Bench> bench = NewRawBench();
|
|
||||||
Decode(state, bench, buffer);
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_Raw_Decode);
|
|
||||||
|
|
||||||
static void BM_Raw_Use(benchmark::State &state) {
|
|
||||||
const int64_t kBufferLength = 1024;
|
|
||||||
uint8_t buffer[kBufferLength];
|
|
||||||
|
|
||||||
std::unique_ptr<Bench> bench = NewRawBench();
|
|
||||||
Use(state, bench, buffer, 218812692406581874);
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_Raw_Use);
|
|
@ -1,52 +0,0 @@
|
|||||||
// Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
|
|
||||||
// trying to represent a typical mix of datatypes:
|
|
||||||
// 1 array of 3 elements, each element: 1 string, 3 nested objects, 9 scalars
|
|
||||||
// root element has the array, additional string and an enum
|
|
||||||
|
|
||||||
namespace benchmarks_flatbuffers;
|
|
||||||
|
|
||||||
enum Enum : short { Apples, Pears, Bananas}
|
|
||||||
|
|
||||||
struct Foo {
|
|
||||||
id:ulong;
|
|
||||||
count:short;
|
|
||||||
prefix:byte;
|
|
||||||
length:uint;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Bar {
|
|
||||||
parent:Foo;
|
|
||||||
time:int;
|
|
||||||
ratio:float;
|
|
||||||
size:ushort;
|
|
||||||
}
|
|
||||||
|
|
||||||
table FooBar {
|
|
||||||
sibling:Bar;
|
|
||||||
name:string;
|
|
||||||
rating:double;
|
|
||||||
postfix:ubyte;
|
|
||||||
}
|
|
||||||
|
|
||||||
table FooBarContainer {
|
|
||||||
list:[FooBar]; // 3 copies of the above
|
|
||||||
initialized:bool;
|
|
||||||
fruit:Enum;
|
|
||||||
location:string;
|
|
||||||
}
|
|
||||||
|
|
||||||
root_type FooBarContainer;
|
|
@ -1,354 +0,0 @@
|
|||||||
// automatically generated by the FlatBuffers compiler, do not modify
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
|
|
||||||
#define FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
|
|
||||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
|
||||||
// generated, otherwise it may not be compatible.
|
|
||||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 2 &&
|
|
||||||
FLATBUFFERS_VERSION_MINOR == 0 &&
|
|
||||||
FLATBUFFERS_VERSION_REVISION == 6,
|
|
||||||
"Non-compatible flatbuffers version included");
|
|
||||||
|
|
||||||
namespace benchmarks_flatbuffers {
|
|
||||||
|
|
||||||
struct Foo;
|
|
||||||
|
|
||||||
struct Bar;
|
|
||||||
|
|
||||||
struct FooBar;
|
|
||||||
struct FooBarBuilder;
|
|
||||||
|
|
||||||
struct FooBarContainer;
|
|
||||||
struct FooBarContainerBuilder;
|
|
||||||
|
|
||||||
enum Enum : int16_t {
|
|
||||||
Enum_Apples = 0,
|
|
||||||
Enum_Pears = 1,
|
|
||||||
Enum_Bananas = 2,
|
|
||||||
Enum_MIN = Enum_Apples,
|
|
||||||
Enum_MAX = Enum_Bananas
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const Enum (&EnumValuesEnum())[3] {
|
|
||||||
static const Enum values[] = {
|
|
||||||
Enum_Apples,
|
|
||||||
Enum_Pears,
|
|
||||||
Enum_Bananas
|
|
||||||
};
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char * const *EnumNamesEnum() {
|
|
||||||
static const char * const names[4] = {
|
|
||||||
"Apples",
|
|
||||||
"Pears",
|
|
||||||
"Bananas",
|
|
||||||
nullptr
|
|
||||||
};
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *EnumNameEnum(Enum e) {
|
|
||||||
if (flatbuffers::IsOutRange(e, Enum_Apples, Enum_Bananas)) return "";
|
|
||||||
const size_t index = static_cast<size_t>(e);
|
|
||||||
return EnumNamesEnum()[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Foo FLATBUFFERS_FINAL_CLASS {
|
|
||||||
private:
|
|
||||||
uint64_t id_;
|
|
||||||
int16_t count_;
|
|
||||||
int8_t prefix_;
|
|
||||||
int8_t padding0__;
|
|
||||||
uint32_t length_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Foo()
|
|
||||||
: id_(0),
|
|
||||||
count_(0),
|
|
||||||
prefix_(0),
|
|
||||||
padding0__(0),
|
|
||||||
length_(0) {
|
|
||||||
(void)padding0__;
|
|
||||||
}
|
|
||||||
Foo(uint64_t _id, int16_t _count, int8_t _prefix, uint32_t _length)
|
|
||||||
: id_(flatbuffers::EndianScalar(_id)),
|
|
||||||
count_(flatbuffers::EndianScalar(_count)),
|
|
||||||
prefix_(flatbuffers::EndianScalar(_prefix)),
|
|
||||||
padding0__(0),
|
|
||||||
length_(flatbuffers::EndianScalar(_length)) {
|
|
||||||
(void)padding0__;
|
|
||||||
}
|
|
||||||
uint64_t id() const {
|
|
||||||
return flatbuffers::EndianScalar(id_);
|
|
||||||
}
|
|
||||||
int16_t count() const {
|
|
||||||
return flatbuffers::EndianScalar(count_);
|
|
||||||
}
|
|
||||||
int8_t prefix() const {
|
|
||||||
return flatbuffers::EndianScalar(prefix_);
|
|
||||||
}
|
|
||||||
uint32_t length() const {
|
|
||||||
return flatbuffers::EndianScalar(length_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
FLATBUFFERS_STRUCT_END(Foo, 16);
|
|
||||||
|
|
||||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Bar FLATBUFFERS_FINAL_CLASS {
|
|
||||||
private:
|
|
||||||
benchmarks_flatbuffers::Foo parent_;
|
|
||||||
int32_t time_;
|
|
||||||
float ratio_;
|
|
||||||
uint16_t size_;
|
|
||||||
int16_t padding0__; int32_t padding1__;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Bar()
|
|
||||||
: parent_(),
|
|
||||||
time_(0),
|
|
||||||
ratio_(0),
|
|
||||||
size_(0),
|
|
||||||
padding0__(0),
|
|
||||||
padding1__(0) {
|
|
||||||
(void)padding0__;
|
|
||||||
(void)padding1__;
|
|
||||||
}
|
|
||||||
Bar(const benchmarks_flatbuffers::Foo &_parent, int32_t _time, float _ratio, uint16_t _size)
|
|
||||||
: parent_(_parent),
|
|
||||||
time_(flatbuffers::EndianScalar(_time)),
|
|
||||||
ratio_(flatbuffers::EndianScalar(_ratio)),
|
|
||||||
size_(flatbuffers::EndianScalar(_size)),
|
|
||||||
padding0__(0),
|
|
||||||
padding1__(0) {
|
|
||||||
(void)padding0__;
|
|
||||||
(void)padding1__;
|
|
||||||
}
|
|
||||||
const benchmarks_flatbuffers::Foo &parent() const {
|
|
||||||
return parent_;
|
|
||||||
}
|
|
||||||
int32_t time() const {
|
|
||||||
return flatbuffers::EndianScalar(time_);
|
|
||||||
}
|
|
||||||
float ratio() const {
|
|
||||||
return flatbuffers::EndianScalar(ratio_);
|
|
||||||
}
|
|
||||||
uint16_t size() const {
|
|
||||||
return flatbuffers::EndianScalar(size_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
FLATBUFFERS_STRUCT_END(Bar, 32);
|
|
||||||
|
|
||||||
struct FooBar FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|
||||||
typedef FooBarBuilder Builder;
|
|
||||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
|
||||||
VT_SIBLING = 4,
|
|
||||||
VT_NAME = 6,
|
|
||||||
VT_RATING = 8,
|
|
||||||
VT_POSTFIX = 10
|
|
||||||
};
|
|
||||||
const benchmarks_flatbuffers::Bar *sibling() const {
|
|
||||||
return GetStruct<const benchmarks_flatbuffers::Bar *>(VT_SIBLING);
|
|
||||||
}
|
|
||||||
const flatbuffers::String *name() const {
|
|
||||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
|
||||||
}
|
|
||||||
double rating() const {
|
|
||||||
return GetField<double>(VT_RATING, 0.0);
|
|
||||||
}
|
|
||||||
uint8_t postfix() const {
|
|
||||||
return GetField<uint8_t>(VT_POSTFIX, 0);
|
|
||||||
}
|
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
|
||||||
return VerifyTableStart(verifier) &&
|
|
||||||
VerifyField<benchmarks_flatbuffers::Bar>(verifier, VT_SIBLING, 8) &&
|
|
||||||
VerifyOffset(verifier, VT_NAME) &&
|
|
||||||
verifier.VerifyString(name()) &&
|
|
||||||
VerifyField<double>(verifier, VT_RATING, 8) &&
|
|
||||||
VerifyField<uint8_t>(verifier, VT_POSTFIX, 1) &&
|
|
||||||
verifier.EndTable();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FooBarBuilder {
|
|
||||||
typedef FooBar Table;
|
|
||||||
flatbuffers::FlatBufferBuilder &fbb_;
|
|
||||||
flatbuffers::uoffset_t start_;
|
|
||||||
void add_sibling(const benchmarks_flatbuffers::Bar *sibling) {
|
|
||||||
fbb_.AddStruct(FooBar::VT_SIBLING, sibling);
|
|
||||||
}
|
|
||||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
|
||||||
fbb_.AddOffset(FooBar::VT_NAME, name);
|
|
||||||
}
|
|
||||||
void add_rating(double rating) {
|
|
||||||
fbb_.AddElement<double>(FooBar::VT_RATING, rating, 0.0);
|
|
||||||
}
|
|
||||||
void add_postfix(uint8_t postfix) {
|
|
||||||
fbb_.AddElement<uint8_t>(FooBar::VT_POSTFIX, postfix, 0);
|
|
||||||
}
|
|
||||||
explicit FooBarBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
|
||||||
: fbb_(_fbb) {
|
|
||||||
start_ = fbb_.StartTable();
|
|
||||||
}
|
|
||||||
flatbuffers::Offset<FooBar> Finish() {
|
|
||||||
const auto end = fbb_.EndTable(start_);
|
|
||||||
auto o = flatbuffers::Offset<FooBar>(end);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline flatbuffers::Offset<FooBar> CreateFooBar(
|
|
||||||
flatbuffers::FlatBufferBuilder &_fbb,
|
|
||||||
const benchmarks_flatbuffers::Bar *sibling = nullptr,
|
|
||||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
|
||||||
double rating = 0.0,
|
|
||||||
uint8_t postfix = 0) {
|
|
||||||
FooBarBuilder builder_(_fbb);
|
|
||||||
builder_.add_rating(rating);
|
|
||||||
builder_.add_name(name);
|
|
||||||
builder_.add_sibling(sibling);
|
|
||||||
builder_.add_postfix(postfix);
|
|
||||||
return builder_.Finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline flatbuffers::Offset<FooBar> CreateFooBarDirect(
|
|
||||||
flatbuffers::FlatBufferBuilder &_fbb,
|
|
||||||
const benchmarks_flatbuffers::Bar *sibling = nullptr,
|
|
||||||
const char *name = nullptr,
|
|
||||||
double rating = 0.0,
|
|
||||||
uint8_t postfix = 0) {
|
|
||||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
|
||||||
return benchmarks_flatbuffers::CreateFooBar(
|
|
||||||
_fbb,
|
|
||||||
sibling,
|
|
||||||
name__,
|
|
||||||
rating,
|
|
||||||
postfix);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FooBarContainer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|
||||||
typedef FooBarContainerBuilder Builder;
|
|
||||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
|
||||||
VT_LIST = 4,
|
|
||||||
VT_INITIALIZED = 6,
|
|
||||||
VT_FRUIT = 8,
|
|
||||||
VT_LOCATION = 10
|
|
||||||
};
|
|
||||||
const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list() const {
|
|
||||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *>(VT_LIST);
|
|
||||||
}
|
|
||||||
bool initialized() const {
|
|
||||||
return GetField<uint8_t>(VT_INITIALIZED, 0) != 0;
|
|
||||||
}
|
|
||||||
benchmarks_flatbuffers::Enum fruit() const {
|
|
||||||
return static_cast<benchmarks_flatbuffers::Enum>(GetField<int16_t>(VT_FRUIT, 0));
|
|
||||||
}
|
|
||||||
const flatbuffers::String *location() const {
|
|
||||||
return GetPointer<const flatbuffers::String *>(VT_LOCATION);
|
|
||||||
}
|
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
|
||||||
return VerifyTableStart(verifier) &&
|
|
||||||
VerifyOffset(verifier, VT_LIST) &&
|
|
||||||
verifier.VerifyVector(list()) &&
|
|
||||||
verifier.VerifyVectorOfTables(list()) &&
|
|
||||||
VerifyField<uint8_t>(verifier, VT_INITIALIZED, 1) &&
|
|
||||||
VerifyField<int16_t>(verifier, VT_FRUIT, 2) &&
|
|
||||||
VerifyOffset(verifier, VT_LOCATION) &&
|
|
||||||
verifier.VerifyString(location()) &&
|
|
||||||
verifier.EndTable();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FooBarContainerBuilder {
|
|
||||||
typedef FooBarContainer Table;
|
|
||||||
flatbuffers::FlatBufferBuilder &fbb_;
|
|
||||||
flatbuffers::uoffset_t start_;
|
|
||||||
void add_list(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list) {
|
|
||||||
fbb_.AddOffset(FooBarContainer::VT_LIST, list);
|
|
||||||
}
|
|
||||||
void add_initialized(bool initialized) {
|
|
||||||
fbb_.AddElement<uint8_t>(FooBarContainer::VT_INITIALIZED, static_cast<uint8_t>(initialized), 0);
|
|
||||||
}
|
|
||||||
void add_fruit(benchmarks_flatbuffers::Enum fruit) {
|
|
||||||
fbb_.AddElement<int16_t>(FooBarContainer::VT_FRUIT, static_cast<int16_t>(fruit), 0);
|
|
||||||
}
|
|
||||||
void add_location(flatbuffers::Offset<flatbuffers::String> location) {
|
|
||||||
fbb_.AddOffset(FooBarContainer::VT_LOCATION, location);
|
|
||||||
}
|
|
||||||
explicit FooBarContainerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
|
||||||
: fbb_(_fbb) {
|
|
||||||
start_ = fbb_.StartTable();
|
|
||||||
}
|
|
||||||
flatbuffers::Offset<FooBarContainer> Finish() {
|
|
||||||
const auto end = fbb_.EndTable(start_);
|
|
||||||
auto o = flatbuffers::Offset<FooBarContainer>(end);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainer(
|
|
||||||
flatbuffers::FlatBufferBuilder &_fbb,
|
|
||||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list = 0,
|
|
||||||
bool initialized = false,
|
|
||||||
benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples,
|
|
||||||
flatbuffers::Offset<flatbuffers::String> location = 0) {
|
|
||||||
FooBarContainerBuilder builder_(_fbb);
|
|
||||||
builder_.add_location(location);
|
|
||||||
builder_.add_list(list);
|
|
||||||
builder_.add_fruit(fruit);
|
|
||||||
builder_.add_initialized(initialized);
|
|
||||||
return builder_.Finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainerDirect(
|
|
||||||
flatbuffers::FlatBufferBuilder &_fbb,
|
|
||||||
const std::vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list = nullptr,
|
|
||||||
bool initialized = false,
|
|
||||||
benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples,
|
|
||||||
const char *location = nullptr) {
|
|
||||||
auto list__ = list ? _fbb.CreateVector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>(*list) : 0;
|
|
||||||
auto location__ = location ? _fbb.CreateString(location) : 0;
|
|
||||||
return benchmarks_flatbuffers::CreateFooBarContainer(
|
|
||||||
_fbb,
|
|
||||||
list__,
|
|
||||||
initialized,
|
|
||||||
fruit,
|
|
||||||
location__);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const benchmarks_flatbuffers::FooBarContainer *GetFooBarContainer(const void *buf) {
|
|
||||||
return flatbuffers::GetRoot<benchmarks_flatbuffers::FooBarContainer>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const benchmarks_flatbuffers::FooBarContainer *GetSizePrefixedFooBarContainer(const void *buf) {
|
|
||||||
return flatbuffers::GetSizePrefixedRoot<benchmarks_flatbuffers::FooBarContainer>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VerifyFooBarContainerBuffer(
|
|
||||||
flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifyBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VerifySizePrefixedFooBarContainerBuffer(
|
|
||||||
flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifySizePrefixedBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FinishFooBarContainerBuffer(
|
|
||||||
flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
flatbuffers::Offset<benchmarks_flatbuffers::FooBarContainer> root) {
|
|
||||||
fbb.Finish(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FinishSizePrefixedFooBarContainerBuffer(
|
|
||||||
flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
flatbuffers::Offset<benchmarks_flatbuffers::FooBarContainer> root) {
|
|
||||||
fbb.FinishSizePrefixed(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace benchmarks_flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
|
|
@ -1,80 +0,0 @@
|
|||||||
#include "benchmarks/cpp/flatbuffers/fb_bench.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "benchmarks/cpp/bench.h"
|
|
||||||
#include "benchmarks/cpp/flatbuffers/bench_generated.h"
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
|
|
||||||
using namespace flatbuffers;
|
|
||||||
using namespace benchmarks_flatbuffers;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
struct FlatBufferBench : Bench {
|
|
||||||
explicit FlatBufferBench(int64_t initial_size, Allocator *allocator)
|
|
||||||
: fbb(initial_size, allocator, false) {}
|
|
||||||
|
|
||||||
uint8_t *Encode(void *, int64_t &len) override {
|
|
||||||
fbb.Clear();
|
|
||||||
|
|
||||||
const int kVectorLength = 3;
|
|
||||||
Offset<FooBar> vec[kVectorLength];
|
|
||||||
|
|
||||||
for (int i = 0; i < kVectorLength; ++i) {
|
|
||||||
Foo foo(0xABADCAFEABADCAFE + i, 10000 + i, '@' + i, 1000000 + i);
|
|
||||||
Bar bar(foo, 123456 + i, 3.14159f + i, 10000 + i);
|
|
||||||
auto name = fbb.CreateString("Hello, World!");
|
|
||||||
auto foobar =
|
|
||||||
CreateFooBar(fbb, &bar, name, 3.1415432432445543543 + i, '!' + i);
|
|
||||||
vec[i] = foobar;
|
|
||||||
}
|
|
||||||
auto location = fbb.CreateString("http://google.com/flatbuffers/");
|
|
||||||
auto foobarvec = fbb.CreateVector(vec, kVectorLength);
|
|
||||||
auto foobarcontainer =
|
|
||||||
CreateFooBarContainer(fbb, foobarvec, true, Enum_Bananas, location);
|
|
||||||
fbb.Finish(foobarcontainer);
|
|
||||||
|
|
||||||
len = fbb.GetSize();
|
|
||||||
return fbb.GetBufferPointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t Use(void *decoded) override {
|
|
||||||
sum = 0;
|
|
||||||
auto foobarcontainer = GetFooBarContainer(decoded);
|
|
||||||
sum = 0;
|
|
||||||
Add(foobarcontainer->initialized());
|
|
||||||
Add(foobarcontainer->location()->Length());
|
|
||||||
Add(foobarcontainer->fruit());
|
|
||||||
for (unsigned int i = 0; i < foobarcontainer->list()->Length(); i++) {
|
|
||||||
auto foobar = foobarcontainer->list()->Get(i);
|
|
||||||
Add(foobar->name()->Length());
|
|
||||||
Add(foobar->postfix());
|
|
||||||
Add(static_cast<int64_t>(foobar->rating()));
|
|
||||||
auto bar = foobar->sibling();
|
|
||||||
Add(static_cast<int64_t>(bar->ratio()));
|
|
||||||
Add(bar->size());
|
|
||||||
Add(bar->time());
|
|
||||||
auto &foo = bar->parent();
|
|
||||||
Add(foo.count());
|
|
||||||
Add(foo.id());
|
|
||||||
Add(foo.length());
|
|
||||||
Add(foo.prefix());
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Decode(void *buffer, int64_t) override { return buffer; }
|
|
||||||
void Dealloc(void *) override {};
|
|
||||||
|
|
||||||
FlatBufferBuilder fbb;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
std::unique_ptr<Bench> NewFlatBuffersBench(int64_t initial_size,
|
|
||||||
Allocator *allocator) {
|
|
||||||
return std::unique_ptr<FlatBufferBench>(
|
|
||||||
new FlatBufferBench(initial_size, allocator));
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
#ifndef BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_
|
|
||||||
#define BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "benchmarks/cpp/bench.h"
|
|
||||||
#include "include/flatbuffers/flatbuffers.h"
|
|
||||||
|
|
||||||
struct StaticAllocator : public flatbuffers::Allocator {
|
|
||||||
explicit StaticAllocator(uint8_t *buffer) : buffer_(buffer) {}
|
|
||||||
|
|
||||||
uint8_t *allocate(size_t) override { return buffer_; }
|
|
||||||
|
|
||||||
void deallocate(uint8_t *, size_t) override {}
|
|
||||||
|
|
||||||
uint8_t *buffer_;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::unique_ptr<Bench> NewFlatBuffersBench(
|
|
||||||
int64_t initial_size = 1024, flatbuffers::Allocator *allocator = nullptr);
|
|
||||||
|
|
||||||
#endif // BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_
|
|
@ -1,109 +0,0 @@
|
|||||||
#include "benchmarks/cpp/raw/raw_bench.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstring>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "benchmarks/cpp/bench.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
const int64_t kStringLength = 32;
|
|
||||||
const int64_t kVectorLength = 3;
|
|
||||||
|
|
||||||
enum Enum { Apples, Pears, Bananas };
|
|
||||||
|
|
||||||
struct Foo {
|
|
||||||
int64_t id;
|
|
||||||
short count;
|
|
||||||
char prefix;
|
|
||||||
int length;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Bar {
|
|
||||||
Foo parent;
|
|
||||||
int time;
|
|
||||||
float ratio;
|
|
||||||
unsigned short size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FooBar {
|
|
||||||
Bar sibling;
|
|
||||||
// We have to stick this in, otherwise strlen() will make it slower than
|
|
||||||
// FlatBuffers:
|
|
||||||
int name_len;
|
|
||||||
char name[kStringLength];
|
|
||||||
double rating;
|
|
||||||
unsigned char postfix;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FooBarContainer {
|
|
||||||
FooBar list[kVectorLength]; // 3 copies of the above
|
|
||||||
bool initialized;
|
|
||||||
Enum fruit;
|
|
||||||
int location_len;
|
|
||||||
char location[kStringLength];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RawBench : Bench {
|
|
||||||
uint8_t *Encode(void *buf, int64_t &len) override {
|
|
||||||
FooBarContainer *fbc = new (buf) FooBarContainer;
|
|
||||||
strcpy(fbc->location, "http://google.com/flatbuffers/"); // Unsafe eek!
|
|
||||||
fbc->location_len = (int)strlen(fbc->location);
|
|
||||||
fbc->fruit = Bananas;
|
|
||||||
fbc->initialized = true;
|
|
||||||
for (int i = 0; i < kVectorLength; i++) {
|
|
||||||
// We add + i to not make these identical copies for a more realistic
|
|
||||||
// compression test.
|
|
||||||
auto &foobar = fbc->list[i];
|
|
||||||
foobar.rating = 3.1415432432445543543 + i;
|
|
||||||
foobar.postfix = '!' + i;
|
|
||||||
strcpy(foobar.name, "Hello, World!");
|
|
||||||
foobar.name_len = (int)strlen(foobar.name);
|
|
||||||
auto &bar = foobar.sibling;
|
|
||||||
bar.ratio = 3.14159f + i;
|
|
||||||
bar.size = 10000 + i;
|
|
||||||
bar.time = 123456 + i;
|
|
||||||
auto &foo = bar.parent;
|
|
||||||
foo.id = 0xABADCAFEABADCAFE + i;
|
|
||||||
foo.count = 10000 + i;
|
|
||||||
foo.length = 1000000 + i;
|
|
||||||
foo.prefix = '@' + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = sizeof(FooBarContainer);
|
|
||||||
return reinterpret_cast<uint8_t *>(fbc);
|
|
||||||
};
|
|
||||||
|
|
||||||
int64_t Use(void *decoded) override {
|
|
||||||
auto foobarcontainer = reinterpret_cast<FooBarContainer *>(decoded);
|
|
||||||
sum = 0;
|
|
||||||
Add(foobarcontainer->initialized);
|
|
||||||
Add(foobarcontainer->location_len);
|
|
||||||
Add(foobarcontainer->fruit);
|
|
||||||
for (unsigned int i = 0; i < kVectorLength; i++) {
|
|
||||||
auto foobar = &foobarcontainer->list[i];
|
|
||||||
Add(foobar->name_len);
|
|
||||||
Add(foobar->postfix);
|
|
||||||
Add(static_cast<int64_t>(foobar->rating));
|
|
||||||
auto bar = &foobar->sibling;
|
|
||||||
Add(static_cast<int64_t>(bar->ratio));
|
|
||||||
Add(bar->size);
|
|
||||||
Add(bar->time);
|
|
||||||
auto &foo = bar->parent;
|
|
||||||
Add(foo.count);
|
|
||||||
Add(foo.id);
|
|
||||||
Add(foo.length);
|
|
||||||
Add(foo.prefix);
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Decode(void *buf, int64_t) override { return buf; }
|
|
||||||
void Dealloc(void *) override{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
std::unique_ptr<Bench> NewRawBench() {
|
|
||||||
return std::unique_ptr<RawBench>(new RawBench());
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
#ifndef BENCHMARKS_CPP_RAW_RAW_BENCH_H_
|
|
||||||
#define BENCHMARKS_CPP_RAW_RAW_BENCH_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "benchmarks/cpp/bench.h"
|
|
||||||
|
|
||||||
std::unique_ptr<Bench> NewRawBench();
|
|
||||||
|
|
||||||
#endif // BENCHMARKS_CPP_RAW_RAW_BENCH_H_
|
|
@ -1,181 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import Benchmark
|
|
||||||
import CoreFoundation
|
|
||||||
import FlatBuffers
|
|
||||||
|
|
||||||
@usableFromInline
|
|
||||||
struct AA: NativeStruct {
|
|
||||||
public init(a: Double, b: Double) {
|
|
||||||
self.a = a
|
|
||||||
self.b = b
|
|
||||||
}
|
|
||||||
var a: Double
|
|
||||||
var b: Double
|
|
||||||
}
|
|
||||||
|
|
||||||
let benchmarks = {
|
|
||||||
let ints: [Int] = Array(repeating: 42, count: 100)
|
|
||||||
let bytes: [UInt8] = Array(repeating: 42, count: 100)
|
|
||||||
let str10 = (0...9).map { _ -> String in "x" }.joined()
|
|
||||||
let str100 = (0...99).map { _ -> String in "x" }.joined()
|
|
||||||
let array: [AA] = [
|
|
||||||
AA(a: 2.4, b: 2.4),
|
|
||||||
AA(a: 2.4, b: 2.4),
|
|
||||||
AA(a: 2.4, b: 2.4),
|
|
||||||
AA(a: 2.4, b: 2.4),
|
|
||||||
AA(a: 2.4, b: 2.4),
|
|
||||||
]
|
|
||||||
|
|
||||||
let metrics: [BenchmarkMetric] = [
|
|
||||||
.cpuTotal,
|
|
||||||
.wallClock,
|
|
||||||
.mallocCountTotal,
|
|
||||||
.releaseCount,
|
|
||||||
.peakMemoryResident,
|
|
||||||
]
|
|
||||||
let maxIterations = 1_000_000
|
|
||||||
let maxDuration: Duration = .seconds(3)
|
|
||||||
let singleConfiguration: Benchmark.Configuration = .init(
|
|
||||||
metrics: metrics,
|
|
||||||
warmupIterations: 1,
|
|
||||||
scalingFactor: .one,
|
|
||||||
maxDuration: maxDuration,
|
|
||||||
maxIterations: maxIterations)
|
|
||||||
let kiloConfiguration: Benchmark.Configuration = .init(
|
|
||||||
metrics: metrics,
|
|
||||||
warmupIterations: 1,
|
|
||||||
scalingFactor: .kilo,
|
|
||||||
maxDuration: maxDuration,
|
|
||||||
maxIterations: maxIterations)
|
|
||||||
let megaConfiguration: Benchmark.Configuration = .init(
|
|
||||||
metrics: metrics,
|
|
||||||
warmupIterations: 1,
|
|
||||||
scalingFactor: .mega,
|
|
||||||
maxDuration: maxDuration,
|
|
||||||
maxIterations: maxIterations)
|
|
||||||
|
|
||||||
Benchmark.defaultConfiguration = megaConfiguration
|
|
||||||
|
|
||||||
Benchmark("Allocating 1GB", configuration: singleConfiguration) { benchmark in
|
|
||||||
for _ in benchmark.scaledIterations {
|
|
||||||
blackHole(FlatBufferBuilder(initialSize: 1_024_000_000))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in
|
|
||||||
var fb = FlatBufferBuilder(initialSize: 1_024_000_000)
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for _ in benchmark.scaledIterations {
|
|
||||||
blackHole(fb.clear())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark("Strings 10") { benchmark in
|
|
||||||
var fb = FlatBufferBuilder(initialSize: 1<<20)
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for _ in benchmark.scaledIterations {
|
|
||||||
blackHole(fb.create(string: str10))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark("Strings 100") { benchmark in
|
|
||||||
var fb = FlatBufferBuilder(initialSize: 1<<20)
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for _ in benchmark.scaledIterations {
|
|
||||||
blackHole(fb.create(string: str100))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark("Vector 1 Bytes") { benchmark in
|
|
||||||
var fb = FlatBufferBuilder(initialSize: 1<<20)
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for _ in benchmark.scaledIterations {
|
|
||||||
blackHole(fb.createVector(bytes: bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark("Vector 1 Ints") { benchmark in
|
|
||||||
var fb = FlatBufferBuilder(initialSize: 1<<20)
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for _ in benchmark.scaledIterations {
|
|
||||||
blackHole(fb.createVector(ints))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark("Vector 100 Ints") { benchmark in
|
|
||||||
var fb = FlatBufferBuilder(initialSize: 1<<20)
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for i in benchmark.scaledIterations {
|
|
||||||
blackHole(fb.createVector(ints))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark("Vector 100 Bytes") { benchmark in
|
|
||||||
var fb = FlatBufferBuilder(initialSize: 1<<20)
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for i in benchmark.scaledIterations {
|
|
||||||
blackHole(fb.createVector(bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark("Vector 100 ContiguousBytes") { benchmark in
|
|
||||||
var fb = FlatBufferBuilder(initialSize: 1<<20)
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for i in benchmark.scaledIterations {
|
|
||||||
blackHole(fb.createVector(bytes: bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark(
|
|
||||||
"FlatBufferBuilder Add",
|
|
||||||
configuration: kiloConfiguration)
|
|
||||||
{ benchmark in
|
|
||||||
var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32)
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for _ in benchmark.scaledIterations {
|
|
||||||
let off = fb.create(string: "T")
|
|
||||||
let s = fb.startTable(with: 4)
|
|
||||||
fb.add(element: 3.2, def: 0, at: 2)
|
|
||||||
fb.add(element: 4.2, def: 0, at: 4)
|
|
||||||
fb.add(element: 5.2, def: 0, at: 6)
|
|
||||||
fb.add(offset: off, at: 8)
|
|
||||||
blackHole(fb.endTable(at: s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark("Structs") { benchmark in
|
|
||||||
let rawSize = ((16 * 5) * benchmark.scaledIterations.count) / 1024
|
|
||||||
var fb = FlatBufferBuilder(initialSize: Int32(rawSize * 1600))
|
|
||||||
var offsets: [Offset] = []
|
|
||||||
|
|
||||||
benchmark.startMeasurement()
|
|
||||||
for _ in benchmark.scaledIterations {
|
|
||||||
let vector = fb.createVector(
|
|
||||||
ofStructs: array)
|
|
||||||
let start = fb.startTable(with: 1)
|
|
||||||
fb.add(offset: vector, at: 4)
|
|
||||||
offsets.append(Offset(offset: fb.endTable(at: start)))
|
|
||||||
}
|
|
||||||
|
|
||||||
let vector = fb.createVector(ofOffsets: offsets)
|
|
||||||
let start = fb.startTable(with: 1)
|
|
||||||
fb.add(offset: vector, at: 4)
|
|
||||||
let root = Offset(offset: fb.endTable(at: start))
|
|
||||||
fb.finish(offset: root)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
// swift-tools-version:5.8
|
|
||||||
/*
|
|
||||||
* Copyright 2020 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import PackageDescription
|
|
||||||
|
|
||||||
let package = Package(
|
|
||||||
name: "benchmarks",
|
|
||||||
platforms: [
|
|
||||||
.macOS(.v13),
|
|
||||||
],
|
|
||||||
dependencies: [
|
|
||||||
.package(path: "../.."),
|
|
||||||
.package(
|
|
||||||
url: "https://github.com/ordo-one/package-benchmark",
|
|
||||||
from: "1.12.0"),
|
|
||||||
],
|
|
||||||
targets: [
|
|
||||||
.executableTarget(
|
|
||||||
name: "FlatbuffersBenchmarks",
|
|
||||||
dependencies: [
|
|
||||||
.product(name: "FlatBuffers", package: "flatbuffers"),
|
|
||||||
.product(name: "Benchmark", package: "package-benchmark"),
|
|
||||||
],
|
|
||||||
path: "Benchmarks/FlatbuffersBenchmarks",
|
|
||||||
plugins: [
|
|
||||||
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"),
|
|
||||||
]),
|
|
||||||
])
|
|
@ -1,9 +0,0 @@
|
|||||||
# Benchmarks
|
|
||||||
|
|
||||||
To open the benchmarks in xcode use:
|
|
||||||
|
|
||||||
`open --env BENCHMARK_DISABLE_JEMALLOC=true Package.swift`
|
|
||||||
|
|
||||||
or running them directly within terminal using:
|
|
||||||
|
|
||||||
`swift package benchmark`
|
|
14
third_party/flatbuffers/docs/footer.html
vendored
@ -1,14 +0,0 @@
|
|||||||
<!-- Google Analytics -->
|
|
||||||
<script>
|
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
||||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
|
||||||
|
|
||||||
ga('create', 'UA-49880327-7', 'auto');
|
|
||||||
ga('send', 'pageview');
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
62
third_party/flatbuffers/docs/header.html
vendored
@ -1,62 +0,0 @@
|
|||||||
<!-- HTML header for doxygen 1.8.6-->
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
|
||||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
|
||||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
|
||||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
|
||||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
|
||||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
|
||||||
$treeview
|
|
||||||
$search
|
|
||||||
$mathjax
|
|
||||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,400italic,500,500italic,700,700italic|Roboto+Mono:400,700" rel="stylesheet">
|
|
||||||
$extrastylesheet
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
|
||||||
|
|
||||||
<!--BEGIN TITLEAREA-->
|
|
||||||
<div id="titlearea" style="height: 110px;">
|
|
||||||
<table cellspacing="0" cellpadding="0">
|
|
||||||
<tbody>
|
|
||||||
<tr style="height: 56px;">
|
|
||||||
<!--BEGIN PROJECT_LOGO-->
|
|
||||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
|
||||||
<!--END PROJECT_LOGO-->
|
|
||||||
<td id="commonprojectlogo">
|
|
||||||
<img alt="Logo" src="$relpath^fpl_logo_small.png"/>
|
|
||||||
</td>
|
|
||||||
<!--BEGIN PROJECT_NAME-->
|
|
||||||
<td style="padding-left: 0.5em;">
|
|
||||||
<div id="projectname">$projectname
|
|
||||||
<!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
|
|
||||||
</div>
|
|
||||||
<div style="font-size:12px;">
|
|
||||||
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
|
|
||||||
</div>
|
|
||||||
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
|
|
||||||
</td>
|
|
||||||
<!--END PROJECT_NAME-->
|
|
||||||
<!--BEGIN !PROJECT_NAME-->
|
|
||||||
<!--BEGIN PROJECT_BRIEF-->
|
|
||||||
<td style="padding-left: 0.5em;">
|
|
||||||
<div id="projectbrief">$projectbrief</div>
|
|
||||||
</td>
|
|
||||||
<!--END PROJECT_BRIEF-->
|
|
||||||
<!--END !PROJECT_NAME-->
|
|
||||||
<!--BEGIN DISABLE_INDEX-->
|
|
||||||
<!--BEGIN SEARCHENGINE-->
|
|
||||||
<td>$searchbox</td>
|
|
||||||
<!--END SEARCHENGINE-->
|
|
||||||
<!--END DISABLE_INDEX-->
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<!--END TITLEAREA-->
|
|
||||||
<!-- end header part -->
|
|
Before Width: | Height: | Size: 5.0 KiB |
BIN
third_party/flatbuffers/docs/images/ftv2mnode.png
vendored
Before Width: | Height: | Size: 1.0 KiB |
BIN
third_party/flatbuffers/docs/images/ftv2pnode.png
vendored
Before Width: | Height: | Size: 1.0 KiB |
@ -1,63 +0,0 @@
|
|||||||
C++ Benchmarks {#flatbuffers_benchmarks}
|
|
||||||
==========
|
|
||||||
|
|
||||||
Comparing against other serialization solutions, running on Windows 7
|
|
||||||
64bit. We use the LITE runtime for Protocol Buffers (less code / lower
|
|
||||||
overhead), Rapid JSON (one of the fastest C++ JSON parsers around),
|
|
||||||
and pugixml, also one of the fastest XML parsers.
|
|
||||||
|
|
||||||
We also compare against code that doesn't use a serialization library
|
|
||||||
at all (the column "Raw structs"), which is what you get if you write
|
|
||||||
hardcoded code that just writes structs. This is the fastest possible,
|
|
||||||
but of course is not cross platform nor has any kind of forwards /
|
|
||||||
backwards compatibility.
|
|
||||||
|
|
||||||
We compare against Flatbuffers with the binary wire format (as
|
|
||||||
intended), and also with JSON as the wire format with the optional JSON
|
|
||||||
parser (which, using a schema, parses JSON into a binary buffer that can
|
|
||||||
then be accessed as before).
|
|
||||||
|
|
||||||
The benchmark object is a set of about 10 objects containing an array, 4
|
|
||||||
strings, and a large variety of int/float scalar values of all sizes,
|
|
||||||
meant to be representative of game data, e.g. a scene format.
|
|
||||||
|
|
||||||
| | FlatBuffers (binary) | Protocol Buffers LITE | Rapid JSON | FlatBuffers (JSON) | pugixml | Raw structs |
|
|
||||||
|--------------------------------------------------------|-----------------------|-----------------------|-----------------------|------------------------| ----------------------| ----------------------|
|
|
||||||
| Decode + Traverse + Dealloc (1 million times, seconds) | 0.08 | 302 | 583 | 105 | 196 | 0.02 |
|
|
||||||
| Decode / Traverse / Dealloc (breakdown) | 0 / 0.08 / 0 | 220 / 0.15 / 81 | 294 / 0.9 / 287 | 70 / 0.08 / 35 | 41 / 3.9 / 150 | 0 / 0.02 / 0 |
|
|
||||||
| Encode (1 million times, seconds) | 3.2 | 185 | 650 | 169 | 273 | 0.15 |
|
|
||||||
| Wire format size (normal / zlib, bytes) | 344 / 220 | 228 / 174 | 1475 / 322 | 1029 / 298 | 1137 / 341 | 312 / 187 |
|
|
||||||
| Memory needed to store decoded wire (bytes / blocks) | 0 / 0 | 760 / 20 | 65689 / 4 | 328 / 1 | 34194 / 3 | 0 / 0 |
|
|
||||||
| Transient memory allocated during decode (KB) | 0 | 1 | 131 | 4 | 34 | 0 |
|
|
||||||
| Generated source code size (KB) | 4 | 61 | 0 | 4 | 0 | 0 |
|
|
||||||
| Field access in handwritten traversal code | typed accessors | typed accessors | manual error checking | typed accessors | manual error checking | typed but no safety |
|
|
||||||
| Library source code (KB) | 15 | some subset of 3800 | 87 | 43 | 327 | 0 |
|
|
||||||
|
|
||||||
### Some other serialization systems we compared against but did not benchmark (yet), in rough order of applicability:
|
|
||||||
|
|
||||||
- Cap'n'Proto promises to reduce Protocol Buffers much like FlatBuffers does,
|
|
||||||
though with a more complicated binary encoding and less flexibility (no
|
|
||||||
optional fields to allow deprecating fields or serializing with missing
|
|
||||||
fields for which defaults exist).
|
|
||||||
It currently also isn't fully cross-platform portable (lack of VS support).
|
|
||||||
- msgpack: has very minimal forwards/backwards compatibility support when used
|
|
||||||
with the typed C++ interface. Also lacks VS2010 support.
|
|
||||||
- Thrift: very similar to Protocol Buffers, but appears to be less efficient,
|
|
||||||
and have more dependencies.
|
|
||||||
- YAML: a superset of JSON and otherwise very similar. Used by e.g. Unity.
|
|
||||||
- C# comes with built-in serialization functionality, as used by Unity also.
|
|
||||||
Being tied to the language, and having no automatic versioning support
|
|
||||||
limits its applicability.
|
|
||||||
- Project Anarchy (the free mobile engine by Havok) comes with a serialization
|
|
||||||
system, that however does no automatic versioning (have to code around new
|
|
||||||
fields manually), is very much tied to the rest of the engine, and works
|
|
||||||
without a schema to generate code (tied to your C++ class definition).
|
|
||||||
|
|
||||||
### Code for benchmarks
|
|
||||||
|
|
||||||
Code for these benchmarks sits in `benchmarks/` in git branch `benchmarks`.
|
|
||||||
It sits in its own branch because it has submodule dependencies that the main
|
|
||||||
project doesn't need, and the code standards do not meet those of the main
|
|
||||||
project. Please read `benchmarks/cpp/README.txt` before working with the code.
|
|
||||||
|
|
||||||
<br>
|
|
133
third_party/flatbuffers/docs/source/Building.md
vendored
@ -1,133 +0,0 @@
|
|||||||
Building {#flatbuffers_guide_building}
|
|
||||||
========
|
|
||||||
|
|
||||||
## Building with CMake
|
|
||||||
|
|
||||||
The distribution comes with a `cmake` file that should allow
|
|
||||||
you to build project/make files for any platform. For details on `cmake`, see
|
|
||||||
<https://www.cmake.org>. In brief, depending on your platform, use one of
|
|
||||||
e.g.:
|
|
||||||
|
|
||||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake -G "Visual Studio 10" -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release
|
|
||||||
|
|
||||||
Then, build as normal for your platform. This should result in a `flatc`
|
|
||||||
executable, essential for the next steps.
|
|
||||||
Note that to use clang instead of gcc, you may need to set up your environment
|
|
||||||
variables, e.g.
|
|
||||||
`CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -G "Unix Makefiles"`.
|
|
||||||
|
|
||||||
Optionally, run the `flattests` executable from the root `flatbuffers/`
|
|
||||||
directory to ensure everything is working correctly on your system. If this
|
|
||||||
fails, please contact us!
|
|
||||||
|
|
||||||
Building should also produce two sample executables, `flatsamplebinary` and
|
|
||||||
`flatsampletext`, see the corresponding `.cpp` files in the
|
|
||||||
`flatbuffers/samples` directory.
|
|
||||||
|
|
||||||
*Note that you MUST be in the root of the FlatBuffers distribution when you
|
|
||||||
run 'flattests' or `flatsampletext`, or it will fail to load its files.*
|
|
||||||
|
|
||||||
### Make all warnings into errors
|
|
||||||
|
|
||||||
By default all Flatbuffers `cmake` targets are **not** built with the `-Werror`
|
|
||||||
(or `/WX` for MSVC) flag that treats any warning as an error. This allows more
|
|
||||||
flexibility for users of Flatbuffers to use newer compilers and toolsets that
|
|
||||||
may add new warnings that would cause a build failure.
|
|
||||||
|
|
||||||
To enable a stricter build that does treat warnings as errors, set the
|
|
||||||
`FLATBUFFERS_STRICT_MODE` `cmake` compliation flag to `ON`.
|
|
||||||
|
|
||||||
```
|
|
||||||
cmake . -DFLATBUFFERS_STRICT_MODE=ON
|
|
||||||
```
|
|
||||||
|
|
||||||
Our CI builds run with strict mode on, ensuring the code that is committed to
|
|
||||||
the project is as portable and warning free as possible. Thus developers
|
|
||||||
contributing to the project should enable strict mode locally before making a
|
|
||||||
PR.
|
|
||||||
|
|
||||||
## Building with VCPKG
|
|
||||||
|
|
||||||
You can download and install flatbuffers using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
|
|
||||||
|
|
||||||
git clone https://github.com/Microsoft/vcpkg.git
|
|
||||||
cd vcpkg
|
|
||||||
./bootstrap-vcpkg.sh
|
|
||||||
./vcpkg integrate install
|
|
||||||
./vcpkg install flatbuffers
|
|
||||||
|
|
||||||
The flatbuffers port in vcpkg is kept up to date by Microsoft team members and community contributors.
|
|
||||||
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
|
||||||
|
|
||||||
## Downloading binaries
|
|
||||||
You can download the binaries from the
|
|
||||||
[GitHub release page](https://github.com/google/flatbuffers/releases).
|
|
||||||
|
|
||||||
We generate [SLSA3 signatures](slsa.dev) using the OpenSSF's [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator). To verify the binaries:
|
|
||||||
1. Install the verification tool from [slsa-framework/slsa-verifier#installation](https://github.com/slsa-framework/slsa-verifier#installation)
|
|
||||||
1. Download the file named `attestation.intoto.jsonl` from the GitHub release
|
|
||||||
1. Run:
|
|
||||||
```shell
|
|
||||||
$ slsa-verifier -artifact-path <downloaded.zip> -provenance attestation.intoto.jsonl -source github.com/google/flatbuffers -tag <version>
|
|
||||||
PASSED: Verified SLSA provenance
|
|
||||||
|
|
||||||
## Building for Android
|
|
||||||
|
|
||||||
There is a `flatbuffers/android` directory that contains all you need to build
|
|
||||||
the test executable on android (use the included `build_apk.sh` script, or use
|
|
||||||
`ndk_build` / `adb` etc. as usual). Upon running, it will output to the log
|
|
||||||
if tests succeeded or not.
|
|
||||||
|
|
||||||
You may also run an android sample from inside the `flatbuffers/samples`, by
|
|
||||||
running the `android_sample.sh` script. Optionally, you may go to the
|
|
||||||
`flatbuffers/samples/android` folder and build the sample with the
|
|
||||||
`build_apk.sh` script or `ndk_build` / `adb` etc.
|
|
||||||
|
|
||||||
## Using FlatBuffers in your own projects
|
|
||||||
|
|
||||||
For C++, there is usually no runtime to compile, as the code consists of a
|
|
||||||
single header, `include/flatbuffers/flatbuffers.h`. You should add the
|
|
||||||
`include` folder to your include paths. If you wish to be
|
|
||||||
able to load schemas and/or parse text into binary buffers at runtime,
|
|
||||||
you additionally need the other headers in `include/flatbuffers`. You must
|
|
||||||
also compile/link `src/idl_parser.cpp` (and `src/idl_gen_text.cpp` if you
|
|
||||||
also want to be able convert binary to text).
|
|
||||||
|
|
||||||
To see how to include FlatBuffers in any of our supported languages, please
|
|
||||||
view the [Tutorial](@ref flatbuffers_guide_tutorial) and select your appropriate
|
|
||||||
language using the radio buttons.
|
|
||||||
|
|
||||||
### Using in CMake-based projects
|
|
||||||
If you want to use FlatBuffers in a project which already uses CMake, then a more
|
|
||||||
robust and flexible approach is to build FlatBuffers as part of that project directly.
|
|
||||||
This is done by making the FlatBuffers source code available to the main build
|
|
||||||
and adding it using CMake's `add_subdirectory()` command. This has the
|
|
||||||
significant advantage that the same compiler and linker settings are used
|
|
||||||
between FlatBuffers and the rest of your project, so issues associated with using
|
|
||||||
incompatible libraries (eg debug/release), etc. are avoided. This is
|
|
||||||
particularly useful on Windows.
|
|
||||||
|
|
||||||
Suppose you put FlatBuffers source code in directory `${FLATBUFFERS_SRC_DIR}`.
|
|
||||||
To build it as part of your project, add following code to your `CMakeLists.txt` file:
|
|
||||||
```cmake
|
|
||||||
# Add FlatBuffers directly to our build. This defines the `flatbuffers` target.
|
|
||||||
add_subdirectory(${FLATBUFFERS_SRC_DIR}
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build
|
|
||||||
EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
# Now simply link against flatbuffers as needed to your already declared target.
|
|
||||||
# The flatbuffers target carry header search path automatically if CMake > 2.8.11.
|
|
||||||
target_link_libraries(own_project_target PRIVATE flatbuffers)
|
|
||||||
```
|
|
||||||
When build your project the `flatbuffers` library will be compiled and linked
|
|
||||||
to a target as part of your project.
|
|
||||||
|
|
||||||
#### Override default depth limit of nested objects
|
|
||||||
To override [the depth limit of recursion](@ref flatbuffers_guide_use_cpp),
|
|
||||||
add this directive:
|
|
||||||
```cmake
|
|
||||||
set(FLATBUFFERS_MAX_PARSING_DEPTH 16)
|
|
||||||
```
|
|
||||||
to `CMakeLists.txt` file before `add_subdirectory(${FLATBUFFERS_SRC_DIR})` line.
|
|
@ -1 +0,0 @@
|
|||||||
../../CONTRIBUTING.md
|
|
224
third_party/flatbuffers/docs/source/CUsage.md
vendored
@ -1,224 +0,0 @@
|
|||||||
Use in C {#flatbuffers_guide_use_c}
|
|
||||||
==========
|
|
||||||
|
|
||||||
The C language binding exists in a separate project named [FlatCC](https://github.com/dvidelabs/flatcc).
|
|
||||||
|
|
||||||
The `flatcc` C schema compiler can generate code offline as well as
|
|
||||||
online via a C library. It can also generate buffer verifiers and fast
|
|
||||||
JSON parsers, printers.
|
|
||||||
|
|
||||||
Great care has been taken to ensure compatibility with the main `flatc`
|
|
||||||
project.
|
|
||||||
|
|
||||||
## General Documention
|
|
||||||
|
|
||||||
- [Tutorial](@ref flatbuffers_guide_tutorial) - select C as language
|
|
||||||
when scrolling down
|
|
||||||
- [FlatCC Guide](https://github.com/dvidelabs/flatcc#flatcc-flatbuffers-in-c-for-c)
|
|
||||||
- [The C Builder Interface](https://github.com/dvidelabs/flatcc/blob/master/doc/builder.md#the-builder-interface)
|
|
||||||
- [The Monster Sample in C](https://github.com/dvidelabs/flatcc/blob/master/samples/monster/monster.c)
|
|
||||||
- [GitHub](https://github.com/dvidelabs/flatcc)
|
|
||||||
|
|
||||||
|
|
||||||
## Supported Platforms
|
|
||||||
|
|
||||||
- Ubuntu (clang / gcc, ninja / gnu make)
|
|
||||||
- OS-X (clang / gcc, ninja / gnu make)
|
|
||||||
- Windows MSVC 2010, 2013, 2015
|
|
||||||
|
|
||||||
CI builds recent versions of gcc, clang and MSVC on OS-X, Ubuntu, and
|
|
||||||
Windows, and occasionally older compiler versions. See main project [Status](https://github.com/dvidelabs/flatcc#status).
|
|
||||||
|
|
||||||
Other platforms may well work, including Centos, but are not tested
|
|
||||||
regularly.
|
|
||||||
|
|
||||||
The monster sample project was specifically written for C99 in order to
|
|
||||||
follow the C++ version and for that reason it will not work with MSVC
|
|
||||||
2010.
|
|
||||||
|
|
||||||
## Modular Object Creation
|
|
||||||
|
|
||||||
In the tutorial we used the call `Monster_create_as_root` to create the
|
|
||||||
root buffer object since this is easier in simple use cases. Sometimes
|
|
||||||
we need more modularity so we can reuse a function to create nested
|
|
||||||
tables and root tables the same way. For this we need the
|
|
||||||
`flatcc_builder_buffer_create_call`. It is best to keep `flatcc_builder`
|
|
||||||
calls isolated at the top driver level, so we get:
|
|
||||||
|
|
||||||
<div class="language-c">
|
|
||||||
~~~{.c}
|
|
||||||
ns(Monster_ref_t) create_orc(flatcc_builder_t *B)
|
|
||||||
{
|
|
||||||
// ... same as in the tutorial.
|
|
||||||
return s(Monster_create(B, ...));
|
|
||||||
}
|
|
||||||
|
|
||||||
void create_monster_buffer()
|
|
||||||
{
|
|
||||||
uint8_t *buf;
|
|
||||||
size_t size;
|
|
||||||
flatcc_builder_t builder, *B;
|
|
||||||
|
|
||||||
// Initialize the builder object.
|
|
||||||
B = &builder;
|
|
||||||
flatcc_builder_init(B);
|
|
||||||
// Only use `buffer_create` without `create/start/end_as_root`.
|
|
||||||
flatcc_builder_buffer_create(create_orc(B));
|
|
||||||
// Allocate and copy buffer to user memory.
|
|
||||||
buf = flatcc_builder_finalize_buffer(B, &size);
|
|
||||||
// ... write the buffer to disk or network, or something.
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
flatcc_builder_clear(B);
|
|
||||||
}
|
|
||||||
~~~
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The same principle applies with `start/end` vs `start/end_as_root` in
|
|
||||||
the top-down approach.
|
|
||||||
|
|
||||||
|
|
||||||
## Top Down Example
|
|
||||||
|
|
||||||
The tutorial uses a bottom up approach. In C it is also possible to use
|
|
||||||
a top-down approach by starting and ending objects nested within each
|
|
||||||
other. In the tutorial there is no deep nesting, so the difference is
|
|
||||||
limited, but it shows the idea:
|
|
||||||
|
|
||||||
<div class="language-c">
|
|
||||||
<br>
|
|
||||||
~~~{.c}
|
|
||||||
uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
|
||||||
size_t treasure_count = c_vec_len(treasure);
|
|
||||||
ns(Weapon_ref_t) axe;
|
|
||||||
|
|
||||||
// NOTE: if we use end_as_root, we MUST also start as root.
|
|
||||||
ns(Monster_start_as_root(B));
|
|
||||||
ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f));
|
|
||||||
ns(Monster_hp_add(B, 300));
|
|
||||||
ns(Monster_mana_add(B, 150));
|
|
||||||
// We use create_str instead of add because we have no existing string reference.
|
|
||||||
ns(Monster_name_create_str(B, "Orc"));
|
|
||||||
// Again we use create because we no existing vector object, only a C-array.
|
|
||||||
ns(Monster_inventory_create(B, treasure, treasure_count));
|
|
||||||
ns(Monster_color_add(B, ns(Color_Red)));
|
|
||||||
if (1) {
|
|
||||||
ns(Monster_weapons_start(B));
|
|
||||||
ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Sword"), 3));
|
|
||||||
// We reuse the axe object later. Note that we dereference a pointer
|
|
||||||
// because push always returns a short-term pointer to the stored element.
|
|
||||||
// We could also have created the axe object first and simply pushed it.
|
|
||||||
axe = *ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Axe"), 5));
|
|
||||||
ns(Monster_weapons_end(B));
|
|
||||||
} else {
|
|
||||||
// We can have more control with the table elements added to a vector:
|
|
||||||
//
|
|
||||||
ns(Monster_weapons_start(B));
|
|
||||||
ns(Monster_weapons_push_start(B));
|
|
||||||
ns(Weapon_name_create_str(B, "Sword"));
|
|
||||||
ns(Weapon_damage_add(B, 3));
|
|
||||||
ns(Monster_weapons_push_end(B));
|
|
||||||
ns(Monster_weapons_push_start(B));
|
|
||||||
ns(Monster_weapons_push_start(B));
|
|
||||||
ns(Weapon_name_create_str(B, "Axe"));
|
|
||||||
ns(Weapon_damage_add(B, 5));
|
|
||||||
axe = *ns(Monster_weapons_push_end(B));
|
|
||||||
ns(Monster_weapons_end(B));
|
|
||||||
}
|
|
||||||
// Unions can get their type by using a type-specific add/create/start method.
|
|
||||||
ns(Monster_equipped_Weapon_add(B, axe));
|
|
||||||
|
|
||||||
ns(Monster_end_as_root(B));
|
|
||||||
~~~
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
## Basic Reflection
|
|
||||||
|
|
||||||
The C-API does support reading binary schema (.bfbs)
|
|
||||||
files via code generated from the `reflection.fbs` schema, and an
|
|
||||||
[example usage](https://github.com/dvidelabs/flatcc/tree/master/samples/reflection)
|
|
||||||
shows how to use this. The reflection schema files are pre-generated
|
|
||||||
in the [runtime distribution](https://github.com/dvidelabs/flatcc/tree/master/include/flatcc/reflection).
|
|
||||||
|
|
||||||
|
|
||||||
## Mutations and Reflection
|
|
||||||
|
|
||||||
The C-API does not support mutating reflection like C++ does, nor does
|
|
||||||
the reader interface support mutating scalars (and it is generally
|
|
||||||
unsafe to do so even after verification).
|
|
||||||
|
|
||||||
The generated reader interface supports sorting vectors in-place after
|
|
||||||
casting them to a mutating type because it is not practical to do so
|
|
||||||
while building a buffer. This is covered in the builder documentation.
|
|
||||||
The reflection example makes use of this feature to look up objects by
|
|
||||||
name.
|
|
||||||
|
|
||||||
It is possible to build new buffers using complex objects from existing
|
|
||||||
buffers as source. This can be very efficient due to direct copy
|
|
||||||
semantics without endian conversion or temporary stack allocation.
|
|
||||||
|
|
||||||
Scalars, structs and strings can be used as source, as well vectors of
|
|
||||||
these.
|
|
||||||
|
|
||||||
It is currently not possible to use an existing table or vector of table
|
|
||||||
as source, but it would be possible to add support for this at some
|
|
||||||
point.
|
|
||||||
|
|
||||||
|
|
||||||
## Namespaces
|
|
||||||
|
|
||||||
The `FLATBUFFERS_WRAP_NAMESPACE` approach used in the tutorial is convenient
|
|
||||||
when each function has a very long namespace prefix. But it isn't always
|
|
||||||
the best approach. If the namespace is absent, or simple and
|
|
||||||
informative, we might as well use the prefix directly. The
|
|
||||||
[reflection example](https://github.com/dvidelabs/flatcc/blob/master/samples/reflection/bfbs2json.c)
|
|
||||||
mentioned above uses this approach.
|
|
||||||
|
|
||||||
|
|
||||||
## Checking for Present Members
|
|
||||||
|
|
||||||
Not all languages support testing if a field is present, but in C we can
|
|
||||||
elaborate the reader section of the tutorial with tests for this. Recall
|
|
||||||
that `mana` was set to the default value `150` and therefore shouldn't
|
|
||||||
be present.
|
|
||||||
|
|
||||||
<div class="language-c">
|
|
||||||
~~~{.c}
|
|
||||||
int hp_present = ns(Monster_hp_is_present(monster)); // 1
|
|
||||||
int mana_present = ns(Monster_mana_is_present(monster)); // 0
|
|
||||||
~~~
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Alternative ways to add a Union
|
|
||||||
|
|
||||||
In the tutorial we used a single call to add a union. Here we show
|
|
||||||
different ways to accomplish the same thing. The last form is rarely
|
|
||||||
used, but is the low-level way to do it. It can be used to group small
|
|
||||||
values together in the table by adding type and data at different
|
|
||||||
points in time.
|
|
||||||
|
|
||||||
<div class="language-c">
|
|
||||||
~~~{.c}
|
|
||||||
ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe));
|
|
||||||
ns(Monster_equipped_add(B, equipped));
|
|
||||||
// or alternatively
|
|
||||||
ns(Monster_equipped_Weapon_add(B, axe);
|
|
||||||
// or alternatively
|
|
||||||
ns(Monster_equipped_add_type(B, ns(Equipment_Weapon));
|
|
||||||
ns(Monster_equipped_add_member(B, axe));
|
|
||||||
~~~
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Why not integrate with the `flatc` tool?
|
|
||||||
|
|
||||||
[It was considered how the C code generator could be integrated into the
|
|
||||||
`flatc` tool](https://github.com/dvidelabs/flatcc/issues/1), but it
|
|
||||||
would either require that the standalone C implementation of the schema
|
|
||||||
compiler was dropped, or it would lead to excessive code duplication, or
|
|
||||||
a complicated intermediate representation would have to be invented.
|
|
||||||
Neither of these alternatives are very attractive, and it isn't a big
|
|
||||||
deal to use the `flatcc` tool instead of `flatc` given that the
|
|
||||||
FlatBuffers C runtime library needs to be made available regardless.
|
|
||||||
|
|
||||||
|
|
242
third_party/flatbuffers/docs/source/Compiler.md
vendored
@ -1,242 +0,0 @@
|
|||||||
Using the schema compiler {#flatbuffers_guide_using_schema_compiler}
|
|
||||||
=========================
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] FILES...
|
|
||||||
[ -- FILES...]
|
|
||||||
|
|
||||||
The files are read and parsed in order, and can contain either schemas
|
|
||||||
or data (see below). Data files are processed according to the definitions of
|
|
||||||
the most recent schema specified.
|
|
||||||
|
|
||||||
`--` indicates that the following files are binary files in
|
|
||||||
FlatBuffer format conforming to the schema indicated before it.
|
|
||||||
|
|
||||||
Depending on the flags passed, additional files may
|
|
||||||
be generated for each file processed:
|
|
||||||
|
|
||||||
For any schema input files, one or more generators can be specified:
|
|
||||||
|
|
||||||
- `--cpp`, `-c` : Generate a C++ header for all definitions in this file (as
|
|
||||||
`filename_generated.h`).
|
|
||||||
|
|
||||||
- `--java`, `-j` : Generate Java code.
|
|
||||||
|
|
||||||
- `--kotlin` , `--kotlin-kmp` : Generate Kotlin code.
|
|
||||||
|
|
||||||
- `--csharp`, `-n` : Generate C# code.
|
|
||||||
|
|
||||||
- `--go`, `-g` : Generate Go code.
|
|
||||||
|
|
||||||
- `--python`, `-p` : Generate Python code.
|
|
||||||
|
|
||||||
- `--js`, `-s` : Generate JavaScript code.
|
|
||||||
|
|
||||||
- `--ts`, `-T` : Generate TypeScript code.
|
|
||||||
|
|
||||||
- `--php` : Generate PHP code.
|
|
||||||
|
|
||||||
- `--grpc` : Generate RPC stub code for GRPC.
|
|
||||||
|
|
||||||
- `--dart`, `-d` : Generate Dart code.
|
|
||||||
|
|
||||||
- `--lua`, `-l` : Generate Lua code.
|
|
||||||
|
|
||||||
- `--lobster` : Generate Lobster code.
|
|
||||||
|
|
||||||
- `--rust`, `-r` : Generate Rust code.
|
|
||||||
|
|
||||||
- `--swift` : Generate Swift code.
|
|
||||||
|
|
||||||
- `--nim` : Generate Nim code.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
For any data input files:
|
|
||||||
|
|
||||||
- `--binary`, `-b` : If data is contained in this file, generate a
|
|
||||||
`filename.bin` containing the binary flatbuffer (or a different extension
|
|
||||||
if one is specified in the schema).
|
|
||||||
|
|
||||||
- `--json`, `-t` : If data is contained in this file, generate a
|
|
||||||
`filename.json` representing the data in the flatbuffer.
|
|
||||||
|
|
||||||
- `--jsonschema` : Generate Json schema
|
|
||||||
|
|
||||||
Additional options:
|
|
||||||
|
|
||||||
- `-o PATH` : Output all generated files to PATH (either absolute, or
|
|
||||||
relative to the current directory). If omitted, PATH will be the
|
|
||||||
current directory. PATH should end in your systems path separator,
|
|
||||||
e.g. `/` or `\`.
|
|
||||||
|
|
||||||
- `-I PATH` : when encountering `include` statements, attempt to load the
|
|
||||||
files from this path. Paths will be tried in the order given, and if all
|
|
||||||
fail (or none are specified) it will try to load relative to the path of
|
|
||||||
the schema file being parsed.
|
|
||||||
|
|
||||||
- `-M` : Print make rules for generated files.
|
|
||||||
|
|
||||||
- `--strict-json` : Require & generate strict JSON (field names are enclosed
|
|
||||||
in quotes, no trailing commas in tables/vectors). By default, no quotes are
|
|
||||||
required/generated, and trailing commas are allowed.
|
|
||||||
|
|
||||||
- `--allow-non-utf8` : Pass non-UTF-8 input through parser and emit nonstandard
|
|
||||||
\x escapes in JSON. (Default is to raise parse error on non-UTF-8 input.)
|
|
||||||
|
|
||||||
- `--natural-utf8` : Output strings with UTF-8 as human-readable strings.
|
|
||||||
By default, UTF-8 characters are printed as \uXXXX escapes."
|
|
||||||
|
|
||||||
- `--defaults-json` : Output fields whose value is equal to the default value
|
|
||||||
when writing JSON text.
|
|
||||||
|
|
||||||
- `--no-prefix` : Don't prefix enum values in generated C++ by their enum
|
|
||||||
type.
|
|
||||||
|
|
||||||
- `--scoped-enums` : Use C++11 style scoped and strongly typed enums in
|
|
||||||
generated C++. This also implies `--no-prefix`.
|
|
||||||
|
|
||||||
- `--no-emit-min-max-enum-values` : Disable generation of MIN and MAX
|
|
||||||
enumerated values for scoped enums and prefixed enums.
|
|
||||||
|
|
||||||
- `--gen-includes` : (deprecated), this is the default behavior.
|
|
||||||
If the original behavior is required (no include
|
|
||||||
statements) use `--no-includes.`
|
|
||||||
|
|
||||||
- `--no-includes` : Don't generate include statements for included schemas the
|
|
||||||
generated file depends on (C++ / Python).
|
|
||||||
|
|
||||||
- `--gen-mutable` : Generate additional non-const accessors for mutating
|
|
||||||
FlatBuffers in-place.
|
|
||||||
|
|
||||||
- `--gen-onefile` : Generate single output file for C#, Go, and Python.
|
|
||||||
|
|
||||||
- `--gen-name-strings` : Generate type name functions for C++.
|
|
||||||
|
|
||||||
- `--gen-object-api` : Generate an additional object-based API. This API is
|
|
||||||
more convenient for object construction and mutation than the base API,
|
|
||||||
at the cost of efficiency (object allocation). Recommended only to be used
|
|
||||||
if other options are insufficient.
|
|
||||||
|
|
||||||
- `--gen-compare` : Generate operator== for object-based API types.
|
|
||||||
|
|
||||||
- `--gen-nullable` : Add Clang \_Nullable for C++ pointer. or @Nullable for Java.
|
|
||||||
|
|
||||||
- `--gen-generated` : Add @Generated annotation for Java.
|
|
||||||
|
|
||||||
- `--gen-jvmstatic` : Add @JvmStatic annotation for Kotlin methods
|
|
||||||
in companion object for interop from Java to Kotlin.
|
|
||||||
|
|
||||||
- `--gen-all` : Generate not just code for the current schema files, but
|
|
||||||
for all files it includes as well. If the language uses a single file for
|
|
||||||
output (by default the case for C++ and JS), all code will end up in
|
|
||||||
this one file.
|
|
||||||
|
|
||||||
- `--cpp-include` : Adds an #include in generated file
|
|
||||||
|
|
||||||
- `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr)
|
|
||||||
|
|
||||||
- `--cpp-str-type T` : Set object API string type (default std::string)
|
|
||||||
T::c_str(), T::length() and T::empty() must be supported.
|
|
||||||
The custom type also needs to be constructible from std::string (see the
|
|
||||||
--cpp-str-flex-ctor option to change this behavior).
|
|
||||||
|
|
||||||
- `--cpp-str-flex-ctor` : Don't construct custom string types by passing
|
|
||||||
std::string from Flatbuffers, but (char* + length). This allows efficient
|
|
||||||
construction of custom string types, including zero-copy construction.
|
|
||||||
|
|
||||||
- `--no-cpp-direct-copy` : Don't generate direct copy methods for C++
|
|
||||||
object-based API.
|
|
||||||
|
|
||||||
- `--cpp-std CPP_STD` : Generate a C++ code using features of selected C++ standard.
|
|
||||||
Supported `CPP_STD` values:
|
|
||||||
* `c++0x` - generate code compatible with old compilers (VS2010),
|
|
||||||
* `c++11` - use C++11 code generator (default),
|
|
||||||
* `c++17` - use C++17 features in generated code (experimental).
|
|
||||||
|
|
||||||
- `--object-prefix` : Customise class prefix for C++ object-based API.
|
|
||||||
|
|
||||||
- `--object-suffix` : Customise class suffix for C++ object-based API.
|
|
||||||
|
|
||||||
- `--go-namespace` : Generate the overrided namespace in Golang.
|
|
||||||
|
|
||||||
- `--go-import` : Generate the overrided import for flatbuffers in Golang.
|
|
||||||
(default is "github.com/google/flatbuffers/go").
|
|
||||||
|
|
||||||
- `--raw-binary` : Allow binaries without a file_indentifier to be read.
|
|
||||||
This may crash flatc given a mismatched schema.
|
|
||||||
|
|
||||||
- `--size-prefixed` : Input binaries are size prefixed buffers.
|
|
||||||
|
|
||||||
- `--proto`: Expect input files to be .proto files (protocol buffers).
|
|
||||||
Output the corresponding .fbs file.
|
|
||||||
Currently supports: `package`, `message`, `enum`, nested declarations,
|
|
||||||
`import` (use `-I` for paths), `extend`, `oneof`, `group`.
|
|
||||||
Does not support, but will skip without error: `option`, `service`,
|
|
||||||
`extensions`, and most everything else.
|
|
||||||
|
|
||||||
- `--oneof-union` : Translate .proto oneofs to flatbuffer unions.
|
|
||||||
|
|
||||||
- `--grpc` : Generate GRPC interfaces for the specified languages.
|
|
||||||
|
|
||||||
- `--schema`: Serialize schemas instead of JSON (use with -b). This will
|
|
||||||
output a binary version of the specified schema that itself corresponds
|
|
||||||
to the reflection/reflection.fbs schema. Loading this binary file is the
|
|
||||||
basis for reflection functionality.
|
|
||||||
|
|
||||||
- `--bfbs-comments`: Add doc comments to the binary schema files.
|
|
||||||
|
|
||||||
- `--conform FILE` : Specify a schema the following schemas should be
|
|
||||||
an evolution of. Gives errors if not. Useful to check if schema
|
|
||||||
modifications don't break schema evolution rules.
|
|
||||||
|
|
||||||
- `--conform-includes PATH` : Include path for the schema given with
|
|
||||||
`--conform PATH`.
|
|
||||||
|
|
||||||
- `--filename-suffix SUFFIX` : The suffix appended to the generated
|
|
||||||
file names. Default is '\_generated'.
|
|
||||||
|
|
||||||
- `--filename-ext EXTENSION` : The extension appended to the generated
|
|
||||||
file names. Default is language-specific (e.g. "h" for C++). This
|
|
||||||
should not be used when multiple languages are specified.
|
|
||||||
|
|
||||||
- `--include-prefix PATH` : Prefix this path to any generated include
|
|
||||||
statements.
|
|
||||||
|
|
||||||
- `--keep-prefix` : Keep original prefix of schema include statement.
|
|
||||||
|
|
||||||
- `--reflect-types` : Add minimal type reflection to code generation.
|
|
||||||
|
|
||||||
- `--reflect-names` : Add minimal type/name reflection.
|
|
||||||
|
|
||||||
- `--root-type T` : Select or override the default root_type.
|
|
||||||
|
|
||||||
- `--require-explicit-ids` : When parsing schemas, require explicit ids (id: x).
|
|
||||||
|
|
||||||
- `--force-defaults` : Emit default values in binary output from JSON.
|
|
||||||
|
|
||||||
- `--force-empty` : When serializing from object API representation, force
|
|
||||||
strings and vectors to empty rather than null.
|
|
||||||
|
|
||||||
- `--force-empty-vectors` : When serializing from object API representation, force
|
|
||||||
vectors to empty rather than null.
|
|
||||||
|
|
||||||
- `--flexbuffers` : Used with "binary" and "json" options, it generates
|
|
||||||
data using schema-less FlexBuffers.
|
|
||||||
|
|
||||||
- `--no-warnings` : Inhibit all warning messages.
|
|
||||||
|
|
||||||
- `--cs-global-alias` : Prepend `global::` to all user generated csharp classes and structs.
|
|
||||||
|
|
||||||
- `--json-nested-bytes` : Allow a nested_flatbuffer field to be parsed as a
|
|
||||||
vector of bytes in JSON, which is unsafe unless checked by a verifier
|
|
||||||
afterwards.
|
|
||||||
|
|
||||||
- `--python-no-type-prefix-suffix` : Skip emission of Python functions that are prefixed
|
|
||||||
with typenames
|
|
||||||
|
|
||||||
- `--python-typing` : Generate Python type annotations
|
|
||||||
|
|
||||||
NOTE: short-form options for generators are deprecated, use the long form
|
|
||||||
whenever possible.
|
|
639
third_party/flatbuffers/docs/source/CppUsage.md
vendored
@ -1,639 +0,0 @@
|
|||||||
Use in C++ {#flatbuffers_guide_use_cpp}
|
|
||||||
==========
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in C++, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
|
||||||
to general FlatBuffers usage in all of the supported languages (including C++).
|
|
||||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
|
||||||
C++.
|
|
||||||
|
|
||||||
#### Prerequisites
|
|
||||||
|
|
||||||
This page assumes you have written a FlatBuffers schema and compiled it
|
|
||||||
with the Schema Compiler. If you have not, please see
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
|
|
||||||
and [Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't
|
|
||||||
matter), you've generated a C++ header called `mygame_generated.h` using the
|
|
||||||
compiler (e.g. `flatc -c mygame.fbs`), you can now start using this in
|
|
||||||
your program by including the header. As noted, this header relies on
|
|
||||||
`flatbuffers/flatbuffers.h`, which should be in your include path.
|
|
||||||
|
|
||||||
## FlatBuffers C++ library code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers C++ library can be found at
|
|
||||||
`flatbuffers/include/flatbuffers`. You can browse the library code on the
|
|
||||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/include/flatbuffers).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers C++ library
|
|
||||||
|
|
||||||
The code to test the C++ library can be found at `flatbuffers/tests`.
|
|
||||||
The test code itself is located in
|
|
||||||
[test.cpp](https://github.com/google/flatbuffers/blob/master/tests/test.cpp).
|
|
||||||
|
|
||||||
This test file is built alongside `flatc`. To review how to build the project,
|
|
||||||
please read the [Building](@ref flatbuffers_guide_building) documentation.
|
|
||||||
|
|
||||||
To run the tests, execute `flattests` from the root `flatbuffers/` directory.
|
|
||||||
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
|
|
||||||
run: `./flattests`.
|
|
||||||
|
|
||||||
## Using the FlatBuffers C++ library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in C++.*
|
|
||||||
|
|
||||||
FlatBuffers supports both reading and writing FlatBuffers in C++.
|
|
||||||
|
|
||||||
To use FlatBuffers in your code, first generate the C++ classes from your
|
|
||||||
schema with the `--cpp` option to `flatc`. Then you can include both FlatBuffers
|
|
||||||
and the generated code to read or write FlatBuffers.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in C++:
|
|
||||||
First, include the library and generated code. Then read the file into
|
|
||||||
a `char *` array, which you pass to `GetMonster()`.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "monster_test_generate.h"
|
|
||||||
#include <iostream> // C++ header file for printing
|
|
||||||
#include <fstream> // C++ header file for file access
|
|
||||||
|
|
||||||
|
|
||||||
std::ifstream infile;
|
|
||||||
infile.open("monsterdata_test.mon", std::ios::binary | std::ios::in);
|
|
||||||
infile.seekg(0,std::ios::end);
|
|
||||||
int length = infile.tellg();
|
|
||||||
infile.seekg(0,std::ios::beg);
|
|
||||||
char *data = new char[length];
|
|
||||||
infile.read(data, length);
|
|
||||||
infile.close();
|
|
||||||
|
|
||||||
auto monster = GetMonster(data);
|
|
||||||
```
|
|
||||||
|
|
||||||
`monster` is of type `Monster *`, and points to somewhere *inside* your
|
|
||||||
buffer (root object pointers are not the same as `buffer_pointer` \!).
|
|
||||||
If you look in your generated header, you'll see it has
|
|
||||||
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
std::cout << "hp : " << monster->hp() << std::endl; // '80'
|
|
||||||
std::cout << "mana : " << monster->mana() << std::endl; // default value of '150'
|
|
||||||
std::cout << "name : " << monster->name()->c_str() << std::endl; // "MyMonster"
|
|
||||||
```
|
|
||||||
|
|
||||||
*Note: That we never stored a `mana` value, so it will return the default.*
|
|
||||||
|
|
||||||
The following attributes are supported:
|
|
||||||
|
|
||||||
- `shared` (on a field): For string fields, this enables the usage of string
|
|
||||||
pooling (i.e. `CreateSharedString`) as default serialization behavior.
|
|
||||||
|
|
||||||
Specifically, `CreateXxxDirect` functions and `Pack` functions for object
|
|
||||||
based API (see below) will use `CreateSharedString` to create strings.
|
|
||||||
|
|
||||||
## Object based API {#flatbuffers_cpp_object_based_api}
|
|
||||||
|
|
||||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
|
||||||
around using as little as possible of it. This does make the API clumsier
|
|
||||||
(requiring pre-order construction of all data, and making mutation harder).
|
|
||||||
|
|
||||||
For times when efficiency is less important a more convenient object based API
|
|
||||||
can be used (through `--gen-object-api`) that is able to unpack & pack a
|
|
||||||
FlatBuffer into objects and standard STL containers, allowing for convenient
|
|
||||||
construction, access and mutation.
|
|
||||||
|
|
||||||
To use:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
// Autogenerated class from table Monster.
|
|
||||||
MonsterT monsterobj;
|
|
||||||
|
|
||||||
// Deserialize from buffer into object.
|
|
||||||
GetMonster(flatbuffer)->UnPackTo(&monsterobj);
|
|
||||||
|
|
||||||
// Update object directly like a C++ class instance.
|
|
||||||
cout << monsterobj.name; // This is now a std::string!
|
|
||||||
monsterobj.name = "Bob"; // Change the name.
|
|
||||||
|
|
||||||
// Serialize into new flatbuffer.
|
|
||||||
FlatBufferBuilder fbb;
|
|
||||||
fbb.Finish(Monster::Pack(fbb, &monsterobj));
|
|
||||||
```
|
|
||||||
|
|
||||||
The following attributes are specific to the object-based API code generation:
|
|
||||||
|
|
||||||
- `native_inline` (on a field): Because FlatBuffer tables and structs are
|
|
||||||
optionally present in a given buffer, they are best represented as pointers
|
|
||||||
(specifically std::unique_ptrs) in the native class since they can be null.
|
|
||||||
This attribute changes the member declaration to use the type directly
|
|
||||||
rather than wrapped in a unique_ptr.
|
|
||||||
|
|
||||||
- `native_default("value")` (on a field): For members that are declared
|
|
||||||
"native_inline", the value specified with this attribute will be included
|
|
||||||
verbatim in the class constructor initializer list for this member.
|
|
||||||
|
|
||||||
- `native_custom_alloc("custom_allocator")` (on a table or struct): When using the
|
|
||||||
object-based API all generated NativeTables that are allocated when unpacking
|
|
||||||
your flatbuffer will use "custom allocator". The allocator is also used by
|
|
||||||
any std::vector that appears in a table defined with `native_custom_alloc`.
|
|
||||||
This can be used to provide allocation from a pool for example, for faster
|
|
||||||
unpacking when using the object-based API.
|
|
||||||
|
|
||||||
Minimal Example:
|
|
||||||
|
|
||||||
schema:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
table mytable(native_custom_alloc:"custom_allocator") {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
with `custom_allocator` defined before `flatbuffers.h` is included, as:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
template <typename T> struct custom_allocator : public std::allocator<T> {
|
|
||||||
|
|
||||||
typedef T *pointer;
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
struct rebind {
|
|
||||||
typedef custom_allocator<U> other;
|
|
||||||
};
|
|
||||||
|
|
||||||
pointer allocate(const std::size_t n) {
|
|
||||||
return std::allocator<T>::allocate(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate(T* ptr, std::size_t n) {
|
|
||||||
return std::allocator<T>::deallocate(ptr,n);
|
|
||||||
}
|
|
||||||
|
|
||||||
custom_allocator() throw() {}
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
custom_allocator(const custom_allocator<U>&) throw() {}
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
- `native_type("type")` (on a struct): In some cases, a more optimal C++ data
|
|
||||||
type exists for a given struct. For example, the following schema:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct Vec2 {
|
|
||||||
x: float;
|
|
||||||
y: float;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
generates the following Object-Based API class:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct Vec2T : flatbuffers::NativeTable {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
However, it can be useful to instead use a user-defined C++ type since it
|
|
||||||
can provide more functionality, eg.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct vector2 {
|
|
||||||
float x = 0, y = 0;
|
|
||||||
vector2 operator+(vector2 rhs) const { ... }
|
|
||||||
vector2 operator-(vector2 rhs) const { ... }
|
|
||||||
float length() const { ... }
|
|
||||||
// etc.
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
The `native_type` attribute will replace the usage of the generated class
|
|
||||||
with the given type. So, continuing with the example, the generated
|
|
||||||
code would use `vector2` in place of `Vec2T` for all generated code of
|
|
||||||
the Object-Based API.
|
|
||||||
|
|
||||||
However, because the `native_type` is unknown to flatbuffers, the user must
|
|
||||||
provide the following functions to aide in the serialization process:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
namespace flatbuffers {
|
|
||||||
Vec2 Pack(const vector2& obj);
|
|
||||||
vector2 UnPack(const Vec2& obj);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `native_type_pack_name("name")` (on a struct when `native_type` is
|
|
||||||
specified, too): when you want to use the same `native_type` multiple times
|
|
||||||
(e. g. with different precision) you must make the names of the Pack/UnPack
|
|
||||||
functions unique, otherwise you will run into compile errors. This attribute
|
|
||||||
appends a name to the expected Pack/UnPack functions. So when you
|
|
||||||
specify `native_type_pack_name("Vec2")` in the above example you now need to
|
|
||||||
implement these serialization functions instead:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
namespace flatbuffers {
|
|
||||||
Vec2 PackVec2(const vector2& obj);
|
|
||||||
vector2 UnPackVec2(const Vec2& obj);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, the following top-level attributes:
|
|
||||||
|
|
||||||
- `native_include("path")` (at file level): Because the `native_type` attribute
|
|
||||||
can be used to introduce types that are unknown to flatbuffers, it may be
|
|
||||||
necessary to include "external" header files in the generated code. This
|
|
||||||
attribute can be used to directly add an #include directive to the top of
|
|
||||||
the generated code that includes the specified path directly.
|
|
||||||
|
|
||||||
- `force_align`: this attribute may not be respected in the object API,
|
|
||||||
depending on the aligned of the allocator used with `new`.
|
|
||||||
|
|
||||||
# External references
|
|
||||||
|
|
||||||
An additional feature of the object API is the ability to allow you to load
|
|
||||||
multiple independent FlatBuffers, and have them refer to eachothers objects
|
|
||||||
using hashes which are then represented as typed pointers in the object API.
|
|
||||||
|
|
||||||
To make this work have a field in the objects you want to referred to which is
|
|
||||||
using the string hashing feature (see `hash` attribute in the
|
|
||||||
[schema](@ref flatbuffers_guide_writing_schema) documentation). Then you have
|
|
||||||
a similar hash in the field referring to it, along with a `cpp_type`
|
|
||||||
attribute specifying the C++ type this will refer to (this can be any C++
|
|
||||||
type, and will get a `*` added).
|
|
||||||
|
|
||||||
Then, in JSON or however you create these buffers, make sure they use the
|
|
||||||
same string (or hash).
|
|
||||||
|
|
||||||
When you call `UnPack` (or `Create`), you'll need a function that maps from
|
|
||||||
hash to the object (see `resolver_function_t` for details).
|
|
||||||
|
|
||||||
# Using different pointer types
|
|
||||||
|
|
||||||
By default the object tree is built out of `std::unique_ptr`, but you can
|
|
||||||
influence this either globally (using the `--cpp-ptr-type` argument to
|
|
||||||
`flatc`) or per field (using the `cpp_ptr_type` attribute) to by any smart
|
|
||||||
pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
|
|
||||||
pointers. Unlike the smart pointers, naked pointers do not manage memory for
|
|
||||||
you, so you'll have to manage their lifecycles manually. To reference the
|
|
||||||
pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a
|
|
||||||
flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`.
|
|
||||||
|
|
||||||
# Using different string type
|
|
||||||
|
|
||||||
By default the object tree is built out of `std::string`, but you can
|
|
||||||
influence this either globally (using the `--cpp-str-type` argument to
|
|
||||||
`flatc`) or per field using the `cpp_str_type` attribute.
|
|
||||||
|
|
||||||
The type must support `T::c_str()`, `T::length()` and `T::empty()` as member functions.
|
|
||||||
|
|
||||||
Further, the type must be constructible from std::string, as by default a
|
|
||||||
std::string instance is constructed and then used to initialize the custom
|
|
||||||
string type. This behavior impedes efficient and zero-copy construction of
|
|
||||||
custom string types; the `--cpp-str-flex-ctor` argument to `flatc` or the
|
|
||||||
per field attribute `cpp_str_flex_ctor` can be used to change this behavior,
|
|
||||||
so that the custom string type is constructed by passing the pointer and
|
|
||||||
length of the FlatBuffers String. The custom string class will require a
|
|
||||||
constructor in the following format: `custom_str_class(const char *, size_t)`.
|
|
||||||
Please note that the character array is not guaranteed to be NULL terminated,
|
|
||||||
you should always use the provided size to determine end of string.
|
|
||||||
|
|
||||||
## Reflection (& Resizing)
|
|
||||||
|
|
||||||
There is experimental support for reflection in FlatBuffers, allowing you to
|
|
||||||
read and write data even if you don't know the exact format of a buffer, and
|
|
||||||
even allows you to change sizes of strings and vectors in-place.
|
|
||||||
|
|
||||||
The way this works is very elegant; there is actually a FlatBuffer schema that
|
|
||||||
describes schemas (\!) which you can find in `reflection/reflection.fbs`.
|
|
||||||
The compiler, `flatc`, can write out any schemas it has just parsed as a binary
|
|
||||||
FlatBuffer, corresponding to this meta-schema.
|
|
||||||
|
|
||||||
Loading in one of these binary schemas at runtime allows you traverse any
|
|
||||||
FlatBuffer data that corresponds to it without knowing the exact format. You
|
|
||||||
can query what fields are present, and then read/write them after.
|
|
||||||
|
|
||||||
For convenient field manipulation, you can include the header
|
|
||||||
`flatbuffers/reflection.h` which includes both the generated code from the meta
|
|
||||||
schema, as well as a lot of helper functions.
|
|
||||||
|
|
||||||
And example of usage, for the time being, can be found in
|
|
||||||
`test.cpp/ReflectionTest()`.
|
|
||||||
|
|
||||||
## Mini Reflection
|
|
||||||
|
|
||||||
A more limited form of reflection is available for direct inclusion in
|
|
||||||
generated code, which doesn't do any (binary) schema access at all. It was designed
|
|
||||||
to keep the overhead of reflection as low as possible (on the order of 2-6
|
|
||||||
bytes per field added to your executable), but doesn't contain all the
|
|
||||||
information the (binary) schema contains.
|
|
||||||
|
|
||||||
You add this information to your generated code by specifying `--reflect-types`
|
|
||||||
(or instead `--reflect-names` if you also want field / enum names).
|
|
||||||
|
|
||||||
You can now use this information, for example to print a FlatBuffer to text:
|
|
||||||
|
|
||||||
auto s = flatbuffers::FlatBufferToString(flatbuf, MonsterTypeTable());
|
|
||||||
|
|
||||||
`MonsterTypeTable()` is declared in the generated code for each type. The
|
|
||||||
string produced is very similar to the JSON produced by the `Parser` based
|
|
||||||
text generator.
|
|
||||||
|
|
||||||
You'll need `flatbuffers/minireflect.h` for this functionality. In there is also
|
|
||||||
a convenient visitor/iterator so you can write your own output / functionality
|
|
||||||
based on the mini reflection tables without having to know the FlatBuffers or
|
|
||||||
reflection encoding.
|
|
||||||
|
|
||||||
## Storing maps / dictionaries in a FlatBuffer
|
|
||||||
|
|
||||||
FlatBuffers doesn't support maps natively, but there is support to
|
|
||||||
emulate their behavior with vectors and binary search, which means you
|
|
||||||
can have fast lookups directly from a FlatBuffer without having to unpack
|
|
||||||
your data into a `std::map` or similar.
|
|
||||||
|
|
||||||
To use it:
|
|
||||||
- Designate one of the fields in a table as they "key" field. You do this
|
|
||||||
by setting the `key` attribute on this field, e.g.
|
|
||||||
`name:string (key)`.
|
|
||||||
You may only have one key field, and it must be of string or scalar type.
|
|
||||||
- Write out tables of this type as usual, collect their offsets in an
|
|
||||||
array or vector.
|
|
||||||
- Instead of `CreateVector`, call `CreateVectorOfSortedTables`,
|
|
||||||
which will first sort all offsets such that the tables they refer to
|
|
||||||
are sorted by the key field, then serialize it.
|
|
||||||
- Now when you're accessing the FlatBuffer, you can use `Vector::LookupByKey`
|
|
||||||
instead of just `Vector::Get` to access elements of the vector, e.g.:
|
|
||||||
`myvector->LookupByKey("Fred")`, which returns a pointer to the
|
|
||||||
corresponding table type, or `nullptr` if not found.
|
|
||||||
`LookupByKey` performs a binary search, so should have a similar speed to
|
|
||||||
`std::map`, though may be faster because of better caching. `LookupByKey`
|
|
||||||
only works if the vector has been sorted, it will likely not find elements
|
|
||||||
if it hasn't been sorted.
|
|
||||||
|
|
||||||
## Direct memory access
|
|
||||||
|
|
||||||
As you can see from the above examples, all elements in a buffer are
|
|
||||||
accessed through generated accessors. This is because everything is
|
|
||||||
stored in little endian format on all platforms (the accessor
|
|
||||||
performs a swap operation on big endian machines), and also because
|
|
||||||
the layout of things is generally not known to the user.
|
|
||||||
|
|
||||||
For structs, layout is deterministic and guaranteed to be the same
|
|
||||||
across platforms (scalars are aligned to their
|
|
||||||
own size, and structs themselves to their largest member), and you
|
|
||||||
are allowed to access this memory directly by using `sizeof()` and
|
|
||||||
`memcpy` on the pointer to a struct, or even an array of structs.
|
|
||||||
|
|
||||||
To compute offsets to sub-elements of a struct, make sure they
|
|
||||||
are a structs themselves, as then you can use the pointers to
|
|
||||||
figure out the offset without having to hardcode it. This is
|
|
||||||
handy for use of arrays of structs with calls like `glVertexAttribPointer`
|
|
||||||
in OpenGL or similar APIs.
|
|
||||||
|
|
||||||
It is important to note is that structs are still little endian on all
|
|
||||||
machines, so only use tricks like this if you can guarantee you're not
|
|
||||||
shipping on a big endian machine (an `assert(FLATBUFFERS_LITTLEENDIAN)`
|
|
||||||
would be wise).
|
|
||||||
|
|
||||||
## Access of untrusted buffers
|
|
||||||
|
|
||||||
The generated accessor functions access fields over offsets, which is
|
|
||||||
very quick. These offsets are not verified at run-time, so a malformed
|
|
||||||
buffer could cause a program to crash by accessing random memory.
|
|
||||||
|
|
||||||
When you're processing large amounts of data from a source you know (e.g.
|
|
||||||
your own generated data on disk), this is acceptable, but when reading
|
|
||||||
data from the network that can potentially have been modified by an
|
|
||||||
attacker, this is undesirable.
|
|
||||||
|
|
||||||
For this reason, you can optionally use a buffer verifier before you
|
|
||||||
access the data. This verifier will check all offsets, all sizes of
|
|
||||||
fields, and null termination of strings to ensure that when a buffer
|
|
||||||
is accessed, all reads will end up inside the buffer.
|
|
||||||
|
|
||||||
Each root type will have a verification function generated for it,
|
|
||||||
e.g. for `Monster`, you can call:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
bool ok = VerifyMonsterBuffer(Verifier(buf, len));
|
|
||||||
```
|
|
||||||
|
|
||||||
if `ok` is true, the buffer is safe to read.
|
|
||||||
|
|
||||||
Besides untrusted data, this function may be useful to call in debug
|
|
||||||
mode, as extra insurance against data being corrupted somewhere along
|
|
||||||
the way.
|
|
||||||
|
|
||||||
While verifying a buffer isn't "free", it is typically faster than
|
|
||||||
a full traversal (since any scalar data is not actually touched),
|
|
||||||
and since it may cause the buffer to be brought into cache before
|
|
||||||
reading, the actual overhead may be even lower than expected.
|
|
||||||
|
|
||||||
In specialized cases where a denial of service attack is possible,
|
|
||||||
the verifier has two additional constructor arguments that allow
|
|
||||||
you to limit the nesting depth and total amount of tables the
|
|
||||||
verifier may encounter before declaring the buffer malformed. The default is
|
|
||||||
`Verifier(buf, len, 64 /* max depth */, 1000000, /* max tables */)` which
|
|
||||||
should be sufficient for most uses.
|
|
||||||
|
|
||||||
## Text & schema parsing
|
|
||||||
|
|
||||||
Using binary buffers with the generated header provides a super low
|
|
||||||
overhead use of FlatBuffer data. There are, however, times when you want
|
|
||||||
to use text formats, for example because it interacts better with source
|
|
||||||
control, or you want to give your users easy access to data.
|
|
||||||
|
|
||||||
Another reason might be that you already have a lot of data in JSON
|
|
||||||
format, or a tool that generates JSON, and if you can write a schema for
|
|
||||||
it, this will provide you an easy way to use that data directly.
|
|
||||||
|
|
||||||
(see the schema documentation for some specifics on the JSON format
|
|
||||||
accepted).
|
|
||||||
|
|
||||||
Schema evolution compatibility for the JSON format follows the same rules as the binary format (JSON formatted data will be forwards/backwards compatible with schemas that evolve in a compatible way).
|
|
||||||
|
|
||||||
There are two ways to use text formats:
|
|
||||||
|
|
||||||
#### Using the compiler as a conversion tool
|
|
||||||
|
|
||||||
This is the preferred path, as it doesn't require you to add any new
|
|
||||||
code to your program, and is maximally efficient since you can ship with
|
|
||||||
binary data. The disadvantage is that it is an extra step for your
|
|
||||||
users/developers to perform, though you might be able to automate it.
|
|
||||||
|
|
||||||
flatc -b myschema.fbs mydata.json
|
|
||||||
|
|
||||||
This will generate the binary file `mydata_wire.bin` which can be loaded
|
|
||||||
as before.
|
|
||||||
|
|
||||||
#### Making your program capable of loading text directly
|
|
||||||
|
|
||||||
This gives you maximum flexibility. You could even opt to support both,
|
|
||||||
i.e. check for both files, and regenerate the binary from text when
|
|
||||||
required, otherwise just load the binary.
|
|
||||||
|
|
||||||
This option is currently only available for C++, or Java through JNI.
|
|
||||||
|
|
||||||
As mentioned in the section "Building" above, this technique requires
|
|
||||||
you to link a few more files into your program, and you'll want to include
|
|
||||||
`flatbuffers/idl.h`.
|
|
||||||
|
|
||||||
Load text (either a schema or json) into an in-memory buffer (there is a
|
|
||||||
convenient `LoadFile()` utility function in `flatbuffers/util.h` if you
|
|
||||||
wish). Construct a parser:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
flatbuffers::Parser parser;
|
|
||||||
```
|
|
||||||
|
|
||||||
Now you can parse any number of text files in sequence:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
parser.Parse(text_file.c_str());
|
|
||||||
```
|
|
||||||
|
|
||||||
This works similarly to how the command-line compiler works: a sequence
|
|
||||||
of files parsed by the same `Parser` object allow later files to
|
|
||||||
reference definitions in earlier files. Typically this means you first
|
|
||||||
load a schema file (which populates `Parser` with definitions), followed
|
|
||||||
by one or more JSON files.
|
|
||||||
|
|
||||||
As optional argument to `Parse`, you may specify a null-terminated list of
|
|
||||||
include paths. If not specified, any include statements try to resolve from
|
|
||||||
the current directory.
|
|
||||||
|
|
||||||
If there were any parsing errors, `Parse` will return `false`, and
|
|
||||||
`Parser::error_` contains a human readable error string with a line number
|
|
||||||
etc, which you should present to the creator of that file.
|
|
||||||
|
|
||||||
After each JSON file, the `Parser::fbb` member variable is the
|
|
||||||
`FlatBufferBuilder` that contains the binary buffer version of that
|
|
||||||
file, that you can access as described above.
|
|
||||||
|
|
||||||
`samples/sample_text.cpp` is a code sample showing the above operations.
|
|
||||||
|
|
||||||
## Threading
|
|
||||||
|
|
||||||
Reading a FlatBuffer does not touch any memory outside the original buffer,
|
|
||||||
and is entirely read-only (all const), so is safe to access from multiple
|
|
||||||
threads even without synchronisation primitives.
|
|
||||||
|
|
||||||
Creating a FlatBuffer is not thread safe. All state related to building
|
|
||||||
a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
|
|
||||||
outside of it is touched. To make this thread safe, either do not
|
|
||||||
share instances of FlatBufferBuilder between threads (recommended), or
|
|
||||||
manually wrap it in synchronisation primitives. There's no automatic way to
|
|
||||||
accomplish this, by design, as we feel multithreaded construction
|
|
||||||
of a single buffer will be rare, and synchronisation overhead would be costly.
|
|
||||||
|
|
||||||
## Advanced union features
|
|
||||||
|
|
||||||
The C++ implementation currently supports vectors of unions (i.e. you can
|
|
||||||
declare a field as `[T]` where `T` is a union type instead of a table type). It
|
|
||||||
also supports structs and strings in unions, besides tables.
|
|
||||||
|
|
||||||
For an example of these features, see `tests/union_vector`, and
|
|
||||||
`UnionVectorTest` in `test.cpp`.
|
|
||||||
|
|
||||||
Since these features haven't been ported to other languages yet, if you
|
|
||||||
choose to use them, you won't be able to use these buffers in other languages
|
|
||||||
(`flatc` will refuse to compile a schema that uses these features).
|
|
||||||
|
|
||||||
These features reduce the amount of "table wrapping" that was previously
|
|
||||||
needed to use unions.
|
|
||||||
|
|
||||||
To use scalars, simply wrap them in a struct.
|
|
||||||
|
|
||||||
## Depth limit of nested objects and stack-overflow control
|
|
||||||
The parser of Flatbuffers schema or json-files is kind of recursive parser.
|
|
||||||
To avoid stack-overflow problem the parser has a built-in limiter of
|
|
||||||
recursion depth. Number of nested declarations in a schema or number of
|
|
||||||
nested json-objects is limited. By default, this depth limit set to `64`.
|
|
||||||
It is possible to override this limit with `FLATBUFFERS_MAX_PARSING_DEPTH`
|
|
||||||
definition. This definition can be helpful for testing purposes or embedded
|
|
||||||
applications. For details see [build](@ref flatbuffers_guide_building) of
|
|
||||||
CMake-based projects.
|
|
||||||
|
|
||||||
## Dependence from C-locale {#flatbuffers_locale_cpp}
|
|
||||||
The Flatbuffers [grammar](@ref flatbuffers grammar) uses ASCII
|
|
||||||
character set for identifiers, alphanumeric literals, reserved words.
|
|
||||||
|
|
||||||
Internal implementation of the Flatbuffers depends from functions which
|
|
||||||
depend from C-locale: `strtod()` or `strtof()`, for example.
|
|
||||||
The library expects the dot `.` symbol as the separator of an integer
|
|
||||||
part from the fractional part of a float number.
|
|
||||||
Another separator symbols (`,` for example) will break the compatibility
|
|
||||||
and may lead to an error while parsing a Flatbuffers schema or a json file.
|
|
||||||
|
|
||||||
The Standard C locale is a global resource, there is only one locale for
|
|
||||||
the entire application. Some modern compilers and platforms have
|
|
||||||
locale-independent or locale-narrow functions `strtof_l`, `strtod_l`,
|
|
||||||
`strtoll_l`, `strtoull_l` to resolve this dependency.
|
|
||||||
These functions use specified locale rather than the global or per-thread
|
|
||||||
locale instead. They are part of POSIX-2008 but not part of the C/C++
|
|
||||||
standard library, therefore, may be missing on some platforms.
|
|
||||||
The Flatbuffers library try to detect these functions at configuration and
|
|
||||||
compile time:
|
|
||||||
- CMake `"CMakeLists.txt"`:
|
|
||||||
- Check existence of `strtol_l` and `strtod_l` in the `<stdlib.h>`.
|
|
||||||
- Compile-time `"/include/base.h"`:
|
|
||||||
- `_MSC_VER >= 1900`: MSVC2012 or higher if build with MSVC.
|
|
||||||
- `_XOPEN_SOURCE>=700`: POSIX-2008 if build with GCC/Clang.
|
|
||||||
|
|
||||||
After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be
|
|
||||||
set to `0` or `1`.
|
|
||||||
To override or stop this detection use CMake `-DFLATBUFFERS_LOCALE_INDEPENDENT={0|1}`
|
|
||||||
or predefine `FLATBUFFERS_LOCALE_INDEPENDENT` symbol.
|
|
||||||
|
|
||||||
To test the compatibility of the Flatbuffers library with
|
|
||||||
a specific locale use the environment variable `FLATBUFFERS_TEST_LOCALE`:
|
|
||||||
```sh
|
|
||||||
>FLATBUFFERS_TEST_LOCALE="" ./flattests
|
|
||||||
>FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests
|
|
||||||
```
|
|
||||||
|
|
||||||
## Support of floating-point numbers
|
|
||||||
The Flatbuffers library assumes that a C++ compiler and a CPU are
|
|
||||||
compatible with the `IEEE-754` floating-point standard.
|
|
||||||
The schema and json parser may fail if `fast-math` or `/fp:fast` mode is active.
|
|
||||||
|
|
||||||
### Support of hexadecimal and special floating-point numbers
|
|
||||||
According to the [grammar](@ref flatbuffers_grammar) `fbs` and `json` files
|
|
||||||
may use hexadecimal and special (`NaN`, `Inf`) floating-point literals.
|
|
||||||
The Flatbuffers uses `strtof` and `strtod` functions to parse floating-point
|
|
||||||
literals. The Flatbuffers library has a code to detect a compiler compatibility
|
|
||||||
with the literals. If necessary conditions are met the preprocessor constant
|
|
||||||
`FLATBUFFERS_HAS_NEW_STRTOD` will be set to `1`.
|
|
||||||
The support of floating-point literals will be limited at compile time
|
|
||||||
if `FLATBUFFERS_HAS_NEW_STRTOD` constant is less than `1`.
|
|
||||||
In this case, schemas with hexadecimal or special literals cannot be used.
|
|
||||||
|
|
||||||
### Comparison of floating-point NaN values
|
|
||||||
The floating-point `NaN` (`not a number`) is special value which
|
|
||||||
representing an undefined or unrepresentable value.
|
|
||||||
`NaN` may be explicitly assigned to variables, typically as a representation
|
|
||||||
for missing values or may be a result of a mathematical operation.
|
|
||||||
The `IEEE-754` defines two kind of `NaNs`:
|
|
||||||
- Quiet NaNs, or `qNaNs`.
|
|
||||||
- Signaling NaNs, or `sNaNs`.
|
|
||||||
|
|
||||||
According to the `IEEE-754`, a comparison with `NaN` always returns
|
|
||||||
an unordered result even when compared with itself. As a result, a whole
|
|
||||||
Flatbuffers object will be not equal to itself if has one or more `NaN`.
|
|
||||||
Flatbuffers scalar fields that have the default value are not actually stored
|
|
||||||
in the serialized data but are generated in code (see [Writing a schema](@ref flatbuffers_guide_writing_schema)).
|
|
||||||
Scalar fields with `NaN` defaults break this behavior.
|
|
||||||
If a schema has a lot of `NaN` defaults the Flatbuffers can override
|
|
||||||
the unordered comparison by the ordered: `(NaN==NaN)->true`.
|
|
||||||
This ordered comparison is enabled when compiling a program with the symbol
|
|
||||||
`FLATBUFFERS_NAN_DEFAULTS` defined.
|
|
||||||
Additional computations added by `FLATBUFFERS_NAN_DEFAULTS` are very cheap
|
|
||||||
if GCC or Clang used. These compilers have a compile-time implementation
|
|
||||||
of `isnan` checking which MSVC does not.
|
|
||||||
|
|
||||||
<br>
|
|
265
third_party/flatbuffers/docs/source/CsharpUsage.md
vendored
@ -1,265 +0,0 @@
|
|||||||
Use in C# {#flatbuffers_guide_use_c-sharp}
|
|
||||||
==============
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in C#, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
|
||||||
general FlatBuffers usage in all of the supported languages (including C#).
|
|
||||||
This page is designed to cover the nuances of FlatBuffers usage,
|
|
||||||
specific to C#.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers C# code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers C# library can be found at
|
|
||||||
`flatbuffers/net/FlatBuffers`. You can browse the library on the
|
|
||||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/
|
|
||||||
FlatBuffers).
|
|
||||||
|
|
||||||
## Building the FlatBuffers C# library
|
|
||||||
|
|
||||||
The `FlatBuffers.csproj` project contains multitargeting for .NET Standard 2.1,
|
|
||||||
.NET 6 and .NET 8.
|
|
||||||
|
|
||||||
You can build for a specific framework target when using the cross-platform
|
|
||||||
[.NET Core SDK](https://dotnet.microsoft.com/download) by adding the `-f`
|
|
||||||
command line option:
|
|
||||||
|
|
||||||
~~~{.sh}
|
|
||||||
dotnet build -f netstandard2.1 "FlatBuffers.csproj"
|
|
||||||
~~~
|
|
||||||
|
|
||||||
The `FlatBuffers.csproj` project also provides support for defining various
|
|
||||||
conditional compilation symbols (see "Conditional compilation symbols" section
|
|
||||||
below) using the `-p` command line option:
|
|
||||||
|
|
||||||
~~~{.sh}
|
|
||||||
dotnet build -f netstandard2.1 -p:ENABLE_SPAN_T=true -p:UNSAFE_BYTEBUFFER=true "FlatBuffers.csproj"
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Testing the FlatBuffers C# library
|
|
||||||
|
|
||||||
The code to test the libraries can be found at `flatbuffers/tests`.
|
|
||||||
|
|
||||||
The test code for C# is located in the [FlatBuffers.Test](https://github.com/
|
|
||||||
google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the
|
|
||||||
tests, open `FlatBuffers.Test.csproj` in [Visual Studio](
|
|
||||||
https://www.visualstudio.com), and compile/run the project.
|
|
||||||
|
|
||||||
Optionally, you can run this using [Mono](http://www.mono-project.com/) instead.
|
|
||||||
Once you have installed Mono, you can run the tests from the command line
|
|
||||||
by running the following commands from inside the `FlatBuffers.Test` folder:
|
|
||||||
|
|
||||||
~~~{.sh}
|
|
||||||
mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs
|
|
||||||
mono Assert.exe
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Using the FlatBuffers C# library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in C#.*
|
|
||||||
|
|
||||||
FlatBuffers supports reading and writing binary FlatBuffers in C#.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate C# classes from your
|
|
||||||
schema with the `--csharp` option to `flatc`.
|
|
||||||
Then you can include both FlatBuffers and the generated code to read
|
|
||||||
or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in C#:
|
|
||||||
First, import the library and generated code. Then, you read a FlatBuffer binary
|
|
||||||
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
|
|
||||||
pass to the `GetRootAsMyRootType` function:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
|
||||||
using MyGame.Example;
|
|
||||||
using Google.FlatBuffers;
|
|
||||||
|
|
||||||
// This snippet ignores exceptions for brevity.
|
|
||||||
byte[] data = File.ReadAllBytes("monsterdata_test.mon");
|
|
||||||
|
|
||||||
ByteBuffer bb = new ByteBuffer(data);
|
|
||||||
Monster monster = Monster.GetRootAsMonster(bb);
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now you can access the data from the `Monster monster`:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
|
||||||
short hp = monster.Hp;
|
|
||||||
Vec3 pos = monster.Pos;
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
C# code naming follows standard C# style with PascalCasing identifiers,
|
|
||||||
e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are
|
|
||||||
available as properties instead of parameterless accessor methods.
|
|
||||||
The performance-enhancing methods to which you can pass an already created
|
|
||||||
object are prefixed with `Get`, e.g.:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
|
||||||
// property
|
|
||||||
var pos = monster.Pos;
|
|
||||||
|
|
||||||
// method filling a preconstructed object
|
|
||||||
var preconstructedPos = new Vec3();
|
|
||||||
monster.GetPos(preconstructedPos);
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
## Storing dictionaries in a FlatBuffer
|
|
||||||
|
|
||||||
FlatBuffers doesn't support dictionaries natively, but there is support to
|
|
||||||
emulate their behavior with vectors and binary search, which means you
|
|
||||||
can have fast lookups directly from a FlatBuffer without having to unpack
|
|
||||||
your data into a `Dictionary` or similar.
|
|
||||||
|
|
||||||
To use it:
|
|
||||||
- Designate one of the fields in a table as the "key" field. You do this
|
|
||||||
by setting the `key` attribute on this field, e.g.
|
|
||||||
`name:string (key)`.
|
|
||||||
You may only have one key field, and it must be of string or scalar type.
|
|
||||||
- Write out tables of this type as usual, collect their offsets in an
|
|
||||||
array.
|
|
||||||
- Instead of calling standard generated method,
|
|
||||||
e.g.: `Monster.createTestarrayoftablesVector`,
|
|
||||||
call `CreateSortedVectorOfMonster` in C#
|
|
||||||
which will first sort all offsets such that the tables they refer to
|
|
||||||
are sorted by the key field, then serialize it.
|
|
||||||
- Now when you're accessing the FlatBuffer, you can use
|
|
||||||
the `ByKey` accessor to access elements of the vector, e.g.:
|
|
||||||
`monster.TestarrayoftablesByKey("Frodo")` in C#,
|
|
||||||
which returns an object of the corresponding table type,
|
|
||||||
or `null` if not found.
|
|
||||||
`ByKey` performs a binary search, so should have a similar
|
|
||||||
speed to `Dictionary`, though may be faster because of better caching.
|
|
||||||
`ByKey` only works if the vector has been sorted, it will
|
|
||||||
likely not find elements if it hasn't been sorted.
|
|
||||||
|
|
||||||
## Buffer verification
|
|
||||||
|
|
||||||
As mentioned in [C++ Usage](@ref flatbuffers_guide_use_cpp) buffer
|
|
||||||
accessor functions do not verify buffer offsets at run-time.
|
|
||||||
If it is necessary, you can optionally use a buffer verifier before you
|
|
||||||
access the data. This verifier will check all offsets, all sizes of
|
|
||||||
fields, and null termination of strings to ensure that when a buffer
|
|
||||||
is accessed, all reads will end up inside the buffer.
|
|
||||||
|
|
||||||
Each root type will have a verification function generated for it,
|
|
||||||
e.g. `Monster.VerifyMonster`. This can be called as shown:
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
|
||||||
var ok = Monster.VerifyMonster(buf);
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
if `ok` is true, the buffer is safe to read.
|
|
||||||
|
|
||||||
For a more detailed control of verification `MonsterVerify.Verify`
|
|
||||||
for `Monster` type can be used:
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
|
||||||
# Sequence of calls
|
|
||||||
FlatBuffers.Verifier verifier = new FlatBuffers.Verifier(buf);
|
|
||||||
var ok = verifier.VerifyBuffer("MONS", false, MonsterVerify.Verify);
|
|
||||||
|
|
||||||
# Or single line call
|
|
||||||
var ok = new FlatBuffers.Verifier(bb).setStringCheck(true).\
|
|
||||||
VerifyBuffer("MONS", false, MonsterVerify.Verify);
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
if `ok` is true, the buffer is safe to read.
|
|
||||||
|
|
||||||
A second parameter of `verifyBuffer` specifies whether buffer content is
|
|
||||||
size prefixed or not. In the example above, the buffer is assumed to not include
|
|
||||||
size prefix (`false`).
|
|
||||||
|
|
||||||
Verifier supports options that can be set using appropriate fluent methods:
|
|
||||||
* SetMaxDepth - limit the nesting depth. Default: 1000000
|
|
||||||
* SetMaxTables - total amount of tables the verifier may encounter. Default: 64
|
|
||||||
* SetAlignmentCheck - check content alignment. Default: True
|
|
||||||
* SetStringCheck - check if strings contain termination '0' character. Default: true
|
|
||||||
|
|
||||||
|
|
||||||
## Text parsing
|
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
|
||||||
from C#, though you could use the C++ parser through native call
|
|
||||||
interfaces available to each language. Please see the
|
|
||||||
C++ documentation for more on text parsing.
|
|
||||||
|
|
||||||
## Object based API
|
|
||||||
|
|
||||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
|
||||||
around using as little as possible of it. This does make the API clumsier
|
|
||||||
(requiring pre-order construction of all data, and making mutation harder).
|
|
||||||
|
|
||||||
For times when efficiency is less important a more convenient object based API
|
|
||||||
can be used (through `--gen-object-api`) that is able to unpack & pack a
|
|
||||||
FlatBuffer into objects and standard `System.Collections.Generic` containers,
|
|
||||||
allowing for convenient construction, access and mutation.
|
|
||||||
|
|
||||||
To use:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
|
||||||
// Deserialize from buffer into object.
|
|
||||||
MonsterT monsterobj = GetMonster(flatbuffer).UnPack();
|
|
||||||
|
|
||||||
// Update object directly like a C# class instance.
|
|
||||||
Console.WriteLine(monsterobj.Name);
|
|
||||||
monsterobj.Name = "Bob"; // Change the name.
|
|
||||||
|
|
||||||
// Serialize into new flatbuffer.
|
|
||||||
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
|
|
||||||
fbb.Finish(Monster.Pack(fbb, monsterobj).Value);
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
### Json Serialization
|
|
||||||
|
|
||||||
An additional feature of the object API is the ability to allow you to
|
|
||||||
serialize & deserialize a JSON text.
|
|
||||||
To use Json Serialization, add `--cs-gen-json-serializer` option to `flatc` and
|
|
||||||
add `Newtonsoft.Json` nuget package to csproj. This requires explicitly setting
|
|
||||||
the `--gen-object-api` option as well.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
|
||||||
// Deserialize MonsterT from json
|
|
||||||
string jsonText = File.ReadAllText(@"Resources/monsterdata_test.json");
|
|
||||||
MonsterT mon = MonsterT.DeserializeFromJson(jsonText);
|
|
||||||
|
|
||||||
// Serialize MonsterT to json
|
|
||||||
string jsonText2 = mon.SerializeToJson();
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
* Limitation
|
|
||||||
* `hash` attribute currently not supported.
|
|
||||||
* NuGet package Dependency
|
|
||||||
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
|
|
||||||
|
|
||||||
## Conditional compilation symbols
|
|
||||||
|
|
||||||
There are three conditional compilation symbols that have an impact on
|
|
||||||
performance/features of the C# `ByteBuffer` implementation.
|
|
||||||
|
|
||||||
* `UNSAFE_BYTEBUFFER`
|
|
||||||
|
|
||||||
This will use unsafe code to manipulate the underlying byte array. This can
|
|
||||||
yield a reasonable performance increase.
|
|
||||||
|
|
||||||
* `BYTEBUFFER_NO_BOUNDS_CHECK`
|
|
||||||
|
|
||||||
This will disable the bounds check asserts to the byte array. This can yield a
|
|
||||||
small performance gain in normal code.
|
|
||||||
|
|
||||||
* `ENABLE_SPAN_T`
|
|
||||||
|
|
||||||
This will enable reading and writing blocks of memory with a `Span<T>` instead
|
|
||||||
of just `T[]`. You can also enable writing directly to shared memory or other
|
|
||||||
types of memory by providing a custom implementation of `ByteBufferAllocator`.
|
|
||||||
`ENABLE_SPAN_T` also requires `UNSAFE_BYTEBUFFER` to be defined, or .NET
|
|
||||||
Standard 2.1.
|
|
||||||
|
|
||||||
Using `UNSAFE_BYTEBUFFER` and `BYTEBUFFER_NO_BOUNDS_CHECK` together can yield a
|
|
||||||
performance gain of ~15% for some operations, however doing so is potentially
|
|
||||||
dangerous. Do so at your own risk!
|
|
||||||
|
|
||||||
<br>
|
|
131
third_party/flatbuffers/docs/source/DartUsage.md
vendored
@ -1,131 +0,0 @@
|
|||||||
Use in Dart {#flatbuffers_guide_use_dart}
|
|
||||||
===========
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in Dart, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
|
||||||
to general FlatBuffers usage in all of the supported languages (including Dart).
|
|
||||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
|
||||||
Dart.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers Dart library code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers Dart library can be found at
|
|
||||||
`flatbuffers/dart`. You can browse the library code on the [FlatBuffers
|
|
||||||
GitHub page](https://github.com/google/flatbuffers/tree/master/dart).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers Dart library
|
|
||||||
|
|
||||||
The code to test the Dart library can be found at `flatbuffers/tests`.
|
|
||||||
The test code itself is located in [dart_test.dart](https://github.com/google/
|
|
||||||
flatbuffers/blob/master/tests/dart_test.dart).
|
|
||||||
|
|
||||||
To run the tests, use the [DartTest.sh](https://github.com/google/flatbuffers/
|
|
||||||
blob/master/tests/DartTest.sh) shell script.
|
|
||||||
|
|
||||||
*Note: The shell script requires the [Dart SDK](https://www.dartlang.org/tools/sdk)
|
|
||||||
to be installed.*
|
|
||||||
|
|
||||||
## Using the FlatBuffers Dart library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in Dart.*
|
|
||||||
|
|
||||||
FlatBuffers supports reading and writing binary FlatBuffers in Dart.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate Dart classes from your
|
|
||||||
schema with the `--dart` option to `flatc`. Then you can include both FlatBuffers
|
|
||||||
and the generated code to read or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in Dart: First,
|
|
||||||
include the library and generated code. Then read a FlatBuffer binary file into
|
|
||||||
a `List<int>`, which you pass to the factory constructor for `Monster`:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
|
|
||||||
import 'dart:io' as io;
|
|
||||||
|
|
||||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
|
||||||
import './monster_my_game.sample_generated.dart' as myGame;
|
|
||||||
|
|
||||||
List<int> data = await new io.File('monster.dat').readAsBytes();
|
|
||||||
var monster = new myGame.Monster(data);
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now you can access values like this:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
|
|
||||||
var hp = monster.hp;
|
|
||||||
var pos = monster.pos;
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
## Differences from the Dart SDK Front End flat_buffers
|
|
||||||
|
|
||||||
The work in this repository is signfiicantly based on the implementation used
|
|
||||||
internally by the Dart SDK in the front end/analyzer package. Several
|
|
||||||
significant changes have been made.
|
|
||||||
|
|
||||||
1. Support for packed boolean lists has been removed. This is not standard
|
|
||||||
in other implementations and is not compatible with them. Do note that,
|
|
||||||
like in the JavaScript implementation, __null values in boolean lists
|
|
||||||
will be treated as false__. It is also still entirely possible to pack data
|
|
||||||
in a single scalar field, but that would have to be done on the application
|
|
||||||
side.
|
|
||||||
2. The SDK implementation supports enums with regular Dart enums, which
|
|
||||||
works if enums are always indexed at 1; however, FlatBuffers does not
|
|
||||||
require that. This implementation uses specialized enum-like classes to
|
|
||||||
ensure proper mapping from FlatBuffers to Dart and other platforms.
|
|
||||||
3. The SDK implementation does not appear to support FlatBuffer structs or
|
|
||||||
vectors of structs - it treated everything as a built-in scalar or a table.
|
|
||||||
This implementation treats structs in a way that is compatible with other
|
|
||||||
non-Dart implementations, and properly handles vectors of structs. Many of
|
|
||||||
the methods prefixed with 'low' have been prepurposed to support this.
|
|
||||||
4. The SDK implementation treats int64 and uint64 as float64s. This
|
|
||||||
implementation does not. This may cause problems with JavaScript
|
|
||||||
compatibility - however, it should be possible to use the JavaScript
|
|
||||||
implementation, or to do a customized implementation that treats all 64 bit
|
|
||||||
numbers as floats. Supporting the Dart VM and Flutter was a more important
|
|
||||||
goal of this implementation. Support for 16 bit integers was also added.
|
|
||||||
5. The code generation in this offers an "ObjectBuilder", which generates code
|
|
||||||
very similar to the SDK classes that consume FlatBuffers, as well as Builder
|
|
||||||
classes, which produces code which more closely resembles the builders in
|
|
||||||
other languages. The ObjectBuilder classes are easier to use, at the cost of
|
|
||||||
additional references allocated.
|
|
||||||
|
|
||||||
## Text Parsing
|
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
|
||||||
from Dart, though you could use the C++ parser through Dart Native Extensions.
|
|
||||||
Please see the C++ documentation for more on text parsing (note that this is
|
|
||||||
not currently an option in Flutter - follow [this issue](https://github.com/flutter/flutter/issues/7053)
|
|
||||||
for the latest).
|
|
||||||
|
|
||||||
## Object based API
|
|
||||||
|
|
||||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
|
||||||
around using as little as possible of it. This does make the API clumsier
|
|
||||||
(requiring pre-order construction of all data, and making mutation harder).
|
|
||||||
|
|
||||||
For times when efficiency is less important a more convenient object based API
|
|
||||||
can be used (through `--gen-object-api`) that is able to unpack & pack a FlatBuffer
|
|
||||||
into objects and lists, allowing for convenient construction, access and mutation.
|
|
||||||
|
|
||||||
To use:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
|
|
||||||
// Deserialize from buffer into object.
|
|
||||||
MonsterT monster = Monster(flatbuffer).unpack();
|
|
||||||
|
|
||||||
// Update object directly like a Dart class instance.
|
|
||||||
print(monster.Name);
|
|
||||||
monster.Name = "Bob"; // Change the name.
|
|
||||||
|
|
||||||
// Serialize into new flatbuffer.
|
|
||||||
final fbb = Builder();
|
|
||||||
fbb.Finish(monster.pack(fbb));
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
188
third_party/flatbuffers/docs/source/FlatBuffers.md
vendored
@ -1,188 +0,0 @@
|
|||||||
FlatBuffers {#flatbuffers_index}
|
|
||||||
===========
|
|
||||||
|
|
||||||
# Overview {#flatbuffers_overview}
|
|
||||||
|
|
||||||
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
|
|
||||||
serialization library for C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust and Swift.
|
|
||||||
It was originally created at Google for game development and other
|
|
||||||
performance-critical applications.
|
|
||||||
|
|
||||||
It is available as Open Source on [GitHub](http://github.com/google/flatbuffers)
|
|
||||||
under the Apache license, v2 (see LICENSE).
|
|
||||||
|
|
||||||
## Why use FlatBuffers?
|
|
||||||
|
|
||||||
- **Access to serialized data without parsing/unpacking** - What sets
|
|
||||||
FlatBuffers apart is that it represents hierarchical data in a flat
|
|
||||||
binary buffer in such a way that it can still be accessed directly
|
|
||||||
without parsing/unpacking, while also still supporting data
|
|
||||||
structure evolution (forwards/backwards compatibility).
|
|
||||||
|
|
||||||
- **Memory efficiency and speed** - The only memory needed to access
|
|
||||||
your data is that of the buffer. It requires 0 additional allocations
|
|
||||||
(in C++, other languages may vary). FlatBuffers is also very
|
|
||||||
suitable for use with mmap (or streaming), requiring only part of the
|
|
||||||
buffer to be in memory. Access is close to the speed of raw
|
|
||||||
struct access with only one extra indirection (a kind of vtable) to
|
|
||||||
allow for format evolution and optional fields. It is aimed at
|
|
||||||
projects where spending time and space (many memory allocations) to
|
|
||||||
be able to access or construct serialized data is undesirable, such
|
|
||||||
as in games or any other performance sensitive applications. See the
|
|
||||||
[benchmarks](@ref flatbuffers_benchmarks) for details.
|
|
||||||
|
|
||||||
- **Flexible** - Optional fields means not only do you get great
|
|
||||||
forwards and backwards compatibility (increasingly important for
|
|
||||||
long-lived games: don't have to update all data with each new
|
|
||||||
version!). It also means you have a lot of choice in what data you
|
|
||||||
write and what data you don't, and how you design data structures.
|
|
||||||
|
|
||||||
- **Tiny code footprint** - Small amounts of generated code, and just
|
|
||||||
a single small header as the minimum dependency, which is very easy
|
|
||||||
to integrate. Again, see the benchmark section for details.
|
|
||||||
|
|
||||||
- **Strongly typed** - Errors happen at compile time rather than
|
|
||||||
manually having to write repetitive and error prone run-time checks.
|
|
||||||
Useful code can be generated for you.
|
|
||||||
|
|
||||||
- **Convenient to use** - Generated C++ code allows for terse access
|
|
||||||
& construction code. Then there's optional functionality for parsing
|
|
||||||
schemas and JSON-like text representations at runtime efficiently if
|
|
||||||
needed (faster and more memory efficient than other JSON
|
|
||||||
parsers).
|
|
||||||
|
|
||||||
Java, Kotlin and Go code supports object-reuse. C# has efficient struct based
|
|
||||||
accessors.
|
|
||||||
|
|
||||||
- **Cross platform code with no dependencies** - C++ code will work
|
|
||||||
with any recent gcc/clang and VS2010. Comes with build files for the tests &
|
|
||||||
samples (Android .mk files, and cmake for all other platforms).
|
|
||||||
|
|
||||||
### Why not use Protocol Buffers, or .. ?
|
|
||||||
|
|
||||||
Protocol Buffers is indeed relatively similar to FlatBuffers,
|
|
||||||
with the primary difference being that FlatBuffers does not need a parsing/
|
|
||||||
unpacking step to a secondary representation before you can
|
|
||||||
access data, often coupled with per-object memory allocation. The code
|
|
||||||
is an order of magnitude bigger, too. Protocol Buffers has no optional
|
|
||||||
text import/export.
|
|
||||||
|
|
||||||
### But all the cool kids use JSON!
|
|
||||||
|
|
||||||
JSON is very readable (which is why we use it as our optional text
|
|
||||||
format) and very convenient when used together with dynamically typed
|
|
||||||
languages (such as JavaScript). When serializing data from statically
|
|
||||||
typed languages, however, JSON not only has the obvious drawback of runtime
|
|
||||||
inefficiency, but also forces you to write *more* code to access data
|
|
||||||
(counterintuitively) due to its dynamic-typing serialization system.
|
|
||||||
In this context, it is only a better choice for systems that have very
|
|
||||||
little to no information ahead of time about what data needs to be stored.
|
|
||||||
|
|
||||||
If you do need to store data that doesn't fit a schema, FlatBuffers also
|
|
||||||
offers a schema-less (self-describing) version!
|
|
||||||
|
|
||||||
Read more about the "why" of FlatBuffers in the
|
|
||||||
[white paper](@ref flatbuffers_white_paper).
|
|
||||||
|
|
||||||
### Who uses FlatBuffers?
|
|
||||||
- [Cocos2d-x](http://www.cocos2d-x.org/), the #1 open source mobile game
|
|
||||||
engine, uses it to serialize all their
|
|
||||||
[game data](http://www.cocos2d-x.org/reference/native-cpp/V3.5/d7/d2d/namespaceflatbuffers.html).
|
|
||||||
- [Facebook](http://facebook.com/) uses it for client-server communication in
|
|
||||||
their Android app. They have a nice
|
|
||||||
[article](https://code.facebook.com/posts/872547912839369/improving-facebook-s-performance-on-android-with-flatbuffers/)
|
|
||||||
explaining how it speeds up loading their posts.
|
|
||||||
- [Fun Propulsion Labs](https://developers.google.com/games/#Tools)
|
|
||||||
at Google uses it extensively in all their libraries and games.
|
|
||||||
|
|
||||||
## Usage in brief
|
|
||||||
|
|
||||||
This section is a quick rundown of how to use this system. Subsequent
|
|
||||||
sections provide a more in-depth usage guide.
|
|
||||||
|
|
||||||
- Write a schema file that allows you to define the data structures
|
|
||||||
you may want to serialize. Fields can have a scalar type
|
|
||||||
(ints/floats of all sizes), or they can be a: string; array of any type;
|
|
||||||
reference to yet another object; or, a set of possible objects (unions).
|
|
||||||
Fields are optional and have defaults, so they don't need to be
|
|
||||||
present for every object instance.
|
|
||||||
|
|
||||||
- Use `flatc` (the FlatBuffer compiler) to generate a C++ header (or
|
|
||||||
Java/Kotlin/C#/Go/Python.. classes) with helper classes to access and construct
|
|
||||||
serialized data. This header (say `mydata_generated.h`) only depends on
|
|
||||||
`flatbuffers.h`, which defines the core functionality.
|
|
||||||
|
|
||||||
- Use the `FlatBufferBuilder` class to construct a flat binary buffer.
|
|
||||||
The generated functions allow you to add objects to this
|
|
||||||
buffer recursively, often as simply as making a single function call.
|
|
||||||
|
|
||||||
- Store or send your buffer somewhere!
|
|
||||||
|
|
||||||
- When reading it back, you can obtain the pointer to the root object
|
|
||||||
from the binary buffer, and from there traverse it conveniently
|
|
||||||
in-place with `object->field()`.
|
|
||||||
|
|
||||||
## In-depth documentation
|
|
||||||
|
|
||||||
- How to [build the compiler](@ref flatbuffers_guide_building) and samples on
|
|
||||||
various platforms.
|
|
||||||
- How to [use the compiler](@ref flatbuffers_guide_using_schema_compiler).
|
|
||||||
- How to [write a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
- How to [use the generated C++ code](@ref flatbuffers_guide_use_cpp) in your
|
|
||||||
own programs.
|
|
||||||
- How to [use the generated Java code](@ref flatbuffers_guide_use_java)
|
|
||||||
in your own programs.
|
|
||||||
- How to [use the generated C# code](@ref flatbuffers_guide_use_c-sharp)
|
|
||||||
in your own programs.
|
|
||||||
- How to [use the generated Kotlin code](@ref flatbuffers_guide_use_kotlin)
|
|
||||||
in your own programs.
|
|
||||||
- How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
|
|
||||||
own programs.
|
|
||||||
- How to [use the generated Lua code](@ref flatbuffers_guide_use_lua) in your
|
|
||||||
own programs.
|
|
||||||
- How to [use the generated JavaScript code](@ref flatbuffers_guide_use_javascript) in your
|
|
||||||
own programs.
|
|
||||||
- How to [use the generated TypeScript code](@ref flatbuffers_guide_use_typescript) in your
|
|
||||||
own programs.
|
|
||||||
- How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your
|
|
||||||
own programs.
|
|
||||||
- How to [use the generated Lobster code](@ref flatbuffers_guide_use_lobster) in your
|
|
||||||
own programs.
|
|
||||||
- How to [use the generated Rust code](@ref flatbuffers_guide_use_rust) in your
|
|
||||||
own programs.
|
|
||||||
- How to [use the generated Swift code](@ref flatbuffers_guide_use_swift) in your
|
|
||||||
own programs.
|
|
||||||
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
|
|
||||||
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
|
|
||||||
using FlatBuffers.
|
|
||||||
- A [white paper](@ref flatbuffers_white_paper) explaining the "why" of
|
|
||||||
FlatBuffers.
|
|
||||||
- How to use the [schema-less](@ref flexbuffers) version of
|
|
||||||
FlatBuffers.
|
|
||||||
- A description of the [internals](@ref flatbuffers_internals) of FlatBuffers.
|
|
||||||
- A formal [grammar](@ref flatbuffers_grammar) of the schema language.
|
|
||||||
|
|
||||||
## Online resources
|
|
||||||
|
|
||||||
- [GitHub repository](http://github.com/google/flatbuffers)
|
|
||||||
- [Landing page](http://google.github.io/flatbuffers)
|
|
||||||
- [FlatBuffers Google Group](https://groups.google.com/forum/#!forum/flatbuffers)
|
|
||||||
- [Discord](https://discord.gg/6qgKs3R) and [Gitter](https://gitter.im/lobster_programming_language/community) chat.
|
|
||||||
- [FlatBuffers Issues Tracker](http://github.com/google/flatbuffers/issues)
|
|
||||||
- Independent implementations & tools:
|
|
||||||
- [FlatCC](https://github.com/dvidelabs/flatcc) Alternative FlatBuffers
|
|
||||||
parser, code generator and runtime all in C.
|
|
||||||
- Videos:
|
|
||||||
- Colt's [DevByte](https://www.youtube.com/watch?v=iQTxMkSJ1dQ).
|
|
||||||
- GDC 2015 [Lightning Talk](https://www.youtube.com/watch?v=olmL1fUnQAQ).
|
|
||||||
- FlatBuffers for [Go](https://www.youtube.com/watch?v=-BPVId_lA5w).
|
|
||||||
- Evolution of FlatBuffers
|
|
||||||
[visualization](https://www.youtube.com/watch?v=a0QE0xS8rKM).
|
|
||||||
- Useful documentation created by others:
|
|
||||||
- [FlatBuffers in Go](https://rwinslow.com/tags/flatbuffers/)
|
|
||||||
- [FlatBuffers in Android](http://frogermcs.github.io/flatbuffers-in-android-introdution/)
|
|
||||||
- [Parsing JSON to FlatBuffers in Java](http://frogermcs.github.io/json-parsing-with-flatbuffers-in-android/)
|
|
||||||
- [FlatBuffers in Unity](http://exiin.com/blog/flatbuffers-for-unity-sample-code/)
|
|
||||||
- [FlexBuffers C#](https://github.com/mzaks/FlexBuffers-CSharp) and
|
|
||||||
[article](https://medium.com/@icex33/flexbuffers-for-unity3d-4d1ab5c53fbe?)
|
|
||||||
on its use.
|
|
204
third_party/flatbuffers/docs/source/FlexBuffers.md
vendored
@ -1,204 +0,0 @@
|
|||||||
FlexBuffers {#flexbuffers}
|
|
||||||
==========
|
|
||||||
|
|
||||||
FlatBuffers was designed around schemas, because when you want maximum
|
|
||||||
performance and data consistency, strong typing is helpful.
|
|
||||||
|
|
||||||
There are however times when you want to store data that doesn't fit a
|
|
||||||
schema, because you can't know ahead of time what all needs to be stored.
|
|
||||||
|
|
||||||
For this, FlatBuffers has a dedicated format, called FlexBuffers.
|
|
||||||
This is a binary format that can be used in conjunction
|
|
||||||
with FlatBuffers (by storing a part of a buffer in FlexBuffers
|
|
||||||
format), or also as its own independent serialization format.
|
|
||||||
|
|
||||||
While it loses the strong typing, you retain the most unique advantage
|
|
||||||
FlatBuffers has over other serialization formats (schema-based or not):
|
|
||||||
FlexBuffers can also be accessed without parsing / copying / object allocation.
|
|
||||||
This is a huge win in efficiency / memory friendly-ness, and allows unique
|
|
||||||
use cases such as mmap-ing large amounts of free-form data.
|
|
||||||
|
|
||||||
FlexBuffers' design and implementation allows for a very compact encoding,
|
|
||||||
combining automatic pooling of strings with automatic sizing of containers to
|
|
||||||
their smallest possible representation (8/16/32/64 bits). Many values and
|
|
||||||
offsets can be encoded in just 8 bits. While a schema-less representation is
|
|
||||||
usually more bulky because of the need to be self-descriptive, FlexBuffers
|
|
||||||
generates smaller binaries for many cases than regular FlatBuffers.
|
|
||||||
|
|
||||||
FlexBuffers is still slower than regular FlatBuffers though, so we recommend to
|
|
||||||
only use it if you need it.
|
|
||||||
|
|
||||||
|
|
||||||
# Usage in C++
|
|
||||||
|
|
||||||
Include the header `flexbuffers.h`, which in turn depends on `flatbuffers.h`
|
|
||||||
and `util.h`.
|
|
||||||
|
|
||||||
To create a buffer:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
|
||||||
flexbuffers::Builder fbb;
|
|
||||||
fbb.Int(13);
|
|
||||||
fbb.Finish();
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
You create any value, followed by `Finish`. Unlike FlatBuffers which requires
|
|
||||||
the root value to be a table, here any value can be the root, including a lonely
|
|
||||||
int value.
|
|
||||||
|
|
||||||
You can now access the `std::vector<uint8_t>` that contains the encoded value
|
|
||||||
as `fbb.GetBuffer()`. Write it, send it, or store it in a parent FlatBuffer. In
|
|
||||||
this case, the buffer is just 3 bytes in size.
|
|
||||||
|
|
||||||
To read this value back, you could just say:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
|
||||||
auto root = flexbuffers::GetRoot(my_buffer);
|
|
||||||
int64_t i = root.AsInt64();
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
FlexBuffers stores ints only as big as needed, so it doesn't differentiate
|
|
||||||
between different sizes of ints. You can ask for the 64 bit version,
|
|
||||||
regardless of what you put in. In fact, since you demand to read the root
|
|
||||||
as an int, if you supply a buffer that actually contains a float, or a
|
|
||||||
string with numbers in it, it will convert it for you on the fly as well,
|
|
||||||
or return 0 if it can't. If instead you actually want to know what is inside
|
|
||||||
the buffer before you access it, you can call `root.GetType()` or `root.IsInt()`
|
|
||||||
etc.
|
|
||||||
|
|
||||||
Here's a slightly more complex value you could write instead of `fbb.Int` above:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
|
||||||
fbb.Map([&]() {
|
|
||||||
fbb.Vector("vec", [&]() {
|
|
||||||
fbb.Int(-100);
|
|
||||||
fbb.String("Fred");
|
|
||||||
fbb.IndirectFloat(4.0f);
|
|
||||||
});
|
|
||||||
fbb.UInt("foo", 100);
|
|
||||||
});
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This stores the equivalent of the JSON value
|
|
||||||
`{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`. The root is a dictionary that has
|
|
||||||
just two key-value pairs, with keys `vec` and `foo`. Unlike FlatBuffers, it
|
|
||||||
actually has to store these keys in the buffer (which it does only once if
|
|
||||||
you store multiple such objects, by pooling key values), but also unlike
|
|
||||||
FlatBuffers it has no restriction on the keys (fields) that you use.
|
|
||||||
|
|
||||||
The map constructor uses a C++11 Lambda to group its children, but you can
|
|
||||||
also use more conventional start/end calls if you prefer.
|
|
||||||
|
|
||||||
The first value in the map is a vector. You'll notice that unlike FlatBuffers,
|
|
||||||
you can use mixed types. There is also a `TypedVector` variant that only
|
|
||||||
allows a single type, and uses a bit less memory.
|
|
||||||
|
|
||||||
`IndirectFloat` is an interesting feature that allows you to store values
|
|
||||||
by offset rather than inline. Though that doesn't make any visible change
|
|
||||||
to the user, the consequence is that large values (especially doubles or
|
|
||||||
64 bit ints) that occur more than once can be shared (see ReuseValue).
|
|
||||||
Another use case is inside of vectors, where the largest element makes
|
|
||||||
up the size of all elements (e.g. a single double forces all elements to
|
|
||||||
64bit), so storing a lot of small integers together with a double is more efficient if the double is indirect.
|
|
||||||
|
|
||||||
Accessing it:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
|
||||||
auto map = flexbuffers::GetRoot(my_buffer).AsMap();
|
|
||||||
map.size(); // 2
|
|
||||||
auto vec = map["vec"].AsVector();
|
|
||||||
vec.size(); // 3
|
|
||||||
vec[0].AsInt64(); // -100;
|
|
||||||
vec[1].AsString().c_str(); // "Fred";
|
|
||||||
vec[1].AsInt64(); // 0 (Number parsing failed).
|
|
||||||
vec[2].AsDouble(); // 4.0
|
|
||||||
vec[2].AsString().IsTheEmptyString(); // true (Wrong Type).
|
|
||||||
vec[2].AsString().c_str(); // "" (This still works though).
|
|
||||||
vec[2].ToString().c_str(); // "4" (Or have it converted).
|
|
||||||
map["foo"].AsUInt8(); // 100
|
|
||||||
map["unknown"].IsNull(); // true
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
# Usage in Java
|
|
||||||
|
|
||||||
Java implementation follows the C++ one, closely.
|
|
||||||
|
|
||||||
For creating the equivalent of the same JSON `{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`,
|
|
||||||
one could use the following code:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
|
||||||
FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
|
|
||||||
FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
|
|
||||||
int smap = builder.startMap();
|
|
||||||
int svec = builder.startVector();
|
|
||||||
builder.putInt(-100);
|
|
||||||
builder.putString("Fred");
|
|
||||||
builder.putFloat(4.0);
|
|
||||||
builder.endVector("vec", svec, false, false);
|
|
||||||
builder.putInt("foo", 100);
|
|
||||||
builder.endMap(null, smap);
|
|
||||||
ByteBuffer bb = builder.finish();
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Similarly, to read the data, just:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
|
||||||
FlexBuffers.Map map = FlexBuffers.getRoot(bb).asMap();
|
|
||||||
map.size(); // 2
|
|
||||||
FlexBuffers.Vector vec = map.get("vec").asVector();
|
|
||||||
vec.size(); // 3
|
|
||||||
vec.get(0).asLong(); // -100;
|
|
||||||
vec.get(1).asString(); // "Fred";
|
|
||||||
vec.get(1).asLong(); // 0 (Number parsing failed).
|
|
||||||
vec.get(2).asFloat(); // 4.0
|
|
||||||
vec.get(2).asString().isEmpty(); // true (Wrong Type).
|
|
||||||
vec.get(2).asString(); // "" (This still works though).
|
|
||||||
vec.get(2).toString(); // "4.0" (Or have it converted).
|
|
||||||
map.get("foo").asUInt(); // 100
|
|
||||||
map.get("unknown").isNull(); // true
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
# Binary encoding
|
|
||||||
|
|
||||||
A description of how FlexBuffers are encoded is in the
|
|
||||||
[internals](@ref flatbuffers_internals) document.
|
|
||||||
|
|
||||||
|
|
||||||
# Nesting inside a FlatBuffer
|
|
||||||
|
|
||||||
You can mark a field as containing a FlexBuffer, e.g.
|
|
||||||
|
|
||||||
a:[ubyte] (flexbuffer);
|
|
||||||
|
|
||||||
A special accessor will be generated that allows you to access the root value
|
|
||||||
directly, e.g. `a_flexbuffer_root().AsInt64()`.
|
|
||||||
|
|
||||||
|
|
||||||
# Efficiency tips
|
|
||||||
|
|
||||||
* Vectors generally are a lot more efficient than maps, so prefer them over maps
|
|
||||||
when possible for small objects. Instead of a map with keys `x`, `y` and `z`,
|
|
||||||
use a vector. Better yet, use a typed vector. Or even better, use a fixed
|
|
||||||
size typed vector.
|
|
||||||
* Maps are backwards compatible with vectors, and can be iterated as such.
|
|
||||||
You can iterate either just the values (`map.Values()`), or in parallel with
|
|
||||||
the keys vector (`map.Keys()`). If you intend
|
|
||||||
to access most or all elements, this is faster than looking up each element
|
|
||||||
by key, since that involves a binary search of the key vector.
|
|
||||||
* When possible, don't mix values that require a big bit width (such as double)
|
|
||||||
in a large vector of smaller values, since all elements will take on this
|
|
||||||
width. Use `IndirectDouble` when this is a possibility. Note that
|
|
||||||
integers automatically use the smallest width possible, i.e. if you ask
|
|
||||||
to serialize an int64_t whose value is actually small, you will use less
|
|
||||||
bits. Doubles are represented as floats whenever possible losslessly, but
|
|
||||||
this is only possible for few values.
|
|
||||||
Since nested vectors/maps are stored over offsets, they typically don't
|
|
||||||
affect the vector width.
|
|
||||||
* To store large arrays of byte data, use a blob. If you'd use a typed
|
|
||||||
vector, the bit width of the size field may make it use more space than
|
|
||||||
expected, and may not be compatible with `memcpy`.
|
|
||||||
Similarly, large arrays of (u)int16_t may be better off stored as a
|
|
||||||
binary blob if their size could exceed 64k elements.
|
|
||||||
Construction and use are otherwise similar to strings.
|
|
26
third_party/flatbuffers/docs/source/GoApi.md
vendored
@ -1,26 +0,0 @@
|
|||||||
Go API
|
|
||||||
======
|
|
||||||
|
|
||||||
\addtogroup flatbuffers_go_api
|
|
||||||
|
|
||||||
<!-- Note: The `GoApi_generate.txt` code snippet was generated using `godoc` and
|
|
||||||
customized for use with this markdown file. To regenerate the file, use the
|
|
||||||
`godoc` tool (http://godoc.org) with the files in the `flatbuffers/go`
|
|
||||||
folder.
|
|
||||||
|
|
||||||
You may need to ensure that copies of the files exist in the `src/`
|
|
||||||
subfolder at the path set by the `$GOROOT` environment variable. You can
|
|
||||||
either move the files to `$GOROOT/src/flatbuffers` manually, if `$GOROOT`
|
|
||||||
is already set, otherwise you will need to manually set the `$GOROOT`
|
|
||||||
variable to a path and create `src/flatbuffers` subfolders at that path.
|
|
||||||
Then copy the flatbuffers files into `$GOROOT/src/flatbuffers`. (Some
|
|
||||||
versions of `godoc` include a `-path` flag. This could be used instead, if
|
|
||||||
available).
|
|
||||||
|
|
||||||
Once the files exist at the `$GOROOT/src/flatbuffers` location, you can
|
|
||||||
regenerate this doc using the following command:
|
|
||||||
`godoc flatbuffers > GoApi_generated.txt`.
|
|
||||||
|
|
||||||
After the documentation is generated, you will have to manually remove any
|
|
||||||
non-user facing documentation from this file. -->
|
|
||||||
\snippet GoApi_generated.txt Go API
|
|
@ -1,125 +0,0 @@
|
|||||||
// This file was generated using `godoc` and customized for use with the
|
|
||||||
// API Reference documentation. To recreate this file, use the `godoc` tool
|
|
||||||
// (http://godoc.org) with the files in the `flatbuffers/go` folder.
|
|
||||||
//
|
|
||||||
// Note: You may need to ensure that copies of the files exist in the
|
|
||||||
// `src/` subfolder at the path set by the `$GOROOT` environment variable.
|
|
||||||
// You can either move the files to `$GOROOT/src/flatbuffers` manually, if
|
|
||||||
// `$GOROOT` is already set, otherwise you will need to manually set the
|
|
||||||
// `$GOROOT` variable to a path and create `src/flatbuffers` subfolders at that
|
|
||||||
// path. Then copy these files into `$GOROOT/src/flatbuffers`. (Some versions of
|
|
||||||
// `godoc` include a `-path` flag. This could be used instead, if available).
|
|
||||||
//
|
|
||||||
// Once the files exist at the `$GOROOT/src/flatbuffers` location, you can
|
|
||||||
// regenerate this doc using the following command:
|
|
||||||
// `godoc flatbuffers > GoApi_generated.txt`.
|
|
||||||
//
|
|
||||||
// After the documentation is generated, you will have to manually remove any
|
|
||||||
// non-user facing documentation from this file.
|
|
||||||
|
|
||||||
/// [Go API]
|
|
||||||
PACKAGE DOCUMENTATION
|
|
||||||
|
|
||||||
package flatbuffers
|
|
||||||
Package flatbuffers provides facilities to read and write flatbuffers
|
|
||||||
objects.
|
|
||||||
|
|
||||||
TYPES
|
|
||||||
|
|
||||||
type Builder struct {
|
|
||||||
// `Bytes` gives raw access to the buffer. Most users will want to use
|
|
||||||
// FinishedBytes() instead.
|
|
||||||
Bytes []byte
|
|
||||||
}
|
|
||||||
Builder is a state machine for creating FlatBuffer objects. Use a
|
|
||||||
Builder to construct object(s) starting from leaf nodes.
|
|
||||||
|
|
||||||
A Builder constructs byte buffers in a last-first manner for simplicity
|
|
||||||
and performance.
|
|
||||||
|
|
||||||
FUNCTIONS
|
|
||||||
|
|
||||||
func NewBuilder(initialSize int) *Builder
|
|
||||||
NewBuilder initializes a Builder of size `initial_size`. The internal
|
|
||||||
buffer is grown as needed.
|
|
||||||
|
|
||||||
func (b *Builder) CreateByteString(s []byte) UOffsetT
|
|
||||||
CreateByteString writes a byte slice as a string (null-terminated).
|
|
||||||
|
|
||||||
func (b *Builder) CreateByteVector(v []byte) UOffsetT
|
|
||||||
CreateByteVector writes a ubyte vector
|
|
||||||
|
|
||||||
func (b *Builder) CreateString(s string) UOffsetT
|
|
||||||
CreateString writes a null-terminated string as a vector.
|
|
||||||
|
|
||||||
func (b *Builder) EndVector(vectorNumElems int) UOffsetT
|
|
||||||
EndVector writes data necessary to finish vector construction.
|
|
||||||
|
|
||||||
func (b *Builder) Finish(rootTable UOffsetT)
|
|
||||||
Finish finalizes a buffer, pointing to the given `rootTable`.
|
|
||||||
|
|
||||||
func (b *Builder) FinishedBytes() []byte
|
|
||||||
FinishedBytes returns a pointer to the written data in the byte buffer.
|
|
||||||
Panics if the builder is not in a finished state (which is caused by
|
|
||||||
calling `Finish()`).
|
|
||||||
|
|
||||||
func (b *Builder) Head() UOffsetT
|
|
||||||
Head gives the start of useful data in the underlying byte buffer. Note:
|
|
||||||
unlike other functions, this value is interpreted as from the left.
|
|
||||||
|
|
||||||
func (b *Builder) PrependBool(x bool)
|
|
||||||
PrependBool prepends a bool to the Builder buffer. Aligns and checks for
|
|
||||||
space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependByte(x byte)
|
|
||||||
PrependByte prepends a byte to the Builder buffer. Aligns and checks for
|
|
||||||
space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependFloat32(x float32)
|
|
||||||
PrependFloat32 prepends a float32 to the Builder buffer. Aligns and
|
|
||||||
checks for space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependFloat64(x float64)
|
|
||||||
PrependFloat64 prepends a float64 to the Builder buffer. Aligns and
|
|
||||||
checks for space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependInt16(x int16)
|
|
||||||
PrependInt16 prepends a int16 to the Builder buffer. Aligns and checks
|
|
||||||
for space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependInt32(x int32)
|
|
||||||
PrependInt32 prepends a int32 to the Builder buffer. Aligns and checks
|
|
||||||
for space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependInt64(x int64)
|
|
||||||
PrependInt64 prepends a int64 to the Builder buffer. Aligns and checks
|
|
||||||
for space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependInt8(x int8)
|
|
||||||
PrependInt8 prepends a int8 to the Builder buffer. Aligns and checks for
|
|
||||||
space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependUOffsetT(off UOffsetT)
|
|
||||||
PrependUOffsetT prepends an UOffsetT, relative to where it will be
|
|
||||||
written.
|
|
||||||
|
|
||||||
func (b *Builder) PrependUint16(x uint16)
|
|
||||||
PrependUint16 prepends a uint16 to the Builder buffer. Aligns and checks
|
|
||||||
for space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependUint32(x uint32)
|
|
||||||
PrependUint32 prepends a uint32 to the Builder buffer. Aligns and checks
|
|
||||||
for space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependUint64(x uint64)
|
|
||||||
PrependUint64 prepends a uint64 to the Builder buffer. Aligns and checks
|
|
||||||
for space.
|
|
||||||
|
|
||||||
func (b *Builder) PrependUint8(x uint8)
|
|
||||||
PrependUint8 prepends a uint8 to the Builder buffer. Aligns and checks
|
|
||||||
for space.
|
|
||||||
|
|
||||||
func (b *Builder) Reset()
|
|
||||||
Reset truncates the underlying Builder buffer, facilitating alloc-free
|
|
||||||
reuse of a Builder. It also resets bookkeeping data.
|
|
||||||
/// [Go API]
|
|
99
third_party/flatbuffers/docs/source/GoUsage.md
vendored
@ -1,99 +0,0 @@
|
|||||||
Use in Go {#flatbuffers_guide_use_go}
|
|
||||||
=========
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in Go, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
|
||||||
to general FlatBuffers usage in all of the supported languages (including Go).
|
|
||||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
|
||||||
Go.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers Go library code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers Go library can be found at
|
|
||||||
`flatbuffers/go`. You can browse the library code on the [FlatBuffers
|
|
||||||
GitHub page](https://github.com/google/flatbuffers/tree/master/go).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers Go library
|
|
||||||
|
|
||||||
The code to test the Go library can be found at `flatbuffers/tests`.
|
|
||||||
The test code itself is located in [go_test.go](https://github.com/google/
|
|
||||||
flatbuffers/blob/master/tests/go_test.go).
|
|
||||||
|
|
||||||
To run the tests, use the [GoTest.sh](https://github.com/google/flatbuffers/
|
|
||||||
blob/master/tests/GoTest.sh) shell script.
|
|
||||||
|
|
||||||
*Note: The shell script requires [Go](https://golang.org/doc/install) to
|
|
||||||
be installed.*
|
|
||||||
|
|
||||||
## Using the FlatBuffers Go library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in Go.*
|
|
||||||
|
|
||||||
FlatBuffers supports reading and writing binary FlatBuffers in Go.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate Go classes from your
|
|
||||||
schema with the `--go` option to `flatc`. Then you can include both FlatBuffers
|
|
||||||
and the generated code to read or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in Go: First,
|
|
||||||
include the library and generated code. Then read a FlatBuffer binary file into
|
|
||||||
a `[]byte`, which you pass to the `GetRootAsMonster` function:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
|
||||||
import (
|
|
||||||
example "MyGame/Example"
|
|
||||||
flatbuffers "github.com/google/flatbuffers/go"
|
|
||||||
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
buf, err := os.ReadFile("monster.dat")
|
|
||||||
// handle err
|
|
||||||
monster := example.GetRootAsMonster(buf, 0)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now you can access values like this:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
|
||||||
hp := monster.Hp()
|
|
||||||
pos := monster.Pos(nil)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
|
||||||
monster := example.GetRootAsMonster(buf, 0)
|
|
||||||
|
|
||||||
// Set table field.
|
|
||||||
if ok := monster.MutateHp(10); !ok {
|
|
||||||
panic("failed to mutate Hp")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set struct field.
|
|
||||||
monster.Pos().MutateZ(4)
|
|
||||||
|
|
||||||
// This mutation will fail because the mana field is not available in
|
|
||||||
// the buffer. It should be set when creating the buffer.
|
|
||||||
if ok := monster.MutateMana(20); !ok {
|
|
||||||
panic("failed to mutate Hp")
|
|
||||||
}
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer.
|
|
||||||
|
|
||||||
## Text Parsing
|
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
|
||||||
from Go, though you could use the C++ parser through cgo. Please see the
|
|
||||||
C++ documentation for more on text parsing.
|
|
||||||
|
|
||||||
<br>
|
|
74
third_party/flatbuffers/docs/source/Grammar.md
vendored
@ -1,74 +0,0 @@
|
|||||||
Grammar of the schema language {#flatbuffers_grammar}
|
|
||||||
==============================
|
|
||||||
|
|
||||||
schema = include*
|
|
||||||
( namespace\_decl | type\_decl | enum\_decl | root\_decl |
|
|
||||||
file_extension_decl | file_identifier_decl |
|
|
||||||
attribute\_decl | rpc\_decl | object )*
|
|
||||||
|
|
||||||
include = `include` string\_constant `;`
|
|
||||||
|
|
||||||
namespace\_decl = `namespace` ident ( `.` ident )* `;`
|
|
||||||
|
|
||||||
attribute\_decl = `attribute` ident | `"` ident `"` `;`
|
|
||||||
|
|
||||||
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
|
||||||
|
|
||||||
enum\_decl = ( `enum` ident `:` type | `union` ident ) metadata `{`
|
|
||||||
commasep( enumval\_decl ) `}`
|
|
||||||
|
|
||||||
root\_decl = `root_type` ident `;`
|
|
||||||
|
|
||||||
field\_decl = ident `:` type [ `=` scalar ] metadata `;`
|
|
||||||
|
|
||||||
rpc\_decl = `rpc_service` ident `{` rpc\_method+ `}`
|
|
||||||
|
|
||||||
rpc\_method = ident `(` ident `)` `:` ident metadata `;`
|
|
||||||
|
|
||||||
type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
|
|
||||||
`float` | `long` | `ulong` | `double` |
|
|
||||||
`int8` | `uint8` | `int16` | `uint16` | `int32` | `uint32`| `int64` | `uint64` |
|
|
||||||
`float32` | `float64` |
|
|
||||||
`string` | `[` type `]` | ident
|
|
||||||
|
|
||||||
enumval\_decl = ident [ `=` integer\_constant ] metadata
|
|
||||||
|
|
||||||
metadata = [ `(` commasep( ident [ `:` single\_value ] ) `)` ]
|
|
||||||
|
|
||||||
scalar = boolean\_constant | integer\_constant | float\_constant
|
|
||||||
|
|
||||||
object = `{` commasep( ident `:` value ) `}`
|
|
||||||
|
|
||||||
single\_value = scalar | string\_constant
|
|
||||||
|
|
||||||
value = single\_value | object | `[` commasep( value ) `]`
|
|
||||||
|
|
||||||
commasep(x) = [ x ( `,` x )\* ]
|
|
||||||
|
|
||||||
file_extension_decl = `file_extension` string\_constant `;`
|
|
||||||
|
|
||||||
file_identifier_decl = `file_identifier` string\_constant `;`
|
|
||||||
|
|
||||||
string\_constant = `\".*?\"`
|
|
||||||
|
|
||||||
ident = `[a-zA-Z_][a-zA-Z0-9_]*`
|
|
||||||
|
|
||||||
`[:digit:]` = `[0-9]`
|
|
||||||
|
|
||||||
`[:xdigit:]` = `[0-9a-fA-F]`
|
|
||||||
|
|
||||||
dec\_integer\_constant = `[-+]?[:digit:]+`
|
|
||||||
|
|
||||||
hex\_integer\_constant = `[-+]?0[xX][:xdigit:]+`
|
|
||||||
|
|
||||||
integer\_constant = dec\_integer\_constant | hex\_integer\_constant
|
|
||||||
|
|
||||||
dec\_float\_constant = `[-+]?(([.][:digit:]+)|([:digit:]+[.][:digit:]*)|([:digit:]+))([eE][-+]?[:digit:]+)?`
|
|
||||||
|
|
||||||
hex\_float\_constant = `[-+]?0[xX](([.][:xdigit:]+)|([:xdigit:]+[.][:xdigit:]*)|([:xdigit:]+))([pP][-+]?[:digit:]+)`
|
|
||||||
|
|
||||||
special\_float\_constant = `[-+]?(nan|inf|infinity)`
|
|
||||||
|
|
||||||
float\_constant = dec\_float\_constant | hex\_float\_constant | special\_float\_constant
|
|
||||||
|
|
||||||
boolean\_constant = `true` | `false`
|
|
@ -1,35 +0,0 @@
|
|||||||
# Flatbuffers Intermediate Representation {#intermediate_representation}
|
|
||||||
|
|
||||||
We use [reflection.fbs](https://github.com/google/flatbuffers/blob/master/reflection/reflection.fbs)
|
|
||||||
as our intermediate representation. `flatc` parses `.fbs` files, checks them for
|
|
||||||
errors and stores the resulting data in this IR, outputting `.bfbs` files.
|
|
||||||
Since this IR is a Flatbuffer, you can load and use it at runtime for runtime
|
|
||||||
reflection purposes.
|
|
||||||
|
|
||||||
There are some quirks:
|
|
||||||
- Tables and Structs are serialized as `Object`s.
|
|
||||||
- Unions and Enums are serialized as `Enum`s.
|
|
||||||
- It is the responsibility of the code generator to check the `advanced_features`
|
|
||||||
field of `Schema`. These mark the presence of new, backwards incompatible,
|
|
||||||
schema features. Code generators must error if generating a schema with
|
|
||||||
unrecognized advanced features.
|
|
||||||
- Filenames are relative to a "project root" denoted by "//" in the path. This
|
|
||||||
may be specified in flatc with `--bfbs-filenames=$PROJECT_ROOT`, or it will be
|
|
||||||
inferred to be the directory containing the first provided schema file.
|
|
||||||
|
|
||||||
|
|
||||||
## Invocation
|
|
||||||
You can invoke it like so
|
|
||||||
```{.sh}
|
|
||||||
flatc -b --schema ${your_fbs_files}
|
|
||||||
```
|
|
||||||
This generates `.bfbs` (binary flatbuffer schema) files.
|
|
||||||
|
|
||||||
Some information is not included by default. See the `--bfbs-filenames` and
|
|
||||||
`--bfbs-comments` flags. These may be necessary for code-generators, so they can
|
|
||||||
add documentation and maybe name generated files (depending on the generator).
|
|
||||||
|
|
||||||
|
|
||||||
TODO(cneo): Flags to output bfbs as flexbuffers or json.
|
|
||||||
|
|
||||||
TODO(cneo): Tutorial for building a flatc plugin.
|
|
468
third_party/flatbuffers/docs/source/Internals.md
vendored
@ -1,468 +0,0 @@
|
|||||||
FlatBuffer Internals {#flatbuffers_internals}
|
|
||||||
====================
|
|
||||||
|
|
||||||
This section is entirely optional for the use of FlatBuffers. In normal
|
|
||||||
usage, you should never need the information contained herein. If you're
|
|
||||||
interested however, it should give you more of an appreciation of why
|
|
||||||
FlatBuffers is both efficient and convenient.
|
|
||||||
|
|
||||||
### Format components
|
|
||||||
|
|
||||||
A FlatBuffer is a binary file and in-memory format consisting mostly of
|
|
||||||
scalars of various sizes, all aligned to their own size. Each scalar is
|
|
||||||
also always represented in little-endian format, as this corresponds to
|
|
||||||
all commonly used CPUs today. FlatBuffers will also work on big-endian
|
|
||||||
machines, but will be slightly slower because of additional
|
|
||||||
byte-swap intrinsics.
|
|
||||||
|
|
||||||
It is assumed that the following conditions are met, to ensure
|
|
||||||
cross-platform interoperability:
|
|
||||||
- The binary `IEEE-754` format is used for floating-point numbers.
|
|
||||||
- The `two's complemented` representation is used for signed integers.
|
|
||||||
- The endianness is the same for floating-point numbers as for integers.
|
|
||||||
|
|
||||||
On purpose, the format leaves a lot of details about where exactly
|
|
||||||
things live in memory undefined, e.g. fields in a table can have any
|
|
||||||
order, and objects to some extent can be stored in many orders. This is
|
|
||||||
because the format doesn't need this information to be efficient, and it
|
|
||||||
leaves room for optimization and extension (for example, fields can be
|
|
||||||
packed in a way that is most compact). Instead, the format is defined in
|
|
||||||
terms of offsets and adjacency only. This may mean two different
|
|
||||||
implementations may produce different binaries given the same input
|
|
||||||
values, and this is perfectly valid.
|
|
||||||
|
|
||||||
### Format identification
|
|
||||||
|
|
||||||
The format also doesn't contain information for format identification
|
|
||||||
and versioning, which is also by design. FlatBuffers is a statically typed
|
|
||||||
system, meaning the user of a buffer needs to know what kind of buffer
|
|
||||||
it is. FlatBuffers can of course be wrapped inside other containers
|
|
||||||
where needed, or you can use its union feature to dynamically identify
|
|
||||||
multiple possible sub-objects stored. Additionally, it can be used
|
|
||||||
together with the schema parser if full reflective capabilities are
|
|
||||||
desired.
|
|
||||||
|
|
||||||
Versioning is something that is intrinsically part of the format (the
|
|
||||||
optionality / extensibility of fields), so the format itself does not
|
|
||||||
need a version number (it's a meta-format, in a sense). We're hoping
|
|
||||||
that this format can accommodate all data needed. If format breaking
|
|
||||||
changes are ever necessary, it would become a new kind of format rather
|
|
||||||
than just a variation.
|
|
||||||
|
|
||||||
### Offsets
|
|
||||||
|
|
||||||
The most important and generic offset type (see `flatbuffers.h`) is
|
|
||||||
`uoffset_t`, which is currently always a `uint32_t`, and is used to
|
|
||||||
refer to all tables/unions/strings/vectors (these are never stored
|
|
||||||
in-line). 32bit is
|
|
||||||
intentional, since we want to keep the format binary compatible between
|
|
||||||
32 and 64bit systems, and a 64bit offset would bloat the size for almost
|
|
||||||
all uses. A version of this format with 64bit (or 16bit) offsets is easy to set
|
|
||||||
when needed. Unsigned means they can only point in one direction, which
|
|
||||||
typically is forward (towards a higher memory location). Any backwards
|
|
||||||
offsets will be explicitly marked as such.
|
|
||||||
|
|
||||||
The format starts with an `uoffset_t` to the root table in the buffer.
|
|
||||||
|
|
||||||
We have two kinds of objects, structs and tables.
|
|
||||||
|
|
||||||
### Structs
|
|
||||||
|
|
||||||
These are the simplest, and as mentioned, intended for simple data that
|
|
||||||
benefits from being extra efficient and doesn't need versioning /
|
|
||||||
extensibility. They are always stored inline in their parent (a struct,
|
|
||||||
table, or vector) for maximum compactness. Structs define a consistent
|
|
||||||
memory layout where all components are aligned to their size, and
|
|
||||||
structs aligned to their largest scalar member. This is done independent
|
|
||||||
of the alignment rules of the underlying compiler to guarantee a cross
|
|
||||||
platform compatible layout. This layout is then enforced in the generated
|
|
||||||
code.
|
|
||||||
|
|
||||||
### Tables
|
|
||||||
|
|
||||||
Unlike structs, these are not stored in inline in their parent, but are
|
|
||||||
referred to by offset.
|
|
||||||
|
|
||||||
They start with an `soffset_t` to a vtable. This is a signed version of
|
|
||||||
`uoffset_t`, since vtables may be stored anywhere relative to the object.
|
|
||||||
This offset is subtracted (not added) from the object start to arrive at
|
|
||||||
the vtable start. This offset is followed by all the
|
|
||||||
fields as aligned scalars (or offsets). Unlike structs, not all fields
|
|
||||||
need to be present. There is no set order and layout. A table may contain
|
|
||||||
field offsets that point to the same value if the user explicitly
|
|
||||||
serializes the same offset twice.
|
|
||||||
|
|
||||||
To be able to access fields regardless of these uncertainties, we go
|
|
||||||
through a vtable of offsets. Vtables are shared between any objects that
|
|
||||||
happen to have the same vtable values.
|
|
||||||
|
|
||||||
The elements of a vtable are all of type `voffset_t`, which is
|
|
||||||
a `uint16_t`. The first element is the size of the vtable in bytes,
|
|
||||||
including the size element. The second one is the size of the object, in bytes
|
|
||||||
(including the vtable offset). This size could be used for streaming, to know
|
|
||||||
how many bytes to read to be able to access all *inline* fields of the object.
|
|
||||||
The remaining elements are the N offsets, where N is the amount of fields
|
|
||||||
declared in the schema when the code that constructed this buffer was
|
|
||||||
compiled (thus, the size of the table is N + 2).
|
|
||||||
|
|
||||||
All accessor functions in the generated code for tables contain the
|
|
||||||
offset into this table as a constant. This offset is checked against the
|
|
||||||
first field (the number of elements), to protect against newer code
|
|
||||||
reading older data. If this offset is out of range, or the vtable entry
|
|
||||||
is 0, that means the field is not present in this object, and the
|
|
||||||
default value is return. Otherwise, the entry is used as offset to the
|
|
||||||
field to be read.
|
|
||||||
|
|
||||||
### Unions
|
|
||||||
|
|
||||||
Unions are encoded as the combination of two fields: an enum representing the
|
|
||||||
union choice and the offset to the actual element. FlatBuffers reserves the
|
|
||||||
enumeration constant `NONE` (encoded as 0) to mean that the union field is not
|
|
||||||
set.
|
|
||||||
|
|
||||||
### Strings and Vectors
|
|
||||||
|
|
||||||
Strings are simply a vector of bytes, and are always
|
|
||||||
null-terminated. Vectors are stored as contiguous aligned scalar
|
|
||||||
elements prefixed by a 32bit element count (not including any
|
|
||||||
null termination). Neither is stored inline in their parent, but are referred to
|
|
||||||
by offset. A vector may consist of more than one offset pointing to the same
|
|
||||||
value if the user explicitly serializes the same offset twice.
|
|
||||||
|
|
||||||
### Construction
|
|
||||||
|
|
||||||
The current implementation constructs these buffers backwards (starting
|
|
||||||
at the highest memory address of the buffer), since
|
|
||||||
that significantly reduces the amount of bookkeeping and simplifies the
|
|
||||||
construction API.
|
|
||||||
|
|
||||||
### Code example
|
|
||||||
|
|
||||||
Here's an example of the code that gets generated for the `samples/monster.fbs`.
|
|
||||||
What follows is the entire file, broken up by comments:
|
|
||||||
|
|
||||||
// automatically generated, do not modify
|
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
|
|
||||||
namespace MyGame {
|
|
||||||
namespace Sample {
|
|
||||||
|
|
||||||
Nested namespace support.
|
|
||||||
|
|
||||||
enum {
|
|
||||||
Color_Red = 0,
|
|
||||||
Color_Green = 1,
|
|
||||||
Color_Blue = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char **EnumNamesColor() {
|
|
||||||
static const char *names[] = { "Red", "Green", "Blue", nullptr };
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *EnumNameColor(int e) { return EnumNamesColor()[e]; }
|
|
||||||
|
|
||||||
Enums and convenient reverse lookup.
|
|
||||||
|
|
||||||
enum {
|
|
||||||
Any_NONE = 0,
|
|
||||||
Any_Monster = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char **EnumNamesAny() {
|
|
||||||
static const char *names[] = { "NONE", "Monster", nullptr };
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *EnumNameAny(int e) { return EnumNamesAny()[e]; }
|
|
||||||
|
|
||||||
Unions share a lot with enums.
|
|
||||||
|
|
||||||
struct Vec3;
|
|
||||||
struct Monster;
|
|
||||||
|
|
||||||
Predeclare all data types since circular references between types are allowed
|
|
||||||
(circular references between object are not, though).
|
|
||||||
|
|
||||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vec3 {
|
|
||||||
private:
|
|
||||||
float x_;
|
|
||||||
float y_;
|
|
||||||
float z_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Vec3(float x, float y, float z)
|
|
||||||
: x_(flatbuffers::EndianScalar(x)), y_(flatbuffers::EndianScalar(y)), z_(flatbuffers::EndianScalar(z)) {}
|
|
||||||
|
|
||||||
float x() const { return flatbuffers::EndianScalar(x_); }
|
|
||||||
float y() const { return flatbuffers::EndianScalar(y_); }
|
|
||||||
float z() const { return flatbuffers::EndianScalar(z_); }
|
|
||||||
};
|
|
||||||
FLATBUFFERS_STRUCT_END(Vec3, 12);
|
|
||||||
|
|
||||||
These ugly macros do a couple of things: they turn off any padding the compiler
|
|
||||||
might normally do, since we add padding manually (though none in this example),
|
|
||||||
and they enforce alignment chosen by FlatBuffers. This ensures the layout of
|
|
||||||
this struct will look the same regardless of compiler and platform. Note that
|
|
||||||
the fields are private: this is because these store little endian scalars
|
|
||||||
regardless of platform (since this is part of the serialized data).
|
|
||||||
`EndianScalar` then converts back and forth, which is a no-op on all current
|
|
||||||
mobile and desktop platforms, and a single machine instruction on the few
|
|
||||||
remaining big endian platforms.
|
|
||||||
|
|
||||||
struct Monster : private flatbuffers::Table {
|
|
||||||
const Vec3 *pos() const { return GetStruct<const Vec3 *>(4); }
|
|
||||||
int16_t mana() const { return GetField<int16_t>(6, 150); }
|
|
||||||
int16_t hp() const { return GetField<int16_t>(8, 100); }
|
|
||||||
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(10); }
|
|
||||||
const flatbuffers::Vector<uint8_t> *inventory() const { return GetPointer<const flatbuffers::Vector<uint8_t> *>(14); }
|
|
||||||
int8_t color() const { return GetField<int8_t>(16, 2); }
|
|
||||||
};
|
|
||||||
|
|
||||||
Tables are a bit more complicated. A table accessor struct is used to point at
|
|
||||||
the serialized data for a table, which always starts with an offset to its
|
|
||||||
vtable. It derives from `Table`, which contains the `GetField` helper functions.
|
|
||||||
GetField takes a vtable offset, and a default value. It will look in the vtable
|
|
||||||
at that offset. If the offset is out of bounds (data from an older version) or
|
|
||||||
the vtable entry is 0, the field is not present and the default is returned.
|
|
||||||
Otherwise, it uses the entry as an offset into the table to locate the field.
|
|
||||||
|
|
||||||
struct MonsterBuilder {
|
|
||||||
flatbuffers::FlatBufferBuilder &fbb_;
|
|
||||||
flatbuffers::uoffset_t start_;
|
|
||||||
void add_pos(const Vec3 *pos) { fbb_.AddStruct(4, pos); }
|
|
||||||
void add_mana(int16_t mana) { fbb_.AddElement<int16_t>(6, mana, 150); }
|
|
||||||
void add_hp(int16_t hp) { fbb_.AddElement<int16_t>(8, hp, 100); }
|
|
||||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(10, name); }
|
|
||||||
void add_inventory(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory) { fbb_.AddOffset(14, inventory); }
|
|
||||||
void add_color(int8_t color) { fbb_.AddElement<int8_t>(16, color, 2); }
|
|
||||||
MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
|
||||||
flatbuffers::Offset<Monster> Finish() { return flatbuffers::Offset<Monster>(fbb_.EndTable(start_, 7)); }
|
|
||||||
};
|
|
||||||
|
|
||||||
`MonsterBuilder` is the base helper struct to construct a table using a
|
|
||||||
`FlatBufferBuilder`. You can add the fields in any order, and the `Finish`
|
|
||||||
call will ensure the correct vtable gets generated.
|
|
||||||
|
|
||||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
|
|
||||||
const Vec3 *pos, int16_t mana,
|
|
||||||
int16_t hp,
|
|
||||||
flatbuffers::Offset<flatbuffers::String> name,
|
|
||||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory,
|
|
||||||
int8_t color) {
|
|
||||||
MonsterBuilder builder_(_fbb);
|
|
||||||
builder_.add_inventory(inventory);
|
|
||||||
builder_.add_name(name);
|
|
||||||
builder_.add_pos(pos);
|
|
||||||
builder_.add_hp(hp);
|
|
||||||
builder_.add_mana(mana);
|
|
||||||
builder_.add_color(color);
|
|
||||||
return builder_.Finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
`CreateMonster` is a convenience function that calls all functions in
|
|
||||||
`MonsterBuilder` above for you. Note that if you pass values which are
|
|
||||||
defaults as arguments, it will not actually construct that field, so
|
|
||||||
you can probably use this function instead of the builder class in
|
|
||||||
almost all cases.
|
|
||||||
|
|
||||||
inline const Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot<Monster>(buf); }
|
|
||||||
|
|
||||||
This function is only generated for the root table type, to be able to
|
|
||||||
start traversing a FlatBuffer from a raw buffer pointer.
|
|
||||||
|
|
||||||
}; // namespace MyGame
|
|
||||||
}; // namespace Sample
|
|
||||||
|
|
||||||
### Encoding example.
|
|
||||||
|
|
||||||
Below is a sample encoding for the following JSON corresponding to the above
|
|
||||||
schema:
|
|
||||||
|
|
||||||
{ pos: { x: 1, y: 2, z: 3 }, name: "fred", hp: 50 }
|
|
||||||
|
|
||||||
Resulting in this binary buffer:
|
|
||||||
|
|
||||||
// Start of the buffer:
|
|
||||||
uint32_t 20 // Offset to the root table.
|
|
||||||
|
|
||||||
// Start of the vtable. Not shared in this example, but could be:
|
|
||||||
uint16_t 16 // Size of table, starting from here.
|
|
||||||
uint16_t 22 // Size of object inline data.
|
|
||||||
uint16_t 4, 0, 20, 16, 0, 0 // Offsets to fields from start of (root) table, 0 for not present.
|
|
||||||
|
|
||||||
// Start of the root table:
|
|
||||||
int32_t 16 // Offset to vtable used (default negative direction)
|
|
||||||
float 1, 2, 3 // the Vec3 struct, inline.
|
|
||||||
uint32_t 8 // Offset to the name string.
|
|
||||||
int16_t 50 // hp field.
|
|
||||||
int16_t 0 // Padding for alignment.
|
|
||||||
|
|
||||||
// Start of name string:
|
|
||||||
uint32_t 4 // Length of string.
|
|
||||||
int8_t 'f', 'r', 'e', 'd', 0, 0, 0, 0 // Text + 0 termination + padding.
|
|
||||||
|
|
||||||
Note that this not the only possible encoding, since the writer has some
|
|
||||||
flexibility in which of the children of root object to write first (though in
|
|
||||||
this case there's only one string), and what order to write the fields in.
|
|
||||||
Different orders may also cause different alignments to happen.
|
|
||||||
|
|
||||||
### Additional reading.
|
|
||||||
|
|
||||||
The author of the C language implementation has made a similar
|
|
||||||
[document](https://github.com/dvidelabs/flatcc/blob/master/doc/binary-format.md#flatbuffers-binary-format)
|
|
||||||
that may further help clarify the format.
|
|
||||||
|
|
||||||
# FlexBuffers
|
|
||||||
|
|
||||||
The [schema-less](@ref flexbuffers) version of FlatBuffers have their
|
|
||||||
own encoding, detailed here.
|
|
||||||
|
|
||||||
It shares many properties mentioned above, in that all data is accessed
|
|
||||||
over offsets, all scalars are aligned to their own size, and
|
|
||||||
all data is always stored in little endian format.
|
|
||||||
|
|
||||||
One difference is that FlexBuffers are built front to back, so children are
|
|
||||||
stored before parents, and the root of the data starts at the last byte.
|
|
||||||
|
|
||||||
Another difference is that scalar data is stored with a variable number of bits
|
|
||||||
(8/16/32/64). The current width is always determined by the *parent*, i.e. if
|
|
||||||
the scalar sits in a vector, the vector determines the bit width for all
|
|
||||||
elements at once. Selecting the minimum bit width for a particular vector is
|
|
||||||
something the encoder does automatically and thus is typically of no concern
|
|
||||||
to the user, though being aware of this feature (and not sticking a double in
|
|
||||||
the same vector as a bunch of byte sized elements) is helpful for efficiency.
|
|
||||||
|
|
||||||
Unlike FlatBuffers there is only one kind of offset, and that is an unsigned
|
|
||||||
integer indicating the number of bytes in a negative direction from the address
|
|
||||||
of itself (where the offset is stored).
|
|
||||||
|
|
||||||
### Vectors
|
|
||||||
|
|
||||||
The representation of the vector is at the core of how FlexBuffers works (since
|
|
||||||
maps are really just a combination of 2 vectors), so it is worth starting there.
|
|
||||||
|
|
||||||
As mentioned, a vector is governed by a single bit width (supplied by its
|
|
||||||
parent). This includes the size field. For example, a vector that stores the
|
|
||||||
integer values `1, 2, 3` is encoded as follows:
|
|
||||||
|
|
||||||
uint8_t 3, 1, 2, 3, 4, 4, 4
|
|
||||||
|
|
||||||
The first `3` is the size field, and is placed before the vector (an offset
|
|
||||||
from the parent to this vector points to the first element, not the size
|
|
||||||
field, so the size field is effectively at index -1).
|
|
||||||
Since this is an untyped vector `SL_VECTOR`, it is followed by 3 type
|
|
||||||
bytes (one per element of the vector), which are always following the vector,
|
|
||||||
and are always a uint8_t even if the vector is made up of bigger scalars.
|
|
||||||
|
|
||||||
A vector may include more than one offset pointing to the same value if the
|
|
||||||
user explicitly serializes the same offset twice.
|
|
||||||
|
|
||||||
### Types
|
|
||||||
|
|
||||||
A type byte is made up of 2 components (see flexbuffers.h for exact values):
|
|
||||||
|
|
||||||
* 2 lower bits representing the bit-width of the child (8, 16, 32, 64).
|
|
||||||
This is only used if the child is accessed over an offset, such as a child
|
|
||||||
vector. It is ignored for inline types.
|
|
||||||
* 6 bits representing the actual type (see flexbuffers.h).
|
|
||||||
|
|
||||||
Thus, in this example `4` means 8 bit child (value 0, unused, since the value is
|
|
||||||
in-line), type `SL_INT` (value 1).
|
|
||||||
|
|
||||||
### Typed Vectors
|
|
||||||
|
|
||||||
These are like the Vectors above, but omit the type bytes. The type is instead
|
|
||||||
determined by the vector type supplied by the parent. Typed vectors are only
|
|
||||||
available for a subset of types for which these savings can be significant,
|
|
||||||
namely inline signed/unsigned integers (`TYPE_VECTOR_INT` / `TYPE_VECTOR_UINT`),
|
|
||||||
floats (`TYPE_VECTOR_FLOAT`), and keys (`TYPE_VECTOR_KEY`, see below).
|
|
||||||
|
|
||||||
Additionally, for scalars, there are fixed length vectors of sizes 2 / 3 / 4
|
|
||||||
that don't store the size (`TYPE_VECTOR_INT2` etc.), for an additional savings
|
|
||||||
in space when storing common vector or color data.
|
|
||||||
|
|
||||||
### Scalars
|
|
||||||
|
|
||||||
FlexBuffers supports integers (`TYPE_INT` and `TYPE_UINT`) and floats
|
|
||||||
(`TYPE_FLOAT`), available in the bit-widths mentioned above. They can be stored
|
|
||||||
both inline and over an offset (`TYPE_INDIRECT_*`).
|
|
||||||
|
|
||||||
The offset version is useful to encode costly 64bit (or even 32bit) quantities
|
|
||||||
into vectors / maps of smaller sizes, and to share / repeat a value multiple
|
|
||||||
times.
|
|
||||||
|
|
||||||
### Booleans and Nulls
|
|
||||||
|
|
||||||
Booleans (`TYPE_BOOL`) and nulls (`TYPE_NULL`) are encoded as inlined unsigned integers.
|
|
||||||
|
|
||||||
### Blobs, Strings and Keys.
|
|
||||||
|
|
||||||
A blob (`TYPE_BLOB`) is encoded similar to a vector, with one difference: the
|
|
||||||
elements are always `uint8_t`. The parent bit width only determines the width of
|
|
||||||
the size field, allowing blobs to be large without the elements being large.
|
|
||||||
|
|
||||||
Strings (`TYPE_STRING`) are similar to blobs, except they have an additional 0
|
|
||||||
termination byte for convenience, and they MUST be UTF-8 encoded (since an
|
|
||||||
accessor in a language that does not support pointers to UTF-8 data may have to
|
|
||||||
convert them to a native string type).
|
|
||||||
|
|
||||||
A "Key" (`TYPE_KEY`) is similar to a string, but doesn't store the size
|
|
||||||
field. They're so named because they are used with maps, which don't care
|
|
||||||
for the size, and can thus be even more compact. Unlike strings, keys cannot
|
|
||||||
contain bytes of value 0 as part of their data (size can only be determined by
|
|
||||||
`strlen`), so while you can use them outside the context of maps if you so
|
|
||||||
desire, you're usually better off with strings.
|
|
||||||
|
|
||||||
### Maps
|
|
||||||
|
|
||||||
A map (`TYPE_MAP`) is like an (untyped) vector, but with 2 prefixes before the
|
|
||||||
size field:
|
|
||||||
|
|
||||||
| index | field |
|
|
||||||
| ----: | :----------------------------------------------------------- |
|
|
||||||
| -3 | An offset to the keys vector (may be shared between tables). |
|
|
||||||
| -2 | Byte width of the keys vector. |
|
|
||||||
| -1 | Size (from here on it is compatible with `TYPE_VECTOR`) |
|
|
||||||
| 0 | Elements. |
|
|
||||||
| Size | Types. |
|
|
||||||
|
|
||||||
Since a map is otherwise the same as a vector, it can be iterated like
|
|
||||||
a vector (which is probably faster than lookup by key).
|
|
||||||
|
|
||||||
The keys vector is a typed vector of keys. Both the keys and corresponding
|
|
||||||
values *have* to be stored in sorted order (as determined by `strcmp`), such
|
|
||||||
that lookups can be made using binary search.
|
|
||||||
|
|
||||||
The reason the key vector is a separate structure from the value vector is
|
|
||||||
such that it can be shared between multiple value vectors, and also to
|
|
||||||
allow it to be treated as its own individual vector in code.
|
|
||||||
|
|
||||||
An example map { foo: 13, bar: 14 } would be encoded as:
|
|
||||||
|
|
||||||
0 : uint8_t 'b', 'a', 'r', 0
|
|
||||||
4 : uint8_t 'f', 'o', 'o', 0
|
|
||||||
8 : uint8_t 2 // key vector of size 2
|
|
||||||
// key vector offset points here
|
|
||||||
9 : uint8_t 9, 6 // offsets to bar_key and foo_key
|
|
||||||
11: uint8_t 2, 1 // offset to key vector, and its byte width
|
|
||||||
13: uint8_t 2 // value vector of size
|
|
||||||
// value vector offset points here
|
|
||||||
14: uint8_t 14, 13 // values
|
|
||||||
16: uint8_t 4, 4 // types
|
|
||||||
|
|
||||||
### The root
|
|
||||||
|
|
||||||
As mentioned, the root starts at the end of the buffer.
|
|
||||||
The last uint8_t is the width in bytes of the root (normally the parent
|
|
||||||
determines the width, but the root has no parent). The uint8_t before this is
|
|
||||||
the type of the root, and the bytes before that are the root value (of the
|
|
||||||
number of bytes specified by the last byte).
|
|
||||||
|
|
||||||
So for example, the integer value `13` as root would be:
|
|
||||||
|
|
||||||
uint8_t 13, 4, 1 // Value, type, root byte width.
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
@ -1,93 +0,0 @@
|
|||||||
Use in JavaScript {#flatbuffers_guide_use_javascript}
|
|
||||||
=================
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in JavaScript, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
|
||||||
general FlatBuffers usage in all of the supported languages
|
|
||||||
(including JavaScript). This page is specifically designed to cover the nuances
|
|
||||||
of FlatBuffers usage in JavaScript.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers JavaScript library code location
|
|
||||||
|
|
||||||
The generated code for the FlatBuffers JavaScript library can be found at
|
|
||||||
https://www.npmjs.com/package/flatbuffers. To use it from sources:
|
|
||||||
|
|
||||||
1. Run `npm run compile` from the main folder to generate JS files from TS.
|
|
||||||
1. In your project, install it as a normal dependency, using the flatbuffers
|
|
||||||
folder as the source.
|
|
||||||
|
|
||||||
## Using the FlatBuffers JavaScript library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers.*
|
|
||||||
|
|
||||||
Due to the complexity related with large amounts of JS flavors and module types,
|
|
||||||
native JS support has been replaced in 2.0 by transpilation from TypeScript.
|
|
||||||
|
|
||||||
Please look at [TypeScript usage](@ref flatbuffers_guide_use_typescript) and
|
|
||||||
transpile your sources to desired JS flavor. The minimal steps to get up and
|
|
||||||
running with JS are:
|
|
||||||
|
|
||||||
1. Generate TS files from `*.fbs` by using the `--ts` option.
|
|
||||||
1. Transpile resulting TS files to desired JS flavor using `tsc` (see
|
|
||||||
https://www.typescriptlang.org/download for installation instructions).
|
|
||||||
|
|
||||||
~~~{.js}
|
|
||||||
// Note: These require functions are an example - use your desired module flavor.
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var flatbuffers = require('../flatbuffers').flatbuffers;
|
|
||||||
var MyGame = require('./monster_generated').MyGame;
|
|
||||||
|
|
||||||
var data = new Uint8Array(fs.readFileSync('monster.dat'));
|
|
||||||
var buf = new flatbuffers.ByteBuffer(data);
|
|
||||||
|
|
||||||
var monster = MyGame.Example.Monster.getRootAsMonster(buf);
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
// Note: This code is an example of browser-based HTML/JavaScript. See above
|
|
||||||
// for the code using JavaScript module loaders (e.g. Node.js).
|
|
||||||
<script src="../js/flatbuffers.js"></script>
|
|
||||||
<script src="monster_generated.js"></script>
|
|
||||||
<script>
|
|
||||||
function readFile() {
|
|
||||||
var reader = new FileReader(); // This example uses the HTML5 FileReader.
|
|
||||||
var file = document.getElementById(
|
|
||||||
'file_input').files[0]; // "monster.dat" from the HTML <input> field.
|
|
||||||
|
|
||||||
reader.onload = function() { // Executes after the file is read.
|
|
||||||
var data = new Uint8Array(reader.result);
|
|
||||||
|
|
||||||
var buf = new flatbuffers.ByteBuffer(data);
|
|
||||||
|
|
||||||
var monster = MyGame.Example.Monster.getRootAsMonster(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.readAsArrayBuffer(file);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
// Open the HTML file in a browser and select "monster.dat" from with the
|
|
||||||
// <input> field.
|
|
||||||
<input type="file" id="file_input" onchange="readFile();">
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Now you can access values like this:
|
|
||||||
|
|
||||||
~~~{.js}
|
|
||||||
var hp = monster.hp();
|
|
||||||
var pos = monster.pos();
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Text parsing FlatBuffers in JavaScript
|
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
|
||||||
from JavaScript.
|
|
114
third_party/flatbuffers/docs/source/JavaUsage.md
vendored
@ -1,114 +0,0 @@
|
|||||||
Use in Java {#flatbuffers_guide_use_java}
|
|
||||||
==============
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in Java, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
|
||||||
general FlatBuffers usage in all of the supported languages (including Java).
|
|
||||||
This page is designed to cover the nuances of FlatBuffers usage,
|
|
||||||
specific to Java.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers Java code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers Java library can be found at
|
|
||||||
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
|
|
||||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
|
||||||
java/com/google/flatbuffers).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers Java libraries
|
|
||||||
|
|
||||||
The code to test the libraries can be found at `flatbuffers/tests`.
|
|
||||||
|
|
||||||
The test code for Java is located in [JavaTest.java](https://github.com/google
|
|
||||||
/flatbuffers/blob/master/tests/JavaTest.java).
|
|
||||||
|
|
||||||
To run the tests, use either [JavaTest.sh](https://github.com/google/
|
|
||||||
flatbuffers/blob/master/tests/JavaTest.sh) or [JavaTest.bat](https://github.com/
|
|
||||||
google/flatbuffers/blob/master/tests/JavaTest.bat), depending on your operating
|
|
||||||
system.
|
|
||||||
|
|
||||||
*Note: These scripts require that [Java](https://www.oracle.com/java/index.html)
|
|
||||||
is installed.*
|
|
||||||
|
|
||||||
## Using the FlatBuffers Java library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in Java.*
|
|
||||||
|
|
||||||
FlatBuffers supports reading and writing binary FlatBuffers in Java.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate Java classes from your
|
|
||||||
schema with the `--java` option to `flatc`.
|
|
||||||
Then you can include both FlatBuffers and the generated code to read
|
|
||||||
or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in Java:
|
|
||||||
First, import the library and generated code. Then, you read a FlatBuffer binary
|
|
||||||
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
|
|
||||||
pass to the `getRootAsMyRootType` function:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
|
||||||
import MyGame.Example.*;
|
|
||||||
import com.google.flatbuffers.FlatBufferBuilder;
|
|
||||||
|
|
||||||
// This snippet ignores exceptions for brevity.
|
|
||||||
File file = new File("monsterdata_test.mon");
|
|
||||||
RandomAccessFile f = new RandomAccessFile(file, "r");
|
|
||||||
byte[] data = new byte[(int)f.length()];
|
|
||||||
f.readFully(data);
|
|
||||||
f.close();
|
|
||||||
|
|
||||||
ByteBuffer bb = ByteBuffer.wrap(data);
|
|
||||||
Monster monster = Monster.getRootAsMonster(bb);
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now you can access the data from the `Monster monster`:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
|
||||||
short hp = monster.hp();
|
|
||||||
Vec3 pos = monster.pos();
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
## Storing dictionaries in a FlatBuffer
|
|
||||||
|
|
||||||
FlatBuffers doesn't support dictionaries natively, but there is support to
|
|
||||||
emulate their behavior with vectors and binary search, which means you
|
|
||||||
can have fast lookups directly from a FlatBuffer without having to unpack
|
|
||||||
your data into a `Dictionary` or similar.
|
|
||||||
|
|
||||||
To use it:
|
|
||||||
- Designate one of the fields in a table as the "key" field. You do this
|
|
||||||
by setting the `key` attribute on this field, e.g.
|
|
||||||
`name:string (key)`.
|
|
||||||
You may only have one key field, and it must be of string or scalar type.
|
|
||||||
- Write out tables of this type as usual, collect their offsets in an
|
|
||||||
array.
|
|
||||||
- Instead of calling standard generated method,
|
|
||||||
e.g.: `Monster.createTestarrayoftablesVector`,
|
|
||||||
call `createSortedVectorOfTables` (from the `FlatBufferBuilder` object).
|
|
||||||
which will first sort all offsets such that the tables they refer to
|
|
||||||
are sorted by the key field, then serialize it.
|
|
||||||
- Now when you're accessing the FlatBuffer, you can use
|
|
||||||
the `ByKey` accessor to access elements of the vector, e.g.:
|
|
||||||
`monster.testarrayoftablesByKey("Frodo")`.
|
|
||||||
which returns an object of the corresponding table type,
|
|
||||||
or `null` if not found.
|
|
||||||
`ByKey` performs a binary search, so should have a similar
|
|
||||||
speed to `Dictionary`, though may be faster because of better caching.
|
|
||||||
`ByKey` only works if the vector has been sorted, it will
|
|
||||||
likely not find elements if it hasn't been sorted.
|
|
||||||
|
|
||||||
## Text parsing
|
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
|
||||||
from Java, though you could use the C++ parser through native call
|
|
||||||
interfaces available to each language. Please see the
|
|
||||||
C++ documentation for more on text parsing.
|
|
||||||
|
|
||||||
<br>
|
|
@ -1,84 +0,0 @@
|
|||||||
Use in Kotlin {#flatbuffers_guide_use_kotlin}
|
|
||||||
==============
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in Kotlin, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
|
||||||
general FlatBuffers usage in all of the supported languages (including K).
|
|
||||||
|
|
||||||
This page is designed to cover the nuances of FlatBuffers usage, specific to Kotlin.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## Kotlin and FlatBuffers Java code location
|
|
||||||
|
|
||||||
Code generated for Kotlin currently uses the flatbuffers java runtime library. That means that Kotlin generated code can only have Java virtual machine as target architecture (which includes Android). Kotlin Native and Kotlin.js are currently not supported.
|
|
||||||
|
|
||||||
The code for the FlatBuffers Java library can be found at
|
|
||||||
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
|
|
||||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
|
||||||
java/com/google/flatbuffers).
|
|
||||||
|
|
||||||
## Testing FlatBuffers Kotlin
|
|
||||||
|
|
||||||
The test code for Java is located in [KotlinTest.java](https://github.com/google
|
|
||||||
/flatbuffers/blob/master/tests/KotlinTest.kt).
|
|
||||||
|
|
||||||
To run the tests, use [KotlinTest.sh](https://github.com/google/
|
|
||||||
flatbuffers/blob/master/tests/KotlinTest.sh) shell script.
|
|
||||||
|
|
||||||
*Note: These scripts require that [Kotlin](https://kotlinlang.org/) is installed.*
|
|
||||||
|
|
||||||
## Using the FlatBuffers Kotlin library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in Kotlin.*
|
|
||||||
|
|
||||||
FlatBuffers supports reading and writing binary FlatBuffers in Kotlin.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate Java classes from your
|
|
||||||
schema with the `--kotlin` option to `flatc`.
|
|
||||||
Then you can include both FlatBuffers and the generated code to read
|
|
||||||
or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in Kotlin:
|
|
||||||
First, import the library and generated code. Then, you read a FlatBuffer binary
|
|
||||||
file into a `ByteArray`. You then turn the `ByteArray` into a `ByteBuffer`, which you
|
|
||||||
pass to the `getRootAsMyRootType` function:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
|
|
||||||
import MyGame.Example.*
|
|
||||||
import com.google.flatbuffers.FlatBufferBuilder
|
|
||||||
|
|
||||||
// This snippet ignores exceptions for brevity.
|
|
||||||
val data = RandomAccessFile(File("monsterdata_test.mon"), "r").use {
|
|
||||||
val temp = ByteArray(it.length().toInt())
|
|
||||||
it.readFully(temp)
|
|
||||||
temp
|
|
||||||
}
|
|
||||||
|
|
||||||
val bb = ByteBuffer.wrap(data)
|
|
||||||
val monster = Monster.getRootAsMonster(bb)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now you can access the data from the `Monster monster`:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
|
|
||||||
val hp = monster.hp
|
|
||||||
val pos = monster.pos!!;
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Differences between Kotlin and Java code
|
|
||||||
|
|
||||||
Kotlin generated code was designed to be as close as possible to the java counterpart, as for now, we only support kotlin on java virtual machine. So the differences in implementation and usage are basically the ones introduced by the Kotlin language itself. You can find more in-depth information [here](https://kotlinlang.org/docs/reference/comparison-to-java.html).
|
|
||||||
|
|
||||||
The most obvious ones are:
|
|
||||||
|
|
||||||
* Fields as accessed as Kotlin [properties](https://kotlinlang.org/docs/reference/properties.html)
|
|
||||||
* Static methods are accessed in [companion object](https://kotlinlang.org/docs/reference/classes.html#companion-objects)
|
|
@ -1,85 +0,0 @@
|
|||||||
Use in Lobster {#flatbuffers_guide_use_lobster}
|
|
||||||
==============
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in Lobster, it should be noted that the
|
|
||||||
[Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to general
|
|
||||||
FlatBuffers usage in all of the supported languages (including Lobster). This
|
|
||||||
page is designed to cover the nuances of FlatBuffers usage, specific to
|
|
||||||
Lobster.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers Lobster library code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers Lobster library can be found at
|
|
||||||
`flatbuffers/lobster`. You can browse the library code on the
|
|
||||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
|
||||||
lobster).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers Lobster library
|
|
||||||
|
|
||||||
The code to test the Lobster library can be found at `flatbuffers/tests`.
|
|
||||||
The test code itself is located in [lobstertest.lobster](https://github.com/google/
|
|
||||||
flatbuffers/blob/master/tests/lobstertest.lobster).
|
|
||||||
|
|
||||||
To run the tests, run `lobster lobstertest.lobster`. To obtain Lobster itself,
|
|
||||||
go to the [Lobster homepage](http://strlen.com/lobster) or
|
|
||||||
[github](https://github.com/aardappel/lobster) to learn how to build it for your
|
|
||||||
platform.
|
|
||||||
|
|
||||||
## Using the FlatBuffers Lobster library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in Lobster.*
|
|
||||||
|
|
||||||
There is support for both reading and writing FlatBuffers in Lobster.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate Lobster classes from your
|
|
||||||
schema with the `--lobster` option to `flatc`. Then you can include both
|
|
||||||
FlatBuffers and the generated code to read or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in Lobster:
|
|
||||||
First, import the library and the generated code. Then read a FlatBuffer binary
|
|
||||||
file into a string, which you pass to the `GetRootAsMonster` function:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
|
|
||||||
include "monster_generated.lobster"
|
|
||||||
|
|
||||||
let fb = read_file("monsterdata_test.mon")
|
|
||||||
assert fb
|
|
||||||
let monster = MyGame_Example_GetRootAsMonster(fb)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now you can access values like this:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
|
|
||||||
let hp = monster.hp
|
|
||||||
let pos = monster.pos
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
As you can see, even though `hp` and `pos` are functions that access FlatBuffer
|
|
||||||
data in-place in the string buffer, they appear as field accesses.
|
|
||||||
|
|
||||||
## Speed
|
|
||||||
|
|
||||||
Using FlatBuffers in Lobster should be relatively fast, as the implementation
|
|
||||||
makes use of native support for writing binary values, and access of vtables.
|
|
||||||
Both generated code and the runtime library are therefore small and fast.
|
|
||||||
|
|
||||||
Actual speed will depend on whether you use Lobster as bytecode VM or compiled to
|
|
||||||
C++.
|
|
||||||
|
|
||||||
## Text Parsing
|
|
||||||
|
|
||||||
Lobster has full support for parsing JSON into FlatBuffers, or generating
|
|
||||||
JSON from FlatBuffers. See `samples/sample_test.lobster` for an example.
|
|
||||||
|
|
||||||
This uses the C++ parser and generator underneath, so should be both fast and
|
|
||||||
conformant.
|
|
||||||
|
|
||||||
<br>
|
|
81
third_party/flatbuffers/docs/source/LuaUsage.md
vendored
@ -1,81 +0,0 @@
|
|||||||
Use in Lua {#flatbuffers_guide_use_lua}
|
|
||||||
=============
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in Lua, it should be noted that the
|
|
||||||
[Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to general
|
|
||||||
FlatBuffers usage in all of the supported languages (including Lua). This
|
|
||||||
page is designed to cover the nuances of FlatBuffers usage, specific to
|
|
||||||
Lua.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers Lua library code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers Lua library can be found at
|
|
||||||
`flatbuffers/lua`. You can browse the library code on the
|
|
||||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/lua).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers Lua library
|
|
||||||
|
|
||||||
The code to test the Lua library can be found at `flatbuffers/tests`.
|
|
||||||
The test code itself is located in [luatest.lua](https://github.com/google/
|
|
||||||
flatbuffers/blob/master/tests/luatest.lua).
|
|
||||||
|
|
||||||
To run the tests, use the [LuaTest.sh](https://github.com/google/flatbuffers/
|
|
||||||
blob/master/tests/LuaTest.sh) shell script.
|
|
||||||
|
|
||||||
*Note: This script requires [Lua 5.3](https://www.lua.org/) and
|
|
||||||
[LuaJIT](http://luajit.org/) to be installed.*
|
|
||||||
|
|
||||||
## Using the FlatBuffers Lua library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in Lua.*
|
|
||||||
|
|
||||||
There is support for both reading and writing FlatBuffers in Lua.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate Lua classes from your
|
|
||||||
schema with the `--lua` option to `flatc`. Then you can include both
|
|
||||||
FlatBuffers and the generated code to read or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in Lua:
|
|
||||||
First, require the module and the generated code. Then read a FlatBuffer binary
|
|
||||||
file into a `string`, which you pass to the `GetRootAsMonster` function:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
|
|
||||||
-- require the library
|
|
||||||
local flatbuffers = require("flatbuffers")
|
|
||||||
|
|
||||||
-- require the generated code
|
|
||||||
local monster = require("MyGame.Sample.Monster")
|
|
||||||
|
|
||||||
-- read the flatbuffer from a file into a string
|
|
||||||
local f = io.open('monster.dat', 'rb')
|
|
||||||
local buf = f:read('*a')
|
|
||||||
f:close()
|
|
||||||
|
|
||||||
-- parse the flatbuffer to get an instance to the root monster
|
|
||||||
local monster1 = monster.GetRootAsMonster(buf, 0)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now you can access values like this:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
|
|
||||||
-- use the : notation to access member data
|
|
||||||
local hp = monster1:Hp()
|
|
||||||
local pos = monster1:Pos()
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
## Text Parsing
|
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
|
||||||
from Lua, though you could use the C++ parser through SWIG or ctypes. Please
|
|
||||||
see the C++ documentation for more on text parsing.
|
|
||||||
|
|
||||||
<br>
|
|
89
third_party/flatbuffers/docs/source/PHPUsage.md
vendored
@ -1,89 +0,0 @@
|
|||||||
Use in PHP {#flatbuffers_guide_use_php}
|
|
||||||
==========
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in PHP, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
|
||||||
general FlatBuffers usage in all of the supported languages
|
|
||||||
(including PHP). This page is specifically designed to cover the nuances of
|
|
||||||
FlatBuffers usage in PHP.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers PHP library code location
|
|
||||||
|
|
||||||
The code for FlatBuffers PHP library can be found at `flatbuffers/php`. You
|
|
||||||
can browse the library code on the [FlatBuffers
|
|
||||||
GitHub page](https://github.com/google/flatbuffers/tree/master/php).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers JavaScript library
|
|
||||||
|
|
||||||
The code to test the PHP library can be found at `flatbuffers/tests`.
|
|
||||||
The test code itself is located in [phpTest.php](https://github.com/google/
|
|
||||||
flatbuffers/blob/master/tests/phpTest.php).
|
|
||||||
|
|
||||||
You can run the test with `php phpTest.php` from the command line.
|
|
||||||
|
|
||||||
*Note: The PHP test file requires
|
|
||||||
[PHP](http://php.net/manual/en/install.php) to be installed.*
|
|
||||||
|
|
||||||
## Using theFlatBuffers PHP library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in PHP.*
|
|
||||||
|
|
||||||
FlatBuffers supports both reading and writing FlatBuffers in PHP.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate PHP classes from your schema
|
|
||||||
with the `--php` option to `flatc`. Then you can include both FlatBuffers and
|
|
||||||
the generated code to read or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in PHP:
|
|
||||||
First, include the library and generated code (using the PSR `autoload`
|
|
||||||
function). Then you can read a FlatBuffer binary file, which you
|
|
||||||
pass the contents of to the `GetRootAsMonster` function:
|
|
||||||
|
|
||||||
~~~{.php}
|
|
||||||
// It is recommended that your use PSR autoload when using FlatBuffers in PHP.
|
|
||||||
// Here is an example:
|
|
||||||
function __autoload($class_name) {
|
|
||||||
// The last segment of the class name matches the file name.
|
|
||||||
$class = substr($class_name, strrpos($class_name, "\\") + 1);
|
|
||||||
$root_dir = join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)))); // `flatbuffers` root.
|
|
||||||
|
|
||||||
// Contains the `*.php` files for the FlatBuffers library and the `flatc` generated files.
|
|
||||||
$paths = array(join(DIRECTORY_SEPARATOR, array($root_dir, "php")),
|
|
||||||
join(DIRECTORY_SEPARATOR, array($root_dir, "tests", "MyGame", "Example")));
|
|
||||||
foreach ($paths as $path) {
|
|
||||||
$file = join(DIRECTORY_SEPARATOR, array($path, $class . ".php"));
|
|
||||||
if (file_exists($file)) {
|
|
||||||
require($file);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the contents of the FlatBuffer binary file.
|
|
||||||
$filename = "monster.dat";
|
|
||||||
$handle = fopen($filename, "rb");
|
|
||||||
$contents = $fread($handle, filesize($filename));
|
|
||||||
fclose($handle);
|
|
||||||
|
|
||||||
// Pass the contents to `GetRootAsMonster`.
|
|
||||||
$monster = \MyGame\Example\Monster::GetRootAsMonster($contents);
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Now you can access values like this:
|
|
||||||
|
|
||||||
~~~{.php}
|
|
||||||
$hp = $monster->GetHp();
|
|
||||||
$pos = $monster->GetPos();
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Text Parsing
|
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
|
||||||
from PHP.
|
|
100
third_party/flatbuffers/docs/source/PythonUsage.md
vendored
@ -1,100 +0,0 @@
|
|||||||
Use in Python {#flatbuffers_guide_use_python}
|
|
||||||
=============
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in Python, it should be noted that the
|
|
||||||
[Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to general
|
|
||||||
FlatBuffers usage in all of the supported languages (including Python). This
|
|
||||||
page is designed to cover the nuances of FlatBuffers usage, specific to
|
|
||||||
Python.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers Python library code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers Python library can be found at
|
|
||||||
`flatbuffers/python/flatbuffers`. You can browse the library code on the
|
|
||||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
|
||||||
python).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers Python library
|
|
||||||
|
|
||||||
The code to test the Python library can be found at `flatbuffers/tests`.
|
|
||||||
The test code itself is located in [py_test.py](https://github.com/google/
|
|
||||||
flatbuffers/blob/master/tests/py_test.py).
|
|
||||||
|
|
||||||
To run the tests, use the [PythonTest.sh](https://github.com/google/flatbuffers/
|
|
||||||
blob/master/tests/PythonTest.sh) shell script.
|
|
||||||
|
|
||||||
*Note: This script requires [python](https://www.python.org/) to be
|
|
||||||
installed.*
|
|
||||||
|
|
||||||
## Using the FlatBuffers Python library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in Python.*
|
|
||||||
|
|
||||||
There is support for both reading and writing FlatBuffers in Python.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate Python classes from your
|
|
||||||
schema with the `--python` option to `flatc`. Then you can include both
|
|
||||||
FlatBuffers and the generated code to read or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in Python:
|
|
||||||
First, import the library and the generated code. Then read a FlatBuffer binary
|
|
||||||
file into a `bytearray`, which you pass to the `GetRootAsMonster` function:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
|
|
||||||
import MyGame.Example as example
|
|
||||||
import flatbuffers
|
|
||||||
|
|
||||||
buf = open('monster.dat', 'rb').read()
|
|
||||||
buf = bytearray(buf)
|
|
||||||
monster = example.GetRootAsMonster(buf, 0)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now you can access values like this:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
|
|
||||||
hp = monster.Hp()
|
|
||||||
pos = monster.Pos()
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
## Support for Numpy arrays
|
|
||||||
|
|
||||||
The Flatbuffers python library also has support for accessing scalar
|
|
||||||
vectors as numpy arrays. This can be orders of magnitude faster than
|
|
||||||
iterating over the vector one element at a time, and is particularly
|
|
||||||
useful when unpacking large nested flatbuffers. The generated code for
|
|
||||||
a scalar vector will have a method `<vector name>AsNumpy()`. In the
|
|
||||||
case of the Monster example, you could access the inventory vector
|
|
||||||
like this:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
|
|
||||||
inventory = monster.InventoryAsNumpy()
|
|
||||||
# inventory is a numpy array of type np.dtype('uint8')
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
instead of
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
|
|
||||||
inventory = []
|
|
||||||
for i in range(monster.InventoryLength()):
|
|
||||||
inventory.append(int(monster.Inventory(i)))
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Numpy is not a requirement. If numpy is not installed on your system,
|
|
||||||
then attempting to access one of the `*asNumpy()` methods will result
|
|
||||||
in a `NumpyRequiredForThisFeature` exception.
|
|
||||||
|
|
||||||
## Text Parsing
|
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
|
||||||
from Python, though you could use the C++ parser through SWIG or ctypes. Please
|
|
||||||
see the C++ documentation for more on text parsing.
|
|
||||||
|
|
||||||
<br>
|
|
@ -1,32 +0,0 @@
|
|||||||
## Prerequisites
|
|
||||||
|
|
||||||
To generate the docs for FlatBuffers from the source files, you
|
|
||||||
will first need to install two programs.
|
|
||||||
|
|
||||||
1. You will need to install `doxygen`. See
|
|
||||||
[Download Doxygen](https://doxygen.nl/download.html).
|
|
||||||
|
|
||||||
2. You will need to install `doxypypy` to format python comments appropriately.
|
|
||||||
Install it from [here](https://github.com/Feneric/doxypypy).
|
|
||||||
|
|
||||||
*Note: You will need both `doxygen` and `doxypypy` to be in your
|
|
||||||
[PATH](https://en.wikipedia.org/wiki/PATH_(variable)) environment variable.*
|
|
||||||
|
|
||||||
After you have both of those files installed and in your path, you need to
|
|
||||||
set up the `py_filter` to invoke `doxypypy` from `doxygen`.
|
|
||||||
|
|
||||||
Follow the steps
|
|
||||||
[here](https://github.com/Feneric/doxypypy#invoking-doxypypy-from-doxygen).
|
|
||||||
|
|
||||||
## Generating Docs
|
|
||||||
|
|
||||||
Run the following commands to generate the docs:
|
|
||||||
|
|
||||||
`cd flatbuffers/docs/source`
|
|
||||||
`doxygen`
|
|
||||||
|
|
||||||
The output is placed in `flatbuffers/docs/html`.
|
|
||||||
|
|
||||||
*Note: The Go API Reference code must be generated ahead of time. For
|
|
||||||
instructions on how to regenerated this file, please read the comments
|
|
||||||
in `GoApi.md`.*
|
|
186
third_party/flatbuffers/docs/source/RustUsage.md
vendored
@ -1,186 +0,0 @@
|
|||||||
Use in Rust {#flatbuffers_guide_use_rust}
|
|
||||||
==========
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in Rust, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
|
||||||
to general FlatBuffers usage in all of the supported languages (including Rust).
|
|
||||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
|
||||||
Rust.
|
|
||||||
|
|
||||||
#### Prerequisites
|
|
||||||
|
|
||||||
This page assumes you have written a FlatBuffers schema and compiled it
|
|
||||||
with the Schema Compiler. If you have not, please see
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
|
|
||||||
and [Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't
|
|
||||||
matter), you've generated a Rust file called `mygame_generated.rs` using the
|
|
||||||
compiler (e.g. `flatc --rust mygame.fbs` or via helpers listed in "Useful
|
|
||||||
tools created by others" section bellow), you can now start using this in
|
|
||||||
your program by including the file. As noted, this header relies on the crate
|
|
||||||
`flatbuffers`, which should be in your include `Cargo.toml`.
|
|
||||||
|
|
||||||
## FlatBuffers Rust library code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers Rust library can be found at
|
|
||||||
`flatbuffers/rust`. You can browse the library code on the
|
|
||||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/rust).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers Rust library
|
|
||||||
|
|
||||||
The code to test the Rust library can be found at `flatbuffers/tests/rust_usage_test`.
|
|
||||||
The test code itself is located in
|
|
||||||
[integration_test.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/tests/integration_test.rs)
|
|
||||||
|
|
||||||
This test file requires `flatc` to be present. To review how to build the project,
|
|
||||||
please read the [Building](@ref flatbuffers_guide_building) documentation.
|
|
||||||
|
|
||||||
To run the tests, execute `RustTest.sh` from the `flatbuffers/tests` directory.
|
|
||||||
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
|
|
||||||
run: `cd tests && ./RustTest.sh`.
|
|
||||||
|
|
||||||
*Note: The shell script requires [Rust](https://www.rust-lang.org) to
|
|
||||||
be installed.*
|
|
||||||
|
|
||||||
## Using the FlatBuffers Rust library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in Rust.*
|
|
||||||
|
|
||||||
FlatBuffers supports both reading and writing FlatBuffers in Rust.
|
|
||||||
|
|
||||||
To use FlatBuffers in your code, first generate the Rust modules from your
|
|
||||||
schema with the `--rust` option to `flatc`. Then you can import both FlatBuffers
|
|
||||||
and the generated code to read or write FlatBuffers.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in Rust:
|
|
||||||
First, include the library and generated code. Then read the file into
|
|
||||||
a `u8` vector, which you pass, as a byte slice, to `root_as_monster()`.
|
|
||||||
|
|
||||||
This full example program is available in the Rust test suite:
|
|
||||||
[monster_example.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/bin/monster_example.rs)
|
|
||||||
|
|
||||||
It can be run by `cd`ing to the `rust_usage_test` directory and executing: `cargo run monster_example`.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
|
|
||||||
extern crate flatbuffers;
|
|
||||||
|
|
||||||
#[allow(dead_code, unused_imports)]
|
|
||||||
#[path = "../../monster_test_generated.rs"]
|
|
||||||
mod monster_test_generated;
|
|
||||||
pub use monster_test_generated::my_game;
|
|
||||||
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut f = std::fs::File::open("../monsterdata_test.mon").unwrap();
|
|
||||||
let mut buf = Vec::new();
|
|
||||||
f.read_to_end(&mut buf).expect("file reading failed");
|
|
||||||
|
|
||||||
let monster = my_game::example::root_as_monster(&buf[..]);
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
`monster` is of type `Monster`, and points to somewhere *inside* your
|
|
||||||
buffer (root object pointers are not the same as `buffer_pointer` !).
|
|
||||||
If you look in your generated header, you'll see it has
|
|
||||||
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
|
|
||||||
println!("{}", monster.hp()); // `80`
|
|
||||||
println!("{}", monster.mana()); // default value of `150`
|
|
||||||
println!("{:?}", monster.name()); // Some("MyMonster")
|
|
||||||
}
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
*Note: That we never stored a `mana` value, so it will return the default.*
|
|
||||||
|
|
||||||
## Direct memory access
|
|
||||||
|
|
||||||
As you can see from the above examples, all elements in a buffer are
|
|
||||||
accessed through generated accessors. This is because everything is
|
|
||||||
stored in little endian format on all platforms (the accessor
|
|
||||||
performs a swap operation on big endian machines), and also because
|
|
||||||
the layout of things is generally not known to the user.
|
|
||||||
|
|
||||||
For structs, layout is deterministic and guaranteed to be the same
|
|
||||||
across platforms (scalars are aligned to their
|
|
||||||
own size, and structs themselves to their largest member), and you
|
|
||||||
are allowed to access this memory directly by using `safe_slice`
|
|
||||||
on the reference to a struct, or even an array of structs.
|
|
||||||
|
|
||||||
To compute offsets to sub-elements of a struct, make sure they
|
|
||||||
are structs themselves, as then you can use the pointers to
|
|
||||||
figure out the offset without having to hardcode it. This is
|
|
||||||
handy for use of arrays of structs with calls like `glVertexAttribPointer`
|
|
||||||
in OpenGL or similar APIs.
|
|
||||||
|
|
||||||
It is important to note is that structs are still little endian on all
|
|
||||||
machines, so the functions to enable tricks like this are only exposed on little
|
|
||||||
endian machines. If you also ship on big endian machines, using an
|
|
||||||
`#[cfg(target_endian = "little")]` attribute would be wise or your code will not
|
|
||||||
compile.
|
|
||||||
|
|
||||||
The special function `safe_slice` is implemented on Vector objects that are
|
|
||||||
represented in memory the same way as they are represented on the wire. This
|
|
||||||
function is always available on vectors of struct, bool, u8, and i8. It is
|
|
||||||
conditionally-compiled on little-endian systems for all the remaining scalar
|
|
||||||
types.
|
|
||||||
|
|
||||||
The FlatBufferBuilder function `create_vector_direct` is implemented for all
|
|
||||||
types that are endian-safe to write with a `memcpy`. It is the write-equivalent
|
|
||||||
of `safe_slice`.
|
|
||||||
|
|
||||||
## Access of untrusted buffers
|
|
||||||
|
|
||||||
The safe Rust functions to interpret a slice as a table (`root`,
|
|
||||||
`size_prefixed_root`, `root_with_opts`, and `size_prefixed_root_with_opts`)
|
|
||||||
verify the data first. This has some performance cost, but is intended to be
|
|
||||||
safe for use on flatbuffers from untrusted sources. There are corresponding
|
|
||||||
`unsafe` versions with names ending in `_unchecked` which skip this
|
|
||||||
verification, and may access arbitrary memory.
|
|
||||||
|
|
||||||
The generated accessor functions access fields over offsets, which is
|
|
||||||
very quick. The current implementation uses these to access memory without any
|
|
||||||
further bounds checking. All of the safe Rust APIs ensure the verifier is run
|
|
||||||
over these flatbuffers before accessing them.
|
|
||||||
|
|
||||||
When you're processing large amounts of data from a source you know (e.g.
|
|
||||||
your own generated data on disk), the `_unchecked` versions are acceptable, but
|
|
||||||
when reading data from the network that can potentially have been modified by an
|
|
||||||
attacker, it is desirable to use the safe versions which use the verifier.
|
|
||||||
|
|
||||||
## Threading
|
|
||||||
|
|
||||||
Reading a FlatBuffer does not touch any memory outside the original buffer,
|
|
||||||
and is entirely read-only (all immutable), so is safe to access from multiple
|
|
||||||
threads even without synchronisation primitives.
|
|
||||||
|
|
||||||
Creating a FlatBuffer is not thread safe. All state related to building
|
|
||||||
a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
|
|
||||||
outside of it is touched. To make this thread safe, either do not
|
|
||||||
share instances of FlatBufferBuilder between threads (recommended), or
|
|
||||||
manually wrap it in synchronisation primitives. There's no automatic way to
|
|
||||||
accomplish this, by design, as we feel multithreaded construction
|
|
||||||
of a single buffer will be rare, and synchronisation overhead would be costly.
|
|
||||||
|
|
||||||
Unlike most other languages, in Rust these properties are exposed to and
|
|
||||||
enforced by the type system. `flatbuffers::Table` and the generated table types
|
|
||||||
are `Send + Sync`, indicating they may be freely shared across threads and data
|
|
||||||
may be accessed from any thread which receives a const (aka shared) reference.
|
|
||||||
There are no functions which require a mutable (aka exclusive) reference, which
|
|
||||||
means all the available functions may be called like this.
|
|
||||||
`flatbuffers::FlatBufferBuilder` is also `Send + Sync`, but all of the mutating
|
|
||||||
functions require a mutable (aka exclusive) reference which can only be created
|
|
||||||
when no other references to the `FlatBufferBuilder` exist, and may not be copied
|
|
||||||
within the same thread, let alone to a second thread.
|
|
||||||
|
|
||||||
## Useful tools created by others
|
|
||||||
|
|
||||||
* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler
|
|
||||||
(flatc) as API for transparent `.fbs` to `.rs` code-generation via Cargo
|
|
||||||
build scripts integration.
|
|
||||||
|
|
||||||
<br>
|
|
685
third_party/flatbuffers/docs/source/Schemas.md
vendored
@ -1,685 +0,0 @@
|
|||||||
Writing a schema {#flatbuffers_guide_writing_schema}
|
|
||||||
================
|
|
||||||
|
|
||||||
The syntax of the schema language (aka IDL, [Interface Definition Language][])
|
|
||||||
should look quite familiar to users of any of the C family of
|
|
||||||
languages, and also to users of other IDLs. Let's look at an example
|
|
||||||
first:
|
|
||||||
|
|
||||||
// example IDL file
|
|
||||||
|
|
||||||
namespace MyGame;
|
|
||||||
|
|
||||||
attribute "priority";
|
|
||||||
|
|
||||||
enum Color : byte { Red = 1, Green, Blue }
|
|
||||||
|
|
||||||
union Any { Monster, Weapon, Pickup }
|
|
||||||
|
|
||||||
struct Vec3 {
|
|
||||||
x:float;
|
|
||||||
y:float;
|
|
||||||
z:float;
|
|
||||||
}
|
|
||||||
|
|
||||||
table Monster {
|
|
||||||
pos:Vec3;
|
|
||||||
mana:short = 150;
|
|
||||||
hp:short = 100;
|
|
||||||
name:string;
|
|
||||||
friendly:bool = false (deprecated, priority: 1);
|
|
||||||
inventory:[ubyte];
|
|
||||||
color:Color = Blue;
|
|
||||||
test:Any;
|
|
||||||
}
|
|
||||||
|
|
||||||
root_type Monster;
|
|
||||||
|
|
||||||
(`Weapon` & `Pickup` not defined as part of this example).
|
|
||||||
|
|
||||||
### Tables
|
|
||||||
|
|
||||||
Tables are the main way of defining objects in FlatBuffers, and consist of a
|
|
||||||
name (here `Monster`) and a list of fields. Each field has a name, a type, and
|
|
||||||
optionally a default value. If the default value is not specified in the schema,
|
|
||||||
it will be `0` for scalar types, or `null` for other types. Some languages
|
|
||||||
support setting a scalar's default to `null`. This makes the scalar optional.
|
|
||||||
|
|
||||||
Fields do not have to appear in the wire representation, and you can choose
|
|
||||||
to omit fields when constructing an object. You have the flexibility to add
|
|
||||||
fields without fear of bloating your data. This design is also FlatBuffer's
|
|
||||||
mechanism for forward and backwards compatibility. Note that:
|
|
||||||
|
|
||||||
- You can add new fields in the schema ONLY at the end of a table
|
|
||||||
definition. Older data will still
|
|
||||||
read correctly, and give you the default value when read. Older code
|
|
||||||
will simply ignore the new field.
|
|
||||||
If you want to have flexibility to use any order for fields in your
|
|
||||||
schema, you can manually assign ids (much like Protocol Buffers),
|
|
||||||
see the `id` attribute below.
|
|
||||||
|
|
||||||
- You cannot delete fields you don't use anymore from the schema,
|
|
||||||
but you can simply
|
|
||||||
stop writing them into your data for almost the same effect.
|
|
||||||
Additionally you can mark them as `deprecated` as in the example
|
|
||||||
above, which will prevent the generation of accessors in the
|
|
||||||
generated C++, as a way to enforce the field not being used any more.
|
|
||||||
(careful: this may break code!).
|
|
||||||
|
|
||||||
- You may change field names and table names, if you're ok with your
|
|
||||||
code breaking until you've renamed them there too.
|
|
||||||
|
|
||||||
See "Schema evolution examples" below for more on this
|
|
||||||
topic.
|
|
||||||
|
|
||||||
### Structs
|
|
||||||
|
|
||||||
Similar to a table, only now none of the fields are optional (so no defaults
|
|
||||||
either), and fields may not be added or be deprecated. Structs may only contain
|
|
||||||
scalars or other structs. Use this for
|
|
||||||
simple objects where you are very sure no changes will ever be made
|
|
||||||
(as quite clear in the example `Vec3`). Structs use less memory than
|
|
||||||
tables and are even faster to access (they are always stored in-line in their
|
|
||||||
parent object, and use no virtual table).
|
|
||||||
|
|
||||||
### Types
|
|
||||||
|
|
||||||
Built-in scalar types are
|
|
||||||
|
|
||||||
- 8 bit: `byte` (`int8`), `ubyte` (`uint8`), `bool`
|
|
||||||
|
|
||||||
- 16 bit: `short` (`int16`), `ushort` (`uint16`)
|
|
||||||
|
|
||||||
- 32 bit: `int` (`int32`), `uint` (`uint32`), `float` (`float32`)
|
|
||||||
|
|
||||||
- 64 bit: `long` (`int64`), `ulong` (`uint64`), `double` (`float64`)
|
|
||||||
|
|
||||||
The type names in parentheses are alias names such that for example
|
|
||||||
`uint8` can be used in place of `ubyte`, and `int32` can be used in
|
|
||||||
place of `int` without affecting code generation.
|
|
||||||
|
|
||||||
Built-in non-scalar types:
|
|
||||||
|
|
||||||
- Vector of any other type (denoted with `[type]`). Nesting vectors
|
|
||||||
is not supported, instead you can wrap the inner vector in a table.
|
|
||||||
|
|
||||||
- `string`, which may only hold UTF-8 or 7-bit ASCII. For other text encodings
|
|
||||||
or general binary data use vectors (`[byte]` or `[ubyte]`) instead.
|
|
||||||
|
|
||||||
- References to other tables or structs, enums or unions (see
|
|
||||||
below).
|
|
||||||
|
|
||||||
You can't change types of fields once they're used, with the exception
|
|
||||||
of same-size data where a `reinterpret_cast` would give you a desirable result,
|
|
||||||
e.g. you could change a `uint` to an `int` if no values in current data use the
|
|
||||||
high bit yet.
|
|
||||||
|
|
||||||
### Arrays
|
|
||||||
|
|
||||||
Arrays are a convenience short-hand for a fixed-length collection of elements.
|
|
||||||
Arrays can be used to replace the following schema:
|
|
||||||
|
|
||||||
struct Vec3 {
|
|
||||||
x:float;
|
|
||||||
y:float;
|
|
||||||
z:float;
|
|
||||||
}
|
|
||||||
|
|
||||||
with the following schema:
|
|
||||||
|
|
||||||
struct Vec3 {
|
|
||||||
v:[float:3];
|
|
||||||
}
|
|
||||||
|
|
||||||
Both representations are binary equivalent.
|
|
||||||
|
|
||||||
Arrays are currently only supported in a `struct`.
|
|
||||||
|
|
||||||
### Default, Optional and Required Values
|
|
||||||
|
|
||||||
There are three, mutually exclusive, reactions to the non-presence of a table's
|
|
||||||
field in the binary data:
|
|
||||||
|
|
||||||
1. Default valued fields will return the default value (as defined in the schema).
|
|
||||||
2. Optional valued fields will return some form of `null` depending on the
|
|
||||||
local language. (In a sense, `null` is the default value).
|
|
||||||
3. Required fields will cause an error. Flatbuffer verifiers would
|
|
||||||
consider the whole buffer invalid. See the `required` tag below.
|
|
||||||
|
|
||||||
When writing a schema, values are a sequence of digits. Values may be optionally
|
|
||||||
followed by a decimal point (`.`) and more digits, for float constants, or
|
|
||||||
optionally prefixed by a `-`. Floats may also be in scientific notation;
|
|
||||||
optionally ending with an `e` or `E`, followed by a `+` or `-` and more digits.
|
|
||||||
Values can also be the keyword `null`.
|
|
||||||
|
|
||||||
Only scalar values can have defaults, non-scalar (string/vector/table) fields
|
|
||||||
default to `null` when not present.
|
|
||||||
|
|
||||||
You generally do not want to change default values after they're initially
|
|
||||||
defined. Fields that have the default value are not actually stored in the
|
|
||||||
serialized data (see also Gotchas below). Values explicitly written by code
|
|
||||||
generated by the old schema old version, if they happen to be the default, will
|
|
||||||
be read as a different value by code generated with the new schema. This is
|
|
||||||
slightly less bad when converting an optional scalar into a default valued
|
|
||||||
scalar since non-presence would not be overloaded with a previous default value.
|
|
||||||
There are situations, however, where this may be desirable, especially if you
|
|
||||||
can ensure a simultaneous rebuild of all code.
|
|
||||||
|
|
||||||
### Enums
|
|
||||||
|
|
||||||
Define a sequence of named constants, each with a given value, or
|
|
||||||
increasing by one from the previous one. The default first value
|
|
||||||
is `0`. As you can see in the enum declaration, you specify the underlying
|
|
||||||
integral type of the enum with `:` (in this case `byte`), which then determines
|
|
||||||
the type of any fields declared with this enum type.
|
|
||||||
|
|
||||||
Only integer types are allowed, i.e. `byte`, `ubyte`, `short` `ushort`, `int`,
|
|
||||||
`uint`, `long` and `ulong`.
|
|
||||||
|
|
||||||
Typically, enum values should only ever be added, never removed (there is no
|
|
||||||
deprecation for enums). This requires code to handle forwards compatibility
|
|
||||||
itself, by handling unknown enum values.
|
|
||||||
|
|
||||||
### Unions
|
|
||||||
|
|
||||||
Unions share a lot of properties with enums, but instead of new names
|
|
||||||
for constants, you use names of tables. You can then declare
|
|
||||||
a union field, which can hold a reference to any of those types, and
|
|
||||||
additionally a field with the suffix `_type` is generated that holds
|
|
||||||
the corresponding enum value, allowing you to know which type to cast
|
|
||||||
to at runtime.
|
|
||||||
|
|
||||||
It's possible to give an alias name to a type union. This way a type can even be
|
|
||||||
used to mean different things depending on the name used:
|
|
||||||
|
|
||||||
table PointPosition { x:uint; y:uint; }
|
|
||||||
table MarkerPosition {}
|
|
||||||
union Position {
|
|
||||||
Start:MarkerPosition,
|
|
||||||
Point:PointPosition,
|
|
||||||
Finish:MarkerPosition
|
|
||||||
}
|
|
||||||
|
|
||||||
Unions contain a special `NONE` marker to denote that no value is stored so that
|
|
||||||
name cannot be used as an alias.
|
|
||||||
|
|
||||||
Unions are a good way to be able to send multiple message types as a FlatBuffer.
|
|
||||||
Note that because a union field is really two fields, it must always be
|
|
||||||
part of a table, it cannot be the root of a FlatBuffer by itself.
|
|
||||||
|
|
||||||
If you have a need to distinguish between different FlatBuffers in a more
|
|
||||||
open-ended way, for example for use as files, see the file identification
|
|
||||||
feature below.
|
|
||||||
|
|
||||||
There is an experimental support only in C++ for a vector of unions (and
|
|
||||||
types). In the example IDL file above, use [Any] to add a vector of Any to
|
|
||||||
Monster table. There is also experimental support for other types besides
|
|
||||||
tables in unions, in particular structs and strings. There's no direct support
|
|
||||||
for scalars in unions, but they can be wrapped in a struct at no space cost.
|
|
||||||
|
|
||||||
### Namespaces
|
|
||||||
|
|
||||||
These will generate the corresponding namespace in C++ for all helper
|
|
||||||
code, and packages in Java. You can use `.` to specify nested namespaces /
|
|
||||||
packages.
|
|
||||||
|
|
||||||
### Includes
|
|
||||||
|
|
||||||
You can include other schemas files in your current one, e.g.:
|
|
||||||
|
|
||||||
include "mydefinitions.fbs";
|
|
||||||
|
|
||||||
This makes it easier to refer to types defined elsewhere. `include`
|
|
||||||
automatically ensures each file is parsed just once, even when referred to
|
|
||||||
more than once.
|
|
||||||
|
|
||||||
When using the `flatc` compiler to generate code for schema definitions,
|
|
||||||
only definitions in the current file will be generated, not those from the
|
|
||||||
included files (those you still generate separately).
|
|
||||||
|
|
||||||
### Root type
|
|
||||||
|
|
||||||
This declares what you consider to be the root table of the serialized
|
|
||||||
data. This is particularly important for parsing JSON data, which doesn't
|
|
||||||
include object type information.
|
|
||||||
|
|
||||||
### File identification and extension
|
|
||||||
|
|
||||||
Typically, a FlatBuffer binary buffer is not self-describing, i.e. it
|
|
||||||
needs you to know its schema to parse it correctly. But if you
|
|
||||||
want to use a FlatBuffer as a file format, it would be convenient
|
|
||||||
to be able to have a "magic number" in there, like most file formats
|
|
||||||
have, to be able to do a sanity check to see if you're reading the
|
|
||||||
kind of file you're expecting.
|
|
||||||
|
|
||||||
Now, you can always prefix a FlatBuffer with your own file header,
|
|
||||||
but FlatBuffers has a built-in way to add an identifier to a
|
|
||||||
FlatBuffer that takes up minimal space, and keeps the buffer
|
|
||||||
compatible with buffers that don't have such an identifier.
|
|
||||||
|
|
||||||
You can specify in a schema, similar to `root_type`, that you intend
|
|
||||||
for this type of FlatBuffer to be used as a file format:
|
|
||||||
|
|
||||||
file_identifier "MYFI";
|
|
||||||
|
|
||||||
Identifiers must always be exactly 4 characters long. These 4 characters
|
|
||||||
will end up as bytes at offsets 4-7 (inclusive) in the buffer.
|
|
||||||
|
|
||||||
For any schema that has such an identifier, `flatc` will automatically
|
|
||||||
add the identifier to any binaries it generates (with `-b`),
|
|
||||||
and generated calls like `FinishMonsterBuffer` also add the identifier.
|
|
||||||
If you have specified an identifier and wish to generate a buffer
|
|
||||||
without one, you can always still do so by calling
|
|
||||||
`FlatBufferBuilder::Finish` explicitly.
|
|
||||||
|
|
||||||
After loading a buffer, you can use a call like
|
|
||||||
`MonsterBufferHasIdentifier` to check if the identifier is present.
|
|
||||||
|
|
||||||
Note that this is best for open-ended uses such as files. If you simply wanted
|
|
||||||
to send one of a set of possible messages over a network for example, you'd
|
|
||||||
be better off with a union.
|
|
||||||
|
|
||||||
Additionally, by default `flatc` will output binary files as `.bin`.
|
|
||||||
This declaration in the schema will change that to whatever you want:
|
|
||||||
|
|
||||||
file_extension "ext";
|
|
||||||
|
|
||||||
### RPC interface declarations
|
|
||||||
|
|
||||||
You can declare RPC calls in a schema, that define a set of functions
|
|
||||||
that take a FlatBuffer as an argument (the request) and return a FlatBuffer
|
|
||||||
as the response (both of which must be table types):
|
|
||||||
|
|
||||||
rpc_service MonsterStorage {
|
|
||||||
Store(Monster):StoreResponse;
|
|
||||||
Retrieve(MonsterId):Monster;
|
|
||||||
}
|
|
||||||
|
|
||||||
What code this produces and how it is used depends on language and RPC system
|
|
||||||
used, there is preliminary support for GRPC through the `--grpc` code generator,
|
|
||||||
see `grpc/tests` for an example.
|
|
||||||
|
|
||||||
### Comments & documentation
|
|
||||||
|
|
||||||
May be written as in most C-based languages. Additionally, a triple
|
|
||||||
comment (`///`) on a line by itself signals that a comment is documentation
|
|
||||||
for whatever is declared on the line after it
|
|
||||||
(table/struct/field/enum/union/element), and the comment is output
|
|
||||||
in the corresponding C++ code. Multiple such lines per item are allowed.
|
|
||||||
|
|
||||||
### Attributes
|
|
||||||
|
|
||||||
Attributes may be attached to a declaration, behind a field/enum value,
|
|
||||||
or after the name of a table/struct/enum/union. These may either have
|
|
||||||
a value or not. Some attributes like `deprecated` are understood by
|
|
||||||
the compiler; user defined ones need to be declared with the attribute
|
|
||||||
declaration (like `priority` in the example above), and are
|
|
||||||
available to query if you parse the schema at runtime.
|
|
||||||
This is useful if you write your own code generators/editors etc., and
|
|
||||||
you wish to add additional information specific to your tool (such as a
|
|
||||||
help text).
|
|
||||||
|
|
||||||
Current understood attributes:
|
|
||||||
|
|
||||||
- `id: n` (on a table field): manually set the field identifier to `n`.
|
|
||||||
If you use this attribute, you must use it on ALL fields of this table,
|
|
||||||
and the numbers must be a contiguous range from 0 onwards.
|
|
||||||
Additionally, since a union type effectively adds two fields, its
|
|
||||||
id must be that of the second field (the first field is the type
|
|
||||||
field and not explicitly declared in the schema).
|
|
||||||
For example, if the last field before the union field had id 6,
|
|
||||||
the union field should have id 8, and the unions type field will
|
|
||||||
implicitly be 7.
|
|
||||||
IDs allow the fields to be placed in any order in the schema.
|
|
||||||
When a new field is added to the schema it must use the next available ID.
|
|
||||||
- `deprecated` (on a field): do not generate accessors for this field
|
|
||||||
anymore, code should stop using this data. Old data may still contain this
|
|
||||||
field, but it won't be accessible anymore by newer code. Note that if you
|
|
||||||
deprecate a field that was previous required, old code may fail to validate
|
|
||||||
new data (when using the optional verifier).
|
|
||||||
- `required` (on a non-scalar table field): this field must always be set.
|
|
||||||
By default, fields do not need to be present in the binary. This is
|
|
||||||
desirable, as it helps with forwards/backwards compatibility, and
|
|
||||||
flexibility of data structures. By specifying this attribute, you make non-
|
|
||||||
presence in an error for both reader and writer. The reading code may access
|
|
||||||
the field directly, without checking for null. If the constructing code does
|
|
||||||
not initialize this field, they will get an assert, and also the verifier
|
|
||||||
will fail on buffers that have missing required fields. Both adding and
|
|
||||||
removing this attribute may be forwards/backwards incompatible as readers
|
|
||||||
will be unable read old or new data, respectively, unless the data happens to
|
|
||||||
always have the field set.
|
|
||||||
- `force_align: size` (on a struct): force the alignment of this struct
|
|
||||||
to be something higher than what it is naturally aligned to. Causes
|
|
||||||
these structs to be aligned to that amount inside a buffer, IF that
|
|
||||||
buffer is allocated with that alignment (which is not necessarily
|
|
||||||
the case for buffers accessed directly inside a `FlatBufferBuilder`).
|
|
||||||
Note: currently not guaranteed to have an effect when used with
|
|
||||||
`--object-api`, since that may allocate objects at alignments less than
|
|
||||||
what you specify with `force_align`.
|
|
||||||
- `force_align: size` (on a vector): force the alignment of this vector to be
|
|
||||||
something different than what the element size would normally dictate.
|
|
||||||
Note: Now only work for generated C++ code.
|
|
||||||
- `bit_flags` (on an unsigned enum): the values of this field indicate bits,
|
|
||||||
meaning that any unsigned value N specified in the schema will end up
|
|
||||||
representing 1<<N, or if you don't specify values at all, you'll get
|
|
||||||
the sequence 1, 2, 4, 8, ...
|
|
||||||
- `nested_flatbuffer: "table_name"` (on a field): this indicates that the field
|
|
||||||
(which must be a vector of ubyte) contains flatbuffer data, for which the
|
|
||||||
root type is given by `table_name`. The generated code will then produce
|
|
||||||
a convenient accessor for the nested FlatBuffer.
|
|
||||||
- `flexbuffer` (on a field): this indicates that the field
|
|
||||||
(which must be a vector of ubyte) contains flexbuffer data. The generated
|
|
||||||
code will then produce a convenient accessor for the FlexBuffer root.
|
|
||||||
- `key` (on a field): this field is meant to be used as a key when sorting
|
|
||||||
a vector of the type of table it sits in. Can be used for in-place
|
|
||||||
binary search.
|
|
||||||
- `hash` (on a field). This is an (un)signed 32/64 bit integer field, whose
|
|
||||||
value during JSON parsing is allowed to be a string, which will then be
|
|
||||||
stored as its hash. The value of attribute is the hashing algorithm to
|
|
||||||
use, one of `fnv1_32` `fnv1_64` `fnv1a_32` `fnv1a_64`.
|
|
||||||
- `original_order` (on a table): since elements in a table do not need
|
|
||||||
to be stored in any particular order, they are often optimized for
|
|
||||||
space by sorting them to size. This attribute stops that from happening.
|
|
||||||
There should generally not be any reason to use this flag.
|
|
||||||
- 'native_*'. Several attributes have been added to support the [C++ object
|
|
||||||
Based API](@ref flatbuffers_cpp_object_based_api). All such attributes
|
|
||||||
are prefixed with the term "native_".
|
|
||||||
|
|
||||||
|
|
||||||
## JSON Parsing
|
|
||||||
|
|
||||||
The same parser that parses the schema declarations above is also able
|
|
||||||
to parse JSON objects that conform to this schema. So, unlike other JSON
|
|
||||||
parsers, this parser is strongly typed, and parses directly into a FlatBuffer
|
|
||||||
(see the compiler documentation on how to do this from the command line, or
|
|
||||||
the C++ documentation on how to do this at runtime).
|
|
||||||
|
|
||||||
Besides needing a schema, there are a few other changes to how it parses
|
|
||||||
JSON:
|
|
||||||
|
|
||||||
- It accepts field names with and without quotes, like many JSON parsers
|
|
||||||
already do. It outputs them without quotes as well, though can be made
|
|
||||||
to output them using the `strict_json` flag.
|
|
||||||
- If a field has an enum type, the parser will recognize symbolic enum
|
|
||||||
values (with or without quotes) instead of numbers, e.g.
|
|
||||||
`field: EnumVal`. If a field is of integral type, you can still use
|
|
||||||
symbolic names, but values need to be prefixed with their type and
|
|
||||||
need to be quoted, e.g. `field: "Enum.EnumVal"`. For enums
|
|
||||||
representing flags, you may place multiple inside a string
|
|
||||||
separated by spaces to OR them, e.g.
|
|
||||||
`field: "EnumVal1 EnumVal2"` or `field: "Enum.EnumVal1 Enum.EnumVal2"`.
|
|
||||||
- Similarly, for unions, these need to specified with two fields much like
|
|
||||||
you do when serializing from code. E.g. for a field `foo`, you must
|
|
||||||
add a field `foo_type: FooOne` right before the `foo` field, where
|
|
||||||
`FooOne` would be the table out of the union you want to use.
|
|
||||||
- A field that has the value `null` (e.g. `field: null`) is intended to
|
|
||||||
have the default value for that field (thus has the same effect as if
|
|
||||||
that field wasn't specified at all).
|
|
||||||
- It has some built in conversion functions, so you can write for example
|
|
||||||
`rad(180)` where ever you'd normally write `3.14159`.
|
|
||||||
Currently supports the following functions: `rad`, `deg`, `cos`, `sin`,
|
|
||||||
`tan`, `acos`, `asin`, `atan`.
|
|
||||||
|
|
||||||
When parsing JSON, it recognizes the following escape codes in strings:
|
|
||||||
|
|
||||||
- `\n` - linefeed.
|
|
||||||
- `\t` - tab.
|
|
||||||
- `\r` - carriage return.
|
|
||||||
- `\b` - backspace.
|
|
||||||
- `\f` - form feed.
|
|
||||||
- `\"` - double quote.
|
|
||||||
- `\\` - backslash.
|
|
||||||
- `\/` - forward slash.
|
|
||||||
- `\uXXXX` - 16-bit unicode code point, converted to the equivalent UTF-8
|
|
||||||
representation.
|
|
||||||
- `\xXX` - 8-bit binary hexadecimal number XX. This is the only one that is
|
|
||||||
not in the JSON spec (see http://json.org/), but is needed to be able to
|
|
||||||
encode arbitrary binary in strings to text and back without losing
|
|
||||||
information (e.g. the byte 0xFF can't be represented in standard JSON).
|
|
||||||
|
|
||||||
It also generates these escape codes back again when generating JSON from a
|
|
||||||
binary representation.
|
|
||||||
|
|
||||||
When parsing numbers, the parser is more flexible than JSON.
|
|
||||||
A format of numeric literals is more close to the C/C++.
|
|
||||||
According to the [grammar](@ref flatbuffers_grammar), it accepts the following
|
|
||||||
numerical literals:
|
|
||||||
|
|
||||||
- An integer literal can have any number of leading zero `0` digits.
|
|
||||||
Unlike C/C++, the parser ignores a leading zero, not interpreting it as the
|
|
||||||
beginning of the octal number.
|
|
||||||
The numbers `[081, -00094]` are equal to `[81, -94]` decimal integers.
|
|
||||||
- The parser accepts unsigned and signed hexadecimal integer numbers.
|
|
||||||
For example: `[0x123, +0x45, -0x67]` are equal to `[291, 69, -103]` decimals.
|
|
||||||
- The format of float-point numbers is fully compatible with C/C++ format.
|
|
||||||
If a modern C++ compiler is used the parser accepts hexadecimal and special
|
|
||||||
floating-point literals as well:
|
|
||||||
`[-1.0, 2., .3e0, 3.e4, 0x21.34p-5, -inf, nan]`.
|
|
||||||
|
|
||||||
The following conventions for floating-point numbers are used:
|
|
||||||
- The exponent suffix of hexadecimal floating-point number is mandatory.
|
|
||||||
- Parsed `NaN` converted to unsigned IEEE-754 `quiet-NaN` value.
|
|
||||||
|
|
||||||
Extended floating-point support was tested with:
|
|
||||||
- x64 Windows: `MSVC2015` and higher.
|
|
||||||
- x64 Linux: `LLVM 6.0`, `GCC 4.9` and higher.
|
|
||||||
|
|
||||||
For details, see [Use in C++](@ref flatbuffers_guide_use_cpp) section.
|
|
||||||
|
|
||||||
- For compatibility with a JSON lint tool all numeric literals of scalar
|
|
||||||
fields can be wrapped to quoted string:
|
|
||||||
`"1", "2.0", "0x48A", "0x0C.0Ep-1", "-inf", "true"`.
|
|
||||||
|
|
||||||
## Guidelines
|
|
||||||
|
|
||||||
### Efficiency
|
|
||||||
|
|
||||||
FlatBuffers is all about efficiency, but to realize that efficiency you
|
|
||||||
require an efficient schema. There are usually multiple choices on
|
|
||||||
how to represent data that have vastly different size characteristics.
|
|
||||||
|
|
||||||
It is very common nowadays to represent any kind of data as dictionaries
|
|
||||||
(as in e.g. JSON), because of its flexibility and extensibility. While
|
|
||||||
it is possible to emulate this in FlatBuffers (as a vector
|
|
||||||
of tables with key and value(s)), this is a bad match for a strongly
|
|
||||||
typed system like FlatBuffers, leading to relatively large binaries.
|
|
||||||
FlatBuffer tables are more flexible than classes/structs in most systems,
|
|
||||||
since having a large number of fields only few of which are actually
|
|
||||||
used is still efficient. You should thus try to organize your data
|
|
||||||
as much as possible such that you can use tables where you might be
|
|
||||||
tempted to use a dictionary.
|
|
||||||
|
|
||||||
Similarly, strings as values should only be used when they are
|
|
||||||
truly open-ended. If you can, always use an enum instead.
|
|
||||||
|
|
||||||
FlatBuffers doesn't have inheritance, so the way to represent a set
|
|
||||||
of related data structures is a union. Unions do have a cost however,
|
|
||||||
so an alternative to a union is to have a single table that has
|
|
||||||
all the fields of all the data structures you are trying to
|
|
||||||
represent, if they are relatively similar / share many fields.
|
|
||||||
Again, this is efficient because non-present fields are cheap.
|
|
||||||
|
|
||||||
FlatBuffers supports the full range of integer sizes, so try to pick
|
|
||||||
the smallest size needed, rather than defaulting to int/long.
|
|
||||||
|
|
||||||
Remember that you can share data (refer to the same string/table
|
|
||||||
within a buffer), so factoring out repeating data into its own
|
|
||||||
data structure may be worth it.
|
|
||||||
|
|
||||||
### Style guide
|
|
||||||
|
|
||||||
Identifiers in a schema are meant to translate to many different programming
|
|
||||||
languages, so using the style of your "main" language is generally a bad idea.
|
|
||||||
|
|
||||||
For this reason, below is a suggested style guide to adhere to, to keep schemas
|
|
||||||
consistent for interoperation regardless of the target language.
|
|
||||||
|
|
||||||
Where possible, the code generators for specific languages will generate
|
|
||||||
identifiers that adhere to the language style, based on the schema identifiers.
|
|
||||||
|
|
||||||
- Table, struct, enum and rpc names (types): UpperCamelCase.
|
|
||||||
- Table and struct field names: snake_case. This is translated to lowerCamelCase
|
|
||||||
automatically for some languages, e.g. Java.
|
|
||||||
- Enum values: UpperCamelCase.
|
|
||||||
- namespaces: UpperCamelCase.
|
|
||||||
|
|
||||||
Formatting (this is less important, but still worth adhering to):
|
|
||||||
|
|
||||||
- Opening brace: on the same line as the start of the declaration.
|
|
||||||
- Spacing: Indent by 2 spaces. None around `:` for types, on both sides for `=`.
|
|
||||||
|
|
||||||
For an example, see the schema at the top of this file.
|
|
||||||
|
|
||||||
## Gotchas
|
|
||||||
|
|
||||||
### Schemas and version control
|
|
||||||
|
|
||||||
FlatBuffers relies on new field declarations being added at the end, and earlier
|
|
||||||
declarations to not be removed, but be marked deprecated when needed. We think
|
|
||||||
this is an improvement over the manual number assignment that happens in
|
|
||||||
Protocol Buffers (and which is still an option using the `id` attribute
|
|
||||||
mentioned above).
|
|
||||||
|
|
||||||
One place where this is possibly problematic however is source control. If user
|
|
||||||
A adds a field, generates new binary data with this new schema, then tries to
|
|
||||||
commit both to source control after user B already committed a new field also,
|
|
||||||
and just auto-merges the schema, the binary files are now invalid compared to
|
|
||||||
the new schema.
|
|
||||||
|
|
||||||
The solution of course is that you should not be generating binary data before
|
|
||||||
your schema changes have been committed, ensuring consistency with the rest of
|
|
||||||
the world. If this is not practical for you, use explicit field ids, which
|
|
||||||
should always generate a merge conflict if two people try to allocate the same
|
|
||||||
id.
|
|
||||||
|
|
||||||
### Schema evolution examples (tables)
|
|
||||||
|
|
||||||
Some examples to clarify what happens as you change a schema:
|
|
||||||
|
|
||||||
If we have the following original schema:
|
|
||||||
|
|
||||||
table { a:int; b:int; }
|
|
||||||
|
|
||||||
And we extend it:
|
|
||||||
|
|
||||||
table { a:int; b:int; c:int; }
|
|
||||||
|
|
||||||
This is ok. Code compiled with the old schema reading data generated with the
|
|
||||||
new one will simply ignore the presence of the new field. Code compiled with the
|
|
||||||
new schema reading old data will get the default value for `c` (which is 0
|
|
||||||
in this case, since it is not specified).
|
|
||||||
|
|
||||||
table { a:int (deprecated); b:int; }
|
|
||||||
|
|
||||||
This is also ok. Code compiled with the old schema reading newer data will now
|
|
||||||
always get the default value for `a` since it is not present. Code compiled
|
|
||||||
with the new schema now cannot read nor write `a` anymore (any existing code
|
|
||||||
that tries to do so will result in compile errors), but can still read
|
|
||||||
old data (they will ignore the field).
|
|
||||||
|
|
||||||
table { c:int; a:int; b:int; }
|
|
||||||
|
|
||||||
This is NOT ok, as this makes the schemas incompatible. Old code reading newer
|
|
||||||
data will interpret `c` as if it was `a`, and new code reading old data
|
|
||||||
accessing `a` will instead receive `b`.
|
|
||||||
|
|
||||||
table { c:int (id: 2); a:int (id: 0); b:int (id: 1); }
|
|
||||||
|
|
||||||
This is ok. If your intent was to order/group fields in a way that makes sense
|
|
||||||
semantically, you can do so using explicit id assignment. Now we are compatible
|
|
||||||
with the original schema, and the fields can be ordered in any way, as long as
|
|
||||||
we keep the sequence of ids.
|
|
||||||
|
|
||||||
table { b:int; }
|
|
||||||
|
|
||||||
NOT ok. We can only remove a field by deprecation, regardless of whether we use
|
|
||||||
explicit ids or not.
|
|
||||||
|
|
||||||
table { a:uint; b:uint; }
|
|
||||||
|
|
||||||
This is MAYBE ok, and only in the case where the type change is the same size,
|
|
||||||
like here. If old data never contained any negative numbers, this will be
|
|
||||||
safe to do.
|
|
||||||
|
|
||||||
table { a:int = 1; b:int = 2; }
|
|
||||||
|
|
||||||
Generally NOT ok. Any older data written that had 0 values were not written to
|
|
||||||
the buffer, and rely on the default value to be recreated. These will now have
|
|
||||||
those values appear to `1` and `2` instead. There may be cases in which this
|
|
||||||
is ok, but care must be taken.
|
|
||||||
|
|
||||||
table { aa:int; bb:int; }
|
|
||||||
|
|
||||||
Occasionally ok. You've renamed fields, which will break all code (and JSON
|
|
||||||
files!) that use this schema, but as long as the change is obvious, this is not
|
|
||||||
incompatible with the actual binary buffers, since those only ever address
|
|
||||||
fields by id/offset.
|
|
||||||
|
|
||||||
#### Schema evolution examples (unions)
|
|
||||||
|
|
||||||
Suppose we have the following schema:
|
|
||||||
```
|
|
||||||
union Foo { A, B }
|
|
||||||
```
|
|
||||||
We can add another variant at the end.
|
|
||||||
```
|
|
||||||
union Foo { A, B, another_a: A }
|
|
||||||
```
|
|
||||||
and this will be okay. Old code will not recognize `another_a`.
|
|
||||||
However if we add `another_a` anywhere but the end, e.g.
|
|
||||||
```
|
|
||||||
union Foo { A, another_a: A, B }
|
|
||||||
```
|
|
||||||
this is not okay. When new code writes `another_a`, old code will
|
|
||||||
misinterpret it as `B` (and vice versa). However you can explicitly
|
|
||||||
set the union's "discriminant" value like so:
|
|
||||||
```
|
|
||||||
union Foo { A = 1, another_a: A = 3, B = 2 }
|
|
||||||
```
|
|
||||||
This is okay.
|
|
||||||
|
|
||||||
```
|
|
||||||
union Foo { original_a: A = 1, another_a: A = 3, B = 2 }
|
|
||||||
```
|
|
||||||
Renaming fields will break code and any saved human readable representations,
|
|
||||||
such as json files, but the binary buffers will be the same.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
### Testing whether a field is present in a table
|
|
||||||
|
|
||||||
Most serialization formats (e.g. JSON or Protocol Buffers) make it very
|
|
||||||
explicit in the format whether a field is present in an object or not,
|
|
||||||
allowing you to use this as "extra" information.
|
|
||||||
|
|
||||||
FlatBuffers will not write fields that are equal to their default value,
|
|
||||||
sometimes resulting in significant space savings. However, this also means we
|
|
||||||
cannot disambiguate the meaning of non-presence as "written default value" or
|
|
||||||
"not written at all". This only applies to scalar fields since only they support
|
|
||||||
default values. Unless otherwise specified, their default is 0.
|
|
||||||
|
|
||||||
If you care about the presence of scalars, most languages support "optional
|
|
||||||
scalars." You can set `null` as the default value in the schema. `null` is a
|
|
||||||
value that's outside of all types, so we will always write if `add_field` is
|
|
||||||
called. The generated field accessor should use the local language's canonical
|
|
||||||
optional type.
|
|
||||||
|
|
||||||
Some `FlatBufferBuilder` implementations have an option called `force_defaults`
|
|
||||||
that circumvents this "not writing defaults" behavior you can then use
|
|
||||||
`IsFieldPresent` to query presence.
|
|
||||||
/
|
|
||||||
Another option that works in all languages is to wrap a scalar field in a
|
|
||||||
struct. This way it will return null if it is not present. This will be slightly
|
|
||||||
less ergonomic but structs don't take up any more space than the scalar they
|
|
||||||
represent.
|
|
||||||
|
|
||||||
[Interface Definition Language]: https://en.wikipedia.org/wiki/Interface_description_language
|
|
||||||
|
|
||||||
## Writing your own code generator.
|
|
||||||
|
|
||||||
See [our intermediate representation](@ref intermediate_representation).
|
|
57
third_party/flatbuffers/docs/source/Support.md
vendored
@ -1,57 +0,0 @@
|
|||||||
Platform / Language / Feature support {#flatbuffers_support}
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
FlatBuffers is actively being worked on, which means that certain platform /
|
|
||||||
language / feature combinations may not be available yet.
|
|
||||||
|
|
||||||
This page tries to track those issues, to make informed decisions easier.
|
|
||||||
In general:
|
|
||||||
|
|
||||||
* Languages: language support beyond the ones created by the original
|
|
||||||
FlatBuffer authors typically depends on community contributions.
|
|
||||||
* Features: C++ was the first language supported, since our original
|
|
||||||
target was high performance game development. It thus has the richest
|
|
||||||
feature set, and is likely most robust. Other languages are catching up
|
|
||||||
however.
|
|
||||||
* Platforms: All language implementations are typically portable to most
|
|
||||||
platforms, unless where noted otherwise.
|
|
||||||
|
|
||||||
NOTE: this table is a start, it needs to be extended.
|
|
||||||
|
|
||||||
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust | Swift
|
|
||||||
------------------------------ | ------ | ----- | -------- | ----- | ------ | ----- | --- | ------ | --- | ------- | ------- | ------ | ------
|
|
||||||
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes | Yes
|
|
||||||
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No | No
|
|
||||||
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No | Yes
|
|
||||||
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No | No
|
|
||||||
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No | No
|
|
||||||
Native Object API | Yes | No | Yes | Yes | Yes | Yes | Yes | No | No | Yes | No | No | No
|
|
||||||
Optional Scalars | Yes | Yes | Yes | No | No | Yes | Yes | Yes | No | No | Yes | Yes | Yes
|
|
||||||
Flexbuffers | Yes | Yes | ? | ? | ? | ? | ? | ? | ? | ? | ? | Yes | ?
|
|
||||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
|
||||||
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes | No
|
|
||||||
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb | Great
|
|
||||||
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes | No
|
|
||||||
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
|
||||||
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
|
||||||
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | No
|
|
||||||
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | Yes
|
|
||||||
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ? | No
|
|
||||||
Primary authors (github) | aard | aard | ev/js/df | rw | rw | ew/ev | kr | mik | ch | df | aard | rw/cn | mi/mz
|
|
||||||
|
|
||||||
Above | Github username
|
|
||||||
----- | -----------------------------
|
|
||||||
aard | aardappel (previously: gwvo)
|
|
||||||
ch | chobie
|
|
||||||
cn | caspern
|
|
||||||
df | dnfield
|
|
||||||
ev | evolutional
|
|
||||||
ew | evanw
|
|
||||||
js | jonsimantov
|
|
||||||
kr | krojew
|
|
||||||
mi | mustiikhalil
|
|
||||||
mik | mikkelfj
|
|
||||||
mz | mzaks
|
|
||||||
rw | rw
|
|
||||||
|
|
||||||
<br>
|
|
@ -1,97 +0,0 @@
|
|||||||
Use in Swift {#flatbuffers_guide_use_swift}
|
|
||||||
=========
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in Swift, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
|
||||||
to general FlatBuffers usage in all of the supported languages (including Swift).
|
|
||||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
|
||||||
Swift.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers Swift library code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers Swift library can be found at
|
|
||||||
`flatbuffers/swift`. You can browse the library code on the [FlatBuffers
|
|
||||||
GitHub page](https://github.com/google/flatbuffers/tree/master/swift).
|
|
||||||
|
|
||||||
## Testing the FlatBuffers Swift library
|
|
||||||
|
|
||||||
The code to test the Swift library can be found at `flatbuffers/tests/swift/tests`.
|
|
||||||
The test code itself is located in [flatbuffers/tests/swift/tests](https://github.com/google/flatbuffers/blob/master/tests/swift/tests).
|
|
||||||
|
|
||||||
To run the tests, use the [SwiftTest.sh](https://github.com/google/flatbuffers/blob/master/tests/swift/tests/SwiftTest.sh) shell script.
|
|
||||||
|
|
||||||
*Note: The shell script requires [Swift](https://swift.org) to
|
|
||||||
be installed.*
|
|
||||||
|
|
||||||
## Using the FlatBuffers Swift library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in Swift.*
|
|
||||||
|
|
||||||
FlatBuffers supports reading and writing binary FlatBuffers in Swift.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate Swift structs from your
|
|
||||||
schema with the `--swift` option to `flatc`. Then include FlatBuffers using `SPM` in
|
|
||||||
by adding the path to `FlatBuffers/swift` into it. The generated code should also be
|
|
||||||
added to xcode or the path of the package you will be using. Note: sometimes xcode cant
|
|
||||||
and wont see the generated files, so it's better that you copy them to xcode.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in Swift: First,
|
|
||||||
include the library and copy thegenerated code. Then read a FlatBuffer binary file or
|
|
||||||
a data object from the server, which you can pass into the `GetRootAsMonster` function.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
|
||||||
import FlatBuffers
|
|
||||||
|
|
||||||
typealias Monster1 = MyGame.Sample.Monster
|
|
||||||
typealias Vec3 = MyGame.Sample.Vec3
|
|
||||||
|
|
||||||
let path = FileManager.default.currentDirectoryPath
|
|
||||||
let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon")
|
|
||||||
guard let data = try? Data(contentsOf: url) else { return }
|
|
||||||
|
|
||||||
let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now you can access values like this:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
|
||||||
let hp = monster.hp
|
|
||||||
let pos = monster.pos // uses native swift structs
|
|
||||||
let pos = monster.mutablePos // uses flatbuffers structs
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
|
||||||
var byteBuffer = ByteBuffer(bytes: data)
|
|
||||||
// Get an accessor to the root object inside the buffer.
|
|
||||||
let monster: Monster = try! getCheckedRoot(byteBuffer: &byteBuffer)
|
|
||||||
// let monster: Monster = getRoot(byteBuffer: &byteBuffer)
|
|
||||||
|
|
||||||
if !monster.mutate(hp: 10) {
|
|
||||||
fatalError("couldn't mutate")
|
|
||||||
}
|
|
||||||
// mutate a struct field using flatbuffers struct
|
|
||||||
// DONT use monster.pos to mutate since swift copy on write
|
|
||||||
// will not mutate the value in the buffer
|
|
||||||
let vec = monster.mutablePos.mutate(z: 4)
|
|
||||||
|
|
||||||
// This mutation will fail because the mana field is not available in
|
|
||||||
// the buffer. It should be set when creating the buffer.
|
|
||||||
if !monster.mutate(mana: 20) {
|
|
||||||
fatalError("couldn't mutate")
|
|
||||||
}
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer.
|
|
||||||
|
|
||||||
<br>
|
|
3563
third_party/flatbuffers/docs/source/Tutorial.md
vendored
@ -1,96 +0,0 @@
|
|||||||
Use in TypeScript {#flatbuffers_guide_use_typescript}
|
|
||||||
=================
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers usage in TypeScript, it should be noted that
|
|
||||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
|
||||||
general FlatBuffers usage in all of the supported languages
|
|
||||||
(including TypeScript). This page is specifically designed to cover the nuances
|
|
||||||
of FlatBuffers usage in TypeScript.
|
|
||||||
|
|
||||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
|
||||||
documentation to build `flatc` and should be familiar with
|
|
||||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
|
||||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
|
||||||
|
|
||||||
## FlatBuffers TypeScript library code location
|
|
||||||
|
|
||||||
The code for the FlatBuffers TypeScript library can be found at
|
|
||||||
https://www.npmjs.com/package/flatbuffers.
|
|
||||||
|
|
||||||
## Testing the FlatBuffers TypeScript library
|
|
||||||
|
|
||||||
To run the tests, use the [TypeScriptTest.py](https://github.com/google/
|
|
||||||
flatbuffers/blob/master/tests/TypeScriptTest.py) Python3 script.
|
|
||||||
|
|
||||||
*Note: The TypeScript test file requires [Node.js](https://nodejs.org/en/).*
|
|
||||||
|
|
||||||
## Using the FlatBuffers TypeScript library
|
|
||||||
|
|
||||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
|
||||||
example of how to use FlatBuffers in TypeScript.*
|
|
||||||
|
|
||||||
FlatBuffers supports both reading and writing FlatBuffers in TypeScript.
|
|
||||||
|
|
||||||
To use FlatBuffers in your own code, first generate TypeScript classes from your
|
|
||||||
schema with the `--ts` option to `flatc`. Then you can include both FlatBuffers
|
|
||||||
and the generated code to read or write a FlatBuffer.
|
|
||||||
|
|
||||||
For example, here is how you would read a FlatBuffer binary file in TypeScript:
|
|
||||||
First, include the library and generated code. Then read the file into an
|
|
||||||
`Uint8Array`. Make a `flatbuffers.ByteBuffer` out of the `Uint8Array`, and pass
|
|
||||||
the ByteBuffer to the `getRootAsMonster` function.
|
|
||||||
|
|
||||||
~~~{.ts}
|
|
||||||
import * as flatbuffers from 'flatbuffers';
|
|
||||||
|
|
||||||
import { MyGame } from './monster_generated';
|
|
||||||
|
|
||||||
let data = new Uint8Array(fs.readFileSync('monster.dat'));
|
|
||||||
let buf = new flatbuffers.ByteBuffer(data);
|
|
||||||
|
|
||||||
let monster = MyGame.Example.Monster.getRootAsMonster(buf);
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Now you can access values like this:
|
|
||||||
|
|
||||||
~~~{.ts}
|
|
||||||
let hp = monster.hp();
|
|
||||||
let pos = monster.pos();
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Object based API
|
|
||||||
|
|
||||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
|
||||||
around using as little as possible of it. This does make the API clumsier
|
|
||||||
(requiring pre-order construction of all data, and making mutation harder).
|
|
||||||
|
|
||||||
For times when efficiency is less important a more convenient object based API
|
|
||||||
can be used (through `--gen-object-api`) that is able to unpack & pack a
|
|
||||||
FlatBuffer into objects and standard TS types.
|
|
||||||
|
|
||||||
To use:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.ts}
|
|
||||||
// Autogenerated class from table Monster.
|
|
||||||
let monsterobj = new MonsterT();
|
|
||||||
|
|
||||||
// Deserialize from buffer into object.
|
|
||||||
Monster.getRootAsMonster(flatbuffer).unpackTo(monsterobj);
|
|
||||||
// or
|
|
||||||
let monsterobj = Monster.getRootAsMonster(flatbuffer).unpack();
|
|
||||||
|
|
||||||
// Update object directly like a regular TS class instance.
|
|
||||||
console.log(monsterobj.name);
|
|
||||||
monsterobj.name = "Bob";
|
|
||||||
|
|
||||||
// Serialize into new flatbuffer.
|
|
||||||
let fbb = new flatbuffers.Builder(1);
|
|
||||||
Monster.finishMonsterBuffer(fbb, monsterobj.pack(fbb));
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
## Text parsing FlatBuffers in TypeScript
|
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
|
||||||
from TypeScript.
|
|
128
third_party/flatbuffers/docs/source/WhitePaper.md
vendored
@ -1,128 +0,0 @@
|
|||||||
FlatBuffers white paper {#flatbuffers_white_paper}
|
|
||||||
=======================
|
|
||||||
|
|
||||||
This document tries to shed some light on to the "why" of FlatBuffers, a
|
|
||||||
new serialization library.
|
|
||||||
|
|
||||||
## Motivation
|
|
||||||
|
|
||||||
Back in the good old days, performance was all about instructions and
|
|
||||||
cycles. Nowadays, processing units have run so far ahead of the memory
|
|
||||||
subsystem, that making an efficient application should start and finish
|
|
||||||
with thinking about memory. How much you use of it. How you lay it out
|
|
||||||
and access it. How you allocate it. When you copy it.
|
|
||||||
|
|
||||||
Serialization is a pervasive activity in a lot programs, and a common
|
|
||||||
source of memory inefficiency, with lots of temporary data structures
|
|
||||||
needed to parse and represent data, and inefficient allocation patterns
|
|
||||||
and locality.
|
|
||||||
|
|
||||||
If it would be possible to do serialization with no temporary objects,
|
|
||||||
no additional allocation, no copying, and good locality, this could be
|
|
||||||
of great value. The reason serialization systems usually don't manage
|
|
||||||
this is because it goes counter to forwards/backwards compatibility, and
|
|
||||||
platform specifics like endianness and alignment.
|
|
||||||
|
|
||||||
FlatBuffers is what you get if you try anyway.
|
|
||||||
|
|
||||||
In particular, FlatBuffers focus is on mobile hardware (where memory
|
|
||||||
size and memory bandwidth is even more constrained than on desktop
|
|
||||||
hardware), and applications that have the highest performance needs:
|
|
||||||
games.
|
|
||||||
|
|
||||||
## FlatBuffers
|
|
||||||
|
|
||||||
*This is a summary of FlatBuffers functionality, with some rationale.
|
|
||||||
A more detailed description can be found in the FlatBuffers
|
|
||||||
documentation.*
|
|
||||||
|
|
||||||
### Summary
|
|
||||||
|
|
||||||
A FlatBuffer is a binary buffer containing nested objects (structs,
|
|
||||||
tables, vectors,..) organized using offsets so that the data can be
|
|
||||||
traversed in-place just like any pointer-based data structure. Unlike
|
|
||||||
most in-memory data structures however, it uses strict rules of
|
|
||||||
alignment and endianness (always little) to ensure these buffers are
|
|
||||||
cross platform. Additionally, for objects that are tables, FlatBuffers
|
|
||||||
provides forwards/backwards compatibility and general optionality of
|
|
||||||
fields, to support most forms of format evolution.
|
|
||||||
|
|
||||||
You define your object types in a schema, which can then be compiled to
|
|
||||||
C++ or Java for low to zero overhead reading & writing.
|
|
||||||
Optionally, JSON data can be dynamically parsed into buffers.
|
|
||||||
|
|
||||||
### Tables
|
|
||||||
|
|
||||||
Tables are the cornerstone of FlatBuffers, since format evolution is
|
|
||||||
essential for most applications of serialization. Typically, dealing
|
|
||||||
with format changes is something that can be done transparently during
|
|
||||||
the parsing process of most serialization solutions out there.
|
|
||||||
But a FlatBuffer isn't parsed before it is accessed.
|
|
||||||
|
|
||||||
Tables get around this by using an extra indirection to access fields,
|
|
||||||
through a *vtable*. Each table comes with a vtable (which may be shared
|
|
||||||
between multiple tables with the same layout), and contains information
|
|
||||||
where fields for this particular kind of instance of vtable are stored.
|
|
||||||
The vtable may also indicate that the field is not present (because this
|
|
||||||
FlatBuffer was written with an older version of the software, or simply
|
|
||||||
because the information was not necessary for this instance, or deemed
|
|
||||||
deprecated), in which case a default value is returned.
|
|
||||||
|
|
||||||
Tables have a low overhead in memory (since vtables are small and
|
|
||||||
shared) and in access cost (an extra indirection), but provide great
|
|
||||||
flexibility. Tables may even cost less memory than the equivalent
|
|
||||||
struct, since fields do not need to be stored when they are equal to
|
|
||||||
their default.
|
|
||||||
|
|
||||||
FlatBuffers additionally offers "naked" structs, which do not offer
|
|
||||||
forwards/backwards compatibility, but can be even smaller (useful for
|
|
||||||
very small objects that are unlikely to change, like e.g. a coordinate
|
|
||||||
pair or a RGBA color).
|
|
||||||
|
|
||||||
### Schemas
|
|
||||||
|
|
||||||
While schemas reduce some generality (you can't just read any data
|
|
||||||
without having its schema), they have a lot of upsides:
|
|
||||||
|
|
||||||
- Most information about the format can be factored into the generated
|
|
||||||
code, reducing memory needed to store data, and time to access it.
|
|
||||||
|
|
||||||
- The strong typing of the data definitions means less error
|
|
||||||
checking/handling at runtime (less can go wrong).
|
|
||||||
|
|
||||||
- A schema enables us to access a buffer without parsing.
|
|
||||||
|
|
||||||
FlatBuffer schemas are fairly similar to those of the incumbent,
|
|
||||||
Protocol Buffers, and generally should be readable to those familiar
|
|
||||||
with the C family of languages. We chose to improve upon the features
|
|
||||||
offered by .proto files in the following ways:
|
|
||||||
|
|
||||||
- Deprecation of fields instead of manual field id assignment.
|
|
||||||
Extending an object in a .proto means hunting for a free slot among
|
|
||||||
the numbers (preferring lower numbers since they have a more compact
|
|
||||||
representation). Besides being inconvenient, it also makes removing
|
|
||||||
fields problematic: you either have to keep them, not making it
|
|
||||||
obvious that this field shouldn't be read/written anymore, and still
|
|
||||||
generating accessors. Or you remove it, but now you risk that
|
|
||||||
there's still old data around that uses that field by the time
|
|
||||||
someone reuses that field id, with nasty consequences.
|
|
||||||
|
|
||||||
- Differentiating between tables and structs (see above). Effectively
|
|
||||||
all table fields are `optional`, and all struct fields are
|
|
||||||
`required`.
|
|
||||||
|
|
||||||
- Having a native vector type instead of `repeated`. This gives you a
|
|
||||||
length without having to collect all items, and in the case of
|
|
||||||
scalars provides for a more compact representation, and one that
|
|
||||||
guarantees adjacency.
|
|
||||||
|
|
||||||
- Having a native `union` type instead of using a series of `optional`
|
|
||||||
fields, all of which must be checked individually.
|
|
||||||
|
|
||||||
- Being able to define defaults for all scalars, instead of having to
|
|
||||||
deal with their optionality at each access.
|
|
||||||
|
|
||||||
- A parser that can deal with both schemas and data definitions (JSON
|
|
||||||
compatible) uniformly.
|
|
||||||
|
|
||||||
<br>
|
|
2375
third_party/flatbuffers/docs/source/doxyfile
vendored
@ -1,254 +0,0 @@
|
|||||||
<!-- Copyright 2015 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
<doxygenlayout version="1.0">
|
|
||||||
<navindex>
|
|
||||||
<tab type="mainpage" visible="no" title=""/>
|
|
||||||
<tab type="usergroup" url="" title="Programmer's Guide">
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_building"
|
|
||||||
title="Building"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_tutorial" title="Tutorial"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_using_schema_compiler"
|
|
||||||
title="Using the schema compiler"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_writing_schema"
|
|
||||||
title="Writing a schema"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_cpp"
|
|
||||||
title="Use in C++"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_c"
|
|
||||||
title="Use in C"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_go"
|
|
||||||
title="Use in Go"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_java"
|
|
||||||
title="Use in Java"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_c-sharp"
|
|
||||||
title="Use in C#"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_javascript"
|
|
||||||
title="Use in JavaScript"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_typescript"
|
|
||||||
title="Use in TypeScript"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_php"
|
|
||||||
title="Use in PHP"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_python"
|
|
||||||
title="Use in Python"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_dart"
|
|
||||||
title="Use in Dart"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_lua"
|
|
||||||
title="Use in Lua"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_lobster"
|
|
||||||
title="Use in Lobster"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_rust"
|
|
||||||
title="Use in Rust"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_swift"
|
|
||||||
title="Use in Swift"/>
|
|
||||||
<tab type="user" url="@ref flexbuffers"
|
|
||||||
title="FlexBuffers (Schema-less version)"/>
|
|
||||||
<tab type="usergroup" url="" title="gRPC">
|
|
||||||
<tab type="user" url="@ref flatbuffers_grpc_guide_use_cpp"
|
|
||||||
title="Use in C++"/>
|
|
||||||
</tab>
|
|
||||||
</tab>
|
|
||||||
<tab type="user" url="@ref flatbuffers_support"
|
|
||||||
title="Platform / Language / Feature support"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_benchmarks"
|
|
||||||
title="Benchmarks"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_white_paper"
|
|
||||||
title="FlatBuffers white paper"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_internals"
|
|
||||||
title="FlatBuffers internals"/>
|
|
||||||
<tab type="user" url="@ref intermediate_representation"
|
|
||||||
title="Intermediate Representation"/>
|
|
||||||
<tab type="user" url="@ref flatbuffers_grammar"
|
|
||||||
title="Grammar of the schema language"/>
|
|
||||||
<tab type="usergroup" url="" title="API Reference">
|
|
||||||
<tab type="modules" visible="yes" title="APIs" intro=""/>
|
|
||||||
<tab type="classes" visible="yes" title="">
|
|
||||||
<tab type="classlist" visible="yes" title="" intro=""/>
|
|
||||||
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
|
|
||||||
<tab type="hierarchy" visible="yes" title="" intro=""/>
|
|
||||||
<tab type="classmembers" visible="yes" title="" intro=""/>
|
|
||||||
</tab>
|
|
||||||
</tab>
|
|
||||||
<tab type="user" url="@ref contributing" title="Contributing"/>
|
|
||||||
</navindex>
|
|
||||||
|
|
||||||
<!-- Layout definition for a class page -->
|
|
||||||
<class>
|
|
||||||
<briefdescription visible="yes"/>
|
|
||||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
|
||||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
|
||||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
|
||||||
<detaileddescription title=""/>
|
|
||||||
<memberdecl>
|
|
||||||
<nestedclasses visible="yes" title=""/>
|
|
||||||
<publictypes title=""/>
|
|
||||||
<services title=""/>
|
|
||||||
<interfaces title=""/>
|
|
||||||
<publicslots title=""/>
|
|
||||||
<signals title=""/>
|
|
||||||
<publicmethods title=""/>
|
|
||||||
<publicstaticmethods title=""/>
|
|
||||||
<publicattributes title=""/>
|
|
||||||
<publicstaticattributes title=""/>
|
|
||||||
<protectedtypes title=""/>
|
|
||||||
<protectedslots title=""/>
|
|
||||||
<protectedmethods title=""/>
|
|
||||||
<protectedstaticmethods title=""/>
|
|
||||||
<protectedattributes title=""/>
|
|
||||||
<protectedstaticattributes title=""/>
|
|
||||||
<packagetypes title=""/>
|
|
||||||
<packagemethods title=""/>
|
|
||||||
<packagestaticmethods title=""/>
|
|
||||||
<packageattributes title=""/>
|
|
||||||
<packagestaticattributes title=""/>
|
|
||||||
<properties title=""/>
|
|
||||||
<events title=""/>
|
|
||||||
<privatetypes title=""/>
|
|
||||||
<privateslots title=""/>
|
|
||||||
<privatemethods title=""/>
|
|
||||||
<privatestaticmethods title=""/>
|
|
||||||
<privateattributes title=""/>
|
|
||||||
<privatestaticattributes title=""/>
|
|
||||||
<friends title=""/>
|
|
||||||
<related title="" subtitle=""/>
|
|
||||||
<membergroups visible="yes"/>
|
|
||||||
</memberdecl>
|
|
||||||
<memberdef>
|
|
||||||
<inlineclasses title=""/>
|
|
||||||
<typedefs title=""/>
|
|
||||||
<enums title=""/>
|
|
||||||
<services title=""/>
|
|
||||||
<interfaces title=""/>
|
|
||||||
<constructors title=""/>
|
|
||||||
<functions title=""/>
|
|
||||||
<related title=""/>
|
|
||||||
<variables title=""/>
|
|
||||||
<properties title=""/>
|
|
||||||
<events title=""/>
|
|
||||||
</memberdef>
|
|
||||||
<allmemberslink visible="yes"/>
|
|
||||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
|
||||||
<authorsection visible="yes"/>
|
|
||||||
</class>
|
|
||||||
|
|
||||||
<!-- Layout definition for a namespace page -->
|
|
||||||
<namespace>
|
|
||||||
<briefdescription visible="yes"/>
|
|
||||||
<memberdecl>
|
|
||||||
<nestednamespaces visible="yes" title=""/>
|
|
||||||
<constantgroups visible="yes" title=""/>
|
|
||||||
<classes visible="yes" title=""/>
|
|
||||||
<typedefs title=""/>
|
|
||||||
<enums title=""/>
|
|
||||||
<functions title=""/>
|
|
||||||
<variables title=""/>
|
|
||||||
<membergroups visible="yes"/>
|
|
||||||
</memberdecl>
|
|
||||||
<detaileddescription title=""/>
|
|
||||||
<memberdef>
|
|
||||||
<inlineclasses title=""/>
|
|
||||||
<typedefs title=""/>
|
|
||||||
<enums title=""/>
|
|
||||||
<functions title=""/>
|
|
||||||
<variables title=""/>
|
|
||||||
</memberdef>
|
|
||||||
<authorsection visible="yes"/>
|
|
||||||
</namespace>
|
|
||||||
|
|
||||||
<!-- Layout definition for a file page -->
|
|
||||||
<file>
|
|
||||||
<briefdescription visible="yes"/>
|
|
||||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
|
||||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
|
||||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
|
||||||
<sourcelink visible="yes"/>
|
|
||||||
<detaileddescription title=""/>
|
|
||||||
<memberdecl>
|
|
||||||
<classes visible="yes" title=""/>
|
|
||||||
<namespaces visible="yes" title=""/>
|
|
||||||
<constantgroups visible="yes" title=""/>
|
|
||||||
<defines title=""/>
|
|
||||||
<typedefs title=""/>
|
|
||||||
<enums title=""/>
|
|
||||||
<functions title=""/>
|
|
||||||
<variables title=""/>
|
|
||||||
<membergroups visible="yes"/>
|
|
||||||
</memberdecl>
|
|
||||||
<memberdef>
|
|
||||||
<inlineclasses title=""/>
|
|
||||||
<defines title=""/>
|
|
||||||
<typedefs title=""/>
|
|
||||||
<enums title=""/>
|
|
||||||
<functions title=""/>
|
|
||||||
<variables title=""/>
|
|
||||||
</memberdef>
|
|
||||||
<authorsection/>
|
|
||||||
</file>
|
|
||||||
|
|
||||||
<!-- Layout definition for a group page -->
|
|
||||||
<group>
|
|
||||||
<briefdescription visible="yes"/>
|
|
||||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
|
||||||
<detaileddescription title=""/>
|
|
||||||
<memberdecl>
|
|
||||||
<nestedgroups visible="yes" title=""/>
|
|
||||||
<dirs visible="yes" title=""/>
|
|
||||||
<files visible="yes" title=""/>
|
|
||||||
<namespaces visible="yes" title=""/>
|
|
||||||
<classes visible="yes" title=""/>
|
|
||||||
<defines title=""/>
|
|
||||||
<typedefs title=""/>
|
|
||||||
<enums title=""/>
|
|
||||||
<enumvalues title=""/>
|
|
||||||
<functions title=""/>
|
|
||||||
<variables title=""/>
|
|
||||||
<signals title=""/>
|
|
||||||
<publicslots title=""/>
|
|
||||||
<protectedslots title=""/>
|
|
||||||
<privateslots title=""/>
|
|
||||||
<events title=""/>
|
|
||||||
<properties title=""/>
|
|
||||||
<friends title=""/>
|
|
||||||
<membergroups visible="yes"/>
|
|
||||||
</memberdecl>
|
|
||||||
<memberdef>
|
|
||||||
<pagedocs/>
|
|
||||||
<inlineclasses title=""/>
|
|
||||||
<defines title=""/>
|
|
||||||
<typedefs title=""/>
|
|
||||||
<enums title=""/>
|
|
||||||
<enumvalues title=""/>
|
|
||||||
<functions title=""/>
|
|
||||||
<variables title=""/>
|
|
||||||
<signals title=""/>
|
|
||||||
<publicslots title=""/>
|
|
||||||
<protectedslots title=""/>
|
|
||||||
<privateslots title=""/>
|
|
||||||
<events title=""/>
|
|
||||||
<properties title=""/>
|
|
||||||
<friends title=""/>
|
|
||||||
</memberdef>
|
|
||||||
<authorsection visible="yes"/>
|
|
||||||
</group>
|
|
||||||
|
|
||||||
<!-- Layout definition for a directory page -->
|
|
||||||
<directory>
|
|
||||||
<briefdescription visible="yes"/>
|
|
||||||
<directorygraph visible="yes"/>
|
|
||||||
<memberdecl>
|
|
||||||
<dirs visible="yes"/>
|
|
||||||
<files visible="yes"/>
|
|
||||||
</memberdecl>
|
|
||||||
<detaileddescription title=""/>
|
|
||||||
</directory>
|
|
||||||
</doxygenlayout>
|
|
@ -1,29 +0,0 @@
|
|||||||
Use in C++ {#flatbuffers_grpc_guide_use_cpp}
|
|
||||||
==========
|
|
||||||
|
|
||||||
## Before you get started
|
|
||||||
|
|
||||||
Before diving into the FlatBuffers gRPC usage in C++, you should already be
|
|
||||||
familiar with the following:
|
|
||||||
|
|
||||||
- FlatBuffers as a serialization format
|
|
||||||
- [gRPC](http://www.grpc.io/docs/) usage
|
|
||||||
|
|
||||||
## Using the FlatBuffers gRPC C++ library
|
|
||||||
|
|
||||||
NOTE: The examples below are also in the `grpc/samples/greeter` directory.
|
|
||||||
|
|
||||||
We will illustrate usage with the following schema:
|
|
||||||
|
|
||||||
@include grpc/samples/greeter/greeter.fbs
|
|
||||||
|
|
||||||
When we run `flatc`, we pass in the `--grpc` option and generage an additional
|
|
||||||
`greeter.grpc.fb.h` and `greeter.grpc.fb.cc`.
|
|
||||||
|
|
||||||
Example server code looks like this:
|
|
||||||
|
|
||||||
@include grpc/samples/greeter/server.cpp
|
|
||||||
|
|
||||||
Example client code looks like this:
|
|
||||||
|
|
||||||
@include grpc/samples/greeter/client.cpp
|
|
23
third_party/flatbuffers/docs/source/groups
vendored
@ -1,23 +0,0 @@
|
|||||||
/// @defgroup flatbuffers_cpp_api C++ API
|
|
||||||
/// @brief FlatBuffers API for C++
|
|
||||||
|
|
||||||
/// @defgroup flatbuffers_csharp_api C# API
|
|
||||||
/// @brief FlatBuffers API for C#
|
|
||||||
|
|
||||||
/// @defgroup flatbuffers_go_api Go API
|
|
||||||
/// @brief FlatBuffers API for Go
|
|
||||||
|
|
||||||
/// @defgroup flatbuffers_java_api Java API
|
|
||||||
/// @brief FlatBuffers API for Java
|
|
||||||
|
|
||||||
/// @defgroup flatbuffers_javascript_api JavaScript API
|
|
||||||
/// @brief FlatBuffers API for JavaScript
|
|
||||||
|
|
||||||
/// @defgroup flatbuffers_typescript_api TypeScript API
|
|
||||||
/// @brief FlatBuffers API for TypeScript
|
|
||||||
|
|
||||||
/// @defgroup flatbuffers_php_api PHP API
|
|
||||||
/// @brief FlatBuffers API for PHP
|
|
||||||
|
|
||||||
/// @defgroup flatbuffers_python_api Python API
|
|
||||||
/// @brief FlatBuffers API for Python
|
|
396
third_party/flatbuffers/docs/source/style.css
vendored
@ -1,396 +0,0 @@
|
|||||||
body,
|
|
||||||
#projectname,
|
|
||||||
table,
|
|
||||||
div,
|
|
||||||
p,
|
|
||||||
dl,
|
|
||||||
.title,
|
|
||||||
.tabs,
|
|
||||||
.tabs2,
|
|
||||||
.tabs3,
|
|
||||||
#nav-tree .label {
|
|
||||||
font-family: roboto, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
#commonprojectlogo {
|
|
||||||
padding: 5px 0px 5px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#projectname {
|
|
||||||
color: #00bcd4;
|
|
||||||
font-size: 280%;
|
|
||||||
padding: 15px 0px;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
#titlearea {
|
|
||||||
border-bottom: 2px solid #e5e5e5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: #212121;
|
|
||||||
font: 300 34px/40px Roboto,sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-tree {
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#navrow1, #navrow2 {
|
|
||||||
border-bottom: 2px solid #e7e7e7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs, .tabs2, .tabs3 {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs,
|
|
||||||
.tabs2,
|
|
||||||
.tabs3,
|
|
||||||
.tablist li,
|
|
||||||
.tablist li.current a {
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablist {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablist li, .tablist li p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablist li a,
|
|
||||||
.tablist li.current a {
|
|
||||||
color: #757575;
|
|
||||||
text-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablist li.current a {
|
|
||||||
background: #00bcd4;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablist a {
|
|
||||||
background-image: none;
|
|
||||||
border-right: 2px solid #e5e5e5;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablist a:hover,
|
|
||||||
.tablist li.current a:hover {
|
|
||||||
background-image: none;
|
|
||||||
text-decoration: underline;
|
|
||||||
text-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablist a:hover {
|
|
||||||
color: #00bcd4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablist li.current a:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.header {
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
background-image: none;
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#MSearchBox {
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 5px;
|
|
||||||
display: inline-block;
|
|
||||||
height: 20px;
|
|
||||||
right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#MSearchBox .left,
|
|
||||||
#MSearchBox .right,
|
|
||||||
#MSearchField {
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.SelectItem:hover {
|
|
||||||
background-color: #00bcd4;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-tree {
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-tree .selected {
|
|
||||||
background-image: none;
|
|
||||||
text-shadow: none;
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-tree a {
|
|
||||||
color: #212121;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-tree .selected a {
|
|
||||||
color: #0288d1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-tree .item:hover {
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-tree .item:hover a {
|
|
||||||
color: #0288d1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-tree .label {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav-sync {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui-resizable-e {
|
|
||||||
background: #ebebeb;
|
|
||||||
border-left: 1px solid #ddd;
|
|
||||||
border-right: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contents tr td .image {
|
|
||||||
margin-top: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image {
|
|
||||||
text-align: left;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:link,
|
|
||||||
a:visited,
|
|
||||||
.contents a:link,
|
|
||||||
.contents a:visited,
|
|
||||||
a.el {
|
|
||||||
color: #0288d1;
|
|
||||||
font-weight: normal;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.contents {
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory tr, .directory tr.even {
|
|
||||||
background: #7cb342;
|
|
||||||
border-top: 1px solid #7cb342;
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory td,
|
|
||||||
.directory td.entry,
|
|
||||||
.directory td.desc {
|
|
||||||
background: rgba(255,255,255,.95);
|
|
||||||
border-left: none;
|
|
||||||
color: #212121;
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
padding-left: 8px;
|
|
||||||
padding-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory tr#row_0_ {
|
|
||||||
border-top-color: #7cb342;
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory tr#row_0_ td {
|
|
||||||
background: #7cb342;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memSeparator {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memitem {
|
|
||||||
background: #7cb342;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memproto, dl.reflist dt {
|
|
||||||
background: #7cb342;
|
|
||||||
background-image: none;
|
|
||||||
border: none;
|
|
||||||
box-shadow: none;
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
color: #fff;
|
|
||||||
text-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memproto .memtemplate,
|
|
||||||
.memproto a.el,
|
|
||||||
.memproto .paramname {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memdoc, dl.reflist dd {
|
|
||||||
border: none;
|
|
||||||
background-color: rgba(255,255,255,.95);
|
|
||||||
background-image: none;
|
|
||||||
box-shadow: none;
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
-webkit-border-bottom-left-radius: 0;
|
|
||||||
-webkit-border-bottom-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memitem, table.doxtable, table.memberdecls {
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.doxtable th {
|
|
||||||
background: #7cb342;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.doxtable tr {
|
|
||||||
background: #7cb342;
|
|
||||||
border-top: 1px solid #7cb342;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.doxtable td, table.doxtable th {
|
|
||||||
border: none;
|
|
||||||
padding: 10px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.doxtable td {
|
|
||||||
background-color: rgba(255,255,255,.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
.memberdecls {
|
|
||||||
background: #7cb342;
|
|
||||||
border-top: 1px solid #7cb342;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memberdecls .heading h2 {
|
|
||||||
border-bottom: none;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 110%;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0 0 0 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memberdecls tr:not(.heading) td {
|
|
||||||
background-color: rgba(255,255,255,.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1, h2, h2.groupheader, h3, h4, h5, h6 {
|
|
||||||
color: #212121;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
border-bottom: 1px solid #ebebeb;
|
|
||||||
font: 400 28px/32px Roboto,sans-serif;
|
|
||||||
letter-spacing: -.01em;
|
|
||||||
margin: 40px 0 20px;
|
|
||||||
padding-bottom: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2, h2.groupheader {
|
|
||||||
border-bottom: 1px solid #ebebeb;
|
|
||||||
font: 400 23px/32px Roboto,sans-serif;
|
|
||||||
letter-spacing: -.01em;
|
|
||||||
margin: 40px 0 20px;
|
|
||||||
padding-bottom: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font: 500 20px/32px Roboto,sans-serif;
|
|
||||||
margin: 32px 0 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font: 500 18px/32px Roboto,sans-serif;
|
|
||||||
margin: 32px 0 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul {
|
|
||||||
margin: 0;
|
|
||||||
padding-left: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol {
|
|
||||||
list-style: decimal outside;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol ol {
|
|
||||||
list-style-type: lower-alpha;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol ol ol {
|
|
||||||
list-style-type: lower-roman;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style: disc outside;
|
|
||||||
}
|
|
||||||
|
|
||||||
li,
|
|
||||||
li p {
|
|
||||||
margin: 8px 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.summary
|
|
||||||
{
|
|
||||||
float: none;
|
|
||||||
font-size: 8pt;
|
|
||||||
padding-left: 5px;
|
|
||||||
width: calc(100% - 10px);
|
|
||||||
text-align: left;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.ingroups {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.fragment {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
color: #455a64;
|
|
||||||
font: 14px/20px Roboto Mono, monospace;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.line {
|
|
||||||
line-height: 1.5;
|
|
||||||
font-size: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
code, pre {
|
|
||||||
color: #455a64;
|
|
||||||
background: #f7f7f7;
|
|
||||||
font: 400 100% Roboto Mono,monospace;
|
|
||||||
padding: 1px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.preprocessor, span.comment {
|
|
||||||
color: #0b8043;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.keywordtype {
|
|
||||||
color: #0097a7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.paramname {
|
|
||||||
color: #ef6c00;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memTemplParams {
|
|
||||||
color: #ef6c00;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.mlabel {
|
|
||||||
background: rgba(255,255,255,.25);
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
}
|
|
2
third_party/flatbuffers/tests/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
# Generated files shouldn't be checked in for tests.
|
|
||||||
**_generated.h
|
|
@ -1,8 +0,0 @@
|
|||||||
namespace v1;
|
|
||||||
|
|
||||||
table RootTable {
|
|
||||||
a:float;
|
|
||||||
b:[uint8];
|
|
||||||
}
|
|
||||||
|
|
||||||
root_type RootTable;
|
|
@ -1,219 +0,0 @@
|
|||||||
// automatically generated by the FlatBuffers compiler, do not modify
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GENERATED_V1_V1_H_
|
|
||||||
#define FLATBUFFERS_GENERATED_V1_V1_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
|
|
||||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
|
||||||
// generated, otherwise it may not be compatible.
|
|
||||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 24 &&
|
|
||||||
FLATBUFFERS_VERSION_MINOR == 3 &&
|
|
||||||
FLATBUFFERS_VERSION_REVISION == 25,
|
|
||||||
"Non-compatible flatbuffers version included");
|
|
||||||
|
|
||||||
namespace v1 {
|
|
||||||
|
|
||||||
struct RootTable;
|
|
||||||
struct RootTableBuilder;
|
|
||||||
struct RootTableT;
|
|
||||||
|
|
||||||
bool operator==(const RootTableT &lhs, const RootTableT &rhs);
|
|
||||||
bool operator!=(const RootTableT &lhs, const RootTableT &rhs);
|
|
||||||
|
|
||||||
inline const ::flatbuffers::TypeTable *RootTableTypeTable();
|
|
||||||
|
|
||||||
struct RootTableT : public ::flatbuffers::NativeTable {
|
|
||||||
typedef RootTable TableType;
|
|
||||||
float a = 0.0f;
|
|
||||||
std::vector<uint8_t> b{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RootTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|
||||||
typedef RootTableT NativeTableType;
|
|
||||||
typedef RootTableBuilder Builder;
|
|
||||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
|
||||||
return RootTableTypeTable();
|
|
||||||
}
|
|
||||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
|
||||||
VT_A = 4,
|
|
||||||
VT_B = 6
|
|
||||||
};
|
|
||||||
float a() const {
|
|
||||||
return GetField<float>(VT_A, 0.0f);
|
|
||||||
}
|
|
||||||
bool mutate_a(float _a = 0.0f) {
|
|
||||||
return SetField<float>(VT_A, _a, 0.0f);
|
|
||||||
}
|
|
||||||
const ::flatbuffers::Vector<uint8_t> *b() const {
|
|
||||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_B);
|
|
||||||
}
|
|
||||||
::flatbuffers::Vector<uint8_t> *mutable_b() {
|
|
||||||
return GetPointer<::flatbuffers::Vector<uint8_t> *>(VT_B);
|
|
||||||
}
|
|
||||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
|
||||||
return VerifyTableStart(verifier) &&
|
|
||||||
VerifyField<float>(verifier, VT_A, 4) &&
|
|
||||||
VerifyOffset(verifier, VT_B) &&
|
|
||||||
verifier.VerifyVector(b()) &&
|
|
||||||
verifier.EndTable();
|
|
||||||
}
|
|
||||||
RootTableT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
|
||||||
void UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
|
||||||
static ::flatbuffers::Offset<RootTable> Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RootTableBuilder {
|
|
||||||
typedef RootTable Table;
|
|
||||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
|
||||||
::flatbuffers::uoffset_t start_;
|
|
||||||
void add_a(float a) {
|
|
||||||
fbb_.AddElement<float>(RootTable::VT_A, a, 0.0f);
|
|
||||||
}
|
|
||||||
void add_b(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> b) {
|
|
||||||
fbb_.AddOffset(RootTable::VT_B, b);
|
|
||||||
}
|
|
||||||
explicit RootTableBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
|
||||||
: fbb_(_fbb) {
|
|
||||||
start_ = fbb_.StartTable();
|
|
||||||
}
|
|
||||||
::flatbuffers::Offset<RootTable> Finish() {
|
|
||||||
const auto end = fbb_.EndTable(start_);
|
|
||||||
auto o = ::flatbuffers::Offset<RootTable>(end);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<RootTable> CreateRootTable(
|
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
|
||||||
float a = 0.0f,
|
|
||||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> b = 0) {
|
|
||||||
RootTableBuilder builder_(_fbb);
|
|
||||||
builder_.add_b(b);
|
|
||||||
builder_.add_a(a);
|
|
||||||
return builder_.Finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<RootTable> CreateRootTableDirect(
|
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
|
||||||
float a = 0.0f,
|
|
||||||
const std::vector<uint8_t> *b = nullptr) {
|
|
||||||
auto b__ = b ? _fbb.CreateVector<uint8_t>(*b) : 0;
|
|
||||||
return v1::CreateRootTable(
|
|
||||||
_fbb,
|
|
||||||
a,
|
|
||||||
b__);
|
|
||||||
}
|
|
||||||
|
|
||||||
::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
|
||||||
|
|
||||||
|
|
||||||
inline bool operator==(const RootTableT &lhs, const RootTableT &rhs) {
|
|
||||||
return
|
|
||||||
(lhs.a == rhs.a) &&
|
|
||||||
(lhs.b == rhs.b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator!=(const RootTableT &lhs, const RootTableT &rhs) {
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline RootTableT *RootTable::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
|
||||||
auto _o = std::unique_ptr<RootTableT>(new RootTableT());
|
|
||||||
UnPackTo(_o.get(), _resolver);
|
|
||||||
return _o.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void RootTable::UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
|
|
||||||
(void)_o;
|
|
||||||
(void)_resolver;
|
|
||||||
{ auto _e = a(); _o->a = _e; }
|
|
||||||
{ auto _e = b(); if (_e) { _o->b.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->b.begin()); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<RootTable> RootTable::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
|
||||||
return CreateRootTable(_fbb, _o, _rehasher);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
|
||||||
(void)_rehasher;
|
|
||||||
(void)_o;
|
|
||||||
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const RootTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
|
||||||
auto _a = _o->a;
|
|
||||||
auto _b = _o->b.size() ? _fbb.CreateVector(_o->b) : 0;
|
|
||||||
return v1::CreateRootTable(
|
|
||||||
_fbb,
|
|
||||||
_a,
|
|
||||||
_b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const ::flatbuffers::TypeTable *RootTableTypeTable() {
|
|
||||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
|
||||||
{ ::flatbuffers::ET_FLOAT, 0, -1 },
|
|
||||||
{ ::flatbuffers::ET_UCHAR, 1, -1 }
|
|
||||||
};
|
|
||||||
static const char * const names[] = {
|
|
||||||
"a",
|
|
||||||
"b"
|
|
||||||
};
|
|
||||||
static const ::flatbuffers::TypeTable tt = {
|
|
||||||
::flatbuffers::ST_TABLE, 2, type_codes, nullptr, nullptr, nullptr, names
|
|
||||||
};
|
|
||||||
return &tt;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const v1::RootTable *GetRootTable(const void *buf) {
|
|
||||||
return ::flatbuffers::GetRoot<v1::RootTable>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const v1::RootTable *GetSizePrefixedRootTable(const void *buf) {
|
|
||||||
return ::flatbuffers::GetSizePrefixedRoot<v1::RootTable>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline RootTable *GetMutableRootTable(void *buf) {
|
|
||||||
return ::flatbuffers::GetMutableRoot<RootTable>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline v1::RootTable *GetMutableSizePrefixedRootTable(void *buf) {
|
|
||||||
return ::flatbuffers::GetMutableSizePrefixedRoot<v1::RootTable>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VerifyRootTableBuffer(
|
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifyBuffer<v1::RootTable>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VerifySizePrefixedRootTableBuffer(
|
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifySizePrefixedBuffer<v1::RootTable>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FinishRootTableBuffer(
|
|
||||||
::flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
::flatbuffers::Offset<v1::RootTable> root) {
|
|
||||||
fbb.Finish(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FinishSizePrefixedRootTableBuffer(
|
|
||||||
::flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
::flatbuffers::Offset<v1::RootTable> root) {
|
|
||||||
fbb.FinishSizePrefixed(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::unique_ptr<v1::RootTableT> UnPackRootTable(
|
|
||||||
const void *buf,
|
|
||||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
|
||||||
return std::unique_ptr<v1::RootTableT>(GetRootTable(buf)->UnPack(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::unique_ptr<v1::RootTableT> UnPackSizePrefixedRootTable(
|
|
||||||
const void *buf,
|
|
||||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
|
||||||
return std::unique_ptr<v1::RootTableT>(GetSizePrefixedRootTable(buf)->UnPack(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace v1
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_GENERATED_V1_V1_H_
|
|
@ -1,9 +0,0 @@
|
|||||||
namespace v2;
|
|
||||||
|
|
||||||
table RootTable {
|
|
||||||
a:float;
|
|
||||||
b:[uint8];
|
|
||||||
big_vector:[uint8] (vector64);
|
|
||||||
}
|
|
||||||
|
|
||||||
root_type RootTable;
|
|
@ -1,243 +0,0 @@
|
|||||||
// automatically generated by the FlatBuffers compiler, do not modify
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GENERATED_V2_V2_H_
|
|
||||||
#define FLATBUFFERS_GENERATED_V2_V2_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
|
|
||||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
|
||||||
// generated, otherwise it may not be compatible.
|
|
||||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 24 &&
|
|
||||||
FLATBUFFERS_VERSION_MINOR == 3 &&
|
|
||||||
FLATBUFFERS_VERSION_REVISION == 25,
|
|
||||||
"Non-compatible flatbuffers version included");
|
|
||||||
|
|
||||||
namespace v2 {
|
|
||||||
|
|
||||||
struct RootTable;
|
|
||||||
struct RootTableBuilder;
|
|
||||||
struct RootTableT;
|
|
||||||
|
|
||||||
bool operator==(const RootTableT &lhs, const RootTableT &rhs);
|
|
||||||
bool operator!=(const RootTableT &lhs, const RootTableT &rhs);
|
|
||||||
|
|
||||||
inline const ::flatbuffers::TypeTable *RootTableTypeTable();
|
|
||||||
|
|
||||||
struct RootTableT : public ::flatbuffers::NativeTable {
|
|
||||||
typedef RootTable TableType;
|
|
||||||
float a = 0.0f;
|
|
||||||
std::vector<uint8_t> b{};
|
|
||||||
std::vector<uint8_t> big_vector{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RootTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|
||||||
typedef RootTableT NativeTableType;
|
|
||||||
typedef RootTableBuilder Builder;
|
|
||||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
|
||||||
return RootTableTypeTable();
|
|
||||||
}
|
|
||||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
|
||||||
VT_A = 4,
|
|
||||||
VT_B = 6,
|
|
||||||
VT_BIG_VECTOR = 8
|
|
||||||
};
|
|
||||||
float a() const {
|
|
||||||
return GetField<float>(VT_A, 0.0f);
|
|
||||||
}
|
|
||||||
bool mutate_a(float _a = 0.0f) {
|
|
||||||
return SetField<float>(VT_A, _a, 0.0f);
|
|
||||||
}
|
|
||||||
const ::flatbuffers::Vector<uint8_t> *b() const {
|
|
||||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_B);
|
|
||||||
}
|
|
||||||
::flatbuffers::Vector<uint8_t> *mutable_b() {
|
|
||||||
return GetPointer<::flatbuffers::Vector<uint8_t> *>(VT_B);
|
|
||||||
}
|
|
||||||
const ::flatbuffers::Vector64<uint8_t> *big_vector() const {
|
|
||||||
return GetPointer64<const ::flatbuffers::Vector64<uint8_t> *>(VT_BIG_VECTOR);
|
|
||||||
}
|
|
||||||
::flatbuffers::Vector64<uint8_t> *mutable_big_vector() {
|
|
||||||
return GetPointer64<::flatbuffers::Vector64<uint8_t> *>(VT_BIG_VECTOR);
|
|
||||||
}
|
|
||||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
|
||||||
return VerifyTableStart(verifier) &&
|
|
||||||
VerifyField<float>(verifier, VT_A, 4) &&
|
|
||||||
VerifyOffset(verifier, VT_B) &&
|
|
||||||
verifier.VerifyVector(b()) &&
|
|
||||||
VerifyOffset64(verifier, VT_BIG_VECTOR) &&
|
|
||||||
verifier.VerifyVector(big_vector()) &&
|
|
||||||
verifier.EndTable();
|
|
||||||
}
|
|
||||||
RootTableT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
|
||||||
void UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
|
||||||
static ::flatbuffers::Offset<RootTable> Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RootTableBuilder {
|
|
||||||
typedef RootTable Table;
|
|
||||||
::flatbuffers::FlatBufferBuilder64 &fbb_;
|
|
||||||
::flatbuffers::uoffset_t start_;
|
|
||||||
void add_a(float a) {
|
|
||||||
fbb_.AddElement<float>(RootTable::VT_A, a, 0.0f);
|
|
||||||
}
|
|
||||||
void add_b(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> b) {
|
|
||||||
fbb_.AddOffset(RootTable::VT_B, b);
|
|
||||||
}
|
|
||||||
void add_big_vector(::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> big_vector) {
|
|
||||||
fbb_.AddOffset(RootTable::VT_BIG_VECTOR, big_vector);
|
|
||||||
}
|
|
||||||
explicit RootTableBuilder(::flatbuffers::FlatBufferBuilder64 &_fbb)
|
|
||||||
: fbb_(_fbb) {
|
|
||||||
start_ = fbb_.StartTable();
|
|
||||||
}
|
|
||||||
::flatbuffers::Offset<RootTable> Finish() {
|
|
||||||
const auto end = fbb_.EndTable(start_);
|
|
||||||
auto o = ::flatbuffers::Offset<RootTable>(end);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<RootTable> CreateRootTable(
|
|
||||||
::flatbuffers::FlatBufferBuilder64 &_fbb,
|
|
||||||
float a = 0.0f,
|
|
||||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> b = 0,
|
|
||||||
::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> big_vector = 0) {
|
|
||||||
RootTableBuilder builder_(_fbb);
|
|
||||||
builder_.add_big_vector(big_vector);
|
|
||||||
builder_.add_b(b);
|
|
||||||
builder_.add_a(a);
|
|
||||||
return builder_.Finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<RootTable> CreateRootTableDirect(
|
|
||||||
::flatbuffers::FlatBufferBuilder64 &_fbb,
|
|
||||||
float a = 0.0f,
|
|
||||||
const std::vector<uint8_t> *b = nullptr,
|
|
||||||
const std::vector<uint8_t> *big_vector = nullptr) {
|
|
||||||
auto big_vector__ = big_vector ? _fbb.CreateVector64(*big_vector) : 0;
|
|
||||||
auto b__ = b ? _fbb.CreateVector<uint8_t>(*b) : 0;
|
|
||||||
return v2::CreateRootTable(
|
|
||||||
_fbb,
|
|
||||||
a,
|
|
||||||
b__,
|
|
||||||
big_vector__);
|
|
||||||
}
|
|
||||||
|
|
||||||
::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
|
||||||
|
|
||||||
|
|
||||||
inline bool operator==(const RootTableT &lhs, const RootTableT &rhs) {
|
|
||||||
return
|
|
||||||
(lhs.a == rhs.a) &&
|
|
||||||
(lhs.b == rhs.b) &&
|
|
||||||
(lhs.big_vector == rhs.big_vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator!=(const RootTableT &lhs, const RootTableT &rhs) {
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline RootTableT *RootTable::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
|
||||||
auto _o = std::unique_ptr<RootTableT>(new RootTableT());
|
|
||||||
UnPackTo(_o.get(), _resolver);
|
|
||||||
return _o.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void RootTable::UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
|
|
||||||
(void)_o;
|
|
||||||
(void)_resolver;
|
|
||||||
{ auto _e = a(); _o->a = _e; }
|
|
||||||
{ auto _e = b(); if (_e) { _o->b.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->b.begin()); } }
|
|
||||||
{ auto _e = big_vector(); if (_e) { _o->big_vector.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->big_vector.begin()); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<RootTable> RootTable::Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
|
||||||
return CreateRootTable(_fbb, _o, _rehasher);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
|
||||||
(void)_rehasher;
|
|
||||||
(void)_o;
|
|
||||||
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder64 *__fbb; const RootTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
|
||||||
auto _a = _o->a;
|
|
||||||
auto _b = _o->b.size() ? _fbb.CreateVector(_o->b) : 0;
|
|
||||||
auto _big_vector = _o->big_vector.size() ? _fbb.CreateVector64(_o->big_vector) : 0;
|
|
||||||
return v2::CreateRootTable(
|
|
||||||
_fbb,
|
|
||||||
_a,
|
|
||||||
_b,
|
|
||||||
_big_vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const ::flatbuffers::TypeTable *RootTableTypeTable() {
|
|
||||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
|
||||||
{ ::flatbuffers::ET_FLOAT, 0, -1 },
|
|
||||||
{ ::flatbuffers::ET_UCHAR, 1, -1 },
|
|
||||||
{ ::flatbuffers::ET_UCHAR, 1, -1 }
|
|
||||||
};
|
|
||||||
static const char * const names[] = {
|
|
||||||
"a",
|
|
||||||
"b",
|
|
||||||
"big_vector"
|
|
||||||
};
|
|
||||||
static const ::flatbuffers::TypeTable tt = {
|
|
||||||
::flatbuffers::ST_TABLE, 3, type_codes, nullptr, nullptr, nullptr, names
|
|
||||||
};
|
|
||||||
return &tt;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const v2::RootTable *GetRootTable(const void *buf) {
|
|
||||||
return ::flatbuffers::GetRoot<v2::RootTable>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const v2::RootTable *GetSizePrefixedRootTable(const void *buf) {
|
|
||||||
return ::flatbuffers::GetSizePrefixedRoot<v2::RootTable,::flatbuffers::uoffset64_t>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline RootTable *GetMutableRootTable(void *buf) {
|
|
||||||
return ::flatbuffers::GetMutableRoot<RootTable>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline v2::RootTable *GetMutableSizePrefixedRootTable(void *buf) {
|
|
||||||
return ::flatbuffers::GetMutableSizePrefixedRoot<v2::RootTable,::flatbuffers::uoffset64_t>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VerifyRootTableBuffer(
|
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifyBuffer<v2::RootTable>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VerifySizePrefixedRootTableBuffer(
|
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifySizePrefixedBuffer<v2::RootTable,::flatbuffers::uoffset64_t>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FinishRootTableBuffer(
|
|
||||||
::flatbuffers::FlatBufferBuilder64 &fbb,
|
|
||||||
::flatbuffers::Offset<v2::RootTable> root) {
|
|
||||||
fbb.Finish(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FinishSizePrefixedRootTableBuffer(
|
|
||||||
::flatbuffers::FlatBufferBuilder64 &fbb,
|
|
||||||
::flatbuffers::Offset<v2::RootTable> root) {
|
|
||||||
fbb.FinishSizePrefixed(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::unique_ptr<v2::RootTableT> UnPackRootTable(
|
|
||||||
const void *buf,
|
|
||||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
|
||||||
return std::unique_ptr<v2::RootTableT>(GetRootTable(buf)->UnPack(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::unique_ptr<v2::RootTableT> UnPackSizePrefixedRootTable(
|
|
||||||
const void *buf,
|
|
||||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
|
||||||
return std::unique_ptr<v2::RootTableT>(GetSizePrefixedRootTable(buf)->UnPack(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace v2
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_GENERATED_V2_V2_H_
|
|
@ -1,458 +0,0 @@
|
|||||||
#include "offset64_test.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <fstream>
|
|
||||||
#include <limits>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/buffer.h"
|
|
||||||
#include "flatbuffers/flatbuffer_builder.h"
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "tests/64bit/evolution/v1_generated.h"
|
|
||||||
#include "tests/64bit/evolution/v2_generated.h"
|
|
||||||
#include "tests/64bit/test_64bit_generated.h"
|
|
||||||
#include "tests/test_assert.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
namespace tests {
|
|
||||||
|
|
||||||
void Offset64Test() {
|
|
||||||
FlatBufferBuilder64 builder;
|
|
||||||
|
|
||||||
const size_t far_vector_size = 1LL << 2;
|
|
||||||
// Make a large number if wanting to test a real large buffer.
|
|
||||||
const size_t big_vector_size = 1LL << 2;
|
|
||||||
|
|
||||||
{
|
|
||||||
// First create the vectors that will be copied to the buffer.
|
|
||||||
std::vector<uint8_t> far_data;
|
|
||||||
far_data.resize(far_vector_size);
|
|
||||||
far_data[0] = 4;
|
|
||||||
far_data[far_vector_size - 1] = 2;
|
|
||||||
|
|
||||||
std::vector<uint8_t> big_data;
|
|
||||||
big_data.resize(big_vector_size);
|
|
||||||
big_data[0] = 8;
|
|
||||||
big_data[big_vector_size - 1] = 3;
|
|
||||||
|
|
||||||
// Then serialize all the fields that have 64-bit offsets, as these must be
|
|
||||||
// serialized before any 32-bit fields are added to the buffer.
|
|
||||||
const Offset64<Vector<uint8_t>> far_vector_offset =
|
|
||||||
builder.CreateVector64<Vector>(far_data);
|
|
||||||
|
|
||||||
const Offset64<String> far_string_offset =
|
|
||||||
builder.CreateString<Offset64>("some far string");
|
|
||||||
|
|
||||||
const Offset64<Vector64<uint8_t>> big_vector_offset =
|
|
||||||
builder.CreateVector64(big_data);
|
|
||||||
|
|
||||||
// Now that we are done with the 64-bit fields, we can create and add the
|
|
||||||
// normal fields.
|
|
||||||
const Offset<String> near_string_offset =
|
|
||||||
builder.CreateString("some near string");
|
|
||||||
|
|
||||||
// Finish by building the root table by passing in all the offsets.
|
|
||||||
const Offset<RootTable> root_table_offset =
|
|
||||||
CreateRootTable(builder, far_vector_offset, 0, far_string_offset,
|
|
||||||
big_vector_offset, near_string_offset);
|
|
||||||
|
|
||||||
// Finish the buffer.
|
|
||||||
builder.Finish(root_table_offset);
|
|
||||||
|
|
||||||
Verifier::Options options;
|
|
||||||
// Allow the verifier to verify 64-bit buffers.
|
|
||||||
options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE;
|
|
||||||
options.assert = true;
|
|
||||||
|
|
||||||
Verifier verifier(builder.GetBufferPointer(), builder.GetSize(), options);
|
|
||||||
|
|
||||||
TEST_EQ(VerifyRootTableBuffer(verifier), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const RootTable *root_table = GetRootTable(builder.GetBufferPointer());
|
|
||||||
|
|
||||||
// Expect the far vector to be properly sized.
|
|
||||||
TEST_EQ(root_table->far_vector()->size(), far_vector_size);
|
|
||||||
TEST_EQ(root_table->far_vector()->Get(0), 4);
|
|
||||||
TEST_EQ(root_table->far_vector()->Get(far_vector_size - 1), 2);
|
|
||||||
|
|
||||||
TEST_EQ_STR(root_table->far_string()->c_str(), "some far string");
|
|
||||||
|
|
||||||
// Expect the big vector to be properly sized.
|
|
||||||
TEST_EQ(root_table->big_vector()->size(), big_vector_size);
|
|
||||||
TEST_EQ(root_table->big_vector()->Get(0), 8);
|
|
||||||
TEST_EQ(root_table->big_vector()->Get(big_vector_size - 1), 3);
|
|
||||||
|
|
||||||
TEST_EQ_STR(root_table->near_string()->c_str(), "some near string");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Offset64SerializedFirst() {
|
|
||||||
FlatBufferBuilder64 fbb;
|
|
||||||
|
|
||||||
// First create the vectors that will be copied to the buffer.
|
|
||||||
std::vector<uint8_t> data;
|
|
||||||
data.resize(64);
|
|
||||||
|
|
||||||
// Then serialize all the fields that have 64-bit offsets, as these must be
|
|
||||||
// serialized before any 32-bit fields are added to the buffer.
|
|
||||||
fbb.CreateVector64(data);
|
|
||||||
|
|
||||||
// TODO(derekbailey): figure out how to test assertions.
|
|
||||||
// Uncommenting this line should fail the test with an assertion.
|
|
||||||
// fbb.CreateString("some near string");
|
|
||||||
|
|
||||||
fbb.CreateVector64(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Offset64NestedFlatBuffer() {
|
|
||||||
FlatBufferBuilder64 fbb;
|
|
||||||
|
|
||||||
// First serialize a nested buffer.
|
|
||||||
const Offset<String> near_string_offset =
|
|
||||||
fbb.CreateString("nested: some near string");
|
|
||||||
|
|
||||||
// Finish by building the root table by passing in all the offsets.
|
|
||||||
const Offset<RootTable> root_table_offset =
|
|
||||||
CreateRootTable(fbb, 0, 0, 0, 0, near_string_offset, 0);
|
|
||||||
|
|
||||||
// Finish the buffer.
|
|
||||||
fbb.Finish(root_table_offset);
|
|
||||||
|
|
||||||
// Ensure the buffer is valid.
|
|
||||||
const RootTable *root_table = GetRootTable(fbb.GetBufferPointer());
|
|
||||||
TEST_EQ_STR(root_table->near_string()->c_str(), "nested: some near string");
|
|
||||||
|
|
||||||
// Copy the data out of the builder.
|
|
||||||
std::vector<uint8_t> nested_data{ fbb.GetBufferPointer(),
|
|
||||||
fbb.GetBufferPointer() + fbb.GetSize() };
|
|
||||||
|
|
||||||
{
|
|
||||||
// Clear so we can reuse the builder.
|
|
||||||
fbb.Clear();
|
|
||||||
|
|
||||||
const Offset64<Vector64<uint8_t>> nested_flatbuffer_offset =
|
|
||||||
fbb.CreateVector64<Vector64>(nested_data);
|
|
||||||
|
|
||||||
// Now that we are done with the 64-bit fields, we can create and add the
|
|
||||||
// normal fields.
|
|
||||||
const Offset<String> near_string_offset =
|
|
||||||
fbb.CreateString("some near string");
|
|
||||||
|
|
||||||
// Finish by building the root table by passing in all the offsets.
|
|
||||||
const Offset<RootTable> root_table_offset = CreateRootTable(
|
|
||||||
fbb, 0, 0, 0, 0, near_string_offset, nested_flatbuffer_offset);
|
|
||||||
|
|
||||||
// Finish the buffer.
|
|
||||||
fbb.Finish(root_table_offset);
|
|
||||||
|
|
||||||
Verifier::Options options;
|
|
||||||
// Allow the verifier to verify 64-bit buffers.
|
|
||||||
options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE;
|
|
||||||
options.assert = true;
|
|
||||||
|
|
||||||
Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize(), options);
|
|
||||||
|
|
||||||
TEST_EQ(VerifyRootTableBuffer(verifier), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const RootTable *root_table = GetRootTable(fbb.GetBufferPointer());
|
|
||||||
|
|
||||||
// Test that the parent buffer field is ok.
|
|
||||||
TEST_EQ_STR(root_table->near_string()->c_str(), "some near string");
|
|
||||||
|
|
||||||
// Expect nested buffer to be properly sized.
|
|
||||||
TEST_EQ(root_table->nested_root()->size(), nested_data.size());
|
|
||||||
|
|
||||||
// Expect the direct accessors to the nested buffer work.
|
|
||||||
TEST_EQ_STR(root_table->nested_root_nested_root()->near_string()->c_str(),
|
|
||||||
"nested: some near string");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Offset64CreateDirect() {
|
|
||||||
FlatBufferBuilder64 fbb;
|
|
||||||
|
|
||||||
// Create a vector of some data
|
|
||||||
std::vector<uint8_t> data{ 0, 1, 2 };
|
|
||||||
|
|
||||||
// Call the "Direct" creation method to ensure that things are added to the
|
|
||||||
// buffer in the correct order, Offset64 first followed by any Offsets.
|
|
||||||
const Offset<RootTable> root_table_offset = CreateRootTableDirect(
|
|
||||||
fbb, &data, 0, "some far string", &data, "some near string");
|
|
||||||
|
|
||||||
// Finish the buffer.
|
|
||||||
fbb.Finish(root_table_offset);
|
|
||||||
|
|
||||||
Verifier::Options options;
|
|
||||||
// Allow the verifier to verify 64-bit buffers.
|
|
||||||
options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE;
|
|
||||||
options.assert = true;
|
|
||||||
|
|
||||||
Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize(), options);
|
|
||||||
|
|
||||||
TEST_EQ(VerifyRootTableBuffer(verifier), true);
|
|
||||||
|
|
||||||
// Verify the data.
|
|
||||||
const RootTable *root_table = GetRootTable(fbb.GetBufferPointer());
|
|
||||||
TEST_EQ(root_table->far_vector()->size(), data.size());
|
|
||||||
TEST_EQ(root_table->big_vector()->size(), data.size());
|
|
||||||
TEST_EQ_STR(root_table->far_string()->c_str(), "some far string");
|
|
||||||
TEST_EQ_STR(root_table->near_string()->c_str(), "some near string");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Offset64Evolution() {
|
|
||||||
// Some common data for the tests.
|
|
||||||
const std::vector<uint8_t> data = { 1, 2, 3, 4 };
|
|
||||||
const std::vector<uint8_t> big_data = { 6, 7, 8, 9, 10 };
|
|
||||||
|
|
||||||
// Built V1 read V2
|
|
||||||
{
|
|
||||||
// Use the 32-bit builder since V1 doesn't have any 64-bit offsets.
|
|
||||||
FlatBufferBuilder builder;
|
|
||||||
|
|
||||||
builder.Finish(v1::CreateRootTableDirect(builder, 1234, &data));
|
|
||||||
|
|
||||||
// Use each version to get a view at the root table.
|
|
||||||
auto v1_root = v1::GetRootTable(builder.GetBufferPointer());
|
|
||||||
auto v2_root = v2::GetRootTable(builder.GetBufferPointer());
|
|
||||||
|
|
||||||
// Test field equivalents for fields common to V1 and V2.
|
|
||||||
TEST_EQ(v1_root->a(), v2_root->a());
|
|
||||||
|
|
||||||
TEST_EQ(v1_root->b(), v2_root->b());
|
|
||||||
TEST_EQ(v1_root->b()->Get(2), 3);
|
|
||||||
TEST_EQ(v2_root->b()->Get(2), 3);
|
|
||||||
|
|
||||||
// This field is added in V2, so it should be null since V1 couldn't have
|
|
||||||
// written it.
|
|
||||||
TEST_ASSERT(v2_root->big_vector() == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Built V2 read V1
|
|
||||||
{
|
|
||||||
// Use the 64-bit builder since V2 has 64-bit offsets.
|
|
||||||
FlatBufferBuilder64 builder;
|
|
||||||
|
|
||||||
builder.Finish(v2::CreateRootTableDirect(builder, 1234, &data, &big_data));
|
|
||||||
|
|
||||||
// Use each version to get a view at the root table.
|
|
||||||
auto v1_root = v1::GetRootTable(builder.GetBufferPointer());
|
|
||||||
auto v2_root = v2::GetRootTable(builder.GetBufferPointer());
|
|
||||||
|
|
||||||
// Test field equivalents for fields common to V1 and V2.
|
|
||||||
TEST_EQ(v1_root->a(), v2_root->a());
|
|
||||||
|
|
||||||
TEST_EQ(v1_root->b(), v2_root->b());
|
|
||||||
TEST_EQ(v1_root->b()->Get(2), 3);
|
|
||||||
TEST_EQ(v2_root->b()->Get(2), 3);
|
|
||||||
|
|
||||||
// Test that V2 can read the big vector, which V1 doesn't even have
|
|
||||||
// accessors for (i.e. v1_root->big_vector() doesn't exist).
|
|
||||||
TEST_ASSERT(v2_root->big_vector() != nullptr);
|
|
||||||
TEST_EQ(v2_root->big_vector()->size(), big_data.size());
|
|
||||||
TEST_EQ(v2_root->big_vector()->Get(2), 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Built V2 read V1, bigger than max 32-bit buffer sized.
|
|
||||||
// This checks that even a large buffer can still be read by V1.
|
|
||||||
{
|
|
||||||
// Use the 64-bit builder since V2 has 64-bit offsets.
|
|
||||||
FlatBufferBuilder64 builder;
|
|
||||||
|
|
||||||
std::vector<uint8_t> giant_data;
|
|
||||||
giant_data.resize(1LL << 3);
|
|
||||||
giant_data[2] = 42;
|
|
||||||
|
|
||||||
builder.Finish(
|
|
||||||
v2::CreateRootTableDirect(builder, 1234, &data, &giant_data));
|
|
||||||
|
|
||||||
// Use each version to get a view at the root table.
|
|
||||||
auto v1_root = v1::GetRootTable(builder.GetBufferPointer());
|
|
||||||
auto v2_root = v2::GetRootTable(builder.GetBufferPointer());
|
|
||||||
|
|
||||||
// Test field equivalents for fields common to V1 and V2.
|
|
||||||
TEST_EQ(v1_root->a(), v2_root->a());
|
|
||||||
|
|
||||||
TEST_EQ(v1_root->b(), v2_root->b());
|
|
||||||
TEST_EQ(v1_root->b()->Get(2), 3);
|
|
||||||
TEST_EQ(v2_root->b()->Get(2), 3);
|
|
||||||
|
|
||||||
// Test that V2 can read the big vector, which V1 doesn't even have
|
|
||||||
// accessors for (i.e. v1_root->big_vector() doesn't exist).
|
|
||||||
TEST_ASSERT(v2_root->big_vector() != nullptr);
|
|
||||||
TEST_EQ(v2_root->big_vector()->size(), giant_data.size());
|
|
||||||
TEST_EQ(v2_root->big_vector()->Get(2), 42);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Offset64VectorOfStructs() {
|
|
||||||
FlatBufferBuilder64 builder;
|
|
||||||
|
|
||||||
std::vector<LeafStruct> far_leaves;
|
|
||||||
far_leaves.emplace_back(LeafStruct{ 123, 4.567 });
|
|
||||||
far_leaves.emplace_back(LeafStruct{ 987, 6.543 });
|
|
||||||
|
|
||||||
std::vector<LeafStruct> big_leaves;
|
|
||||||
big_leaves.emplace_back(LeafStruct{ 72, 72.8 });
|
|
||||||
big_leaves.emplace_back(LeafStruct{ 82, 82.8 });
|
|
||||||
big_leaves.emplace_back(LeafStruct{ 92, 92.8 });
|
|
||||||
|
|
||||||
// Add the two vectors of leaf structs.
|
|
||||||
const Offset<RootTable> root_table_offset =
|
|
||||||
CreateRootTableDirect(builder, nullptr, 0, nullptr, nullptr, nullptr,
|
|
||||||
nullptr, &far_leaves, &big_leaves);
|
|
||||||
|
|
||||||
// Finish the buffer.
|
|
||||||
builder.Finish(root_table_offset);
|
|
||||||
|
|
||||||
Verifier::Options options;
|
|
||||||
// Allow the verifier to verify 64-bit buffers.
|
|
||||||
options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE;
|
|
||||||
options.assert = true;
|
|
||||||
|
|
||||||
Verifier verifier(builder.GetBufferPointer(), builder.GetSize(), options);
|
|
||||||
|
|
||||||
TEST_EQ(VerifyRootTableBuffer(verifier), true);
|
|
||||||
|
|
||||||
// Verify the data.
|
|
||||||
const RootTable *root_table = GetRootTable(builder.GetBufferPointer());
|
|
||||||
TEST_EQ(root_table->far_struct_vector()->size(), far_leaves.size());
|
|
||||||
TEST_EQ(root_table->far_struct_vector()->Get(0)->a(), 123);
|
|
||||||
TEST_EQ(root_table->far_struct_vector()->Get(0)->b(), 4.567);
|
|
||||||
TEST_EQ(root_table->far_struct_vector()->Get(1)->a(), 987);
|
|
||||||
TEST_EQ(root_table->far_struct_vector()->Get(1)->b(), 6.543);
|
|
||||||
|
|
||||||
TEST_EQ(root_table->big_struct_vector()->size(), big_leaves.size());
|
|
||||||
TEST_EQ(root_table->big_struct_vector()->Get(0)->a(), 72);
|
|
||||||
TEST_EQ(root_table->big_struct_vector()->Get(0)->b(), 72.8);
|
|
||||||
TEST_EQ(root_table->big_struct_vector()->Get(1)->a(), 82);
|
|
||||||
TEST_EQ(root_table->big_struct_vector()->Get(1)->b(), 82.8);
|
|
||||||
TEST_EQ(root_table->big_struct_vector()->Get(2)->a(), 92);
|
|
||||||
TEST_EQ(root_table->big_struct_vector()->Get(2)->b(), 92.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Offset64SizePrefix() {
|
|
||||||
FlatBufferBuilder64 builder;
|
|
||||||
|
|
||||||
// First serialize a nested buffer.
|
|
||||||
const Offset<String> near_string_offset =
|
|
||||||
builder.CreateString("some near string");
|
|
||||||
|
|
||||||
// Finish by building the root table by passing in all the offsets.
|
|
||||||
const Offset<RootTable> root_table_offset =
|
|
||||||
CreateRootTable(builder, 0, 0, 0, 0, near_string_offset, 0);
|
|
||||||
|
|
||||||
// Finish the buffer.
|
|
||||||
FinishSizePrefixedRootTableBuffer(builder, root_table_offset);
|
|
||||||
|
|
||||||
TEST_EQ(GetPrefixedSize<uoffset64_t>(builder.GetBufferPointer()),
|
|
||||||
builder.GetSize() - sizeof(uoffset64_t));
|
|
||||||
|
|
||||||
Verifier::Options options;
|
|
||||||
// Allow the verifier to verify 64-bit buffers.
|
|
||||||
options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE;
|
|
||||||
options.assert = true;
|
|
||||||
|
|
||||||
Verifier verifier(builder.GetBufferPointer(), builder.GetSize(), options);
|
|
||||||
|
|
||||||
TEST_EQ(VerifySizePrefixedRootTableBuffer(verifier), true);
|
|
||||||
|
|
||||||
const RootTable *root_table =
|
|
||||||
GetSizePrefixedRootTable(builder.GetBufferPointer());
|
|
||||||
|
|
||||||
// Verify the fields.
|
|
||||||
TEST_EQ_STR(root_table->near_string()->c_str(), "some near string");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Offset64ManyVectors() {
|
|
||||||
FlatBufferBuilder64 builder;
|
|
||||||
|
|
||||||
// Setup some data to serialize.
|
|
||||||
std::vector<int8_t> data;
|
|
||||||
data.resize(20);
|
|
||||||
data.front() = 42;
|
|
||||||
data.back() = 18;
|
|
||||||
|
|
||||||
const size_t kNumVectors = 20;
|
|
||||||
|
|
||||||
// First serialize all the 64-bit address vectors. We need to store all the
|
|
||||||
// offsets to later add to a wrapper table. We cannot serialize one vector and
|
|
||||||
// then add it to a table immediately, as it would violate the strict ordering
|
|
||||||
// of putting all 64-bit things at the tail of the buffer.
|
|
||||||
std::array<Offset64<Vector<int8_t>>, kNumVectors> offsets_64bit;
|
|
||||||
for (size_t i = 0; i < kNumVectors; ++i) {
|
|
||||||
offsets_64bit[i] = builder.CreateVector64<Vector>(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create some unrelated, 64-bit offset value for later testing.
|
|
||||||
const Offset64<String> far_string_offset =
|
|
||||||
builder.CreateString<Offset64>("some far string");
|
|
||||||
|
|
||||||
// Now place all the offsets into their own wrapper tables. Again, we have to
|
|
||||||
// store the offsets before we can add them to the root table vector.
|
|
||||||
std::array<Offset<WrapperTable>, kNumVectors> offsets_wrapper;
|
|
||||||
for (size_t i = 0; i < kNumVectors; ++i) {
|
|
||||||
offsets_wrapper[i] = CreateWrapperTable(builder, offsets_64bit[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now create the 32-bit vector that is stored in the root table.
|
|
||||||
// TODO(derekbailey): the array type wasn't auto deduced, see if that could be
|
|
||||||
// fixed.
|
|
||||||
const Offset<Vector<Offset<WrapperTable>>> many_vectors_offset =
|
|
||||||
builder.CreateVector<Offset<WrapperTable>>(offsets_wrapper);
|
|
||||||
|
|
||||||
// Finish by building using the root table builder, to exercise a different
|
|
||||||
// code path than the other tests.
|
|
||||||
RootTableBuilder root_table_builder(builder);
|
|
||||||
root_table_builder.add_many_vectors(many_vectors_offset);
|
|
||||||
root_table_builder.add_far_string(far_string_offset);
|
|
||||||
const Offset<RootTable> root_table_offset = root_table_builder.Finish();
|
|
||||||
|
|
||||||
// Finish the buffer.
|
|
||||||
FinishRootTableBuffer(builder, root_table_offset);
|
|
||||||
|
|
||||||
Verifier::Options options;
|
|
||||||
// Allow the verifier to verify 64-bit buffers.
|
|
||||||
options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE;
|
|
||||||
options.assert = true;
|
|
||||||
|
|
||||||
Verifier verifier(builder.GetBufferPointer(), builder.GetSize(), options);
|
|
||||||
|
|
||||||
TEST_EQ(VerifyRootTableBuffer(verifier), true);
|
|
||||||
|
|
||||||
const RootTable *root_table = GetRootTable(builder.GetBufferPointer());
|
|
||||||
|
|
||||||
// Verify the fields.
|
|
||||||
TEST_EQ_STR(root_table->far_string()->c_str(), "some far string");
|
|
||||||
TEST_EQ(root_table->many_vectors()->size(), kNumVectors);
|
|
||||||
|
|
||||||
// Spot check one of the vectors.
|
|
||||||
TEST_EQ(root_table->many_vectors()->Get(12)->vector()->size(), 20);
|
|
||||||
TEST_EQ(root_table->many_vectors()->Get(12)->vector()->Get(0), 42);
|
|
||||||
TEST_EQ(root_table->many_vectors()->Get(12)->vector()->Get(19), 18);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Offset64ForceAlign() {
|
|
||||||
FlatBufferBuilder64 builder;
|
|
||||||
|
|
||||||
// Setup some data to serialize that is less than the force_align size of 32
|
|
||||||
// bytes.
|
|
||||||
std::vector<uint8_t> data{ 1, 2, 3 };
|
|
||||||
|
|
||||||
// Use the CreateDirect which calls the ForceVectorAlign
|
|
||||||
const auto root_table_offset =
|
|
||||||
CreateRootTableDirect(builder, nullptr, 0, nullptr, nullptr, nullptr,
|
|
||||||
nullptr, nullptr, nullptr, nullptr, &data);
|
|
||||||
|
|
||||||
// Finish the buffer.
|
|
||||||
FinishRootTableBuffer(builder, root_table_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace tests
|
|
||||||
} // namespace flatbuffers
|
|
@ -1,20 +0,0 @@
|
|||||||
#ifndef TESTS_64BIT_OFFSET64_TEST_H
|
|
||||||
#define TESTS_64BIT_OFFSET64_TEST_H
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
namespace tests {
|
|
||||||
|
|
||||||
void Offset64Test();
|
|
||||||
void Offset64SerializedFirst();
|
|
||||||
void Offset64NestedFlatBuffer();
|
|
||||||
void Offset64CreateDirect();
|
|
||||||
void Offset64Evolution();
|
|
||||||
void Offset64VectorOfStructs();
|
|
||||||
void Offset64SizePrefix();
|
|
||||||
void Offset64ManyVectors();
|
|
||||||
void Offset64ForceAlign();
|
|
||||||
|
|
||||||
} // namespace tests
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // TESTS_64BIT_OFFSET64_TEST_H
|
|
@ -1,74 +0,0 @@
|
|||||||
// Annotated Flatbuffer Binary
|
|
||||||
//
|
|
||||||
// Schema file: tests/64bit/test_64bit.fbs
|
|
||||||
// Binary file: tests/64bit/test_64bit.bin
|
|
||||||
|
|
||||||
header:
|
|
||||||
+0x00 | 1C 00 00 00 | UOffset32 | 0x0000001C (28) Loc: 0x1C | offset to root table `RootTable`
|
|
||||||
|
|
||||||
padding:
|
|
||||||
+0x04 | 00 00 00 00 | uint8_t[4] | .... | padding
|
|
||||||
|
|
||||||
vtable (RootTable):
|
|
||||||
+0x08 | 14 00 | uint16_t | 0x0014 (20) | size of this vtable
|
|
||||||
+0x0A | 34 00 | uint16_t | 0x0034 (52) | size of referring table
|
|
||||||
+0x0C | 04 00 | VOffset16 | 0x0004 (4) | offset to field `far_vector` (id: 0)
|
|
||||||
+0x0E | 10 00 | VOffset16 | 0x0010 (16) | offset to field `a` (id: 1)
|
|
||||||
+0x10 | 14 00 | VOffset16 | 0x0014 (20) | offset to field `far_string` (id: 2)
|
|
||||||
+0x12 | 24 00 | VOffset16 | 0x0024 (36) | offset to field `big_vector` (id: 3)
|
|
||||||
+0x14 | 20 00 | VOffset16 | 0x0020 (32) | offset to field `near_string` (id: 4)
|
|
||||||
+0x16 | 00 00 | VOffset16 | 0x0000 (0) | offset to field `nested_root` (id: 5) <null> (Vector64)
|
|
||||||
+0x18 | 00 00 | VOffset16 | 0x0000 (0) | offset to field `far_struct_vector` (id: 6) <null> (Vector)
|
|
||||||
+0x1A | 2C 00 | VOffset16 | 0x002C (44) | offset to field `big_struct_vector` (id: 7)
|
|
||||||
|
|
||||||
root_table (RootTable):
|
|
||||||
+0x1C | 14 00 00 00 | SOffset32 | 0x00000014 (20) Loc: 0x08 | offset to vtable
|
|
||||||
+0x20 | D0 00 00 00 00 00 00 00 | UOffset64 | 0x00000000000000D0 (208) Loc: 0xF0 | offset to field `far_vector` (vector)
|
|
||||||
+0x28 | 00 00 00 00 | uint8_t[4] | .... | padding
|
|
||||||
+0x2C | D2 04 00 00 | uint32_t | 0x000004D2 (1234) | table field `a` (Int)
|
|
||||||
+0x30 | 8C 00 00 00 00 00 00 00 | UOffset64 | 0x000000000000008C (140) Loc: 0xBC | offset to field `far_string` (string)
|
|
||||||
+0x38 | 00 00 00 00 | uint8_t[4] | .... | padding
|
|
||||||
+0x3C | 40 00 00 00 | UOffset32 | 0x00000040 (64) Loc: 0x7C | offset to field `near_string` (string)
|
|
||||||
+0x40 | 70 00 00 00 00 00 00 00 | UOffset64 | 0x0000000000000070 (112) Loc: 0xB0 | offset to field `big_vector` (vector64)
|
|
||||||
+0x48 | 08 00 00 00 00 00 00 00 | UOffset64 | 0x0000000000000008 (8) Loc: 0x50 | offset to field `big_struct_vector` (vector64)
|
|
||||||
|
|
||||||
vector64 (RootTable.big_struct_vector):
|
|
||||||
+0x50 | 02 00 00 00 00 00 00 00 | uint64_t | 0x0000000000000002 (2) | length of vector (# items)
|
|
||||||
+0x58 | 0C 00 00 00 | uint32_t | 0x0000000C (12) | struct field `[0].a` of 'LeafStruct' (Int)
|
|
||||||
<4 regions omitted>
|
|
||||||
+0x70 | 33 33 33 33 33 33 22 40 | double | 0x4022333333333333 (9.1) | struct field `[1].b` of 'LeafStruct' (Double)
|
|
||||||
|
|
||||||
padding:
|
|
||||||
+0x78 | 00 00 00 00 | uint8_t[4] | .... | padding
|
|
||||||
|
|
||||||
string (RootTable.near_string):
|
|
||||||
+0x7C | 2F 00 00 00 | uint32_t | 0x0000002F (47) | length of string
|
|
||||||
+0x80 | 74 68 69 73 20 69 73 20 | char[47] | this is | string literal
|
|
||||||
+0x88 | 61 20 6E 65 61 72 20 73 | | a near s
|
|
||||||
+0x90 | 74 72 69 6E 67 20 77 68 | | tring wh
|
|
||||||
+0x98 | 69 63 68 20 68 61 73 20 | | ich has
|
|
||||||
+0xA0 | 61 20 33 32 2D 62 69 74 | | a 32-bit
|
|
||||||
+0xA8 | 20 6F 66 66 73 65 74 | | offset
|
|
||||||
+0xAF | 00 | char | 0x00 (0) | string terminator
|
|
||||||
|
|
||||||
vector64 (RootTable.big_vector):
|
|
||||||
+0xB0 | 04 00 00 00 00 00 00 00 | uint64_t | 0x0000000000000004 (4) | length of vector (# items)
|
|
||||||
+0xB8 | 05 | uint8_t | 0x05 (5) | value[0]
|
|
||||||
<2 regions omitted>
|
|
||||||
+0xBB | 08 | uint8_t | 0x08 (8) | value[3]
|
|
||||||
|
|
||||||
string (RootTable.far_string):
|
|
||||||
+0xBC | 2E 00 00 00 | uint32_t | 0x0000002E (46) | length of string
|
|
||||||
+0xC0 | 74 68 69 73 20 69 73 20 | char[46] | this is | string literal
|
|
||||||
+0xC8 | 61 20 66 61 72 20 73 74 | | a far st
|
|
||||||
+0xD0 | 72 69 6E 67 20 77 68 69 | | ring whi
|
|
||||||
+0xD8 | 63 68 20 68 61 73 20 61 | | ch has a
|
|
||||||
+0xE0 | 20 36 34 2D 62 69 74 20 | | 64-bit
|
|
||||||
+0xE8 | 6F 66 66 73 65 74 | | offset
|
|
||||||
+0xEE | 00 | char | 0x00 (0) | string terminator
|
|
||||||
|
|
||||||
vector (RootTable.far_vector):
|
|
||||||
+0xF0 | 03 00 00 00 | uint32_t | 0x00000003 (3) | length of vector (# items)
|
|
||||||
+0xF4 | 01 | uint8_t | 0x01 (1) | value[0]
|
|
||||||
+0xF5 | 02 | uint8_t | 0x02 (2) | value[1]
|
|
||||||
+0xF6 | 03 | uint8_t | 0x03 (3) | value[2]
|
|