Compare commits

..

2 Commits

Author SHA1 Message Date
Derek Bailey
72b56fd081 FlatBuffers Version 23.5.9 (#7945) 2023-05-09 09:33:30 -07:00
Derek Bailey
63b7b25289 FlatBuffers 64 for C++ (#7935)
* First working hack of adding 64-bit. Don't judge :)

* Made vector_downward work on 64 bit types

* vector_downward uses size_t, added offset64 to reflection

* cleaned up adding offset64 in parser

* Add C++ testing skeleton for 64-bit

* working test for CreateVector64

* working >2 GiB buffers

* support for large strings

* simplified CreateString<> to just provide the offset type

* generalize CreateVector template

* update test_64.afb due to upstream format change

* Added Vector64 type, which is just an alias for vector ATM

* Switch to Offset64 for Vector64

* Update for reflection bfbs output change

* Starting to add support for vector64 type in C++

* made a generic CreateVector that can handle different offsets and vector types

* Support for 32-vector with 64-addressing

* Vector64 basic builder + tests working

* basic support for json vector64 support

* renamed fields in test_64bit.fbs to better reflect their use

* working C++ vector64 builder

* Apply --annotate-sparse-vector to 64-bit tests

* Enable Vector64 for --annotate-sparse-vectors

* Merged from upstream

* Add `near_string` field for testing 32-bit offsets alongside

* keep track of where the 32-bit and 64-bit regions are for flatbufferbuilder

* move template<> outside class body for GCC

* update run.sh to build and run tests

* basic assertion for adding 64-bit offset at the wrong time

* started to separate `FlatBufferBuilder` into two classes, 1 64-bit aware, the other not

* add test for nested flatbuffer vector64, fix bug in alignment of big vectors

* fixed CreateDirect method by iterating by Offset64 first

* internal refactoring of flatbufferbuilder

* block not supported languages in the parser from using 64-bit

* evolution tests for adding a vector64 field

* conformity tests for adding/removing offset64 attributes

* ensure test is for a big buffer

* add parser error tests for `offset64` and `vector64` attributes

* add missing static that GCC only complains about

* remove stdint-uintn.h header that gets automatically added

* move 64-bit CalculateOffset internal

* fixed return size of EndVector

* various fixes on windows

* add SizeT to vector_downward

* minimze range of size changes in vector and builder

* reworked how tracking if 64-offsets are added

* Add ReturnT to EndVector

* small cleanups

* remove need for second Array definition

* combine IndirectHelpers into one definition

* started support for vector of struct

* Support for 32/64-vectors of structs + Offset64

* small cleanups

* add verification for vector64

* add sized prefix for 64-bit buffers

* add fuzzer for 64-bit

* add example of adding many vectors using a wrapper table

* run the new -bfbs-gen-embed logic on the 64-bit tests

* remove run.sh and fix cmakelist issue

* fixed bazel rules

* fixed some PR comments

* add 64-bit tests to cmakelist
2023-05-09 09:16:30 -07:00
227 changed files with 3515 additions and 766 deletions

View File

@@ -4,6 +4,10 @@ All major or breaking changes will be documented in this file, as well as any
new features that should be highlighted. Minor fixes or improvements are not new features that should be highlighted. Minor fixes or improvements are not
necessarily listed. necessarily listed.
## [23.5.9 (May 9 2023)](https://github.com/google/flatbuffers/releases/tag/v23.5.9)
* 64-bit support for C++ (#7935)
## [23.5.8 (May 8 2023)](https://github.com/google/flatbuffers/releases/tag/v23.5.8) ## [23.5.8 (May 8 2023)](https://github.com/google/flatbuffers/releases/tag/v23.5.8)
* add key_field to compiled tests * add key_field to compiled tests

View File

@@ -1,6 +1,6 @@
set(VERSION_MAJOR 23) set(VERSION_MAJOR 23)
set(VERSION_MINOR 5) set(VERSION_MINOR 5)
set(VERSION_PATCH 8) set(VERSION_PATCH 9)
set(VERSION_COMMIT 0) set(VERSION_COMMIT 0)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")

View File

@@ -234,6 +234,8 @@ set(FlatBuffers_Tests_SRCS
tests/native_type_test_impl.cpp tests/native_type_test_impl.cpp
tests/alignment_test.h tests/alignment_test.h
tests/alignment_test.cpp tests/alignment_test.cpp
tests/64bit/offset64_test.h
tests/64bit/offset64_test.cpp
include/flatbuffers/code_generators.h include/flatbuffers/code_generators.h
src/code_generators.cpp src/code_generators.cpp
) )
@@ -527,6 +529,9 @@ if(FLATBUFFERS_BUILD_TESTS)
compile_schema_for_test(tests/native_inline_table_test.fbs "${FLATC_OPT_COMP}") compile_schema_for_test(tests/native_inline_table_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/native_type_test.fbs "${FLATC_OPT}") compile_schema_for_test(tests/native_type_test.fbs "${FLATC_OPT}")
compile_schema_for_test(tests/key_field/key_field_sample.fbs "${FLATC_OPT_COMP}") compile_schema_for_test(tests/key_field/key_field_sample.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/64bit/test_64bit.fbs "${FLATC_OPT_COMP};--bfbs-gen-embed")
compile_schema_for_test(tests/64bit/evolution/v1.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/64bit/evolution/v2.fbs "${FLATC_OPT_COMP}")
if(FLATBUFFERS_CODE_SANITIZE) if(FLATBUFFERS_CODE_SANITIZE)
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE}) add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})

View File

@@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'FlatBuffers' s.name = 'FlatBuffers'
s.version = '23.5.8' s.version = '23.5.9'
s.summary = 'FlatBuffers: Memory Efficient Serialization Library' s.summary = 'FlatBuffers: Memory Efficient Serialization Library'
s.description = "FlatBuffers is a cross platform serialization library architected for s.description = "FlatBuffers is a cross platform serialization library architected for

View File

@@ -57,7 +57,7 @@ class Animal : Table() {
return if(o != 0) bb.getShort(o + bb_pos).toUShort() else 0u return if(o != 0) bb.getShort(o + bb_pos).toUShort() else 0u
} }
companion object { companion object {
fun validateVersion() = Constants.FLATBUFFERS_23_5_8() fun validateVersion() = Constants.FLATBUFFERS_23_5_9()
fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal()) fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal())
fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal { fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal {
_bb.order(ByteOrder.LITTLE_ENDIAN) _bb.order(ByteOrder.LITTLE_ENDIAN)

View File

@@ -1,5 +1,5 @@
name: flat_buffers name: flat_buffers
version: 23.5.8 version: 23.5.9
description: FlatBuffers reading and writing library for Dart. Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team. description: FlatBuffers reading and writing library for Dart. Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team.
homepage: https://github.com/google/flatbuffers homepage: https://github.com/google/flatbuffers
documentation: https://google.github.io/flatbuffers/index.html documentation: https://google.github.io/flatbuffers/index.html

View File

@@ -9,8 +9,8 @@
// Ensure the included flatbuffers.h is the same version as when this file was // Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible. // generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
FLATBUFFERS_VERSION_MINOR == 3 && FLATBUFFERS_VERSION_MINOR == 5 &&
FLATBUFFERS_VERSION_REVISION == 3, FLATBUFFERS_VERSION_REVISION == 9,
"Non-compatible flatbuffers version included"); "Non-compatible flatbuffers version included");
struct Galaxy; struct Galaxy;

View File

@@ -10,7 +10,7 @@ public struct Galaxy : IFlatbufferObject
{ {
private Table __p; private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } } public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_9(); }
public static Galaxy GetRootAsGalaxy(ByteBuffer _bb) { return GetRootAsGalaxy(_bb, new Galaxy()); } public static Galaxy GetRootAsGalaxy(ByteBuffer _bb) { return GetRootAsGalaxy(_bb, new Galaxy()); }
public static Galaxy GetRootAsGalaxy(ByteBuffer _bb, Galaxy obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } public static Galaxy GetRootAsGalaxy(ByteBuffer _bb, Galaxy obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }

View File

@@ -10,7 +10,7 @@ public struct Universe : IFlatbufferObject
{ {
private Table __p; private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } } public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_9(); }
public static Universe GetRootAsUniverse(ByteBuffer _bb) { return GetRootAsUniverse(_bb, new Universe()); } public static Universe GetRootAsUniverse(ByteBuffer _bb) { return GetRootAsUniverse(_bb, new Universe()); }
public static Universe GetRootAsUniverse(ByteBuffer _bb, Universe obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } public static Universe GetRootAsUniverse(ByteBuffer _bb, Universe obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public static bool VerifyUniverse(ByteBuffer _bb) {Google.FlatBuffers.Verifier verifier = new Google.FlatBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, UniverseVerify.Verify); } public static bool VerifyUniverse(ByteBuffer _bb) {Google.FlatBuffers.Verifier verifier = new Google.FlatBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, UniverseVerify.Verify); }

View File

@@ -19,7 +19,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Galaxy extends Table { public final class Galaxy extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static Galaxy getRootAsGalaxy(ByteBuffer _bb) { return getRootAsGalaxy(_bb, new Galaxy()); } public static Galaxy getRootAsGalaxy(ByteBuffer _bb) { return getRootAsGalaxy(_bb, new Galaxy()); }
public static Galaxy getRootAsGalaxy(ByteBuffer _bb, Galaxy obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static Galaxy getRootAsGalaxy(ByteBuffer _bb, Galaxy obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -19,7 +19,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Universe extends Table { public final class Universe extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static Universe getRootAsUniverse(ByteBuffer _bb) { return getRootAsUniverse(_bb, new Universe()); } public static Universe getRootAsUniverse(ByteBuffer _bb) { return getRootAsUniverse(_bb, new Universe()); }
public static Universe getRootAsUniverse(ByteBuffer _bb, Universe obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static Universe getRootAsUniverse(ByteBuffer _bb, Universe obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -32,7 +32,7 @@ class Galaxy : Table() {
return if(o != 0) bb.getLong(o + bb_pos) else 0L return if(o != 0) bb.getLong(o + bb_pos) else 0L
} }
companion object { companion object {
fun validateVersion() = Constants.FLATBUFFERS_23_5_8() fun validateVersion() = Constants.FLATBUFFERS_23_5_9()
fun getRootAsGalaxy(_bb: ByteBuffer): Galaxy = getRootAsGalaxy(_bb, Galaxy()) fun getRootAsGalaxy(_bb: ByteBuffer): Galaxy = getRootAsGalaxy(_bb, Galaxy())
fun getRootAsGalaxy(_bb: ByteBuffer, obj: Galaxy): Galaxy { fun getRootAsGalaxy(_bb: ByteBuffer, obj: Galaxy): Galaxy {
_bb.order(ByteOrder.LITTLE_ENDIAN) _bb.order(ByteOrder.LITTLE_ENDIAN)

View File

@@ -45,7 +45,7 @@ class Universe : Table() {
val o = __offset(6); return if (o != 0) __vector_len(o) else 0 val o = __offset(6); return if (o != 0) __vector_len(o) else 0
} }
companion object { companion object {
fun validateVersion() = Constants.FLATBUFFERS_23_5_8() fun validateVersion() = Constants.FLATBUFFERS_23_5_9()
fun getRootAsUniverse(_bb: ByteBuffer): Universe = getRootAsUniverse(_bb, Universe()) fun getRootAsUniverse(_bb: ByteBuffer): Universe = getRootAsUniverse(_bb, Universe())
fun getRootAsUniverse(_bb: ByteBuffer, obj: Universe): Universe { fun getRootAsUniverse(_bb: ByteBuffer, obj: Universe): Universe {
_bb.order(ByteOrder.LITTLE_ENDIAN) _bb.order(ByteOrder.LITTLE_ENDIAN)

View File

@@ -6,7 +6,7 @@ import FlatBuffers
public struct Galaxy: FlatBufferObject, Verifiable { public struct Galaxy: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_23_5_8() } static func validateVersion() { FlatBuffersVersion_23_5_9() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table
@@ -41,7 +41,7 @@ public struct Galaxy: FlatBufferObject, Verifiable {
public struct Universe: FlatBufferObject, Verifiable { public struct Universe: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_23_5_8() } static func validateVersion() { FlatBuffersVersion_23_5_9() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table

View File

@@ -6,7 +6,7 @@ import FlatBuffers
public struct models_HelloReply: FlatBufferObject, Verifiable { public struct models_HelloReply: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_23_5_8() } static func validateVersion() { FlatBuffersVersion_23_5_9() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table
@@ -53,7 +53,7 @@ extension models_HelloReply: Encodable {
public struct models_HelloRequest: FlatBufferObject, Verifiable { public struct models_HelloRequest: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_23_5_8() } static func validateVersion() { FlatBuffersVersion_23_5_9() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table

View File

@@ -17,6 +17,7 @@
#ifndef FLATBUFFERS_ARRAY_H_ #ifndef FLATBUFFERS_ARRAY_H_
#define FLATBUFFERS_ARRAY_H_ #define FLATBUFFERS_ARRAY_H_
#include <cstdint>
#include <memory> #include <memory>
#include "flatbuffers/base.h" #include "flatbuffers/base.h"
@@ -37,7 +38,7 @@ template<typename T, uint16_t length> class Array {
public: public:
typedef uint16_t size_type; typedef uint16_t size_type;
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type; typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
typedef VectorConstIterator<T, return_type> const_iterator; typedef VectorConstIterator<T, return_type, uoffset_t> const_iterator;
typedef VectorReverseIterator<const_iterator> const_reverse_iterator; typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
// If T is a LE-scalar or a struct (!scalar_tag::value). // If T is a LE-scalar or a struct (!scalar_tag::value).
@@ -158,11 +159,13 @@ template<typename T, uint16_t length> class Array {
// Specialization for Array[struct] with access using Offset<void> pointer. // Specialization for Array[struct] with access using Offset<void> pointer.
// This specialization used by idl_gen_text.cpp. // This specialization used by idl_gen_text.cpp.
template<typename T, uint16_t length> class Array<Offset<T>, length> { template<typename T, uint16_t length, template<typename> class OffsetT>
class Array<OffsetT<T>, length> {
static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T"); static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
public: public:
typedef const void *return_type; typedef const void *return_type;
typedef uint16_t size_type;
const uint8_t *Data() const { return data_; } const uint8_t *Data() const { return data_; }

View File

@@ -43,6 +43,7 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include <algorithm> #include <algorithm>
#include <limits>
#include <iterator> #include <iterator>
#include <memory> #include <memory>
@@ -140,7 +141,7 @@
#define FLATBUFFERS_VERSION_MAJOR 23 #define FLATBUFFERS_VERSION_MAJOR 23
#define FLATBUFFERS_VERSION_MINOR 5 #define FLATBUFFERS_VERSION_MINOR 5
#define FLATBUFFERS_VERSION_REVISION 8 #define FLATBUFFERS_VERSION_REVISION 9
#define FLATBUFFERS_STRING_EXPAND(X) #X #define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
namespace flatbuffers { namespace flatbuffers {
@@ -323,9 +324,11 @@ namespace flatbuffers {
// Also, using a consistent offset type maintains compatibility of serialized // Also, using a consistent offset type maintains compatibility of serialized
// offset values between 32bit and 64bit systems. // offset values between 32bit and 64bit systems.
typedef uint32_t uoffset_t; typedef uint32_t uoffset_t;
typedef uint64_t uoffset64_t;
// Signed offsets for references that can go in both directions. // Signed offsets for references that can go in both directions.
typedef int32_t soffset_t; typedef int32_t soffset_t;
typedef int64_t soffset64_t;
// Offset/index used in v-tables, can be changed to uint8_t in // Offset/index used in v-tables, can be changed to uint8_t in
// format forks to save a bit of space if desired. // format forks to save a bit of space if desired.
@@ -334,7 +337,8 @@ typedef uint16_t voffset_t;
typedef uintmax_t largest_scalar_t; typedef uintmax_t largest_scalar_t;
// In 32bits, this evaluates to 2GB - 1 // In 32bits, this evaluates to 2GB - 1
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1) #define FLATBUFFERS_MAX_BUFFER_SIZE std::numeric_limits<::flatbuffers::soffset_t>::max()
#define FLATBUFFERS_MAX_64_BUFFER_SIZE std::numeric_limits<::flatbuffers::soffset64_t>::max()
// The minimum size buffer that can be a valid flatbuffer. // The minimum size buffer that can be a valid flatbuffer.
// Includes the offset to the root table (uoffset_t), the offset to the vtable // Includes the offset to the root table (uoffset_t), the offset to the vtable

View File

@@ -25,14 +25,33 @@ namespace flatbuffers {
// Wrapper for uoffset_t to allow safe template specialization. // Wrapper for uoffset_t to allow safe template specialization.
// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset). // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
template<typename T> struct Offset { template<typename T = void> struct Offset {
uoffset_t o; // The type of offset to use.
typedef uoffset_t offset_type;
offset_type o;
Offset() : o(0) {} Offset() : o(0) {}
Offset(uoffset_t _o) : o(_o) {} Offset(const offset_type _o) : o(_o) {}
Offset<void> Union() const { return Offset<void>(o); } Offset<> Union() const { return o; }
bool IsNull() const { return !o; } bool IsNull() const { return !o; }
}; };
// Wrapper for uoffset64_t Offsets.
template<typename T = void> struct Offset64 {
// The type of offset to use.
typedef uoffset64_t offset_type;
offset_type o;
Offset64() : o(0) {}
Offset64(const offset_type offset) : o(offset) {}
Offset64<> Union() const { return o; }
bool IsNull() const { return !o; }
};
// Litmus check for ensuring the Offsets are the expected size.
static_assert(sizeof(Offset<>) == 4, "Offset has wrong size");
static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size");
inline void EndianCheck() { inline void EndianCheck() {
int endiantest = 1; int endiantest = 1;
// If this fails, see FLATBUFFERS_LITTLEENDIAN above. // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
@@ -75,35 +94,59 @@ template<typename T> struct IndirectHelper {
typedef T return_type; typedef T return_type;
typedef T mutable_return_type; typedef T mutable_return_type;
static const size_t element_stride = sizeof(T); static const size_t element_stride = sizeof(T);
static return_type Read(const uint8_t *p, uoffset_t i) {
static return_type Read(const uint8_t *p, const size_t i) {
return EndianScalar((reinterpret_cast<const T *>(p))[i]); return EndianScalar((reinterpret_cast<const T *>(p))[i]);
} }
static return_type Read(uint8_t *p, uoffset_t i) { static mutable_return_type Read(uint8_t *p, const size_t i) {
return Read(const_cast<const uint8_t *>(p), i); return reinterpret_cast<mutable_return_type>(
Read(const_cast<const uint8_t *>(p), i));
} }
}; };
template<typename T> struct IndirectHelper<Offset<T>> {
// For vector of Offsets.
template<typename T, template<typename> class OffsetT>
struct IndirectHelper<OffsetT<T>> {
typedef const T *return_type; typedef const T *return_type;
typedef T *mutable_return_type; typedef T *mutable_return_type;
static const size_t element_stride = sizeof(uoffset_t); typedef typename OffsetT<T>::offset_type offset_type;
static return_type Read(const uint8_t *p, uoffset_t i) { static const offset_type element_stride = sizeof(offset_type);
p += i * sizeof(uoffset_t);
return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p)); static return_type Read(const uint8_t *const p, const offset_type i) {
// Offsets are relative to themselves, so first update the pointer to
// point to the offset location.
const uint8_t *const offset_location = p + i * element_stride;
// Then read the scalar value of the offset (which may be 32 or 64-bits) and
// then determine the relative location from the offset location.
return reinterpret_cast<return_type>(
offset_location + ReadScalar<offset_type>(offset_location));
} }
static mutable_return_type Read(uint8_t *p, uoffset_t i) { static mutable_return_type Read(uint8_t *const p, const offset_type i) {
p += i * sizeof(uoffset_t); // Offsets are relative to themselves, so first update the pointer to
return reinterpret_cast<mutable_return_type>(p + ReadScalar<uoffset_t>(p)); // point to the offset location.
uint8_t *const offset_location = p + i * element_stride;
// Then read the scalar value of the offset (which may be 32 or 64-bits) and
// then determine the relative location from the offset location.
return reinterpret_cast<mutable_return_type>(
offset_location + ReadScalar<offset_type>(offset_location));
} }
}; };
// For vector of structs.
template<typename T> struct IndirectHelper<const T *> { template<typename T> struct IndirectHelper<const T *> {
typedef const T *return_type; typedef const T *return_type;
typedef T *mutable_return_type; typedef T *mutable_return_type;
static const size_t element_stride = sizeof(T); static const size_t element_stride = sizeof(T);
static return_type Read(const uint8_t *p, uoffset_t i) {
return reinterpret_cast<return_type>(p + i * sizeof(T)); static return_type Read(const uint8_t *const p, const size_t i) {
// Structs are stored inline, relative to the first struct pointer.
return reinterpret_cast<return_type>(p + i * element_stride);
} }
static mutable_return_type Read(uint8_t *p, uoffset_t i) { static mutable_return_type Read(uint8_t *const p, const size_t i) {
return reinterpret_cast<mutable_return_type>(p + i * sizeof(T)); // Structs are stored inline, relative to the first struct pointer.
return reinterpret_cast<mutable_return_type>(p + i * element_stride);
} }
}; };
@@ -130,23 +173,25 @@ inline bool BufferHasIdentifier(const void *buf, const char *identifier,
/// @cond FLATBUFFERS_INTERNAL /// @cond FLATBUFFERS_INTERNAL
// Helpers to get a typed pointer to the root object contained in the buffer. // Helpers to get a typed pointer to the root object contained in the buffer.
template<typename T> T *GetMutableRoot(void *buf) { template<typename T> T *GetMutableRoot(void *buf) {
if (!buf) return nullptr;
EndianCheck(); EndianCheck();
return reinterpret_cast<T *>( return reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>(buf) + reinterpret_cast<uint8_t *>(buf) +
EndianScalar(*reinterpret_cast<uoffset_t *>(buf))); EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
} }
template<typename T> T *GetMutableSizePrefixedRoot(void *buf) { template<typename T, typename SizeT = uoffset_t>
return GetMutableRoot<T>(reinterpret_cast<uint8_t *>(buf) + T *GetMutableSizePrefixedRoot(void *buf) {
sizeof(uoffset_t)); return GetMutableRoot<T>(reinterpret_cast<uint8_t *>(buf) + sizeof(SizeT));
} }
template<typename T> const T *GetRoot(const void *buf) { template<typename T> const T *GetRoot(const void *buf) {
return GetMutableRoot<T>(const_cast<void *>(buf)); return GetMutableRoot<T>(const_cast<void *>(buf));
} }
template<typename T> const T *GetSizePrefixedRoot(const void *buf) { template<typename T, typename SizeT = uoffset_t>
return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t)); const T *GetSizePrefixedRoot(const void *buf) {
return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(SizeT));
} }
} // namespace flatbuffers } // namespace flatbuffers

View File

@@ -18,12 +18,15 @@
#define FLATBUFFERS_FLATBUFFER_BUILDER_H_ #define FLATBUFFERS_FLATBUFFER_BUILDER_H_
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <functional> #include <functional>
#include <initializer_list> #include <initializer_list>
#include <type_traits>
#include "flatbuffers/allocator.h" #include "flatbuffers/allocator.h"
#include "flatbuffers/array.h" #include "flatbuffers/array.h"
#include "flatbuffers/base.h" #include "flatbuffers/base.h"
#include "flatbuffers/buffer.h"
#include "flatbuffers/buffer_ref.h" #include "flatbuffers/buffer_ref.h"
#include "flatbuffers/default_allocator.h" #include "flatbuffers/default_allocator.h"
#include "flatbuffers/detached_buffer.h" #include "flatbuffers/detached_buffer.h"
@@ -40,8 +43,9 @@ namespace flatbuffers {
// Converts a Field ID to a virtual table offset. // Converts a Field ID to a virtual table offset.
inline voffset_t FieldIndexToOffset(voffset_t field_id) { inline voffset_t FieldIndexToOffset(voffset_t field_id) {
// Should correspond to what EndTable() below builds up. // Should correspond to what EndTable() below builds up.
const voffset_t fixed_fields = 2 * sizeof(voffset_t); // Vtable size and Object Size. const voffset_t fixed_fields =
return fixed_fields + field_id * sizeof(voffset_t); 2 * sizeof(voffset_t); // Vtable size and Object Size.
return fixed_fields + field_id * sizeof(voffset_t);
} }
template<typename T, typename Alloc = std::allocator<T>> template<typename T, typename Alloc = std::allocator<T>>
@@ -68,8 +72,13 @@ T *data(std::vector<T, Alloc> &v) {
/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/ /// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
/// `CreateVector` functions. Do this is depth-first order to build up a tree to /// `CreateVector` functions. Do this is depth-first order to build up a tree to
/// the root. `Finish()` wraps up the buffer ready for transport. /// the root. `Finish()` wraps up the buffer ready for transport.
class FlatBufferBuilder { template<bool Is64Aware = false> class FlatBufferBuilderImpl {
public: public:
// This switches the size type of the builder, based on if its 64-bit aware
// (uoffset64_t) or not (uoffset_t).
typedef
typename std::conditional<Is64Aware, uoffset64_t, uoffset_t>::type SizeT;
/// @brief Default constructor for FlatBufferBuilder. /// @brief Default constructor for FlatBufferBuilder.
/// @param[in] initial_size The initial size of the buffer, in bytes. Defaults /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
/// to `1024`. /// to `1024`.
@@ -81,13 +90,16 @@ class FlatBufferBuilder {
/// minimum alignment upon reallocation. Only needed if you intend to store /// minimum alignment upon reallocation. Only needed if you intend to store
/// types with custom alignment AND you wish to read the buffer in-place /// types with custom alignment AND you wish to read the buffer in-place
/// directly after creation. /// directly after creation.
explicit FlatBufferBuilder( explicit FlatBufferBuilderImpl(
size_t initial_size = 1024, Allocator *allocator = nullptr, size_t initial_size = 1024, Allocator *allocator = nullptr,
bool own_allocator = false, bool own_allocator = false,
size_t buffer_minalign = AlignOf<largest_scalar_t>()) size_t buffer_minalign = AlignOf<largest_scalar_t>())
: buf_(initial_size, allocator, own_allocator, buffer_minalign), : buf_(initial_size, allocator, own_allocator, buffer_minalign,
static_cast<SizeT>(Is64Aware ? FLATBUFFERS_MAX_64_BUFFER_SIZE
: FLATBUFFERS_MAX_BUFFER_SIZE)),
num_field_loc(0), num_field_loc(0),
max_voffset_(0), max_voffset_(0),
length_of_64_bit_region_(0),
nested(false), nested(false),
finished(false), finished(false),
minalign_(1), minalign_(1),
@@ -98,10 +110,13 @@ class FlatBufferBuilder {
} }
/// @brief Move constructor for FlatBufferBuilder. /// @brief Move constructor for FlatBufferBuilder.
FlatBufferBuilder(FlatBufferBuilder &&other) noexcept FlatBufferBuilderImpl(FlatBufferBuilderImpl &&other) noexcept
: buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()), : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>(),
static_cast<SizeT>(Is64Aware ? FLATBUFFERS_MAX_64_BUFFER_SIZE
: FLATBUFFERS_MAX_BUFFER_SIZE)),
num_field_loc(0), num_field_loc(0),
max_voffset_(0), max_voffset_(0),
length_of_64_bit_region_(0),
nested(false), nested(false),
finished(false), finished(false),
minalign_(1), minalign_(1),
@@ -116,18 +131,19 @@ class FlatBufferBuilder {
} }
/// @brief Move assignment operator for FlatBufferBuilder. /// @brief Move assignment operator for FlatBufferBuilder.
FlatBufferBuilder &operator=(FlatBufferBuilder &&other) noexcept { FlatBufferBuilderImpl &operator=(FlatBufferBuilderImpl &&other) noexcept {
// Move construct a temporary and swap idiom // Move construct a temporary and swap idiom
FlatBufferBuilder temp(std::move(other)); FlatBufferBuilderImpl temp(std::move(other));
Swap(temp); Swap(temp);
return *this; return *this;
} }
void Swap(FlatBufferBuilder &other) { void Swap(FlatBufferBuilderImpl &other) {
using std::swap; using std::swap;
buf_.swap(other.buf_); buf_.swap(other.buf_);
swap(num_field_loc, other.num_field_loc); swap(num_field_loc, other.num_field_loc);
swap(max_voffset_, other.max_voffset_); swap(max_voffset_, other.max_voffset_);
swap(length_of_64_bit_region_, other.length_of_64_bit_region_);
swap(nested, other.nested); swap(nested, other.nested);
swap(finished, other.finished); swap(finished, other.finished);
swap(minalign_, other.minalign_); swap(minalign_, other.minalign_);
@@ -136,7 +152,7 @@ class FlatBufferBuilder {
swap(string_pool, other.string_pool); swap(string_pool, other.string_pool);
} }
~FlatBufferBuilder() { ~FlatBufferBuilderImpl() {
if (string_pool) delete string_pool; if (string_pool) delete string_pool;
} }
@@ -153,12 +169,36 @@ class FlatBufferBuilder {
nested = false; nested = false;
finished = false; finished = false;
minalign_ = 1; minalign_ = 1;
length_of_64_bit_region_ = 0;
if (string_pool) string_pool->clear(); if (string_pool) string_pool->clear();
} }
/// @brief The current size of the serialized buffer, counting from the end. /// @brief The current size of the serialized buffer, counting from the end.
/// @return Returns an `SizeT` with the current size of the buffer.
SizeT GetSize() const { return buf_.size(); }
/// @brief The current size of the serialized buffer relative to the end of
/// the 32-bit region.
/// @return Returns an `uoffset_t` with the current size of the buffer. /// @return Returns an `uoffset_t` with the current size of the buffer.
uoffset_t GetSize() const { return buf_.size(); } template<bool is_64 = Is64Aware>
// Only enable this method for the 64-bit builder, as only that builder is
// concerned with the 32/64-bit boundary, and should be the one to bare any
// run time costs.
typename std::enable_if<is_64, uoffset_t>::type GetSizeRelative32BitRegion()
const {
//[32-bit region][64-bit region]
// [XXXXXXXXXXXXXXXXXXX] GetSize()
// [YYYYYYYYYYYYY] length_of_64_bit_region_
// [ZZZZ] return size
return static_cast<uoffset_t>(GetSize() - length_of_64_bit_region_);
}
template<bool is_64 = Is64Aware>
// Only enable this method for the 32-bit builder.
typename std::enable_if<!is_64, uoffset_t>::type GetSizeRelative32BitRegion()
const {
return static_cast<uoffset_t>(GetSize());
}
/// @brief Get the serialized buffer (after you call `Finish()`). /// @brief Get the serialized buffer (after you call `Finish()`).
/// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
@@ -270,14 +310,16 @@ class FlatBufferBuilder {
} }
// Write a single aligned scalar to the buffer // Write a single aligned scalar to the buffer
template<typename T> uoffset_t PushElement(T element) { template<typename T, typename ReturnT = uoffset_t>
ReturnT PushElement(T element) {
AssertScalarT<T>(); AssertScalarT<T>();
Align(sizeof(T)); Align(sizeof(T));
buf_.push_small(EndianScalar(element)); buf_.push_small(EndianScalar(element));
return GetSize(); return CalculateOffset<ReturnT>();
} }
template<typename T> uoffset_t PushElement(Offset<T> off) { template<typename T, template<typename> class OffsetT = Offset>
uoffset_t PushElement(OffsetT<T> off) {
// Special case for offsets: see ReferTo below. // Special case for offsets: see ReferTo below.
return PushElement(ReferTo(off.o)); return PushElement(ReferTo(off.o));
} }
@@ -307,11 +349,16 @@ class FlatBufferBuilder {
AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0)); AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
} }
template<typename T> void AddOffset(voffset_t field, Offset64<T> off) {
if (off.IsNull()) return; // Don't store.
AddElement(field, ReferTo(off.o), static_cast<uoffset64_t>(0));
}
template<typename T> void AddStruct(voffset_t field, const T *structptr) { template<typename T> void AddStruct(voffset_t field, const T *structptr) {
if (!structptr) return; // Default, don't store. if (!structptr) return; // Default, don't store.
Align(AlignOf<T>()); Align(AlignOf<T>());
buf_.push_small(*structptr); buf_.push_small(*structptr);
TrackField(field, GetSize()); TrackField(field, CalculateOffset<uoffset_t>());
} }
void AddStructOffset(voffset_t field, uoffset_t off) { void AddStructOffset(voffset_t field, uoffset_t off) {
@@ -322,12 +369,29 @@ class FlatBufferBuilder {
// This function converts them to be relative to the current location // This function converts them to be relative to the current location
// in the buffer (when stored here), pointing upwards. // in the buffer (when stored here), pointing upwards.
uoffset_t ReferTo(uoffset_t off) { uoffset_t ReferTo(uoffset_t off) {
// Align to ensure GetSize() below is correct. // Align to ensure GetSizeRelative32BitRegion() below is correct.
Align(sizeof(uoffset_t)); Align(sizeof(uoffset_t));
// Offset must refer to something already in buffer. // 32-bit offsets are relative to the tail of the 32-bit region of the
const uoffset_t size = GetSize(); // buffer. For most cases (without 64-bit entities) this is equivalent to
// size of the whole buffer (e.g. GetSize())
return ReferTo(off, GetSizeRelative32BitRegion());
}
uoffset64_t ReferTo(uoffset64_t off) {
// Align to ensure GetSize() below is correct.
Align(sizeof(uoffset64_t));
// 64-bit offsets are relative to tail of the whole buffer
return ReferTo(off, GetSize());
}
template<typename T, typename T2> T ReferTo(const T off, const T2 size) {
FLATBUFFERS_ASSERT(off && off <= size); FLATBUFFERS_ASSERT(off && off <= size);
return size - off + static_cast<uoffset_t>(sizeof(uoffset_t)); return size - off + static_cast<T>(sizeof(T));
}
template<typename T> T ReferTo(const T off, const T size) {
FLATBUFFERS_ASSERT(off && off <= size);
return size - off + static_cast<T>(sizeof(T));
} }
void NotNested() { void NotNested() {
@@ -349,7 +413,7 @@ class FlatBufferBuilder {
uoffset_t StartTable() { uoffset_t StartTable() {
NotNested(); NotNested();
nested = true; nested = true;
return GetSize(); return GetSizeRelative32BitRegion();
} }
// This finishes one serialized object by generating the vtable if it's a // This finishes one serialized object by generating the vtable if it's a
@@ -360,7 +424,9 @@ class FlatBufferBuilder {
FLATBUFFERS_ASSERT(nested); FLATBUFFERS_ASSERT(nested);
// Write the vtable offset, which is the start of any Table. // Write the vtable offset, which is the start of any Table.
// We fill its value later. // We fill its value later.
const uoffset_t vtableoffsetloc = PushElement<soffset_t>(0); // This is relative to the end of the 32-bit region.
const uoffset_t vtable_offset_loc =
static_cast<uoffset_t>(PushElement<soffset_t>(0));
// Write a vtable, which consists entirely of voffset_t elements. // Write a vtable, which consists entirely of voffset_t elements.
// It starts with the number of offsets, followed by a type id, followed // It starts with the number of offsets, followed by a type id, followed
// by the offsets themselves. In reverse: // by the offsets themselves. In reverse:
@@ -370,7 +436,7 @@ class FlatBufferBuilder {
(std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)), (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
FieldIndexToOffset(0)); FieldIndexToOffset(0));
buf_.fill_big(max_voffset_); buf_.fill_big(max_voffset_);
auto table_object_size = vtableoffsetloc - start; const uoffset_t table_object_size = vtable_offset_loc - start;
// Vtable use 16bit offsets. // Vtable use 16bit offsets.
FLATBUFFERS_ASSERT(table_object_size < 0x10000); FLATBUFFERS_ASSERT(table_object_size < 0x10000);
WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t), WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
@@ -380,7 +446,8 @@ class FlatBufferBuilder {
for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc); for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
it < buf_.scratch_end(); it += sizeof(FieldLoc)) { it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
auto field_location = reinterpret_cast<FieldLoc *>(it); auto field_location = reinterpret_cast<FieldLoc *>(it);
auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off); const voffset_t pos =
static_cast<voffset_t>(vtable_offset_loc - field_location->off);
// If this asserts, it means you've set a field twice. // If this asserts, it means you've set a field twice.
FLATBUFFERS_ASSERT( FLATBUFFERS_ASSERT(
!ReadScalar<voffset_t>(buf_.data() + field_location->id)); !ReadScalar<voffset_t>(buf_.data() + field_location->id));
@@ -389,7 +456,7 @@ class FlatBufferBuilder {
ClearOffsets(); ClearOffsets();
auto vt1 = reinterpret_cast<voffset_t *>(buf_.data()); auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
auto vt1_size = ReadScalar<voffset_t>(vt1); auto vt1_size = ReadScalar<voffset_t>(vt1);
auto vt_use = GetSize(); auto vt_use = GetSizeRelative32BitRegion();
// See if we already have generated a vtable with this exact same // See if we already have generated a vtable with this exact same
// layout before. If so, make it point to the old one, remove this one. // layout before. If so, make it point to the old one, remove this one.
if (dedup_vtables_) { if (dedup_vtables_) {
@@ -400,23 +467,24 @@ class FlatBufferBuilder {
auto vt2_size = ReadScalar<voffset_t>(vt2); auto vt2_size = ReadScalar<voffset_t>(vt2);
if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue; if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
vt_use = *vt_offset_ptr; vt_use = *vt_offset_ptr;
buf_.pop(GetSize() - static_cast<size_t>(vtableoffsetloc)); buf_.pop(GetSizeRelative32BitRegion() - vtable_offset_loc);
break; break;
} }
} }
// If this is a new vtable, remember it. // If this is a new vtable, remember it.
if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); } if (vt_use == GetSizeRelative32BitRegion()) {
buf_.scratch_push_small(vt_use);
}
// Fill the vtable offset we created above. // Fill the vtable offset we created above.
// The offset points from the beginning of the object to where the // The offset points from the beginning of the object to where the vtable is
// vtable is stored. // stored.
// Offsets default direction is downward in memory for future format // Offsets default direction is downward in memory for future format
// flexibility (storing all vtables at the start of the file). // flexibility (storing all vtables at the start of the file).
WriteScalar(buf_.data_at(vtableoffsetloc), WriteScalar(buf_.data_at(vtable_offset_loc + length_of_64_bit_region_),
static_cast<soffset_t>(vt_use) - static_cast<soffset_t>(vt_use) -
static_cast<soffset_t>(vtableoffsetloc)); static_cast<soffset_t>(vtable_offset_loc));
nested = false; nested = false;
return vtableoffsetloc; return vtable_offset_loc;
} }
FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]]) FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]])
@@ -426,14 +494,20 @@ class FlatBufferBuilder {
// This checks a required field has been set in a given table that has // This checks a required field has been set in a given table that has
// just been constructed. // just been constructed.
template<typename T> void Required(Offset<T> table, voffset_t field); template<typename T> void Required(Offset<T> table, voffset_t field) {
auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
// If this fails, the caller will show what field needs to be set.
FLATBUFFERS_ASSERT(ok);
(void)ok;
}
uoffset_t StartStruct(size_t alignment) { uoffset_t StartStruct(size_t alignment) {
Align(alignment); Align(alignment);
return GetSize(); return GetSizeRelative32BitRegion();
} }
uoffset_t EndStruct() { return GetSize(); } uoffset_t EndStruct() { return GetSizeRelative32BitRegion(); }
void ClearOffsets() { void ClearOffsets() {
buf_.scratch_pop(num_field_loc * sizeof(FieldLoc)); buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
@@ -442,15 +516,18 @@ class FlatBufferBuilder {
} }
// Aligns such that when "len" bytes are written, an object can be written // Aligns such that when "len" bytes are written, an object can be written
// after it with "alignment" without padding. // after it (forward in the buffer) with "alignment" without padding.
void PreAlign(size_t len, size_t alignment) { void PreAlign(size_t len, size_t alignment) {
if (len == 0) return; if (len == 0) return;
TrackMinAlign(alignment); TrackMinAlign(alignment);
buf_.fill(PaddingBytes(GetSize() + len, alignment)); buf_.fill(PaddingBytes(GetSize() + len, alignment));
} }
template<typename T> void PreAlign(size_t len) {
AssertScalarT<T>(); // Aligns such than when "len" bytes are written, an object of type `AlignT`
PreAlign(len, AlignOf<T>()); // can be written after it (forward in the buffer) without padding.
template<typename AlignT> void PreAlign(size_t len) {
AssertScalarT<AlignT>();
PreAlign(len, AlignOf<AlignT>());
} }
/// @endcond /// @endcond
@@ -458,34 +535,35 @@ class FlatBufferBuilder {
/// @param[in] str A const char pointer to the data to be stored as a string. /// @param[in] str A const char pointer to the data to be stored as a string.
/// @param[in] len The number of bytes that should be stored from `str`. /// @param[in] len The number of bytes that should be stored from `str`.
/// @return Returns the offset in the buffer where the string starts. /// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateString(const char *str, size_t len) { template<template<typename> class OffsetT = Offset>
NotNested(); OffsetT<String> CreateString(const char *str, size_t len) {
PreAlign<uoffset_t>(len + 1); // Always 0-terminated. CreateStringImpl(str, len);
buf_.fill(1); return OffsetT<String>(
PushBytes(reinterpret_cast<const uint8_t *>(str), len); CalculateOffset<typename OffsetT<String>::offset_type>());
PushElement(static_cast<uoffset_t>(len));
return Offset<String>(GetSize());
} }
/// @brief Store a string in the buffer, which is null-terminated. /// @brief Store a string in the buffer, which is null-terminated.
/// @param[in] str A const char pointer to a C-string to add to the buffer. /// @param[in] str A const char pointer to a C-string to add to the buffer.
/// @return Returns the offset in the buffer where the string starts. /// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateString(const char *str) { template<template<typename> class OffsetT = Offset>
return CreateString(str, strlen(str)); OffsetT<String> CreateString(const char *str) {
return CreateString<OffsetT>(str, strlen(str));
} }
/// @brief Store a string in the buffer, which is null-terminated. /// @brief Store a string in the buffer, which is null-terminated.
/// @param[in] str A char pointer to a C-string to add to the buffer. /// @param[in] str A char pointer to a C-string to add to the buffer.
/// @return Returns the offset in the buffer where the string starts. /// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateString(char *str) { template<template<typename> class OffsetT = Offset>
return CreateString(str, strlen(str)); OffsetT<String> CreateString(char *str) {
return CreateString<OffsetT>(str, strlen(str));
} }
/// @brief Store a string in the buffer, which can contain any binary data. /// @brief Store a string in the buffer, which can contain any binary data.
/// @param[in] str A const reference to a std::string to store in the buffer. /// @param[in] str A const reference to a std::string to store in the buffer.
/// @return Returns the offset in the buffer where the string starts. /// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateString(const std::string &str) { template<template<typename> class OffsetT = Offset>
return CreateString(str.c_str(), str.length()); OffsetT<String> CreateString(const std::string &str) {
return CreateString<OffsetT>(str.c_str(), str.length());
} }
// clang-format off // clang-format off
@@ -493,8 +571,9 @@ class FlatBufferBuilder {
/// @brief Store a string in the buffer, which can contain any binary data. /// @brief Store a string in the buffer, which can contain any binary data.
/// @param[in] str A const string_view to copy in to the buffer. /// @param[in] str A const string_view to copy in to the buffer.
/// @return Returns the offset in the buffer where the string starts. /// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateString(flatbuffers::string_view str) { template<template <typename> class OffsetT = Offset>
return CreateString(str.data(), str.size()); OffsetT<String>CreateString(flatbuffers::string_view str) {
return CreateString<OffsetT>(str.data(), str.size());
} }
#endif // FLATBUFFERS_HAS_STRING_VIEW #endif // FLATBUFFERS_HAS_STRING_VIEW
// clang-format on // clang-format on
@@ -502,16 +581,21 @@ class FlatBufferBuilder {
/// @brief Store a string in the buffer, which can contain any binary data. /// @brief Store a string in the buffer, which can contain any binary data.
/// @param[in] str A const pointer to a `String` struct to add to the buffer. /// @param[in] str A const pointer to a `String` struct to add to the buffer.
/// @return Returns the offset in the buffer where the string starts /// @return Returns the offset in the buffer where the string starts
Offset<String> CreateString(const String *str) { template<template<typename> class OffsetT = Offset>
return str ? CreateString(str->c_str(), str->size()) : 0; OffsetT<String> CreateString(const String *str) {
return str ? CreateString<OffsetT>(str->c_str(), str->size()) : 0;
} }
/// @brief Store a string in the buffer, which can contain any binary data. /// @brief Store a string in the buffer, which can contain any binary data.
/// @param[in] str A const reference to a std::string like type with support /// @param[in] str A const reference to a std::string like type with support
/// of T::c_str() and T::length() to store in the buffer. /// of T::c_str() and T::length() to store in the buffer.
/// @return Returns the offset in the buffer where the string starts. /// @return Returns the offset in the buffer where the string starts.
template<typename T> Offset<String> CreateString(const T &str) { template<template<typename> class OffsetT = Offset,
return CreateString(str.c_str(), str.length()); // No need to explicitly declare the T type, let the compiler deduce
// it.
int &...ExplicitArgumentBarrier, typename T>
OffsetT<String> CreateString(const T &str) {
return CreateString<OffsetT>(str.c_str(), str.length());
} }
/// @brief Store a string in the buffer, which can contain any binary data. /// @brief Store a string in the buffer, which can contain any binary data.
@@ -523,12 +607,14 @@ class FlatBufferBuilder {
/// @return Returns the offset in the buffer where the string starts. /// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateSharedString(const char *str, size_t len) { Offset<String> CreateSharedString(const char *str, size_t len) {
FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK); FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
if (!string_pool) if (!string_pool) {
string_pool = new StringOffsetMap(StringOffsetCompare(buf_)); string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
}
const size_t size_before_string = buf_.size(); const size_t size_before_string = buf_.size();
// Must first serialize the string, since the set is all offsets into // Must first serialize the string, since the set is all offsets into
// buffer. // buffer.
auto off = CreateString(str, len); const Offset<String> off = CreateString<Offset>(str, len);
auto it = string_pool->find(off); auto it = string_pool->find(off);
// If it exists we reuse existing serialized data! // If it exists we reuse existing serialized data!
if (it != string_pool->end()) { if (it != string_pool->end()) {
@@ -584,21 +670,27 @@ class FlatBufferBuilder {
} }
/// @cond FLATBUFFERS_INTERNAL /// @cond FLATBUFFERS_INTERNAL
uoffset_t EndVector(size_t len) { template<typename LenT = uoffset_t, typename ReturnT = uoffset_t>
ReturnT EndVector(size_t len) {
FLATBUFFERS_ASSERT(nested); // Hit if no corresponding StartVector. FLATBUFFERS_ASSERT(nested); // Hit if no corresponding StartVector.
nested = false; nested = false;
return PushElement(static_cast<uoffset_t>(len)); return PushElement<LenT, ReturnT>(static_cast<LenT>(len));
} }
template<template<typename> class OffsetT = Offset, typename LenT = uint32_t>
void StartVector(size_t len, size_t elemsize, size_t alignment) { void StartVector(size_t len, size_t elemsize, size_t alignment) {
NotNested(); NotNested();
nested = true; nested = true;
PreAlign<uoffset_t>(len * elemsize); // Align to the Length type of the vector (either 32-bit or 64-bit), so
// that the length of the buffer can be added without padding.
PreAlign<LenT>(len * elemsize);
PreAlign(len * elemsize, alignment); // Just in case elemsize > uoffset_t. PreAlign(len * elemsize, alignment); // Just in case elemsize > uoffset_t.
} }
template<typename T> void StartVector(size_t len) { template<typename T, template<typename> class OffsetT = Offset,
return StartVector(len, sizeof(T), AlignOf<T>()); typename LenT = uint32_t>
void StartVector(size_t len) {
return StartVector<OffsetT, LenT>(len, sizeof(T), AlignOf<T>());
} }
// Call this right before StartVector/CreateVector if you want to force the // Call this right before StartVector/CreateVector if you want to force the
@@ -623,31 +715,40 @@ class FlatBufferBuilder {
/// @brief Serialize an array into a FlatBuffer `vector`. /// @brief Serialize an array into a FlatBuffer `vector`.
/// @tparam T The data type of the array elements. /// @tparam T The data type of the array elements.
/// @tparam OffsetT the type of offset to return
/// @tparam VectorT the type of vector to cast to.
/// @param[in] v A pointer to the array of type `T` to serialize into the /// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`. /// buffer as a `vector`.
/// @param[in] len The number of elements to serialize. /// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `TOffset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) { template<template<typename...> class OffsetT = Offset,
template<typename...> class VectorT = Vector,
int &...ExplicitArgumentBarrier, typename T>
OffsetT<VectorT<T>> CreateVector(const T *v, size_t len) {
// The type of the length field in the vector.
typedef typename VectorT<T>::size_type LenT;
typedef typename OffsetT<VectorT<T>>::offset_type offset_type;
// If this assert hits, you're specifying a template argument that is // If this assert hits, you're specifying a template argument that is
// causing the wrong overload to be selected, remove it. // causing the wrong overload to be selected, remove it.
AssertScalarT<T>(); AssertScalarT<T>();
StartVector<T>(len); StartVector<T, OffsetT, LenT>(len);
if (len == 0) { return Offset<Vector<T>>(EndVector(len)); } if (len > 0) {
// clang-format off // clang-format off
#if FLATBUFFERS_LITTLEENDIAN #if FLATBUFFERS_LITTLEENDIAN
PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T)); PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
#else #else
if (sizeof(T) == 1) { if (sizeof(T) == 1) {
PushBytes(reinterpret_cast<const uint8_t *>(v), len); PushBytes(reinterpret_cast<const uint8_t *>(v), len);
} else { } else {
for (auto i = len; i > 0; ) { for (auto i = len; i > 0; ) {
PushElement(v[--i]); PushElement(v[--i]);
}
} }
} #endif
#endif // clang-format on
// clang-format on }
return Offset<Vector<T>>(EndVector(len)); return OffsetT<VectorT<T>>(EndVector<LenT, offset_type>(len));
} }
/// @brief Serialize an array like object into a FlatBuffer `vector`. /// @brief Serialize an array like object into a FlatBuffer `vector`.
@@ -689,6 +790,12 @@ class FlatBufferBuilder {
return CreateVector(data(v), v.size()); return CreateVector(data(v), v.size());
} }
template<template<typename...> class VectorT = Vector64,
int &...ExplicitArgumentBarrier, typename T>
Offset64<VectorT<T>> CreateVector64(const std::vector<T> &v) {
return CreateVector<Offset64, VectorT>(data(v), v.size());
}
// vector<bool> may be implemented using a bit-set, so we can't access it as // vector<bool> may be implemented using a bit-set, so we can't access it as
// an array. Instead, read elements manually. // an array. Instead, read elements manually.
// Background: https://isocpp.org/blog/2012/11/on-vectorbool // Background: https://isocpp.org/blog/2012/11/on-vectorbool
@@ -785,47 +892,19 @@ class FlatBufferBuilder {
/// @param[in] len The number of elements to serialize. /// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T> template<typename T, template<typename...> class OffsetT = Offset,
Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) { template<typename...> class VectorT = Vector>
StartVector(len * sizeof(T) / AlignOf<T>(), sizeof(T), AlignOf<T>()); OffsetT<VectorT<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
// The type of the length field in the vector.
typedef typename VectorT<T>::size_type LenT;
typedef typename OffsetT<VectorT<const T *>>::offset_type offset_type;
StartVector<OffsetT, LenT>(len * sizeof(T) / AlignOf<T>(), sizeof(T),
AlignOf<T>());
if (len > 0) { if (len > 0) {
PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len); PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
} }
return Offset<Vector<const T *>>(EndVector(len)); return OffsetT<VectorT<const T *>>(EndVector<LenT, offset_type>(len));
}
/// @brief Serialize an array of native structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @tparam S The data type of the native struct array elements.
/// @param[in] v A pointer to the array of type `S` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @param[in] pack_func Pointer to a function to convert the native struct
/// to the FlatBuffer struct.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename S>
Offset<Vector<const T *>> CreateVectorOfNativeStructs(
const S *v, size_t len, T (*const pack_func)(const S &)) {
FLATBUFFERS_ASSERT(pack_func);
auto structs = StartVectorOfStructs<T>(len);
for (size_t i = 0; i < len; i++) { structs[i] = pack_func(v[i]); }
return EndVectorOfStructs<T>(len);
}
/// @brief Serialize an array of native structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @tparam S The data type of the native struct array elements.
/// @param[in] v A pointer to the array of type `S` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename S>
Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
size_t len) {
extern T Pack(const S &);
return CreateVectorOfNativeStructs(v, len, Pack);
} }
/// @brief Serialize an array of structs into a FlatBuffer `vector`. /// @brief Serialize an array of structs into a FlatBuffer `vector`.
@@ -873,10 +952,52 @@ class FlatBufferBuilder {
/// serialize into the buffer as a `vector`. /// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T, typename Alloc = std::allocator<T>> template<typename T, template<typename...> class OffsetT = Offset,
Offset<Vector<const T *>> CreateVectorOfStructs( template<typename...> class VectorT = Vector,
typename Alloc = std::allocator<T>>
OffsetT<VectorT<const T *>> CreateVectorOfStructs(
const std::vector<T, Alloc> &v) { const std::vector<T, Alloc> &v) {
return CreateVectorOfStructs(data(v), v.size()); return CreateVectorOfStructs<T, OffsetT, VectorT>(data(v), v.size());
}
template<template<typename...> class VectorT = Vector64, int &..., typename T>
Offset64<VectorT<const T *>> CreateVectorOfStructs64(
const std::vector<T> &v) {
return CreateVectorOfStructs<T, Offset64, VectorT>(data(v), v.size());
}
/// @brief Serialize an array of native structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @tparam S The data type of the native struct array elements.
/// @param[in] v A pointer to the array of type `S` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @param[in] pack_func Pointer to a function to convert the native struct
/// to the FlatBuffer struct.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename S>
Offset<Vector<const T *>> CreateVectorOfNativeStructs(
const S *v, size_t len, T (*const pack_func)(const S &)) {
FLATBUFFERS_ASSERT(pack_func);
auto structs = StartVectorOfStructs<T>(len);
for (size_t i = 0; i < len; i++) { structs[i] = pack_func(v[i]); }
return EndVectorOfStructs<T>(len);
}
/// @brief Serialize an array of native structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @tparam S The data type of the native struct array elements.
/// @param[in] v A pointer to the array of type `S` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename S>
Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
size_t len) {
extern T Pack(const S &);
return CreateVectorOfNativeStructs(v, len, Pack);
} }
/// @brief Serialize a `std::vector` of native structs into a FlatBuffer /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
@@ -979,14 +1100,14 @@ class FlatBufferBuilder {
/// @cond FLATBUFFERS_INTERNAL /// @cond FLATBUFFERS_INTERNAL
template<typename T> struct TableKeyComparator { template<typename T> struct TableKeyComparator {
TableKeyComparator(vector_downward &buf) : buf_(buf) {} explicit TableKeyComparator(vector_downward<SizeT> &buf) : buf_(buf) {}
TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {} TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {}
bool operator()(const Offset<T> &a, const Offset<T> &b) const { bool operator()(const Offset<T> &a, const Offset<T> &b) const {
auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o)); auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o)); auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
return table_a->KeyCompareLessThan(table_b); return table_a->KeyCompareLessThan(table_b);
} }
vector_downward &buf_; vector_downward<SizeT> &buf_;
private: private:
FLATBUFFERS_DELETE_FUNC( FLATBUFFERS_DELETE_FUNC(
@@ -1034,7 +1155,7 @@ class FlatBufferBuilder {
NotNested(); NotNested();
StartVector(len, elemsize, alignment); StartVector(len, elemsize, alignment);
buf_.make_space(len * elemsize); buf_.make_space(len * elemsize);
auto vec_start = GetSize(); const uoffset_t vec_start = GetSizeRelative32BitRegion();
auto vec_end = EndVector(len); auto vec_end = EndVector(len);
*buf = buf_.data_at(vec_start); *buf = buf_.data_at(vec_start);
return vec_end; return vec_end;
@@ -1085,7 +1206,8 @@ class FlatBufferBuilder {
NotNested(); NotNested();
Align(AlignOf<T>()); Align(AlignOf<T>());
buf_.push_small(structobj); buf_.push_small(structobj);
return Offset<const T *>(GetSize()); return Offset<const T *>(
CalculateOffset<typename Offset<const T *>::offset_type>());
} }
/// @brief Finish serializing a buffer by writing the root offset. /// @brief Finish serializing a buffer by writing the root offset.
@@ -1109,7 +1231,7 @@ class FlatBufferBuilder {
Finish(root.o, file_identifier, true); Finish(root.o, file_identifier, true);
} }
void SwapBufAllocator(FlatBufferBuilder &other) { void SwapBufAllocator(FlatBufferBuilderImpl &other) {
buf_.swap_allocator(other.buf_); buf_.swap_allocator(other.buf_);
} }
@@ -1119,16 +1241,23 @@ class FlatBufferBuilder {
protected: protected:
// You shouldn't really be copying instances of this class. // You shouldn't really be copying instances of this class.
FlatBufferBuilder(const FlatBufferBuilder &); FlatBufferBuilderImpl(const FlatBufferBuilderImpl &);
FlatBufferBuilder &operator=(const FlatBufferBuilder &); FlatBufferBuilderImpl &operator=(const FlatBufferBuilderImpl &);
void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) { void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
NotNested(); NotNested();
buf_.clear_scratch(); buf_.clear_scratch();
const size_t prefix_size = size_prefix ? sizeof(SizeT) : 0;
// Make sure we track the alignment of the size prefix.
TrackMinAlign(prefix_size);
const size_t root_offset_size = sizeof(uoffset_t);
const size_t file_id_size = file_identifier ? kFileIdentifierLength : 0;
// This will cause the whole buffer to be aligned. // This will cause the whole buffer to be aligned.
PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) + PreAlign(prefix_size + root_offset_size + file_id_size, minalign_);
(file_identifier ? kFileIdentifierLength : 0),
minalign_);
if (file_identifier) { if (file_identifier) {
FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength); FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
PushBytes(reinterpret_cast<const uint8_t *>(file_identifier), PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
@@ -1144,7 +1273,7 @@ class FlatBufferBuilder {
voffset_t id; voffset_t id;
}; };
vector_downward buf_; vector_downward<SizeT> buf_;
// Accumulating offsets of table members while it is being built. // Accumulating offsets of table members while it is being built.
// We store these in the scratch pad of buf_, after the vtable offsets. // We store these in the scratch pad of buf_, after the vtable offsets.
@@ -1153,6 +1282,31 @@ class FlatBufferBuilder {
// possible vtable. // possible vtable.
voffset_t max_voffset_; voffset_t max_voffset_;
// This is the length of the 64-bit region of the buffer. The buffer supports
// 64-bit offsets by forcing serialization of those elements in the "tail"
// region of the buffer (i.e. "64-bit region"). To properly keep track of
// offsets that are referenced from the tail of the buffer to not overflow
// their size (e.g. Offset is a uint32_t type), the boundary of the 32-/64-bit
// regions must be tracked.
//
// [ Complete FlatBuffer ]
// [32-bit region][64-bit region]
// ^ ^
// | Tail of the buffer.
// |
// Tail of the 32-bit region of the buffer.
//
// This keeps track of the size of the 64-bit region so that the tail of the
// 32-bit region can be calculated as `GetSize() - length_of_64_bit_region_`.
//
// This will remain 0 if no 64-bit offset types are added to the buffer.
size_t length_of_64_bit_region_;
// When true, 64-bit offsets can still be added to the builder. When false,
// only 32-bit offsets can be added, and attempts to add a 64-bit offset will
// raise an assertion. This is typically a compile-time error in ordering the
// serialization of 64-bit offset fields not at the tail of the buffer.
// Ensure objects are not nested. // Ensure objects are not nested.
bool nested; bool nested;
@@ -1166,14 +1320,15 @@ class FlatBufferBuilder {
bool dedup_vtables_; bool dedup_vtables_;
struct StringOffsetCompare { struct StringOffsetCompare {
StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {} explicit StringOffsetCompare(const vector_downward<SizeT> &buf)
: buf_(&buf) {}
bool operator()(const Offset<String> &a, const Offset<String> &b) const { bool operator()(const Offset<String> &a, const Offset<String> &b) const {
auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o)); auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o)); auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
return StringLessThan(stra->data(), stra->size(), strb->data(), return StringLessThan(stra->data(), stra->size(), strb->data(),
strb->size()); strb->size());
} }
const vector_downward *buf_; const vector_downward<SizeT> *buf_;
}; };
// For use with CreateSharedString. Instantiated on first use only. // For use with CreateSharedString. Instantiated on first use only.
@@ -1181,23 +1336,122 @@ class FlatBufferBuilder {
StringOffsetMap *string_pool; StringOffsetMap *string_pool;
private: private:
void CanAddOffset64() {
// If you hit this assertion, you are attempting to add a 64-bit offset to
// a 32-bit only builder. This is because the builder has overloads that
// differ only on the offset size returned: e.g.:
//
// FlatBufferBuilder builder;
// Offset64<String> string_offset = builder.CreateString<Offset64>();
//
// Either use a 64-bit aware builder, or don't try to create an Offset64
// return type.
//
// TODO(derekbailey): we can probably do more enable_if to avoid this
// looking like its possible to the user.
static_assert(Is64Aware, "cannot add 64-bit offset to a 32-bit builder");
// If you hit this assertion, you are attempting to add an 64-bit offset
// item after already serializing a 32-bit item. All 64-bit offsets have to
// added to the tail of the buffer before any 32-bit items can be added.
// Otherwise some items might not be addressable due to the maximum range of
// the 32-bit offset.
FLATBUFFERS_ASSERT(GetSize() == length_of_64_bit_region_);
}
/// @brief Store a string in the buffer, which can contain any binary data.
/// @param[in] str A const char pointer to the data to be stored as a string.
/// @param[in] len The number of bytes that should be stored from `str`.
/// @return Returns the offset in the buffer where the string starts.
void CreateStringImpl(const char *str, size_t len) {
NotNested();
PreAlign<uoffset_t>(len + 1); // Always 0-terminated.
buf_.fill(1);
PushBytes(reinterpret_cast<const uint8_t *>(str), len);
PushElement(static_cast<uoffset_t>(len));
}
// Allocates space for a vector of structures. // Allocates space for a vector of structures.
// Must be completed with EndVectorOfStructs(). // Must be completed with EndVectorOfStructs().
template<typename T> T *StartVectorOfStructs(size_t vector_size) { template<typename T, template<typename> class OffsetT = Offset>
StartVector(vector_size * sizeof(T) / AlignOf<T>(), sizeof(T), T *StartVectorOfStructs(size_t vector_size) {
AlignOf<T>()); StartVector<OffsetT>(vector_size * sizeof(T) / AlignOf<T>(), sizeof(T),
AlignOf<T>());
return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T))); return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
} }
// End the vector of structures in the flatbuffers. // End the vector of structures in the flatbuffers.
// Vector should have previously be started with StartVectorOfStructs(). // Vector should have previously be started with StartVectorOfStructs().
template<typename T, template<typename> class OffsetT = Offset>
OffsetT<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
return OffsetT<Vector<const T *>>(
EndVector<typename Vector<const T *>::size_type,
typename OffsetT<Vector<const T *>>::offset_type>(
vector_size));
}
template<typename T> template<typename T>
Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) { typename std::enable_if<std::is_same<T, uoffset_t>::value, T>::type
return Offset<Vector<const T *>>(EndVector(vector_size)); CalculateOffset() {
// Default to the end of the 32-bit region. This may or may not be the end
// of the buffer, depending on if any 64-bit offsets have been added.
return GetSizeRelative32BitRegion();
}
// Specializations to handle the 64-bit CalculateOffset, which is relative to
// end of the buffer.
template<typename T>
typename std::enable_if<std::is_same<T, uoffset64_t>::value, T>::type
CalculateOffset() {
// This should never be compiled in when not using a 64-bit builder.
static_assert(Is64Aware, "invalid 64-bit offset in 32-bit builder");
// Store how big the 64-bit region of the buffer is, so we can determine
// where the 32/64 bit boundary is.
length_of_64_bit_region_ = GetSize();
return length_of_64_bit_region_;
} }
}; };
/// @} /// @}
// Hack to `FlatBufferBuilder` mean `FlatBufferBuilder<false>` or
// `FlatBufferBuilder<>`, where the template < > syntax is required.
typedef FlatBufferBuilderImpl<false> FlatBufferBuilder;
typedef FlatBufferBuilderImpl<true> FlatBufferBuilder64;
// These are external due to GCC not allowing them in the class.
// See: https://stackoverflow.com/q/8061456/868247
template<>
template<>
inline Offset64<String> FlatBufferBuilder64::CreateString(const char *str,
size_t len) {
CanAddOffset64();
CreateStringImpl(str, len);
return Offset64<String>(
CalculateOffset<typename Offset64<String>::offset_type>());
}
// Used to distinguish from real Offsets.
template<typename T = void> struct EmptyOffset {};
// TODO(derekbailey): it would be nice to combine these two methods.
template<>
template<>
inline void FlatBufferBuilder64::StartVector<Offset64, uint32_t>(
size_t len, size_t elemsize, size_t alignment) {
CanAddOffset64();
StartVector<EmptyOffset, uint32_t>(len, elemsize, alignment);
}
template<>
template<>
inline void FlatBufferBuilder64::StartVector<Offset64, uint64_t>(
size_t len, size_t elemsize, size_t alignment) {
CanAddOffset64();
StartVector<EmptyOffset, uint64_t>(len, elemsize, alignment);
}
/// Helpers to get a typed pointer to objects that are currently being built. /// Helpers to get a typed pointer to objects that are currently being built.
/// @warning Creating new objects will lead to reallocations and invalidates /// @warning Creating new objects will lead to reallocations and invalidates
/// the pointer! /// the pointer!
@@ -1212,15 +1466,6 @@ const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
return GetMutableTemporaryPointer<T>(fbb, offset); return GetMutableTemporaryPointer<T>(fbb, offset);
} }
template<typename T>
void FlatBufferBuilder::Required(Offset<T> table, voffset_t field) {
auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
// If this fails, the caller will show what field needs to be set.
FLATBUFFERS_ASSERT(ok);
(void)ok;
}
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATBUFFERS_VECTOR_DOWNWARD_H_ #endif // FLATBUFFERS_FLATBUFFER_BUILDER_H_

View File

@@ -76,8 +76,9 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
} }
/// @brief This return the prefixed size of a FlatBuffer. /// @brief This return the prefixed size of a FlatBuffer.
inline uoffset_t GetPrefixedSize(const uint8_t *buf) { template<typename SizeT = uoffset_t>
return ReadScalar<uoffset_t>(buf); inline SizeT GetPrefixedSize(const uint8_t *buf) {
return ReadScalar<SizeT>(buf);
} }
// Base class for native objects (FlatBuffer data de-serialized into native // Base class for native objects (FlatBuffer data de-serialized into native

View File

@@ -45,26 +45,27 @@ namespace flatbuffers {
// of type tokens. // of type tokens.
// clang-format off // clang-format off
#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ #define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 0) \ TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 0) \
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 1) /* begin scalar/int */ \ TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 1) /* begin scalar/int */ \
TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool, 2) \ TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool, 2) \
TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8, 3) \ TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8, 3) \
TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 4) \ TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 4) \
TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16, 5) \ TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16, 5) \
TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16, 6) \ TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16, 6) \
TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32, 7) \ TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32, 7) \
TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32, 8) \ TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32, 8) \
TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64, 9) \ TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64, 9) \
TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64, 10) /* end int */ \ TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64, 10) /* end int */ \
TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32, 11) /* begin float */ \ TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32, 11) /* begin float */ \
TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double, 12) /* end float/scalar */ TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double, 12) /* end float/scalar */
#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \ #define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>, 13) \ TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>, 13) \
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>, 14) \ TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>, 14) \
TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>, 15) \ TD(VECTOR64, "", Offset64<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>, 18) \
TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>, 16) TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>, 15) \
TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>, 16)
#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \ #define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>, 17) TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>, 17)
// The fields are: // The fields are:
// - enum // - enum
// - FlatBuffers schema type. // - FlatBuffers schema type.
@@ -139,6 +140,8 @@ inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; } inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE && inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
t <= BASE_TYPE_UCHAR; } t <= BASE_TYPE_UCHAR; }
inline bool IsVector (BaseType t) { return t == BASE_TYPE_VECTOR ||
t == BASE_TYPE_VECTOR64; }
inline bool IsUnsigned(BaseType t) { inline bool IsUnsigned(BaseType t) {
return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) || return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
@@ -210,7 +213,8 @@ struct Type {
bool Deserialize(const Parser &parser, const reflection::Type *type); bool Deserialize(const Parser &parser, const reflection::Type *type);
BaseType base_type; BaseType base_type;
BaseType element; // only set if t == BASE_TYPE_VECTOR BaseType element; // only set if t == BASE_TYPE_VECTOR or
// BASE_TYPE_VECTOR64
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE, EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
// or for an integral type derived from an enum. // or for an integral type derived from an enum.
@@ -326,6 +330,7 @@ struct FieldDef : public Definition {
shared(false), shared(false),
native_inline(false), native_inline(false),
flexbuffer(false), flexbuffer(false),
offset64(false),
presence(kDefault), presence(kDefault),
nested_flatbuffer(nullptr), nested_flatbuffer(nullptr),
padding(0), padding(0),
@@ -352,6 +357,7 @@ struct FieldDef : public Definition {
bool native_inline; // Field will be defined inline (instead of as a pointer) bool native_inline; // Field will be defined inline (instead of as a pointer)
// for native tables if field is a struct. // for native tables if field is a struct.
bool flexbuffer; // This field contains FlexBuffer data. bool flexbuffer; // This field contains FlexBuffer data.
bool offset64; // If the field uses 64-bit offsets.
enum Presence { enum Presence {
// Field must always be present. // Field must always be present.
@@ -528,9 +534,7 @@ inline bool IsUnionType(const Type &type) {
return IsUnion(type) && IsInteger(type.base_type); return IsUnion(type) && IsInteger(type.base_type);
} }
inline bool IsVector(const Type &type) { inline bool IsVector(const Type &type) { return IsVector(type.base_type); }
return type.base_type == BASE_TYPE_VECTOR;
}
inline bool IsVectorOfStruct(const Type &type) { inline bool IsVectorOfStruct(const Type &type) {
return IsVector(type) && IsStruct(type.VectorType()); return IsVector(type) && IsStruct(type.VectorType());
@@ -952,6 +956,13 @@ class Parser : public ParserState {
known_attributes_["native_default"] = true; known_attributes_["native_default"] = true;
known_attributes_["flexbuffer"] = true; known_attributes_["flexbuffer"] = true;
known_attributes_["private"] = true; known_attributes_["private"] = true;
// An attribute added to a field to indicate that is uses 64-bit addressing.
known_attributes_["offset64"] = true;
// An attribute added to a vector field to indicate that it uses 64-bit
// addressing and it has a 64-bit length.
known_attributes_["vector64"] = true;
} }
// Copying is not allowed // Copying is not allowed
@@ -1062,7 +1073,7 @@ class Parser : public ParserState {
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field, FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn, size_t parent_fieldn,
const StructDef *parent_struct_def, const StructDef *parent_struct_def,
uoffset_t count, size_t count,
bool inside_vector = false); bool inside_vector = false);
template<typename F> template<typename F>
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn, FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
@@ -1074,7 +1085,7 @@ class Parser : public ParserState {
void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def, void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
const Value &val); const Value &val);
template<typename F> template<typename F>
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body); FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(size_t &count, F body);
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue, FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
FieldDef *field, size_t fieldn); FieldDef *field, size_t fieldn);
FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array); FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
@@ -1139,6 +1150,7 @@ class Parser : public ParserState {
bool SupportsAdvancedArrayFeatures() const; bool SupportsAdvancedArrayFeatures() const;
bool SupportsOptionalScalars() const; bool SupportsOptionalScalars() const;
bool SupportsDefaultVectorsAndStrings() const; bool SupportsDefaultVectorsAndStrings() const;
bool Supports64BitOffsets() const;
Namespace *UniqueNamespace(Namespace *ns); Namespace *UniqueNamespace(Namespace *ns);
FLATBUFFERS_CHECKED_ERROR RecurseError(); FLATBUFFERS_CHECKED_ERROR RecurseError();
@@ -1288,8 +1300,7 @@ extern bool GenerateSwift(const Parser &parser, const std::string &path,
// Generate a schema file from the internal representation, useful after // Generate a schema file from the internal representation, useful after
// parsing a .proto schema. // parsing a .proto schema.
extern std::string GenerateFBS(const Parser &parser, extern std::string GenerateFBS(const Parser &parser,
const std::string &file_name, const std::string &file_name, bool no_log);
bool no_log);
extern bool GenerateFBS(const Parser &parser, const std::string &path, extern bool GenerateFBS(const Parser &parser, const std::string &path,
const std::string &file_name, bool no_log); const std::string &file_name, bool no_log);

View File

@@ -66,6 +66,7 @@ inline size_t GetTypeSize(reflection::BaseType base_type) {
4, // Union 4, // Union
0, // Array. Only used in structs. 0 was chosen to prevent out-of-bounds 0, // Array. Only used in structs. 0 was chosen to prevent out-of-bounds
// errors. // errors.
8, // Vector64
0 // MaxBaseType. This must be kept the last entry in this array. 0 // MaxBaseType. This must be kept the last entry in this array.
}; };

View File

@@ -10,7 +10,7 @@
// generated, otherwise it may not be compatible. // generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
FLATBUFFERS_VERSION_MINOR == 5 && FLATBUFFERS_VERSION_MINOR == 5 &&
FLATBUFFERS_VERSION_REVISION == 8, FLATBUFFERS_VERSION_REVISION == 9,
"Non-compatible flatbuffers version included"); "Non-compatible flatbuffers version included");
namespace reflection { namespace reflection {
@@ -64,10 +64,11 @@ enum BaseType {
Obj = 15, Obj = 15,
Union = 16, Union = 16,
Array = 17, Array = 17,
MaxBaseType = 18 Vector64 = 18,
MaxBaseType = 19
}; };
inline const BaseType (&EnumValuesBaseType())[19] { inline const BaseType (&EnumValuesBaseType())[20] {
static const BaseType values[] = { static const BaseType values[] = {
None, None,
UType, UType,
@@ -87,13 +88,14 @@ inline const BaseType (&EnumValuesBaseType())[19] {
Obj, Obj,
Union, Union,
Array, Array,
Vector64,
MaxBaseType MaxBaseType
}; };
return values; return values;
} }
inline const char * const *EnumNamesBaseType() { inline const char * const *EnumNamesBaseType() {
static const char * const names[20] = { static const char * const names[21] = {
"None", "None",
"UType", "UType",
"Bool", "Bool",
@@ -112,6 +114,7 @@ inline const char * const *EnumNamesBaseType() {
"Obj", "Obj",
"Union", "Union",
"Array", "Array",
"Vector64",
"MaxBaseType", "MaxBaseType",
nullptr nullptr
}; };
@@ -601,7 +604,8 @@ struct Field FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
VT_ATTRIBUTES = 22, VT_ATTRIBUTES = 22,
VT_DOCUMENTATION = 24, VT_DOCUMENTATION = 24,
VT_OPTIONAL = 26, VT_OPTIONAL = 26,
VT_PADDING = 28 VT_PADDING = 28,
VT_OFFSET64 = 30
}; };
const ::flatbuffers::String *name() const { const ::flatbuffers::String *name() const {
return GetPointer<const ::flatbuffers::String *>(VT_NAME); return GetPointer<const ::flatbuffers::String *>(VT_NAME);
@@ -649,6 +653,10 @@ struct Field FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
uint16_t padding() const { uint16_t padding() const {
return GetField<uint16_t>(VT_PADDING, 0); return GetField<uint16_t>(VT_PADDING, 0);
} }
/// If the field uses 64-bit offsets.
bool offset64() const {
return GetField<uint8_t>(VT_OFFSET64, 0) != 0;
}
bool Verify(::flatbuffers::Verifier &verifier) const { bool Verify(::flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) && return VerifyTableStart(verifier) &&
VerifyOffsetRequired(verifier, VT_NAME) && VerifyOffsetRequired(verifier, VT_NAME) &&
@@ -670,6 +678,7 @@ struct Field FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
verifier.VerifyVectorOfStrings(documentation()) && verifier.VerifyVectorOfStrings(documentation()) &&
VerifyField<uint8_t>(verifier, VT_OPTIONAL, 1) && VerifyField<uint8_t>(verifier, VT_OPTIONAL, 1) &&
VerifyField<uint16_t>(verifier, VT_PADDING, 2) && VerifyField<uint16_t>(verifier, VT_PADDING, 2) &&
VerifyField<uint8_t>(verifier, VT_OFFSET64, 1) &&
verifier.EndTable(); verifier.EndTable();
} }
}; };
@@ -717,6 +726,9 @@ struct FieldBuilder {
void add_padding(uint16_t padding) { void add_padding(uint16_t padding) {
fbb_.AddElement<uint16_t>(Field::VT_PADDING, padding, 0); fbb_.AddElement<uint16_t>(Field::VT_PADDING, padding, 0);
} }
void add_offset64(bool offset64) {
fbb_.AddElement<uint8_t>(Field::VT_OFFSET64, static_cast<uint8_t>(offset64), 0);
}
explicit FieldBuilder(::flatbuffers::FlatBufferBuilder &_fbb) explicit FieldBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) { : fbb_(_fbb) {
start_ = fbb_.StartTable(); start_ = fbb_.StartTable();
@@ -744,7 +756,8 @@ inline ::flatbuffers::Offset<Field> CreateField(
::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0, ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0, ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0,
bool optional = false, bool optional = false,
uint16_t padding = 0) { uint16_t padding = 0,
bool offset64 = false) {
FieldBuilder builder_(_fbb); FieldBuilder builder_(_fbb);
builder_.add_default_real(default_real); builder_.add_default_real(default_real);
builder_.add_default_integer(default_integer); builder_.add_default_integer(default_integer);
@@ -755,6 +768,7 @@ inline ::flatbuffers::Offset<Field> CreateField(
builder_.add_padding(padding); builder_.add_padding(padding);
builder_.add_offset(offset); builder_.add_offset(offset);
builder_.add_id(id); builder_.add_id(id);
builder_.add_offset64(offset64);
builder_.add_optional(optional); builder_.add_optional(optional);
builder_.add_key(key); builder_.add_key(key);
builder_.add_required(required); builder_.add_required(required);
@@ -776,7 +790,8 @@ inline ::flatbuffers::Offset<Field> CreateFieldDirect(
std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr, std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr, const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
bool optional = false, bool optional = false,
uint16_t padding = 0) { uint16_t padding = 0,
bool offset64 = false) {
auto name__ = name ? _fbb.CreateString(name) : 0; auto name__ = name ? _fbb.CreateString(name) : 0;
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0; auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0; auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
@@ -794,7 +809,8 @@ inline ::flatbuffers::Offset<Field> CreateFieldDirect(
attributes__, attributes__,
documentation__, documentation__,
optional, optional,
padding); padding,
offset64);
} }
struct Object FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { struct Object FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {

View File

@@ -47,14 +47,24 @@ class Table {
return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval; return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
} }
template<typename P> P GetPointer(voffset_t field) { template<typename P, typename OffsetSize = uoffset_t>
P GetPointer(voffset_t field) {
auto field_offset = GetOptionalFieldOffset(field); auto field_offset = GetOptionalFieldOffset(field);
auto p = data_ + field_offset; auto p = data_ + field_offset;
return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p)) return field_offset ? reinterpret_cast<P>(p + ReadScalar<OffsetSize>(p))
: nullptr; : nullptr;
} }
template<typename P> P GetPointer(voffset_t field) const { template<typename P, typename OffsetSize = uoffset_t>
return const_cast<Table *>(this)->GetPointer<P>(field); P GetPointer(voffset_t field) const {
return const_cast<Table *>(this)->GetPointer<P, OffsetSize>(field);
}
template<typename P> P GetPointer64(voffset_t field) {
return GetPointer<P, uoffset64_t>(field);
}
template<typename P> P GetPointer64(voffset_t field) const {
return GetPointer<P, uoffset64_t>(field);
} }
template<typename P> P GetStruct(voffset_t field) const { template<typename P> P GetStruct(voffset_t field) const {
@@ -131,15 +141,25 @@ class Table {
} }
// Versions for offsets. // Versions for offsets.
template<typename OffsetT = uoffset_t>
bool VerifyOffset(const Verifier &verifier, voffset_t field) const { bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
auto field_offset = GetOptionalFieldOffset(field); auto field_offset = GetOptionalFieldOffset(field);
return !field_offset || verifier.VerifyOffset(data_, field_offset); return !field_offset || verifier.VerifyOffset<OffsetT>(data_, field_offset);
} }
template<typename OffsetT = uoffset_t>
bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const { bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
auto field_offset = GetOptionalFieldOffset(field); auto field_offset = GetOptionalFieldOffset(field);
return verifier.Check(field_offset != 0) && return verifier.Check(field_offset != 0) &&
verifier.VerifyOffset(data_, field_offset); verifier.VerifyOffset<OffsetT>(data_, field_offset);
}
bool VerifyOffset64(const Verifier &verifier, voffset_t field) const {
return VerifyOffset<uoffset64_t>(verifier, field);
}
bool VerifyOffset64Required(const Verifier &verifier, voffset_t field) const {
return VerifyOffsetRequired<uoffset64_t>(verifier, field);
} }
private: private:

View File

@@ -27,7 +27,8 @@ struct String;
// An STL compatible iterator implementation for Vector below, effectively // An STL compatible iterator implementation for Vector below, effectively
// calling Get() for every element. // calling Get() for every element.
template<typename T, typename IT, typename Data = uint8_t *> template<typename T, typename IT, typename Data = uint8_t *,
typename SizeT = uoffset_t>
struct VectorIterator { struct VectorIterator {
typedef std::random_access_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
typedef IT value_type; typedef IT value_type;
@@ -35,8 +36,9 @@ struct VectorIterator {
typedef IT *pointer; typedef IT *pointer;
typedef IT &reference; typedef IT &reference;
VectorIterator(Data data, uoffset_t i) static const SizeT element_stride = IndirectHelper<T>::element_stride;
: data_(data + IndirectHelper<T>::element_stride * i) {}
VectorIterator(Data data, SizeT i) : data_(data + element_stride * i) {}
VectorIterator(const VectorIterator &other) : data_(other.data_) {} VectorIterator(const VectorIterator &other) : data_(other.data_) {}
VectorIterator() : data_(nullptr) {} VectorIterator() : data_(nullptr) {}
@@ -63,7 +65,7 @@ struct VectorIterator {
} }
difference_type operator-(const VectorIterator &other) const { difference_type operator-(const VectorIterator &other) const {
return (data_ - other.data_) / IndirectHelper<T>::element_stride; return (data_ - other.data_) / element_stride;
} }
// Note: return type is incompatible with the standard // Note: return type is incompatible with the standard
@@ -75,44 +77,42 @@ struct VectorIterator {
IT operator->() const { return IndirectHelper<T>::Read(data_, 0); } IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
VectorIterator &operator++() { VectorIterator &operator++() {
data_ += IndirectHelper<T>::element_stride; data_ += element_stride;
return *this; return *this;
} }
VectorIterator operator++(int) { VectorIterator operator++(int) {
VectorIterator temp(data_, 0); VectorIterator temp(data_, 0);
data_ += IndirectHelper<T>::element_stride; data_ += element_stride;
return temp; return temp;
} }
VectorIterator operator+(const uoffset_t &offset) const { VectorIterator operator+(const SizeT &offset) const {
return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, return VectorIterator(data_ + offset * element_stride, 0);
0);
} }
VectorIterator &operator+=(const uoffset_t &offset) { VectorIterator &operator+=(const SizeT &offset) {
data_ += offset * IndirectHelper<T>::element_stride; data_ += offset * element_stride;
return *this; return *this;
} }
VectorIterator &operator--() { VectorIterator &operator--() {
data_ -= IndirectHelper<T>::element_stride; data_ -= element_stride;
return *this; return *this;
} }
VectorIterator operator--(int) { VectorIterator operator--(int) {
VectorIterator temp(data_, 0); VectorIterator temp(data_, 0);
data_ -= IndirectHelper<T>::element_stride; data_ -= element_stride;
return temp; return temp;
} }
VectorIterator operator-(const uoffset_t &offset) const { VectorIterator operator-(const SizeT &offset) const {
return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, return VectorIterator(data_ - offset * element_stride, 0);
0);
} }
VectorIterator &operator-=(const uoffset_t &offset) { VectorIterator &operator-=(const SizeT &offset) {
data_ -= offset * IndirectHelper<T>::element_stride; data_ -= offset * element_stride;
return *this; return *this;
} }
@@ -120,8 +120,8 @@ struct VectorIterator {
Data data_; Data data_;
}; };
template<typename T, typename IT> template<typename T, typename IT, typename SizeT = uoffset_t>
using VectorConstIterator = VectorIterator<T, IT, const uint8_t *>; using VectorConstIterator = VectorIterator<T, IT, const uint8_t *, SizeT>;
template<typename Iterator> template<typename Iterator>
struct VectorReverseIterator : public std::reverse_iterator<Iterator> { struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
@@ -145,11 +145,14 @@ struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
// This is used as a helper type for accessing vectors. // This is used as a helper type for accessing vectors.
// Vector::data() assumes the vector elements start after the length field. // Vector::data() assumes the vector elements start after the length field.
template<typename T> class Vector { template<typename T, typename SizeT = uoffset_t> class Vector {
public: public:
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type> typedef VectorIterator<T,
typename IndirectHelper<T>::mutable_return_type,
uint8_t *, SizeT>
iterator; iterator;
typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type> typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type,
SizeT>
const_iterator; const_iterator;
typedef VectorReverseIterator<iterator> reverse_iterator; typedef VectorReverseIterator<iterator> reverse_iterator;
typedef VectorReverseIterator<const_iterator> const_reverse_iterator; typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
@@ -160,39 +163,41 @@ template<typename T> class Vector {
static FLATBUFFERS_CONSTEXPR bool is_span_observable = static FLATBUFFERS_CONSTEXPR bool is_span_observable =
scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1); scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1);
uoffset_t size() const { return EndianScalar(length_); } SizeT size() const { return EndianScalar(length_); }
// Deprecated: use size(). Here for backwards compatibility. // Deprecated: use size(). Here for backwards compatibility.
FLATBUFFERS_ATTRIBUTE([[deprecated("use size() instead")]]) FLATBUFFERS_ATTRIBUTE([[deprecated("use size() instead")]])
uoffset_t Length() const { return size(); } SizeT Length() const { return size(); }
typedef SizeT size_type;
typedef typename IndirectHelper<T>::return_type return_type; typedef typename IndirectHelper<T>::return_type return_type;
typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type; typedef typename IndirectHelper<T>::mutable_return_type
mutable_return_type;
typedef return_type value_type; typedef return_type value_type;
return_type Get(uoffset_t i) const { return_type Get(SizeT i) const {
FLATBUFFERS_ASSERT(i < size()); FLATBUFFERS_ASSERT(i < size());
return IndirectHelper<T>::Read(Data(), i); return IndirectHelper<T>::Read(Data(), i);
} }
return_type operator[](uoffset_t i) const { return Get(i); } return_type operator[](SizeT i) const { return Get(i); }
// If this is a Vector of enums, T will be its storage type, not the enum // If this is a Vector of enums, T will be its storage type, not the enum
// type. This function makes it convenient to retrieve value with enum // type. This function makes it convenient to retrieve value with enum
// type E. // type E.
template<typename E> E GetEnum(uoffset_t i) const { template<typename E> E GetEnum(SizeT i) const {
return static_cast<E>(Get(i)); return static_cast<E>(Get(i));
} }
// If this a vector of unions, this does the cast for you. There's no check // If this a vector of unions, this does the cast for you. There's no check
// to make sure this is the right type! // to make sure this is the right type!
template<typename U> const U *GetAs(uoffset_t i) const { template<typename U> const U *GetAs(SizeT i) const {
return reinterpret_cast<const U *>(Get(i)); return reinterpret_cast<const U *>(Get(i));
} }
// If this a vector of unions, this does the cast for you. There's no check // If this a vector of unions, this does the cast for you. There's no check
// to make sure this is actually a string! // to make sure this is actually a string!
const String *GetAsString(uoffset_t i) const { const String *GetAsString(SizeT i) const {
return reinterpret_cast<const String *>(Get(i)); return reinterpret_cast<const String *>(Get(i));
} }
@@ -226,7 +231,7 @@ template<typename T> class Vector {
// Change elements if you have a non-const pointer to this object. // Change elements if you have a non-const pointer to this object.
// Scalars only. See reflection.h, and the documentation. // Scalars only. See reflection.h, and the documentation.
void Mutate(uoffset_t i, const T &val) { void Mutate(SizeT i, const T &val) {
FLATBUFFERS_ASSERT(i < size()); FLATBUFFERS_ASSERT(i < size());
WriteScalar(data() + i, val); WriteScalar(data() + i, val);
} }
@@ -234,15 +239,15 @@ template<typename T> class Vector {
// Change an element of a vector of tables (or strings). // Change an element of a vector of tables (or strings).
// "val" points to the new table/string, as you can obtain from // "val" points to the new table/string, as you can obtain from
// e.g. reflection::AddFlatBuffer(). // e.g. reflection::AddFlatBuffer().
void MutateOffset(uoffset_t i, const uint8_t *val) { void MutateOffset(SizeT i, const uint8_t *val) {
FLATBUFFERS_ASSERT(i < size()); FLATBUFFERS_ASSERT(i < size());
static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types"); static_assert(sizeof(T) == sizeof(SizeT), "Unrelated types");
WriteScalar(data() + i, WriteScalar(data() + i,
static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t)))); static_cast<SizeT>(val - (Data() + i * sizeof(SizeT))));
} }
// Get a mutable pointer to tables/strings inside this vector. // Get a mutable pointer to tables/strings inside this vector.
mutable_return_type GetMutableObject(uoffset_t i) const { mutable_return_type GetMutableObject(SizeT i) const {
FLATBUFFERS_ASSERT(i < size()); FLATBUFFERS_ASSERT(i < size());
return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i)); return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
} }
@@ -280,7 +285,7 @@ template<typename T> class Vector {
// try to construct these manually. // try to construct these manually.
Vector(); Vector();
uoffset_t length_; SizeT length_;
private: private:
// This class is a pointer. Copying will therefore create an invalid object. // This class is a pointer. Copying will therefore create an invalid object.
@@ -299,6 +304,8 @@ template<typename T> class Vector {
} }
}; };
template<typename T> using Vector64 = Vector<T, uoffset64_t>;
template<class U> template<class U>
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> &vec) FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> &vec)
FLATBUFFERS_NOEXCEPT { FLATBUFFERS_NOEXCEPT {

View File

@@ -17,6 +17,8 @@
#ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_ #ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_
#define FLATBUFFERS_VECTOR_DOWNWARD_H_ #define FLATBUFFERS_VECTOR_DOWNWARD_H_
#include <cstdint>
#include <algorithm> #include <algorithm>
#include "flatbuffers/base.h" #include "flatbuffers/base.h"
@@ -31,13 +33,15 @@ namespace flatbuffers {
// Since this vector leaves the lower part unused, we support a "scratch-pad" // Since this vector leaves the lower part unused, we support a "scratch-pad"
// that can be stored there for temporary data, to share the allocated space. // that can be stored there for temporary data, to share the allocated space.
// Essentially, this supports 2 std::vectors in a single buffer. // Essentially, this supports 2 std::vectors in a single buffer.
class vector_downward { template<typename SizeT = uoffset_t> class vector_downward {
public: public:
explicit vector_downward(size_t initial_size, Allocator *allocator, explicit vector_downward(size_t initial_size, Allocator *allocator,
bool own_allocator, size_t buffer_minalign) bool own_allocator, size_t buffer_minalign,
const SizeT max_size = FLATBUFFERS_MAX_BUFFER_SIZE)
: allocator_(allocator), : allocator_(allocator),
own_allocator_(own_allocator), own_allocator_(own_allocator),
initial_size_(initial_size), initial_size_(initial_size),
max_size_(max_size),
buffer_minalign_(buffer_minalign), buffer_minalign_(buffer_minalign),
reserved_(0), reserved_(0),
size_(0), size_(0),
@@ -50,6 +54,7 @@ class vector_downward {
: allocator_(other.allocator_), : allocator_(other.allocator_),
own_allocator_(other.own_allocator_), own_allocator_(other.own_allocator_),
initial_size_(other.initial_size_), initial_size_(other.initial_size_),
max_size_(other.max_size_),
buffer_minalign_(other.buffer_minalign_), buffer_minalign_(other.buffer_minalign_),
reserved_(other.reserved_), reserved_(other.reserved_),
size_(other.size_), size_(other.size_),
@@ -111,7 +116,7 @@ class vector_downward {
uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) { uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
auto *buf = buf_; auto *buf = buf_;
allocated_bytes = reserved_; allocated_bytes = reserved_;
offset = static_cast<size_t>(cur_ - buf_); offset = vector_downward::offset();
// release_raw only relinquishes the buffer ownership. // release_raw only relinquishes the buffer ownership.
// Does not deallocate or reset the allocator. Destructor will do that. // Does not deallocate or reset the allocator. Destructor will do that.
@@ -136,10 +141,10 @@ class vector_downward {
size_t ensure_space(size_t len) { size_t ensure_space(size_t len) {
FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_); FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); } // If the length is larger than the unused part of the buffer, we need to
// Beyond this, signed offsets may not have enough range: // grow.
// (FlatBuffers > 2GB not supported). if (len > unused_buffer_size()) { reallocate(len); }
FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE); FLATBUFFERS_ASSERT(size() < max_size_);
return len; return len;
} }
@@ -147,7 +152,7 @@ class vector_downward {
if (len) { if (len) {
ensure_space(len); ensure_space(len);
cur_ -= len; cur_ -= len;
size_ += static_cast<uoffset_t>(len); size_ += static_cast<SizeT>(len);
} }
return cur_; return cur_;
} }
@@ -155,11 +160,17 @@ class vector_downward {
// Returns nullptr if using the DefaultAllocator. // Returns nullptr if using the DefaultAllocator.
Allocator *get_custom_allocator() { return allocator_; } Allocator *get_custom_allocator() { return allocator_; }
inline uoffset_t size() const { return size_; } // The current offset into the buffer.
size_t offset() const { return cur_ - buf_; }
uoffset_t scratch_size() const { // The total size of the vector (both the buffer and scratch parts).
return static_cast<uoffset_t>(scratch_ - buf_); inline SizeT size() const { return size_; }
}
// The size of the buffer part of the vector that is currently unused.
SizeT unused_buffer_size() const { return static_cast<SizeT>(cur_ - scratch_); }
// The size of the scratch part of the vector.
SizeT scratch_size() const { return static_cast<SizeT>(scratch_ - buf_); }
size_t capacity() const { return reserved_; } size_t capacity() const { return reserved_; }
@@ -211,7 +222,7 @@ class vector_downward {
void pop(size_t bytes_to_remove) { void pop(size_t bytes_to_remove) {
cur_ += bytes_to_remove; cur_ += bytes_to_remove;
size_ -= static_cast<uoffset_t>(bytes_to_remove); size_ -= static_cast<SizeT>(bytes_to_remove);
} }
void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; } void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
@@ -224,6 +235,7 @@ class vector_downward {
swap(buffer_minalign_, other.buffer_minalign_); swap(buffer_minalign_, other.buffer_minalign_);
swap(reserved_, other.reserved_); swap(reserved_, other.reserved_);
swap(size_, other.size_); swap(size_, other.size_);
swap(max_size_, other.max_size_);
swap(buf_, other.buf_); swap(buf_, other.buf_);
swap(cur_, other.cur_); swap(cur_, other.cur_);
swap(scratch_, other.scratch_); swap(scratch_, other.scratch_);
@@ -243,9 +255,12 @@ class vector_downward {
Allocator *allocator_; Allocator *allocator_;
bool own_allocator_; bool own_allocator_;
size_t initial_size_; size_t initial_size_;
// The maximum size the vector can be.
SizeT max_size_;
size_t buffer_minalign_; size_t buffer_minalign_;
size_t reserved_; size_t reserved_;
uoffset_t size_; SizeT size_;
uint8_t *buf_; uint8_t *buf_;
uint8_t *cur_; // Points at location between empty (below) and used (above). uint8_t *cur_; // Points at location between empty (below) and used (above).
uint8_t *scratch_; // Points to the end of the scratchpad in use. uint8_t *scratch_; // Points to the end of the scratchpad in use.

View File

@@ -34,12 +34,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
bool check_alignment = true; bool check_alignment = true;
// If true, run verifier on nested flatbuffers // If true, run verifier on nested flatbuffers
bool check_nested_flatbuffers = true; bool check_nested_flatbuffers = true;
// The maximum size of a buffer.
size_t max_size = FLATBUFFERS_MAX_BUFFER_SIZE;
// Use assertions to check for errors.
bool assert = false;
}; };
explicit Verifier(const uint8_t *const buf, const size_t buf_len, explicit Verifier(const uint8_t *const buf, const size_t buf_len,
const Options &opts) const Options &opts)
: buf_(buf), size_(buf_len), opts_(opts) { : buf_(buf), size_(buf_len), opts_(opts) {
FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE); FLATBUFFERS_ASSERT(size_ < opts.max_size);
} }
// Deprecated API, please construct with Verifier::Options. // Deprecated API, please construct with Verifier::Options.
@@ -58,7 +62,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
bool Check(const bool ok) const { bool Check(const bool ok) const {
// clang-format off // clang-format off
#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
FLATBUFFERS_ASSERT(ok); if (opts_.assert) { FLATBUFFERS_ASSERT(ok); }
#endif #endif
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
if (!ok) if (!ok)
@@ -113,41 +117,43 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
} }
// Verify a pointer (may be NULL) of any vector type. // Verify a pointer (may be NULL) of any vector type.
template<typename T> bool VerifyVector(const Vector<T> *const vec) const { template<int &..., typename T, typename LenT>
return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec), bool VerifyVector(const Vector<T, LenT> *const vec) const {
sizeof(T)); return !vec || VerifyVectorOrString<LenT>(
reinterpret_cast<const uint8_t *>(vec), sizeof(T));
} }
// Verify a pointer (may be NULL) of a vector to struct. // Verify a pointer (may be NULL) of a vector to struct.
template<typename T> template<int &..., typename T, typename LenT>
bool VerifyVector(const Vector<const T *> *const vec) const { bool VerifyVector(const Vector<const T *, LenT> *const vec) const {
return VerifyVector(reinterpret_cast<const Vector<T> *>(vec)); return VerifyVector(reinterpret_cast<const Vector<T, LenT> *>(vec));
} }
// Verify a pointer (may be NULL) to string. // Verify a pointer (may be NULL) to string.
bool VerifyString(const String *const str) const { bool VerifyString(const String *const str) const {
size_t end; size_t end;
return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str), return !str || (VerifyVectorOrString<uoffset_t>(
1, &end) && reinterpret_cast<const uint8_t *>(str), 1, &end) &&
Verify(end, 1) && // Must have terminator Verify(end, 1) && // Must have terminator
Check(buf_[end] == '\0')); // Terminating byte must be 0. Check(buf_[end] == '\0')); // Terminating byte must be 0.
} }
// Common code between vectors and strings. // Common code between vectors and strings.
template<typename LenT = uoffset_t>
bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size, bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size,
size_t *const end = nullptr) const { size_t *const end = nullptr) const {
const auto veco = static_cast<size_t>(vec - buf_); const auto vec_offset = static_cast<size_t>(vec - buf_);
// Check we can read the size field. // Check we can read the size field.
if (!Verify<uoffset_t>(veco)) return false; if (!Verify<LenT>(vec_offset)) return false;
// Check the whole array. If this is a string, the byte past the array must // Check the whole array. If this is a string, the byte past the array must
// be 0. // be 0.
const auto size = ReadScalar<uoffset_t>(vec); const LenT size = ReadScalar<LenT>(vec);
const auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size; const auto max_elems = opts_.max_size / elem_size;
if (!Check(size < max_elems)) if (!Check(size < max_elems))
return false; // Protect against byte_size overflowing. return false; // Protect against byte_size overflowing.
const auto byte_size = sizeof(size) + elem_size * size; const auto byte_size = sizeof(LenT) + elem_size * size;
if (end) *end = veco + byte_size; if (end) *end = vec_offset + byte_size;
return Verify(veco, byte_size); return Verify(vec_offset, byte_size);
} }
// Special case for string contents, after the above has been called. // Special case for string contents, after the above has been called.
@@ -203,7 +209,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
} }
// Call T::Verify, which must be in the generated code for this type. // Call T::Verify, which must be in the generated code for this type.
const auto o = VerifyOffset(start); const auto o = VerifyOffset<uoffset_t>(start);
return Check(o != 0) && return Check(o != 0) &&
reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this) reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
// clang-format off // clang-format off
@@ -214,8 +220,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// clang-format on // clang-format on
} }
template<typename T> template<typename T, int &..., typename SizeT>
bool VerifyNestedFlatBuffer(const Vector<uint8_t> *const buf, bool VerifyNestedFlatBuffer(const Vector<uint8_t, SizeT> *const buf,
const char *const identifier) { const char *const identifier) {
// Caller opted out of this. // Caller opted out of this.
if (!opts_.check_nested_flatbuffers) return true; if (!opts_.check_nested_flatbuffers) return true;
@@ -226,7 +232,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// If there is a nested buffer, it must be greater than the min size. // If there is a nested buffer, it must be greater than the min size.
if (!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false; if (!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
Verifier nested_verifier(buf->data(), buf->size()); Verifier nested_verifier(buf->data(), buf->size(), opts_);
return nested_verifier.VerifyBuffer<T>(identifier); return nested_verifier.VerifyBuffer<T>(identifier);
} }
@@ -237,29 +243,30 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return VerifyBufferFromStart<T>(identifier, 0); return VerifyBufferFromStart<T>(identifier, 0);
} }
template<typename T> template<typename T, typename SizeT = uoffset_t>
bool VerifySizePrefixedBuffer(const char *const identifier) { bool VerifySizePrefixedBuffer(const char *const identifier) {
return Verify<uoffset_t>(0U) && return Verify<SizeT>(0U) &&
Check(ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t)) && Check(ReadScalar<SizeT>(buf_) == size_ - sizeof(SizeT)) &&
VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t)); VerifyBufferFromStart<T>(identifier, sizeof(SizeT));
} }
uoffset_t VerifyOffset(const size_t start) const { template<typename OffsetT = uoffset_t, typename SOffsetT = soffset_t>
if (!Verify<uoffset_t>(start)) return 0; size_t VerifyOffset(const size_t start) const {
const auto o = ReadScalar<uoffset_t>(buf_ + start); if (!Verify<OffsetT>(start)) return 0;
const auto o = ReadScalar<OffsetT>(buf_ + start);
// May not point to itself. // May not point to itself.
if (!Check(o != 0)) return 0; if (!Check(o != 0)) return 0;
// Can't wrap around / buffers are max 2GB. // Can't wrap around larger than the max size.
if (!Check(static_cast<soffset_t>(o) >= 0)) return 0; if (!Check(static_cast<SOffsetT>(o) >= 0)) return 0;
// Must be inside the buffer to create a pointer from it (pointer outside // Must be inside the buffer to create a pointer from it (pointer outside
// buffer is UB). // buffer is UB).
if (!Verify(start + o, 1)) return 0; if (!Verify(start + o, 1)) return 0;
return o; return o;
} }
uoffset_t VerifyOffset(const uint8_t *const base, template<typename OffsetT = uoffset_t>
const voffset_t start) const { size_t VerifyOffset(const uint8_t *const base, const voffset_t start) const {
return VerifyOffset(static_cast<size_t>(base - buf_) + start); return VerifyOffset<OffsetT>(static_cast<size_t>(base - buf_) + start);
} }
// Called at the start of a table to increase counters measuring data // Called at the start of a table to increase counters measuring data
@@ -312,6 +319,12 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
std::vector<uint8_t> *flex_reuse_tracker_ = nullptr; std::vector<uint8_t> *flex_reuse_tracker_ = nullptr;
}; };
// Specialization for 64-bit offsets.
template<>
inline size_t Verifier::VerifyOffset<uoffset64_t>(const size_t start) const {
return VerifyOffset<uoffset64_t, soffset64_t>(start);
}
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATBUFFERS_VERIFIER_H_ #endif // FLATBUFFERS_VERIFIER_H_

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.google.flatbuffers</groupId> <groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId> <artifactId>flatbuffers-java</artifactId>
<version>23.5.8</version> <version>23.5.9</version>
<packaging>bundle</packaging> <packaging>bundle</packaging>
<name>FlatBuffers Java API</name> <name>FlatBuffers Java API</name>
<description> <description>

View File

@@ -46,7 +46,7 @@ public class Constants {
Changes to the Java implementation need to be sure to change Changes to the Java implementation need to be sure to change
the version here and in the code generator on every possible the version here and in the code generator on every possible
incompatible change */ incompatible change */
public static void FLATBUFFERS_23_5_8() {} public static void FLATBUFFERS_23_5_9() {}
} }
/// @endcond /// @endcond

View File

@@ -23,9 +23,10 @@ public final class BaseType {
public static final byte Obj = 15; public static final byte Obj = 15;
public static final byte Union = 16; public static final byte Union = 16;
public static final byte Array = 17; public static final byte Array = 17;
public static final byte MaxBaseType = 18; public static final byte Vector64 = 18;
public static final byte MaxBaseType = 19;
public static final String[] names = { "None", "UType", "Bool", "Byte", "UByte", "Short", "UShort", "Int", "UInt", "Long", "ULong", "Float", "Double", "String", "Vector", "Obj", "Union", "Array", "MaxBaseType", }; public static final String[] names = { "None", "UType", "Bool", "Byte", "UByte", "Short", "UShort", "Int", "UInt", "Long", "ULong", "Float", "Double", "String", "Vector", "Obj", "Union", "Array", "Vector64", "MaxBaseType", };
public static String name(int e) { return names[e]; } public static String name(int e) { return names[e]; }
} }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Enum extends Table { public final class Enum extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static Enum getRootAsEnum(ByteBuffer _bb) { return getRootAsEnum(_bb, new Enum()); } public static Enum getRootAsEnum(ByteBuffer _bb) { return getRootAsEnum(_bb, new Enum()); }
public static Enum getRootAsEnum(ByteBuffer _bb, Enum obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static Enum getRootAsEnum(ByteBuffer _bb, Enum obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class EnumVal extends Table { public final class EnumVal extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static EnumVal getRootAsEnumVal(ByteBuffer _bb) { return getRootAsEnumVal(_bb, new EnumVal()); } public static EnumVal getRootAsEnumVal(ByteBuffer _bb) { return getRootAsEnumVal(_bb, new EnumVal()); }
public static EnumVal getRootAsEnumVal(ByteBuffer _bb, EnumVal obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static EnumVal getRootAsEnumVal(ByteBuffer _bb, EnumVal obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Field extends Table { public final class Field extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static Field getRootAsField(ByteBuffer _bb) { return getRootAsField(_bb, new Field()); } public static Field getRootAsField(ByteBuffer _bb) { return getRootAsField(_bb, new Field()); }
public static Field getRootAsField(ByteBuffer _bb, Field obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static Field getRootAsField(ByteBuffer _bb, Field obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }
@@ -55,6 +55,10 @@ public final class Field extends Table {
* Number of padding octets to always add after this field. Structs only. * Number of padding octets to always add after this field. Structs only.
*/ */
public int padding() { int o = __offset(28); return o != 0 ? bb.getShort(o + bb_pos) & 0xFFFF : 0; } public int padding() { int o = __offset(28); return o != 0 ? bb.getShort(o + bb_pos) & 0xFFFF : 0; }
/**
* If the field uses 64-bit offsets.
*/
public boolean offset64() { int o = __offset(30); return o != 0 ? 0!=bb.get(o + bb_pos) : false; }
public static int createField(FlatBufferBuilder builder, public static int createField(FlatBufferBuilder builder,
int nameOffset, int nameOffset,
@@ -69,8 +73,9 @@ public final class Field extends Table {
int attributesOffset, int attributesOffset,
int documentationOffset, int documentationOffset,
boolean optional, boolean optional,
int padding) { int padding,
builder.startTable(13); boolean offset64) {
builder.startTable(14);
Field.addDefaultReal(builder, defaultReal); Field.addDefaultReal(builder, defaultReal);
Field.addDefaultInteger(builder, defaultInteger); Field.addDefaultInteger(builder, defaultInteger);
Field.addDocumentation(builder, documentationOffset); Field.addDocumentation(builder, documentationOffset);
@@ -80,6 +85,7 @@ public final class Field extends Table {
Field.addPadding(builder, padding); Field.addPadding(builder, padding);
Field.addOffset(builder, offset); Field.addOffset(builder, offset);
Field.addId(builder, id); Field.addId(builder, id);
Field.addOffset64(builder, offset64);
Field.addOptional(builder, optional); Field.addOptional(builder, optional);
Field.addKey(builder, key); Field.addKey(builder, key);
Field.addRequired(builder, required); Field.addRequired(builder, required);
@@ -87,7 +93,7 @@ public final class Field extends Table {
return Field.endField(builder); return Field.endField(builder);
} }
public static void startField(FlatBufferBuilder builder) { builder.startTable(13); } public static void startField(FlatBufferBuilder builder) { builder.startTable(14); }
public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(nameOffset); builder.slot(0); } public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(nameOffset); builder.slot(0); }
public static void addType(FlatBufferBuilder builder, int typeOffset) { builder.addOffset(1, typeOffset, 0); } public static void addType(FlatBufferBuilder builder, int typeOffset) { builder.addOffset(1, typeOffset, 0); }
public static void addId(FlatBufferBuilder builder, int id) { builder.addShort(2, (short) id, (short) 0); } public static void addId(FlatBufferBuilder builder, int id) { builder.addShort(2, (short) id, (short) 0); }
@@ -105,6 +111,7 @@ public final class Field extends Table {
public static void startDocumentationVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static void startDocumentationVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); }
public static void addOptional(FlatBufferBuilder builder, boolean optional) { builder.addBoolean(11, optional, false); } public static void addOptional(FlatBufferBuilder builder, boolean optional) { builder.addBoolean(11, optional, false); }
public static void addPadding(FlatBufferBuilder builder, int padding) { builder.addShort(12, (short) padding, (short) 0); } public static void addPadding(FlatBufferBuilder builder, int padding) { builder.addShort(12, (short) padding, (short) 0); }
public static void addOffset64(FlatBufferBuilder builder, boolean offset64) { builder.addBoolean(13, offset64, false); }
public static int endField(FlatBufferBuilder builder) { public static int endField(FlatBufferBuilder builder) {
int o = builder.endTable(); int o = builder.endTable();
builder.required(o, 4); // name builder.required(o, 4); // name

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class KeyValue extends Table { public final class KeyValue extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static KeyValue getRootAsKeyValue(ByteBuffer _bb) { return getRootAsKeyValue(_bb, new KeyValue()); } public static KeyValue getRootAsKeyValue(ByteBuffer _bb) { return getRootAsKeyValue(_bb, new KeyValue()); }
public static KeyValue getRootAsKeyValue(ByteBuffer _bb, KeyValue obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static KeyValue getRootAsKeyValue(ByteBuffer _bb, KeyValue obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Object extends Table { public final class Object extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static Object getRootAsObject(ByteBuffer _bb) { return getRootAsObject(_bb, new Object()); } public static Object getRootAsObject(ByteBuffer _bb) { return getRootAsObject(_bb, new Object()); }
public static Object getRootAsObject(ByteBuffer _bb, Object obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static Object getRootAsObject(ByteBuffer _bb, Object obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class RPCCall extends Table { public final class RPCCall extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static RPCCall getRootAsRPCCall(ByteBuffer _bb) { return getRootAsRPCCall(_bb, new RPCCall()); } public static RPCCall getRootAsRPCCall(ByteBuffer _bb) { return getRootAsRPCCall(_bb, new RPCCall()); }
public static RPCCall getRootAsRPCCall(ByteBuffer _bb, RPCCall obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static RPCCall getRootAsRPCCall(ByteBuffer _bb, RPCCall obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Schema extends Table { public final class Schema extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static Schema getRootAsSchema(ByteBuffer _bb) { return getRootAsSchema(_bb, new Schema()); } public static Schema getRootAsSchema(ByteBuffer _bb) { return getRootAsSchema(_bb, new Schema()); }
public static Schema getRootAsSchema(ByteBuffer _bb, Schema obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static Schema getRootAsSchema(ByteBuffer _bb, Schema obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public static boolean SchemaBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "BFBS"); } public static boolean SchemaBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "BFBS"); }

View File

@@ -26,7 +26,7 @@ import java.nio.ByteOrder;
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class SchemaFile extends Table { public final class SchemaFile extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static SchemaFile getRootAsSchemaFile(ByteBuffer _bb) { return getRootAsSchemaFile(_bb, new SchemaFile()); } public static SchemaFile getRootAsSchemaFile(ByteBuffer _bb) { return getRootAsSchemaFile(_bb, new SchemaFile()); }
public static SchemaFile getRootAsSchemaFile(ByteBuffer _bb, SchemaFile obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static SchemaFile getRootAsSchemaFile(ByteBuffer _bb, SchemaFile obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Service extends Table { public final class Service extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static Service getRootAsService(ByteBuffer _bb) { return getRootAsService(_bb, new Service()); } public static Service getRootAsService(ByteBuffer _bb) { return getRootAsService(_bb, new Service()); }
public static Service getRootAsService(ByteBuffer _bb, Service obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static Service getRootAsService(ByteBuffer _bb, Service obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Type extends Table { public final class Type extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static Type getRootAsType(ByteBuffer _bb) { return getRootAsType(_bb, new Type()); } public static Type getRootAsType(ByteBuffer _bb) { return getRootAsType(_bb, new Type()); }
public static Type getRootAsType(ByteBuffer _bb, Type obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static Type getRootAsType(ByteBuffer _bb, Type obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -32,6 +32,6 @@ namespace Google.FlatBuffers
Changes to the C# implementation need to be sure to change Changes to the C# implementation need to be sure to change
the version here and in the code generator on every possible the version here and in the code generator on every possible
incompatible change */ incompatible change */
public static void FLATBUFFERS_23_5_8() {} public static void FLATBUFFERS_23_5_9() {}
} }
} }

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.1;netstandard2.0;net46</TargetFrameworks> <TargetFrameworks>netstandard2.1;netstandard2.0;net46</TargetFrameworks>
<Description>A cross-platform memory efficient serialization library</Description> <Description>A cross-platform memory efficient serialization library</Description>
<PackageVersion>23.5.8</PackageVersion> <PackageVersion>23.5.9</PackageVersion>
<Authors>Google LLC</Authors> <Authors>Google LLC</Authors>
<PackageProjectUrl>https://github.com/google/flatbuffers</PackageProjectUrl> <PackageProjectUrl>https://github.com/google/flatbuffers</PackageProjectUrl>
<RepositoryUrl>https://github.com/google/flatbuffers</RepositoryUrl> <RepositoryUrl>https://github.com/google/flatbuffers</RepositoryUrl>

View File

@@ -1,6 +1,6 @@
{ {
"name": "flatbuffers", "name": "flatbuffers",
"version": "23.5.8", "version": "23.5.9",
"description": "Memory Efficient Serialization Library", "description": "Memory Efficient Serialization Library",
"files": [ "files": [
"js/**/*.js", "js/**/*.js",

View File

@@ -14,4 +14,4 @@
# Placeholder, to be updated during the release process # Placeholder, to be updated during the release process
# by the setup.py # by the setup.py
__version__ = u"23.5.8" __version__ = u"23.5.9"

View File

@@ -21,4 +21,5 @@ class BaseType(object):
Obj = 15 Obj = 15
Union = 16 Union = 16
Array = 17 Array = 17
MaxBaseType = 18 Vector64 = 18
MaxBaseType = 19

View File

@@ -155,8 +155,16 @@ class Field(object):
return self._tab.Get(flatbuffers.number_types.Uint16Flags, o + self._tab.Pos) return self._tab.Get(flatbuffers.number_types.Uint16Flags, o + self._tab.Pos)
return 0 return 0
# If the field uses 64-bit offsets.
# Field
def Offset64(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(30))
if o != 0:
return bool(self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
return False
def FieldStart(builder): def FieldStart(builder):
builder.StartObject(13) builder.StartObject(14)
def Start(builder): def Start(builder):
FieldStart(builder) FieldStart(builder)
@@ -251,6 +259,12 @@ def FieldAddPadding(builder, padding):
def AddPadding(builder: flatbuffers.Builder, padding: int): def AddPadding(builder: flatbuffers.Builder, padding: int):
FieldAddPadding(builder, padding) FieldAddPadding(builder, padding)
def FieldAddOffset64(builder, offset64):
builder.PrependBoolSlot(13, offset64, 0)
def AddOffset64(builder: flatbuffers.Builder, offset64: bool):
FieldAddOffset64(builder, offset64)
def FieldEnd(builder): def FieldEnd(builder):
return builder.EndObject() return builder.EndObject()

View File

@@ -16,7 +16,7 @@ from setuptools import setup
setup( setup(
name='flatbuffers', name='flatbuffers',
version='23.5.8', version='23.5.9',
license='Apache 2.0', license='Apache 2.0',
license_files='../LICENSE', license_files='../LICENSE',
author='Derek Bailey', author='Derek Bailey',

View File

@@ -25,6 +25,7 @@ enum BaseType : byte {
Obj, // Used for tables & structs. Obj, // Used for tables & structs.
Union, Union,
Array, Array,
Vector64,
// Add any new type above this value. // Add any new type above this value.
MaxBaseType MaxBaseType
@@ -85,6 +86,8 @@ table Field {
optional:bool = false; optional:bool = false;
/// Number of padding octets to always add after this field. Structs only. /// Number of padding octets to always add after this field. Structs only.
padding:uint16 = 0; padding:uint16 = 0;
/// If the field uses 64-bit offsets.
offset64:bool = false;
} }
table Object { // Used for both tables and structs. table Object { // Used for both tables and structs.

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "flatbuffers" name = "flatbuffers"
version = "23.5.8" version = "23.5.9"
edition = "2018" edition = "2018"
authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"] authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"]
license = "Apache-2.0" license = "Apache-2.0"

View File

@@ -10,7 +10,7 @@
// generated, otherwise it may not be compatible. // generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
FLATBUFFERS_VERSION_MINOR == 5 && FLATBUFFERS_VERSION_MINOR == 5 &&
FLATBUFFERS_VERSION_REVISION == 8, FLATBUFFERS_VERSION_REVISION == 9,
"Non-compatible flatbuffers version included"); "Non-compatible flatbuffers version included");
namespace MyGame { namespace MyGame {

View File

@@ -36,7 +36,7 @@ public enum MyGame_Sample_Equipment: UInt8, UnionEnum {
public struct MyGame_Sample_Vec3: NativeStruct, Verifiable, FlatbuffersInitializable { public struct MyGame_Sample_Vec3: NativeStruct, Verifiable, FlatbuffersInitializable {
static func validateVersion() { FlatBuffersVersion_23_5_8() } static func validateVersion() { FlatBuffersVersion_23_5_9() }
private var _x: Float32 private var _x: Float32
private var _y: Float32 private var _y: Float32
@@ -72,7 +72,7 @@ public struct MyGame_Sample_Vec3: NativeStruct, Verifiable, FlatbuffersInitializ
public struct MyGame_Sample_Vec3_Mutable: FlatBufferObject { public struct MyGame_Sample_Vec3_Mutable: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_23_5_8() } static func validateVersion() { FlatBuffersVersion_23_5_9() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Struct private var _accessor: Struct
@@ -88,7 +88,7 @@ public struct MyGame_Sample_Vec3_Mutable: FlatBufferObject {
public struct MyGame_Sample_Monster: FlatBufferObject, Verifiable { public struct MyGame_Sample_Monster: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_23_5_8() } static func validateVersion() { FlatBuffersVersion_23_5_9() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table
@@ -200,7 +200,7 @@ public struct MyGame_Sample_Monster: FlatBufferObject, Verifiable {
public struct MyGame_Sample_Weapon: FlatBufferObject, Verifiable { public struct MyGame_Sample_Weapon: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_23_5_8() } static func validateVersion() { FlatBuffersVersion_23_5_9() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table

View File

@@ -1,6 +1,7 @@
#include "annotated_binary_text_gen.h" #include "annotated_binary_text_gen.h"
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <fstream> #include <fstream>
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
@@ -36,6 +37,7 @@ static std::string ToString(const BinarySectionType type) {
case BinarySectionType::Struct: return "struct"; case BinarySectionType::Struct: return "struct";
case BinarySectionType::String: return "string"; case BinarySectionType::String: return "string";
case BinarySectionType::Vector: return "vector"; case BinarySectionType::Vector: return "vector";
case BinarySectionType::Vector64: return "vector64";
case BinarySectionType::Unknown: return "unknown"; case BinarySectionType::Unknown: return "unknown";
case BinarySectionType::Union: return "union"; case BinarySectionType::Union: return "union";
case BinarySectionType::Padding: return "padding"; case BinarySectionType::Padding: return "padding";
@@ -44,7 +46,9 @@ static std::string ToString(const BinarySectionType type) {
} }
static bool IsOffset(const BinaryRegionType type) { static bool IsOffset(const BinaryRegionType type) {
return type == BinaryRegionType::UOffset || type == BinaryRegionType::SOffset; return type == BinaryRegionType::UOffset ||
type == BinaryRegionType::SOffset ||
type == BinaryRegionType::UOffset64;
} }
template<typename T> std::string ToString(T value) { template<typename T> std::string ToString(T value) {
@@ -119,6 +123,9 @@ static std::string ToValueString(const BinaryRegion &region,
case BinaryRegionType::UType: return ToValueString<uint8_t>(region, binary); case BinaryRegionType::UType: return ToValueString<uint8_t>(region, binary);
// Handle Offsets separately, incase they add additional details. // Handle Offsets separately, incase they add additional details.
case BinaryRegionType::UOffset64:
s += ToValueString<uint64_t>(region, binary);
break;
case BinaryRegionType::UOffset: case BinaryRegionType::UOffset:
s += ToValueString<uint32_t>(region, binary); s += ToValueString<uint32_t>(region, binary);
break; break;
@@ -368,7 +375,8 @@ static void GenerateSection(std::ostream &os, const BinarySection &section,
// As a space saving measure, skip generating every vector element, just put // As a space saving measure, skip generating every vector element, just put
// the first and last elements in the output. Skip the whole thing if there // the first and last elements in the output. Skip the whole thing if there
// are only three or fewer elements, as it doesn't save space. // are only three or fewer elements, as it doesn't save space.
if (section.type == BinarySectionType::Vector && if ((section.type == BinarySectionType::Vector ||
section.type == BinarySectionType::Vector64) &&
!output_config.include_vector_contents && section.regions.size() > 4) { !output_config.include_vector_contents && section.regions.size() > 4) {
// Generate the length region which should be first. // Generate the length region which should be first.
GenerateRegion(os, section.regions[0], section, binary, output_config); GenerateRegion(os, section.regions[0], section, binary, output_config);

View File

@@ -1,10 +1,13 @@
#include "binary_annotator.h" #include "binary_annotator.h"
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <iostream>
#include <limits> #include <limits>
#include <string> #include <string>
#include <vector> #include <vector>
#include "flatbuffers/base.h"
#include "flatbuffers/reflection.h" #include "flatbuffers/reflection.h"
#include "flatbuffers/util.h" #include "flatbuffers/util.h"
#include "flatbuffers/verifier.h" #include "flatbuffers/verifier.h"
@@ -37,9 +40,9 @@ static BinaryRegion MakeBinaryRegion(
return region; return region;
} }
static BinarySection MakeBinarySection( static BinarySection MakeBinarySection(const std::string &name,
const std::string &name, const BinarySectionType type, const BinarySectionType type,
std::vector<BinaryRegion> regions) { std::vector<BinaryRegion> regions) {
BinarySection section; BinarySection section;
section.name = name; section.name = name;
section.type = type; section.type = type;
@@ -118,12 +121,15 @@ static BinarySection GenerateMissingSection(const uint64_t offset,
std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() { std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_)); flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_));
if (!reflection::VerifySchemaBuffer(verifier)) { return {}; }
if ((is_size_prefixed_ &&
!reflection::VerifySizePrefixedSchemaBuffer(verifier)) ||
!reflection::VerifySchemaBuffer(verifier)) {
return {};
}
// The binary is too short to read as a flatbuffers. // The binary is too short to read as a flatbuffers.
// TODO(dbaileychess): We could spit out the annotated buffer sections, but if (binary_length_ < FLATBUFFERS_MIN_BUFFER_SIZE) { return {}; }
// I'm not sure if it is worth it.
if (binary_length_ < 4) { return {}; }
// Make sure we start with a clean slate. // Make sure we start with a clean slate.
vtables_.clear(); vtables_.clear();
@@ -151,7 +157,41 @@ std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
} }
uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) { uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
const auto root_table_offset = ReadScalar<uint32_t>(header_offset); uint64_t offset = header_offset;
std::vector<BinaryRegion> regions;
// If this binary is a size prefixed one, attempt to parse the size.
if (is_size_prefixed_) {
BinaryRegionComment prefix_length_comment;
prefix_length_comment.type = BinaryRegionCommentType::SizePrefix;
bool has_prefix_value = false;
const auto prefix_length = ReadScalar<uoffset64_t>(offset);
if (*prefix_length <= binary_length_) {
regions.push_back(MakeBinaryRegion(offset, sizeof(uoffset64_t),
BinaryRegionType::Uint64, 0, 0,
prefix_length_comment));
offset += sizeof(uoffset64_t);
has_prefix_value = true;
}
if (!has_prefix_value) {
const auto prefix_length = ReadScalar<uoffset_t>(offset);
if (*prefix_length <= binary_length_) {
regions.push_back(MakeBinaryRegion(offset, sizeof(uoffset_t),
BinaryRegionType::Uint32, 0, 0,
prefix_length_comment));
offset += sizeof(uoffset_t);
has_prefix_value = true;
}
}
if (!has_prefix_value) {
SetError(prefix_length_comment, BinaryRegionStatus::ERROR);
}
}
const auto root_table_offset = ReadScalar<uint32_t>(offset);
if (!root_table_offset.has_value()) { if (!root_table_offset.has_value()) {
// This shouldn't occur, since we validate the min size of the buffer // This shouldn't occur, since we validate the min size of the buffer
@@ -159,22 +199,20 @@ uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
return std::numeric_limits<uint64_t>::max(); return std::numeric_limits<uint64_t>::max();
} }
std::vector<BinaryRegion> regions; const auto root_table_loc = offset + *root_table_offset;
uint64_t offset = header_offset;
// TODO(dbaileychess): sized prefixed value
BinaryRegionComment root_offset_comment; BinaryRegionComment root_offset_comment;
root_offset_comment.type = BinaryRegionCommentType::RootTableOffset; root_offset_comment.type = BinaryRegionCommentType::RootTableOffset;
root_offset_comment.name = schema_->root_table()->name()->str(); root_offset_comment.name = schema_->root_table()->name()->str();
if (!IsValidOffset(root_table_offset.value())) { if (!IsValidOffset(root_table_loc)) {
SetError(root_offset_comment, SetError(root_offset_comment,
BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY); BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
} }
regions.push_back( regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
MakeBinaryRegion(offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0, BinaryRegionType::UOffset, 0,
root_table_offset.value(), root_offset_comment)); root_table_loc, root_offset_comment));
offset += sizeof(uint32_t); offset += sizeof(uint32_t);
if (IsValidRead(offset, flatbuffers::kFileIdentifierLength) && if (IsValidRead(offset, flatbuffers::kFileIdentifierLength) &&
@@ -193,7 +231,7 @@ uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
AddSection(header_offset, MakeBinarySection("", BinarySectionType::Header, AddSection(header_offset, MakeBinarySection("", BinarySectionType::Header,
std::move(regions))); std::move(regions)));
return root_table_offset.value(); return root_table_loc;
} }
BinaryAnnotator::VTable *BinaryAnnotator::GetOrBuildVTable( BinaryAnnotator::VTable *BinaryAnnotator::GetOrBuildVTable(
@@ -656,7 +694,18 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
} }
// Read the offset // Read the offset
const auto offset_from_field = ReadScalar<uint32_t>(field_offset); uint64_t offset = 0;
uint64_t length = sizeof(uint32_t);
BinaryRegionType region_type = BinaryRegionType::UOffset;
if (field->offset64()) {
length = sizeof(uint64_t);
region_type = BinaryRegionType::UOffset64;
offset = ReadScalar<uint64_t>(field_offset).value_or(0);
} else {
offset = ReadScalar<uint32_t>(field_offset).value_or(0);
}
// const auto offset_from_field = ReadScalar<uint32_t>(field_offset);
uint64_t offset_of_next_item = 0; uint64_t offset_of_next_item = 0;
BinaryRegionComment offset_field_comment; BinaryRegionComment offset_field_comment;
offset_field_comment.type = BinaryRegionCommentType::TableOffsetField; offset_field_comment.type = BinaryRegionCommentType::TableOffsetField;
@@ -666,7 +715,7 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
// Validate any field that isn't inline (i.e., non-structs). // Validate any field that isn't inline (i.e., non-structs).
if (!IsInlineField(field)) { if (!IsInlineField(field)) {
if (!offset_from_field.has_value()) { if (offset == 0) {
const uint64_t remaining = RemainingBytes(field_offset); const uint64_t remaining = RemainingBytes(field_offset);
SetError(offset_field_comment, SetError(offset_field_comment,
@@ -678,14 +727,14 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
continue; continue;
} }
offset_of_next_item = field_offset + offset_from_field.value(); offset_of_next_item = field_offset + offset;
if (!IsValidOffset(offset_of_next_item)) { if (!IsValidOffset(offset_of_next_item)) {
SetError(offset_field_comment, SetError(offset_field_comment,
BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY); BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
regions.push_back(MakeBinaryRegion( regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0, offset_of_next_item,
offset_of_next_item, offset_field_comment)); offset_field_comment));
continue; continue;
} }
} }
@@ -702,9 +751,9 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
} else { } else {
offset_field_comment.default_value = "(table)"; offset_field_comment.default_value = "(table)";
regions.push_back(MakeBinaryRegion( regions.push_back(MakeBinaryRegion(field_offset, length, region_type,
field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0, 0, offset_of_next_item,
offset_of_next_item, offset_field_comment)); offset_field_comment));
BuildTable(offset_of_next_item, BinarySectionType::Table, BuildTable(offset_of_next_item, BinarySectionType::Table,
next_object); next_object);
@@ -713,17 +762,25 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
case reflection::BaseType::String: { case reflection::BaseType::String: {
offset_field_comment.default_value = "(string)"; offset_field_comment.default_value = "(string)";
regions.push_back(MakeBinaryRegion( regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0, offset_of_next_item,
offset_of_next_item, offset_field_comment)); offset_field_comment));
BuildString(offset_of_next_item, table, field); BuildString(offset_of_next_item, table, field);
} break; } break;
case reflection::BaseType::Vector: { case reflection::BaseType::Vector: {
offset_field_comment.default_value = "(vector)"; offset_field_comment.default_value = "(vector)";
regions.push_back(MakeBinaryRegion( regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0, offset_of_next_item,
offset_of_next_item, offset_field_comment)); offset_field_comment));
BuildVector(offset_of_next_item, table, field, table_offset,
vtable->fields);
} break;
case reflection::BaseType::Vector64: {
offset_field_comment.default_value = "(vector64)";
regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
offset_of_next_item,
offset_field_comment));
BuildVector(offset_of_next_item, table, field, table_offset, BuildVector(offset_of_next_item, table, field, table_offset,
vtable->fields); vtable->fields);
} break; } break;
@@ -768,8 +825,7 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
offset_field_comment.default_value = offset_field_comment.default_value =
"(union of type `" + enum_type + "`)"; "(union of type `" + enum_type + "`)";
regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint32_t), regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
BinaryRegionType::UOffset, 0,
union_offset, offset_field_comment)); union_offset, offset_field_comment));
} break; } break;
@@ -986,7 +1042,28 @@ void BinaryAnnotator::BuildVector(
BinaryRegionComment vector_length_comment; BinaryRegionComment vector_length_comment;
vector_length_comment.type = BinaryRegionCommentType::VectorLength; vector_length_comment.type = BinaryRegionCommentType::VectorLength;
const auto vector_length = ReadScalar<uint32_t>(vector_offset); const bool is_64_bit_vector =
field->type()->base_type() == reflection::BaseType::Vector64;
flatbuffers::Optional<uint64_t> vector_length;
uint32_t vector_length_size_type = 0;
BinaryRegionType region_type = BinaryRegionType::Uint32;
BinarySectionType section_type = BinarySectionType::Vector;
if (is_64_bit_vector) {
auto v = ReadScalar<uint64_t>(vector_offset);
if (v.has_value()) { vector_length = v.value(); }
vector_length_size_type = sizeof(uint64_t);
region_type = BinaryRegionType::Uint64;
section_type = BinarySectionType::Vector64;
} else {
auto v = ReadScalar<uint32_t>(vector_offset);
if (v.has_value()) { vector_length = v.value(); }
vector_length_size_type = sizeof(uint32_t);
region_type = BinaryRegionType::Uint32;
section_type = BinarySectionType::Vector;
}
if (!vector_length.has_value()) { if (!vector_length.has_value()) {
const uint64_t remaining = RemainingBytes(vector_offset); const uint64_t remaining = RemainingBytes(vector_offset);
SetError(vector_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, SetError(vector_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
@@ -1006,7 +1083,7 @@ void BinaryAnnotator::BuildVector(
// Validate there are enough bytes left in the binary to process all the // Validate there are enough bytes left in the binary to process all the
// items. // items.
const uint64_t last_item_offset = const uint64_t last_item_offset =
vector_offset + sizeof(uint32_t) + vector_offset + vector_length_size_type +
vector_length.value() * GetElementSize(field); vector_length.value() * GetElementSize(field);
if (!IsValidOffset(last_item_offset - 1)) { if (!IsValidOffset(last_item_offset - 1)) {
@@ -1016,20 +1093,18 @@ void BinaryAnnotator::BuildVector(
MakeSingleRegionBinarySection( MakeSingleRegionBinarySection(
std::string(table->name()->c_str()) + "." + field->name()->c_str(), std::string(table->name()->c_str()) + "." + field->name()->c_str(),
BinarySectionType::Vector, BinarySectionType::Vector,
MakeBinaryRegion(vector_offset, sizeof(uint32_t), MakeBinaryRegion(vector_offset, vector_length_size_type,
BinaryRegionType::Uint32, 0, 0, region_type, 0, 0, vector_length_comment)));
vector_length_comment)));
return; return;
} }
std::vector<BinaryRegion> regions; std::vector<BinaryRegion> regions;
regions.push_back(MakeBinaryRegion(vector_offset, sizeof(uint32_t), regions.push_back(MakeBinaryRegion(vector_offset, vector_length_size_type,
BinaryRegionType::Uint32, 0, 0, region_type, 0, 0, vector_length_comment));
vector_length_comment));
// Consume the vector length offset. // Consume the vector length offset.
uint64_t offset = vector_offset + sizeof(uint32_t); uint64_t offset = vector_offset + vector_length_size_type;
switch (field->type()->element()) { switch (field->type()->element()) {
case reflection::BaseType::Obj: { case reflection::BaseType::Obj: {
@@ -1302,7 +1377,7 @@ void BinaryAnnotator::BuildVector(
AddSection(vector_offset, AddSection(vector_offset,
MakeBinarySection(std::string(table->name()->c_str()) + "." + MakeBinarySection(std::string(table->name()->c_str()) + "." +
field->name()->c_str(), field->name()->c_str(),
BinarySectionType::Vector, std::move(regions))); section_type, std::move(regions)));
} }
std::string BinaryAnnotator::BuildUnion(const uint64_t union_offset, std::string BinaryAnnotator::BuildUnion(const uint64_t union_offset,

View File

@@ -48,6 +48,7 @@ enum class BinaryRegionType {
Float = 15, Float = 15,
Double = 16, Double = 16,
UType = 17, UType = 17,
UOffset64 = 18,
}; };
template<typename T> template<typename T>
@@ -179,6 +180,7 @@ enum class BinarySectionType {
Vector = 7, Vector = 7,
Union = 8, Union = 8,
Padding = 9, Padding = 9,
Vector64 = 10,
}; };
// A section of the binary that is grouped together in some logical manner, and // A section of the binary that is grouped together in some logical manner, and
@@ -216,6 +218,7 @@ inline static BinaryRegionType GetRegionType(reflection::BaseType base_type) {
inline static std::string ToString(const BinaryRegionType type) { inline static std::string ToString(const BinaryRegionType type) {
switch (type) { switch (type) {
case BinaryRegionType::UOffset: return "UOffset32"; case BinaryRegionType::UOffset: return "UOffset32";
case BinaryRegionType::UOffset64: return "UOffset64";
case BinaryRegionType::SOffset: return "SOffset32"; case BinaryRegionType::SOffset: return "SOffset32";
case BinaryRegionType::VOffset: return "VOffset16"; case BinaryRegionType::VOffset: return "VOffset16";
case BinaryRegionType::Bool: return "bool"; case BinaryRegionType::Bool: return "bool";
@@ -242,12 +245,14 @@ class BinaryAnnotator {
explicit BinaryAnnotator(const uint8_t *const bfbs, explicit BinaryAnnotator(const uint8_t *const bfbs,
const uint64_t bfbs_length, const uint64_t bfbs_length,
const uint8_t *const binary, const uint8_t *const binary,
const uint64_t binary_length) const uint64_t binary_length,
const bool is_size_prefixed)
: bfbs_(bfbs), : bfbs_(bfbs),
bfbs_length_(bfbs_length), bfbs_length_(bfbs_length),
schema_(reflection::GetSchema(bfbs)), schema_(reflection::GetSchema(bfbs)),
binary_(binary), binary_(binary),
binary_length_(binary_length) {} binary_length_(binary_length),
is_size_prefixed_(is_size_prefixed) {}
std::map<uint64_t, BinarySection> Annotate(); std::map<uint64_t, BinarySection> Annotate();
@@ -387,6 +392,7 @@ class BinaryAnnotator {
// The binary data itself. // The binary data itself.
const uint8_t *binary_; const uint8_t *binary_;
const uint64_t binary_length_; const uint64_t binary_length_;
const bool is_size_prefixed_;
// Map of binary offset to vtables, to dedupe vtables. // Map of binary offset to vtables, to dedupe vtables.
std::map<uint64_t, std::list<VTable>> vtables_; std::map<uint64_t, std::list<VTable>> vtables_;

View File

@@ -252,10 +252,9 @@ const static FlatCOption flatc_options[] = {
"Currently this is required to generate private types in Rust" }, "Currently this is required to generate private types in Rust" },
{ "", "python-no-type-prefix-suffix", "", { "", "python-no-type-prefix-suffix", "",
"Skip emission of Python functions that are prefixed with typenames" }, "Skip emission of Python functions that are prefixed with typenames" },
{ "", "python-typing", "", { "", "python-typing", "", "Generate Python type annotations" },
"Generate Python type annotations" },
{ "", "file-names-only", "", { "", "file-names-only", "",
"Print out generated file names without writing to the files"}, "Print out generated file names without writing to the files" },
}; };
auto cmp = [](FlatCOption a, FlatCOption b) { return a.long_opt < b.long_opt; }; auto cmp = [](FlatCOption a, FlatCOption b) { return a.long_opt < b.long_opt; };
@@ -394,9 +393,11 @@ void FlatCompiler::AnnotateBinaries(const uint8_t *binary_schema,
const uint8_t *binary = const uint8_t *binary =
reinterpret_cast<const uint8_t *>(binary_contents.c_str()); reinterpret_cast<const uint8_t *>(binary_contents.c_str());
const size_t binary_size = binary_contents.size(); const size_t binary_size = binary_contents.size();
const bool is_size_prefixed = options.opts.size_prefixed;
flatbuffers::BinaryAnnotator binary_annotator( flatbuffers::BinaryAnnotator binary_annotator(
binary_schema, binary_schema_size, binary, binary_size); binary_schema, binary_schema_size, binary, binary_size,
is_size_prefixed);
auto annotations = binary_annotator.Annotate(); auto annotations = binary_annotator.Annotate();
@@ -663,7 +664,7 @@ FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc,
} else if (arg == "--annotate") { } else if (arg == "--annotate") {
if (++argi >= argc) Error("missing path following: " + arg, true); if (++argi >= argc) Error("missing path following: " + arg, true);
options.annotate_schema = flatbuffers::PosixPath(argv[argi]); options.annotate_schema = flatbuffers::PosixPath(argv[argi]);
} else if(arg == "--file-names-only") { } else if (arg == "--file-names-only") {
// TODO (khhn): Provide 2 implementation // TODO (khhn): Provide 2 implementation
options.file_names_only = true; options.file_names_only = true;
} else { } else {

View File

@@ -77,8 +77,7 @@ static std::string GenIncludeGuard(const std::string &file_name,
static bool IsVectorOfPointers(const FieldDef &field) { static bool IsVectorOfPointers(const FieldDef &field) {
const auto &type = field.value.type; const auto &type = field.value.type;
const auto &vector_type = type.VectorType(); const auto &vector_type = type.VectorType();
return type.base_type == BASE_TYPE_VECTOR && return IsVector(type) && vector_type.base_type == BASE_TYPE_STRUCT &&
vector_type.base_type == BASE_TYPE_STRUCT &&
!vector_type.struct_def->fixed && !field.native_inline; !vector_type.struct_def->fixed && !field.native_inline;
} }
@@ -107,6 +106,21 @@ struct IDLOptionsCpp : public IDLOptions {
: IDLOptions(opts), g_cpp_std(CPP_STD_11), g_only_fixed_enums(true) {} : IDLOptions(opts), g_cpp_std(CPP_STD_11), g_only_fixed_enums(true) {}
}; };
// Iterates over all the fields of the object first by Offset type (Offset64
// before Offset32) and then by definition order.
static void ForAllFieldsOrderedByOffset(
const StructDef &object, std::function<void(const FieldDef *field)> func) {
// Loop over all the fields and call the func on all offset64 fields.
for (const FieldDef *field_def : object.fields.vec) {
if (field_def->offset64) { func(field_def); }
}
// Loop over all the fields a second time and call the func on all offset
// fields.
for (const FieldDef *field_def : object.fields.vec) {
if (!field_def->offset64) { func(field_def); }
}
}
class CppGenerator : public BaseGenerator { class CppGenerator : public BaseGenerator {
public: public:
CppGenerator(const Parser &parser, const std::string &path, CppGenerator(const Parser &parser, const std::string &path,
@@ -273,6 +287,25 @@ class CppGenerator : public BaseGenerator {
} }
} }
void MarkIf64BitBuilderIsNeeded() {
if (needs_64_bit_builder_) { return; }
for (auto t : parser_.structs_.vec) {
if (t == nullptr) continue;
for (auto f : t->fields.vec) {
if (f == nullptr) continue;
if (f->offset64) {
needs_64_bit_builder_ = true;
break;
}
}
}
}
std::string GetBuilder() {
return std::string("::flatbuffers::FlatBufferBuilder") +
(needs_64_bit_builder_ ? "64" : "");
}
void GenExtraIncludes() { void GenExtraIncludes() {
for (const std::string &cpp_include : opts_.cpp_includes) { for (const std::string &cpp_include : opts_.cpp_includes) {
code_ += "#include \"" + cpp_include + "\""; code_ += "#include \"" + cpp_include + "\"";
@@ -396,6 +429,9 @@ class CppGenerator : public BaseGenerator {
// Iterate through all definitions we haven't generate code for (enums, // Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file. // structs, and tables) and output them to a single file.
bool generate() { bool generate() {
// Check if we require a 64-bit flatbuffer builder.
MarkIf64BitBuilderIsNeeded();
code_.Clear(); code_.Clear();
code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n"; code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
@@ -530,6 +566,8 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("STRUCT_NAME", name); code_.SetValue("STRUCT_NAME", name);
code_.SetValue("CPP_NAME", cpp_name); code_.SetValue("CPP_NAME", cpp_name);
code_.SetValue("NULLABLE_EXT", NullableExtension()); code_.SetValue("NULLABLE_EXT", NullableExtension());
code_.SetValue(
"SIZE_T", needs_64_bit_builder_ ? ",::flatbuffers::uoffset64_t" : "");
// The root datatype accessor: // The root datatype accessor:
code_ += "inline \\"; code_ += "inline \\";
@@ -546,7 +584,8 @@ class CppGenerator : public BaseGenerator {
"*{{NULLABLE_EXT}}GetSizePrefixed{{STRUCT_NAME}}(const void " "*{{NULLABLE_EXT}}GetSizePrefixed{{STRUCT_NAME}}(const void "
"*buf) {"; "*buf) {";
code_ += code_ +=
" return ::flatbuffers::GetSizePrefixedRoot<{{CPP_NAME}}>(buf);"; " return "
"::flatbuffers::GetSizePrefixedRoot<{{CPP_NAME}}{{SIZE_T}}>(buf);";
code_ += "}"; code_ += "}";
code_ += ""; code_ += "";
@@ -565,7 +604,8 @@ class CppGenerator : public BaseGenerator {
"*buf) {"; "*buf) {";
code_ += code_ +=
" return " " return "
"::flatbuffers::GetMutableSizePrefixedRoot<{{CPP_NAME}}>(buf);"; "::flatbuffers::GetMutableSizePrefixedRoot<{{CPP_NAME}}{{SIZE_T}}>("
"buf);";
code_ += "}"; code_ += "}";
code_ += ""; code_ += "";
} }
@@ -612,7 +652,8 @@ class CppGenerator : public BaseGenerator {
code_ += "inline bool VerifySizePrefixed{{STRUCT_NAME}}Buffer("; code_ += "inline bool VerifySizePrefixed{{STRUCT_NAME}}Buffer(";
code_ += " ::flatbuffers::Verifier &verifier) {"; code_ += " ::flatbuffers::Verifier &verifier) {";
code_ += code_ +=
" return verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}>({{ID}});"; " return "
"verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}{{SIZE_T}}>({{ID}});";
code_ += "}"; code_ += "}";
code_ += ""; code_ += "";
@@ -626,7 +667,7 @@ class CppGenerator : public BaseGenerator {
// Finish a buffer with a given root object: // Finish a buffer with a given root object:
code_ += "inline void Finish{{STRUCT_NAME}}Buffer("; code_ += "inline void Finish{{STRUCT_NAME}}Buffer(";
code_ += " ::flatbuffers::FlatBufferBuilder &fbb,"; code_ += " " + GetBuilder() + " &fbb,";
code_ += " ::flatbuffers::Offset<{{CPP_NAME}}> root) {"; code_ += " ::flatbuffers::Offset<{{CPP_NAME}}> root) {";
if (parser_.file_identifier_.length()) if (parser_.file_identifier_.length())
code_ += " fbb.Finish(root, {{STRUCT_NAME}}Identifier());"; code_ += " fbb.Finish(root, {{STRUCT_NAME}}Identifier());";
@@ -636,7 +677,7 @@ class CppGenerator : public BaseGenerator {
code_ += ""; code_ += "";
code_ += "inline void FinishSizePrefixed{{STRUCT_NAME}}Buffer("; code_ += "inline void FinishSizePrefixed{{STRUCT_NAME}}Buffer(";
code_ += " ::flatbuffers::FlatBufferBuilder &fbb,"; code_ += " " + GetBuilder() + " &fbb,";
code_ += " ::flatbuffers::Offset<{{CPP_NAME}}> root) {"; code_ += " ::flatbuffers::Offset<{{CPP_NAME}}> root) {";
if (parser_.file_identifier_.length()) if (parser_.file_identifier_.length())
code_ += " fbb.FinishSizePrefixed(root, {{STRUCT_NAME}}Identifier());"; code_ += " fbb.FinishSizePrefixed(root, {{STRUCT_NAME}}Identifier());";
@@ -696,6 +737,7 @@ class CppGenerator : public BaseGenerator {
const IDLOptionsCpp opts_; const IDLOptionsCpp opts_;
const TypedFloatConstantGenerator float_const_gen_; const TypedFloatConstantGenerator float_const_gen_;
bool needs_64_bit_builder_ = false;
const Namespace *CurrentNameSpace() const { return cur_name_space_; } const Namespace *CurrentNameSpace() const { return cur_name_space_; }
@@ -747,10 +789,14 @@ class CppGenerator : public BaseGenerator {
case BASE_TYPE_STRING: { case BASE_TYPE_STRING: {
return "::flatbuffers::String"; return "::flatbuffers::String";
} }
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeWire( const auto type_name = GenTypeWire(
type.VectorType(), "", VectorElementUserFacing(type.VectorType())); type.VectorType(), "", VectorElementUserFacing(type.VectorType()));
return "::flatbuffers::Vector<" + type_name + ">"; return "::flatbuffers::Vector" +
std::string((type.base_type == BASE_TYPE_VECTOR64) ? "64<"
: "<") +
type_name + ">";
} }
case BASE_TYPE_STRUCT: { case BASE_TYPE_STRUCT: {
return WrapInNameSpace(*type.struct_def); return WrapInNameSpace(*type.struct_def);
@@ -766,13 +812,15 @@ class CppGenerator : public BaseGenerator {
// Return a C++ type for any type (scalar/pointer) specifically for // Return a C++ type for any type (scalar/pointer) specifically for
// building a flatbuffer. // building a flatbuffer.
std::string GenTypeWire(const Type &type, const char *postfix, std::string GenTypeWire(const Type &type, const char *postfix,
bool user_facing_type) const { bool user_facing_type,
bool _64_bit_offset = false) const {
if (IsScalar(type.base_type)) { if (IsScalar(type.base_type)) {
return GenTypeBasic(type, user_facing_type) + postfix; return GenTypeBasic(type, user_facing_type) + postfix;
} else if (IsStruct(type)) { } else if (IsStruct(type)) {
return "const " + GenTypePointer(type) + " *"; return "const " + GenTypePointer(type) + " *";
} else { } else {
return "::flatbuffers::Offset<" + GenTypePointer(type) + ">" + postfix; return "::flatbuffers::Offset" + std::string(_64_bit_offset ? "64" : "") +
"<" + GenTypePointer(type) + ">" + postfix;
} }
} }
@@ -858,6 +906,7 @@ class CppGenerator : public BaseGenerator {
case BASE_TYPE_STRING: { case BASE_TYPE_STRING: {
return NativeString(&field); return NativeString(&field);
} }
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeNative(type.VectorType(), true, field); const auto type_name = GenTypeNative(type.VectorType(), true, field);
if (type.struct_def && if (type.struct_def &&
@@ -866,8 +915,9 @@ class CppGenerator : public BaseGenerator {
type.struct_def->attributes.Lookup("native_custom_alloc"); type.struct_def->attributes.Lookup("native_custom_alloc");
return "std::vector<" + type_name + "," + return "std::vector<" + type_name + "," +
native_custom_alloc->constant + "<" + type_name + ">>"; native_custom_alloc->constant + "<" + type_name + ">>";
} else } else {
return "std::vector<" + type_name + ">"; return "std::vector<" + type_name + ">";
}
} }
case BASE_TYPE_STRUCT: { case BASE_TYPE_STRUCT: {
auto type_name = WrapInNameSpace(*type.struct_def); auto type_name = WrapInNameSpace(*type.struct_def);
@@ -1015,8 +1065,8 @@ class CppGenerator : public BaseGenerator {
std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) { std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) {
return "::flatbuffers::Offset<void> " + return "::flatbuffers::Offset<void> " +
(inclass ? "" : Name(enum_def) + "Union::") + (inclass ? "" : Name(enum_def) + "Union::") + "Pack(" +
"Pack(::flatbuffers::FlatBufferBuilder &_fbb, " + GetBuilder() + " &_fbb, " +
"const ::flatbuffers::rehasher_function_t *_rehasher" + "const ::flatbuffers::rehasher_function_t *_rehasher" +
(inclass ? " = nullptr" : "") + ") const"; (inclass ? " = nullptr" : "") + ") const";
} }
@@ -1024,8 +1074,7 @@ class CppGenerator : public BaseGenerator {
std::string TableCreateSignature(const StructDef &struct_def, bool predecl, std::string TableCreateSignature(const StructDef &struct_def, bool predecl,
const IDLOptions &opts) { const IDLOptions &opts) {
return "::flatbuffers::Offset<" + Name(struct_def) + "> Create" + return "::flatbuffers::Offset<" + Name(struct_def) + "> Create" +
Name(struct_def) + Name(struct_def) + "(" + GetBuilder() + " &_fbb, const " +
"(::flatbuffers::FlatBufferBuilder &_fbb, const " +
NativeName(Name(struct_def), &struct_def, opts) + NativeName(Name(struct_def), &struct_def, opts) +
" *_o, const ::flatbuffers::rehasher_function_t *_rehasher" + " *_o, const ::flatbuffers::rehasher_function_t *_rehasher" +
(predecl ? " = nullptr" : "") + ")"; (predecl ? " = nullptr" : "") + ")";
@@ -1035,7 +1084,7 @@ class CppGenerator : public BaseGenerator {
const IDLOptions &opts) { const IDLOptions &opts) {
return std::string(inclass ? "static " : "") + "::flatbuffers::Offset<" + return std::string(inclass ? "static " : "") + "::flatbuffers::Offset<" +
Name(struct_def) + "> " + (inclass ? "" : Name(struct_def) + "::") + Name(struct_def) + "> " + (inclass ? "" : Name(struct_def) + "::") +
"Pack(::flatbuffers::FlatBufferBuilder &_fbb, " + "const " + "Pack(" + GetBuilder() + " &_fbb, " + "const " +
NativeName(Name(struct_def), &struct_def, opts) + "* _o, " + NativeName(Name(struct_def), &struct_def, opts) + "* _o, " +
"const ::flatbuffers::rehasher_function_t *_rehasher" + "const ::flatbuffers::rehasher_function_t *_rehasher" +
(inclass ? " = nullptr" : "") + ")"; (inclass ? " = nullptr" : "") + ")";
@@ -1791,7 +1840,8 @@ class CppGenerator : public BaseGenerator {
if (IsStruct(vtype)) { if (IsStruct(vtype)) {
type = WrapInNameSpace(*vtype.struct_def); type = WrapInNameSpace(*vtype.struct_def);
} else { } else {
type = GenTypeWire(vtype, "", VectorElementUserFacing(vtype)); type = GenTypeWire(vtype, "", VectorElementUserFacing(vtype),
field.offset64);
} }
if (TypeHasKey(vtype)) { if (TypeHasKey(vtype)) {
code_.SetValue("PARAM_TYPE", "std::vector<" + type + "> *"); code_.SetValue("PARAM_TYPE", "std::vector<" + type + "> *");
@@ -1805,7 +1855,8 @@ class CppGenerator : public BaseGenerator {
if (field.IsScalarOptional()) if (field.IsScalarOptional())
code_.SetValue("PARAM_TYPE", GenOptionalDecl(type) + " "); code_.SetValue("PARAM_TYPE", GenOptionalDecl(type) + " ");
else else
code_.SetValue("PARAM_TYPE", GenTypeWire(type, " ", true)); code_.SetValue("PARAM_TYPE",
GenTypeWire(type, " ", true, field.offset64));
} }
code_ += "{{PRE}}{{PARAM_TYPE}}{{PARAM_NAME}} = {{PARAM_VALUE}}\\"; code_ += "{{PRE}}{{PARAM_TYPE}}{{PARAM_NAME}} = {{PARAM_VALUE}}\\";
} }
@@ -1814,7 +1865,7 @@ class CppGenerator : public BaseGenerator {
void GenMember(const FieldDef &field) { void GenMember(const FieldDef &field) {
if (!field.deprecated && // Deprecated fields won't be accessible. if (!field.deprecated && // Deprecated fields won't be accessible.
field.value.type.base_type != BASE_TYPE_UTYPE && field.value.type.base_type != BASE_TYPE_UTYPE &&
(field.value.type.base_type != BASE_TYPE_VECTOR || (!IsVector(field.value.type) ||
field.value.type.element != BASE_TYPE_UTYPE)) { field.value.type.element != BASE_TYPE_UTYPE)) {
auto type = GenTypeNative(field.value.type, false, field); auto type = GenTypeNative(field.value.type, false, field);
auto cpp_type = field.attributes.Lookup("cpp_type"); auto cpp_type = field.attributes.Lookup("cpp_type");
@@ -1918,7 +1969,7 @@ class CppGenerator : public BaseGenerator {
Name(field) + "(" + native_default->constant + ")"; Name(field) + "(" + native_default->constant + ")";
} }
} }
} else if (cpp_type && field.value.type.base_type != BASE_TYPE_VECTOR) { } else if (cpp_type && !IsVector(field.value.type)) {
if (!initializer_list.empty()) { initializer_list += ",\n "; } if (!initializer_list.empty()) { initializer_list += ",\n "; }
initializer_list += Name(field) + "(0)"; initializer_list += Name(field) + "(0)";
} }
@@ -2063,7 +2114,7 @@ class CppGenerator : public BaseGenerator {
const auto rhs_accessor = "rhs." + accessor; const auto rhs_accessor = "rhs." + accessor;
if (!field.deprecated && // Deprecated fields won't be accessible. if (!field.deprecated && // Deprecated fields won't be accessible.
field.value.type.base_type != BASE_TYPE_UTYPE && field.value.type.base_type != BASE_TYPE_UTYPE &&
(field.value.type.base_type != BASE_TYPE_VECTOR || (!IsVector(field.value.type) ||
field.value.type.element != BASE_TYPE_UTYPE)) { field.value.type.element != BASE_TYPE_UTYPE)) {
if (!compare_op.empty()) { compare_op += " &&\n "; } if (!compare_op.empty()) { compare_op += " &&\n "; }
if (struct_def.fixed || field.native_inline || if (struct_def.fixed || field.native_inline ||
@@ -2195,7 +2246,10 @@ class CppGenerator : public BaseGenerator {
"{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, " "{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, "
"{{OFFSET}}, {{ALIGN}})\\"; "{{OFFSET}}, {{ALIGN}})\\";
} else { } else {
code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\"; code_.SetValue("OFFSET_SIZE", field.offset64 ? "64" : "");
code_ +=
"{{PRE}}VerifyOffset{{OFFSET_SIZE}}{{REQUIRED}}(verifier, "
"{{OFFSET}})\\";
} }
switch (field.value.type.base_type) { switch (field.value.type.base_type) {
@@ -2217,6 +2271,7 @@ class CppGenerator : public BaseGenerator {
code_ += "{{PRE}}verifier.VerifyString({{NAME}}())\\"; code_ += "{{PRE}}verifier.VerifyString({{NAME}}())\\";
break; break;
} }
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
code_ += "{{PRE}}verifier.VerifyVector({{NAME}}())\\"; code_ += "{{PRE}}verifier.VerifyVector({{NAME}}())\\";
@@ -2468,12 +2523,18 @@ class CppGenerator : public BaseGenerator {
if (!field.IsScalarOptional()) { if (!field.IsScalarOptional()) {
const bool is_scalar = IsScalar(type.base_type); const bool is_scalar = IsScalar(type.base_type);
std::string accessor; std::string accessor;
if (is_scalar) std::string offset_size = "";
if (is_scalar) {
accessor = "GetField<"; accessor = "GetField<";
else if (IsStruct(type)) } else if (IsStruct(type)) {
accessor = "GetStruct<"; accessor = "GetStruct<";
else } else {
accessor = "GetPointer<"; if (field.offset64) {
accessor = "GetPointer64<";
} else {
accessor = "GetPointer<";
}
}
auto offset_type = GenTypeGet(type, "", "const ", " *", false); auto offset_type = GenTypeGet(type, "", "const ", " *", false);
auto call = accessor + offset_type + ">(" + offset_str; auto call = accessor + offset_type + ">(" + offset_str;
// Default value as second arg for non-pointer types. // Default value as second arg for non-pointer types.
@@ -2633,7 +2694,7 @@ class CppGenerator : public BaseGenerator {
auto offset_str = GenFieldOffsetName(field); auto offset_str = GenFieldOffsetName(field);
if (is_scalar) { if (is_scalar) {
const auto wire_type = GenTypeWire(type, "", false); const auto wire_type = GenTypeWire(type, "", false, field.offset64);
code_.SetValue("SET_FN", "SetField<" + wire_type + ">"); code_.SetValue("SET_FN", "SetField<" + wire_type + ">");
code_.SetValue("OFFSET_NAME", offset_str); code_.SetValue("OFFSET_NAME", offset_str);
code_.SetValue("FIELD_TYPE", GenTypeBasic(type, true)); code_.SetValue("FIELD_TYPE", GenTypeBasic(type, true));
@@ -2665,7 +2726,11 @@ class CppGenerator : public BaseGenerator {
} else { } else {
auto postptr = " *" + NullableExtension(); auto postptr = " *" + NullableExtension();
auto wire_type = GenTypeGet(type, " ", "", postptr.c_str(), true); auto wire_type = GenTypeGet(type, " ", "", postptr.c_str(), true);
std::string accessor = IsStruct(type) ? "GetStruct<" : "GetPointer<"; const std::string accessor = [&]() {
if (IsStruct(type)) { return "GetStruct<"; }
if (field.offset64) { return "GetPointer64<"; }
return "GetPointer<";
}();
auto underlying = accessor + wire_type + ">(" + offset_str + ")"; auto underlying = accessor + wire_type + ">(" + offset_str + ")";
code_.SetValue("FIELD_TYPE", wire_type); code_.SetValue("FIELD_TYPE", wire_type);
code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, underlying)); code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, underlying));
@@ -2859,9 +2924,9 @@ class CppGenerator : public BaseGenerator {
// Generate code to do force_align for the vector. // Generate code to do force_align for the vector.
if (align > 1) { if (align > 1) {
const auto vtype = field.value.type.VectorType(); const auto vtype = field.value.type.VectorType();
const std::string &type = IsStruct(vtype) const std::string &type =
? WrapInNameSpace(*vtype.struct_def) IsStruct(vtype) ? WrapInNameSpace(*vtype.struct_def)
: GenTypeWire(vtype, "", false); : GenTypeWire(vtype, "", false, field.offset64);
return "_fbb.ForceVectorAlignment(" + field_size + ", sizeof(" + type + return "_fbb.ForceVectorAlignment(" + field_size + ", sizeof(" + type +
"), " + std::to_string(static_cast<long long>(align)) + ");"; "), " + std::to_string(static_cast<long long>(align)) + ");";
} }
@@ -2874,7 +2939,7 @@ class CppGenerator : public BaseGenerator {
// Generate a builder struct: // Generate a builder struct:
code_ += "struct {{STRUCT_NAME}}Builder {"; code_ += "struct {{STRUCT_NAME}}Builder {";
code_ += " typedef {{STRUCT_NAME}} Table;"; code_ += " typedef {{STRUCT_NAME}} Table;";
code_ += " ::flatbuffers::FlatBufferBuilder &fbb_;"; code_ += " " + GetBuilder() + " &fbb_;";
code_ += " ::flatbuffers::uoffset_t start_;"; code_ += " ::flatbuffers::uoffset_t start_;";
bool has_string_or_vector_fields = false; bool has_string_or_vector_fields = false;
@@ -2897,12 +2962,14 @@ class CppGenerator : public BaseGenerator {
// fbb_.AddElement<type>(offset, name, default); // fbb_.AddElement<type>(offset, name, default);
// } // }
code_.SetValue("FIELD_NAME", Name(field)); code_.SetValue("FIELD_NAME", Name(field));
code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true)); code_.SetValue("FIELD_TYPE",
GenTypeWire(field.value.type, " ", true, field.offset64));
code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset); code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset);
code_.SetValue("ADD_NAME", name); code_.SetValue("ADD_NAME", name);
code_.SetValue("ADD_VALUE", value); code_.SetValue("ADD_VALUE", value);
if (is_scalar) { if (is_scalar) {
const auto type = GenTypeWire(field.value.type, "", false); const auto type =
GenTypeWire(field.value.type, "", false, field.offset64);
code_.SetValue("ADD_FN", "AddElement<" + type + ">"); code_.SetValue("ADD_FN", "AddElement<" + type + ">");
} else if (IsStruct(field.value.type)) { } else if (IsStruct(field.value.type)) {
code_.SetValue("ADD_FN", "AddStruct"); code_.SetValue("ADD_FN", "AddStruct");
@@ -2921,9 +2988,9 @@ class CppGenerator : public BaseGenerator {
} }
// Builder constructor // Builder constructor
code_ += code_ += " explicit {{STRUCT_NAME}}Builder(" + GetBuilder() +
" explicit {{STRUCT_NAME}}Builder(::flatbuffers::FlatBufferBuilder " " "
"&_fbb)"; "&_fbb)";
code_ += " : fbb_(_fbb) {"; code_ += " : fbb_(_fbb) {";
code_ += " start_ = fbb_.StartTable();"; code_ += " start_ = fbb_.StartTable();";
code_ += " }"; code_ += " }";
@@ -2950,7 +3017,7 @@ class CppGenerator : public BaseGenerator {
code_ += code_ +=
"inline ::flatbuffers::Offset<{{STRUCT_NAME}}> " "inline ::flatbuffers::Offset<{{STRUCT_NAME}}> "
"Create{{STRUCT_NAME}}("; "Create{{STRUCT_NAME}}(";
code_ += " ::flatbuffers::FlatBufferBuilder &_fbb\\"; code_ += " " + GetBuilder() + " &_fbb\\";
for (const auto &field : struct_def.fields.vec) { for (const auto &field : struct_def.fields.vec) {
if (!field->deprecated) { GenParam(*field, false, ",\n "); } if (!field->deprecated) { GenParam(*field, false, ",\n "); }
} }
@@ -2988,7 +3055,7 @@ class CppGenerator : public BaseGenerator {
code_ += code_ +=
"inline ::flatbuffers::Offset<{{STRUCT_NAME}}> " "inline ::flatbuffers::Offset<{{STRUCT_NAME}}> "
"Create{{STRUCT_NAME}}Direct("; "Create{{STRUCT_NAME}}Direct(";
code_ += " ::flatbuffers::FlatBufferBuilder &_fbb\\"; code_ += " " + GetBuilder() + " &_fbb\\";
for (const auto &field : struct_def.fields.vec) { for (const auto &field : struct_def.fields.vec) {
if (!field->deprecated) { GenParam(*field, true, ",\n "); } if (!field->deprecated) { GenParam(*field, true, ",\n "); }
} }
@@ -2997,54 +3064,85 @@ class CppGenerator : public BaseGenerator {
struct_def.defined_namespace->GetFullyQualifiedName("Create"); struct_def.defined_namespace->GetFullyQualifiedName("Create");
code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name)); code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name));
code_ += ") {"; code_ += ") {";
for (const auto &field : struct_def.fields.vec) { // Offset64 bit fields need to be added to the buffer first, so here we
if (!field->deprecated) { // loop over the fields in order of their offset size, followed by their
code_.SetValue("FIELD_NAME", Name(*field)); // definition order. Otherwise the emitted code might add a Offset
if (IsString(field->value.type)) { // followed by an Offset64 which would trigger an assertion.
if (!field->shared) {
code_.SetValue("CREATE_STRING", "CreateString"); // TODO(derekbailey): maybe optimize for the case where there is no
} else { // 64offsets in the whole schema?
code_.SetValue("CREATE_STRING", "CreateSharedString"); ForAllFieldsOrderedByOffset(struct_def, [&](const FieldDef *field) {
} if (field->deprecated) { return; }
code_ += code_.SetValue("FIELD_NAME", Name(*field));
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? " if (IsString(field->value.type)) {
"_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : 0;"; if (!field->shared) {
} else if (IsVector(field->value.type)) { code_.SetValue(
const std::string force_align_code = "CREATE_STRING",
GenVectorForceAlign(*field, Name(*field) + "->size()"); "CreateString" + std::string(field->offset64
if (!force_align_code.empty()) { ? "<::flatbuffers::Offset64>"
code_ += " if ({{FIELD_NAME}}) { " + force_align_code + " }"; : ""));
} } else {
code_ += " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\"; code_.SetValue("CREATE_STRING", "CreateSharedString");
const auto vtype = field->value.type.VectorType();
const auto has_key = TypeHasKey(vtype);
if (IsStruct(vtype)) {
const auto type = WrapInNameSpace(*vtype.struct_def);
code_ += (has_key ? "_fbb.CreateVectorOfSortedStructs<"
: "_fbb.CreateVectorOfStructs<") +
type + ">\\";
} else if (has_key) {
const auto type = WrapInNameSpace(*vtype.struct_def);
code_ += "_fbb.CreateVectorOfSortedTables<" + type + ">\\";
} else {
const auto type =
GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
code_ += "_fbb.CreateVector<" + type + ">\\";
}
code_ +=
has_key ? "({{FIELD_NAME}}) : 0;" : "(*{{FIELD_NAME}}) : 0;";
} }
code_ +=
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
"_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : 0;";
} else if (IsVector(field->value.type)) {
const std::string force_align_code =
GenVectorForceAlign(*field, Name(*field) + "->size()");
if (!force_align_code.empty()) {
code_ += " if ({{FIELD_NAME}}) { " + force_align_code + " }";
}
code_ += " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\";
const auto vtype = field->value.type.VectorType();
const auto has_key = TypeHasKey(vtype);
if (IsStruct(vtype)) {
const std::string type = WrapInNameSpace(*vtype.struct_def);
if (has_key) {
code_ += "_fbb.CreateVectorOfSortedStructs<" + type + ">\\";
} else {
// If the field uses 64-bit addressing, create a 64-bit vector.
if (field->value.type.base_type == BASE_TYPE_VECTOR64) {
code_ += "_fbb.CreateVectorOfStructs64\\";
} else {
code_ += "_fbb.CreateVectorOfStructs\\";
if (field->offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code_ += "64<::flatbuffers::Vector>\\";
} else {
code_ += "<" + type + ">\\";
}
}
}
} else if (has_key) {
const auto type = WrapInNameSpace(*vtype.struct_def);
code_ += "_fbb.CreateVectorOfSortedTables<" + type + ">\\";
} else {
const auto type = GenTypeWire(
vtype, "", VectorElementUserFacing(vtype), field->offset64);
if (field->value.type.base_type == BASE_TYPE_VECTOR64) {
code_ += "_fbb.CreateVector64\\";
} else {
// If the field uses 64-bit addressing, create a 64-bit vector.
code_.SetValue("64OFFSET", field->offset64 ? "64" : "");
code_.SetValue("TYPE",
field->offset64 ? "::flatbuffers::Vector" : type);
code_ += "_fbb.CreateVector{{64OFFSET}}<{{TYPE}}>\\";
}
}
code_ += has_key ? "({{FIELD_NAME}}) : 0;" : "(*{{FIELD_NAME}}) : 0;";
} }
} });
code_ += " return {{CREATE_NAME}}{{STRUCT_NAME}}("; code_ += " return {{CREATE_NAME}}{{STRUCT_NAME}}(";
code_ += " _fbb\\"; code_ += " _fbb\\";
for (const auto &field : struct_def.fields.vec) { for (const auto &field : struct_def.fields.vec) {
if (!field->deprecated) { if (field->deprecated) { continue; }
code_.SetValue("FIELD_NAME", Name(*field)); code_.SetValue("FIELD_NAME", Name(*field));
code_ += ",\n {{FIELD_NAME}}\\"; code_ += ",\n {{FIELD_NAME}}\\";
if (IsString(field->value.type) || IsVector(field->value.type)) { if (IsString(field->value.type) || IsVector(field->value.type)) {
code_ += "__\\"; code_ += "__\\";
}
} }
} }
code_ += ");"; code_ += ");";
@@ -3115,6 +3213,7 @@ class CppGenerator : public BaseGenerator {
const FieldDef *union_field) { const FieldDef *union_field) {
std::string code; std::string code;
switch (field.value.type.base_type) { switch (field.value.type.base_type) {
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
auto name = Name(field); auto name = Name(field);
if (field.value.type.element == BASE_TYPE_UTYPE) { if (field.value.type.element == BASE_TYPE_UTYPE) {
@@ -3151,8 +3250,11 @@ class CppGenerator : public BaseGenerator {
? ".type" ? ".type"
: (field.value.type.element == BASE_TYPE_UNION ? ".value" : (field.value.type.element == BASE_TYPE_UNION ? ".value"
: ""); : "");
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
code += "for (::flatbuffers::uoffset_t _i = 0;"; code += "for (::flatbuffers::uoffset64_t _i = 0;";
} else {
code += "for (::flatbuffers::uoffset_t _i = 0;";
}
code += " _i < _e->size(); _i++) { "; code += " _i < _e->size(); _i++) { ";
auto cpp_type = field.attributes.Lookup("cpp_type"); auto cpp_type = field.attributes.Lookup("cpp_type");
if (cpp_type) { if (cpp_type) {
@@ -3265,8 +3367,7 @@ class CppGenerator : public BaseGenerator {
} else { } else {
value += Name(field); value += Name(field);
} }
if (field.value.type.base_type != BASE_TYPE_VECTOR && if (!IsVector(field.value.type) && field.attributes.Lookup("cpp_type")) {
field.attributes.Lookup("cpp_type")) {
auto type = GenTypeBasic(field.value.type, false); auto type = GenTypeBasic(field.value.type, false);
value = value =
"_rehasher ? " "_rehasher ? "
@@ -3282,7 +3383,10 @@ class CppGenerator : public BaseGenerator {
// _fbb.CreateSharedString(_o->field) // _fbb.CreateSharedString(_o->field)
case BASE_TYPE_STRING: { case BASE_TYPE_STRING: {
if (!field.shared) { if (!field.shared) {
code += "_fbb.CreateString("; code +=
"_fbb.CreateString" +
std::string(field.offset64 ? "<::flatbuffers::Offset64>" : "") +
"(";
} else { } else {
code += "_fbb.CreateSharedString("; code += "_fbb.CreateSharedString(";
} }
@@ -3309,6 +3413,7 @@ class CppGenerator : public BaseGenerator {
// _fbb.CreateVector<Offset<T>>(_o->field.size() [&](size_t i) { // _fbb.CreateVector<Offset<T>>(_o->field.size() [&](size_t i) {
// return CreateT(_fbb, _o->Get(i), rehasher); // return CreateT(_fbb, _o->Get(i), rehasher);
// }); // });
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
auto vector_type = field.value.type.VectorType(); auto vector_type = field.value.type.VectorType();
switch (vector_type.base_type) { switch (vector_type.base_type) {
@@ -3347,7 +3452,16 @@ class CppGenerator : public BaseGenerator {
} }
code += ")"; code += ")";
} else { } else {
code += "_fbb.CreateVectorOfStructs"; // If the field uses 64-bit addressing, create a 64-bit vector.
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
code += "_fbb.CreateVectorOfStructs64";
} else {
code += "_fbb.CreateVectorOfStructs";
if (field.offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code += "64<::flatbuffers::Vector>";
}
}
code += "(" + value + ")"; code += "(" + value + ")";
} }
} else { } else {
@@ -3413,7 +3527,17 @@ class CppGenerator : public BaseGenerator {
code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0"; code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0";
code += "; }, &_va )"; code += "; }, &_va )";
} else { } else {
code += "_fbb.CreateVector(" + value + ")"; // If the field uses 64-bit addressing, create a 64-bit vector.
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
code += "_fbb.CreateVector64(" + value + ")";
} else {
code += "_fbb.CreateVector";
if (field.offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code += "64<::flatbuffers::Vector>";
}
code += "(" + value + ")";
}
} }
break; break;
} }
@@ -3540,7 +3664,9 @@ class CppGenerator : public BaseGenerator {
code_ += code_ +=
" struct _VectorArgs " " struct _VectorArgs "
"{ ::flatbuffers::FlatBufferBuilder *__fbb; " "{ " +
GetBuilder() +
" *__fbb; "
"const " + "const " +
NativeName(Name(struct_def), &struct_def, opts_) + NativeName(Name(struct_def), &struct_def, opts_) +
"* __o; " "* __o; "

View File

@@ -826,7 +826,7 @@ class CSharpGenerator : public BaseGenerator {
// Force compile time error if not using the same version runtime. // Force compile time error if not using the same version runtime.
code += " public static void ValidateVersion() {"; code += " public static void ValidateVersion() {";
code += " FlatBufferConstants."; code += " FlatBufferConstants.";
code += "FLATBUFFERS_23_5_8(); "; code += "FLATBUFFERS_23_5_9(); ";
code += "}\n"; code += "}\n";
// Generate a special accessor for the table that when used as the root // Generate a special accessor for the table that when used as the root

View File

@@ -703,7 +703,7 @@ class JavaGenerator : public BaseGenerator {
// Force compile time error if not using the same version runtime. // Force compile time error if not using the same version runtime.
code += " public static void ValidateVersion() {"; code += " public static void ValidateVersion() {";
code += " Constants."; code += " Constants.";
code += "FLATBUFFERS_23_5_8(); "; code += "FLATBUFFERS_23_5_9(); ";
code += "}\n"; code += "}\n";
// Generate a special accessor for the table that when used as the root // Generate a special accessor for the table that when used as the root

View File

@@ -524,7 +524,7 @@ class KotlinGenerator : public BaseGenerator {
// runtime. // runtime.
GenerateFunOneLine( GenerateFunOneLine(
writer, "validateVersion", "", "", writer, "validateVersion", "", "",
[&]() { writer += "Constants.FLATBUFFERS_23_5_8()"; }, [&]() { writer += "Constants.FLATBUFFERS_23_5_9()"; },
options.gen_jvmstatic); options.gen_jvmstatic);
GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options); GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options);

View File

@@ -1842,7 +1842,7 @@ class SwiftGenerator : public BaseGenerator {
} }
std::string ValidateFunc() { std::string ValidateFunc() {
return "static func validateVersion() { FlatBuffersVersion_23_5_8() }"; return "static func validateVersion() { FlatBuffersVersion_23_5_9() }";
} }
std::string GenType(const Type &type, std::string GenType(const Type &type,

View File

@@ -19,6 +19,7 @@
#include <algorithm> #include <algorithm>
#include "flatbuffers/base.h"
#include "flatbuffers/code_generator.h" #include "flatbuffers/code_generator.h"
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
#include "flatbuffers/flexbuffers.h" #include "flatbuffers/flexbuffers.h"
@@ -101,13 +102,13 @@ struct JsonPrinter {
// Print a vector or an array of JSON values, comma seperated, wrapped in // Print a vector or an array of JSON values, comma seperated, wrapped in
// "[]". // "[]".
template<typename Container> template<typename Container, typename SizeT = typename Container::size_type>
const char *PrintContainer(PrintScalarTag, const Container &c, size_t size, const char *PrintContainer(PrintScalarTag, const Container &c, SizeT size,
const Type &type, int indent, const uint8_t *) { const Type &type, int indent, const uint8_t *) {
const auto elem_indent = indent + Indent(); const auto elem_indent = indent + Indent();
text += '['; text += '[';
AddNewLine(); AddNewLine();
for (uoffset_t i = 0; i < size; i++) { for (SizeT i = 0; i < size; i++) {
if (i) { if (i) {
AddComma(); AddComma();
AddNewLine(); AddNewLine();
@@ -123,14 +124,14 @@ struct JsonPrinter {
// Print a vector or an array of JSON values, comma seperated, wrapped in // Print a vector or an array of JSON values, comma seperated, wrapped in
// "[]". // "[]".
template<typename Container> template<typename Container, typename SizeT = typename Container::size_type>
const char *PrintContainer(PrintPointerTag, const Container &c, size_t size, const char *PrintContainer(PrintPointerTag, const Container &c, SizeT size,
const Type &type, int indent, const uint8_t *prev_val) { const Type &type, int indent, const uint8_t *prev_val) {
const auto is_struct = IsStruct(type); const auto is_struct = IsStruct(type);
const auto elem_indent = indent + Indent(); const auto elem_indent = indent + Indent();
text += '['; text += '[';
AddNewLine(); AddNewLine();
for (uoffset_t i = 0; i < size; i++) { for (SizeT i = 0; i < size; i++) {
if (i) { if (i) {
AddComma(); AddComma();
AddNewLine(); AddNewLine();
@@ -149,10 +150,10 @@ struct JsonPrinter {
return nullptr; return nullptr;
} }
template<typename T> template<typename T, typename SizeT = uoffset_t>
const char *PrintVector(const void *val, const Type &type, int indent, const char *PrintVector(const void *val, const Type &type, int indent,
const uint8_t *prev_val) { const uint8_t *prev_val) {
typedef Vector<T> Container; typedef Vector<T, SizeT> Container;
typedef typename PrintTag<typename Container::return_type>::type tag; typedef typename PrintTag<typename Container::return_type>::type tag;
auto &vec = *reinterpret_cast<const Container *>(val); auto &vec = *reinterpret_cast<const Container *>(val);
return PrintContainer<Container>(tag(), vec, vec.size(), type, indent, return PrintContainer<Container>(tag(), vec, vec.size(), type, indent,
@@ -161,8 +162,9 @@ struct JsonPrinter {
// Print an array a sequence of JSON values, comma separated, wrapped in "[]". // Print an array a sequence of JSON values, comma separated, wrapped in "[]".
template<typename T> template<typename T>
const char *PrintArray(const void *val, size_t size, const Type &type, const char *PrintArray(const void *val, uint16_t size, const Type &type,
int indent) {
int indent) {
typedef Array<T, 0xFFFF> Container; typedef Array<T, 0xFFFF> Container;
typedef typename PrintTag<typename Container::return_type>::type tag; typedef typename PrintTag<typename Container::return_type>::type tag;
auto &arr = *reinterpret_cast<const Container *>(val); auto &arr = *reinterpret_cast<const Container *>(val);
@@ -240,7 +242,7 @@ struct JsonPrinter {
} }
template<typename T> static T GetFieldDefault(const FieldDef &fd) { template<typename T> static T GetFieldDefault(const FieldDef &fd) {
T val; T val{};
auto check = StringToNumber(fd.value.constant.c_str(), &val); auto check = StringToNumber(fd.value.constant.c_str(), &val);
(void)check; (void)check;
FLATBUFFERS_ASSERT(check); FLATBUFFERS_ASSERT(check);

View File

@@ -16,12 +16,15 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <iostream>
#include <list> #include <list>
#include <string> #include <string>
#include <utility> #include <utility>
#include "flatbuffers/base.h" #include "flatbuffers/base.h"
#include "flatbuffers/buffer.h"
#include "flatbuffers/idl.h" #include "flatbuffers/idl.h"
#include "flatbuffers/reflection_generated.h"
#include "flatbuffers/util.h" #include "flatbuffers/util.h"
namespace flatbuffers { namespace flatbuffers {
@@ -42,7 +45,8 @@ static const double kPi = 3.14159265358979323846;
// The enums in the reflection schema should match the ones we use internally. // The enums in the reflection schema should match the ones we use internally.
// Compare the last element to check if these go out of sync. // Compare the last element to check if these go out of sync.
static_assert(BASE_TYPE_UNION == static_cast<BaseType>(reflection::Union), static_assert(BASE_TYPE_VECTOR64 ==
static_cast<BaseType>(reflection::MaxBaseType - 1),
"enums don't match"); "enums don't match");
// Any parsing calls have to be wrapped in this macro, which automates // Any parsing calls have to be wrapped in this macro, which automates
@@ -124,6 +128,14 @@ CheckedError atot<Offset<void>>(const char *s, Parser &parser,
return NoError(); return NoError();
} }
template<>
CheckedError atot<Offset64<void>>(const char *s, Parser &parser,
Offset64<void> *val) {
(void)parser;
*val = Offset64<void>(atoi(s));
return NoError();
}
template<typename T> template<typename T>
static T *LookupTableByName(const SymbolTable<T> &table, static T *LookupTableByName(const SymbolTable<T> &table,
const std::string &name, const std::string &name,
@@ -957,11 +969,11 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
ECHECK(AddField(struct_def, name, type, &field)); ECHECK(AddField(struct_def, name, type, &field));
if (typefield) { if (typefield) {
// We preserve the relation between the typefield // We preserve the relation between the typefield
// and field, so we can easily map it in the code // and field, so we can easily map it in the code
// generators. // generators.
typefield->sibling_union_field = field; typefield->sibling_union_field = field;
field->sibling_union_field = typefield; field->sibling_union_field = typefield;
} }
if (token_ == '=') { if (token_ == '=') {
@@ -1036,6 +1048,65 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
} }
} }
if (field->attributes.Lookup("vector64") != nullptr) {
if (!IsVector(type)) {
return Error("`vector64` attribute can only be applied on vectors.");
}
// Upgrade the type to be a BASE_TYPE_VECTOR64, since the attributes are
// parsed after the type.
const BaseType element_base_type = type.element;
type = Type(BASE_TYPE_VECTOR64, type.struct_def, type.enum_def);
type.element = element_base_type;
// Since the field was already added to the parent object, update the type
// in place.
field->value.type = type;
// 64-bit vectors imply the offset64 attribute.
field->offset64 = true;
}
// Record that this field uses 64-bit offsets.
if (field->attributes.Lookup("offset64") != nullptr) {
// TODO(derekbailey): would be nice to have this be a recommendation or hint
// instead of a warning.
if (type.base_type == BASE_TYPE_VECTOR64) {
Warning("attribute `vector64` implies `offset64` and isn't required.");
}
field->offset64 = true;
}
// Check for common conditions with Offset64 fields.
if (field->offset64) {
// TODO(derekbailey): this is where we can disable string support for
// offset64, as that is not a hard requirement to have.
if (!IsString(type) && !IsVector(type)) {
return Error(
"only string and vectors can have `offset64` attribute applied");
}
// If this is a Vector, only scalar and scalar-like (structs) items are
// allowed.
// TODO(derekbailey): allow vector of strings, just require that the strings
// are Offset64<string>.
if (IsVector(type) &&
!((IsScalar(type.element) && !IsEnum(type.VectorType())) ||
IsStruct(type.VectorType()))) {
return Error("only vectors of scalars are allowed to be 64-bit.");
}
// Lastly, check if it is supported by the specified generated languages. Do
// this last so the above checks can inform the user of schema errors to fix
// first.
if (!Supports64BitOffsets()) {
return Error(
"fields using 64-bit offsets are not yet supported in at least one "
"of the specified programming languages.");
}
}
// For historical convenience reasons, string keys are assumed required. // For historical convenience reasons, string keys are assumed required.
// Scalars are kDefault unless otherwise specified. // Scalars are kDefault unless otherwise specified.
// Nonscalars are kOptional unless required; // Nonscalars are kOptional unless required;
@@ -1058,7 +1129,8 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (field->key) { if (field->key) {
if (struct_def.has_key) return Error("only one field may be set as 'key'"); if (struct_def.has_key) return Error("only one field may be set as 'key'");
struct_def.has_key = true; struct_def.has_key = true;
auto is_valid = IsScalar(type.base_type) || IsString(type) || IsStruct(type); auto is_valid =
IsScalar(type.base_type) || IsString(type) || IsStruct(type);
if (IsArray(type)) { if (IsArray(type)) {
is_valid |= is_valid |=
IsScalar(type.VectorType().base_type) || IsStruct(type.VectorType()); IsScalar(type.VectorType().base_type) || IsStruct(type.VectorType());
@@ -1161,7 +1233,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (nested->type.base_type != BASE_TYPE_STRING) if (nested->type.base_type != BASE_TYPE_STRING)
return Error( return Error(
"nested_flatbuffer attribute must be a string (the root type)"); "nested_flatbuffer attribute must be a string (the root type)");
if (type.base_type != BASE_TYPE_VECTOR || type.element != BASE_TYPE_UCHAR) if (!IsVector(type.base_type) || type.element != BASE_TYPE_UCHAR)
return Error( return Error(
"nested_flatbuffer attribute may only apply to a vector of ubyte"); "nested_flatbuffer attribute may only apply to a vector of ubyte");
// This will cause an error if the root type of the nested flatbuffer // This will cause an error if the root type of the nested flatbuffer
@@ -1230,7 +1302,7 @@ CheckedError Parser::ParseComma() {
CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn, size_t parent_fieldn,
const StructDef *parent_struct_def, const StructDef *parent_struct_def,
uoffset_t count, bool inside_vector) { size_t count, bool inside_vector) {
switch (val.type.base_type) { switch (val.type.base_type) {
case BASE_TYPE_UNION: { case BASE_TYPE_UNION: {
FLATBUFFERS_ASSERT(field); FLATBUFFERS_ASSERT(field);
@@ -1300,7 +1372,7 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
return Error( return Error(
"union types vector smaller than union values vector for: " + "union types vector smaller than union values vector for: " +
field->name); field->name);
enum_idx = vector_of_union_types->Get(count); enum_idx = vector_of_union_types->Get(static_cast<uoffset_t>(count));
} else { } else {
ECHECK(atot(constant.c_str(), *this, &enum_idx)); ECHECK(atot(constant.c_str(), *this, &enum_idx));
} }
@@ -1329,9 +1401,10 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
ECHECK(ParseString(val, field->shared)); ECHECK(ParseString(val, field->shared));
break; break;
} }
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
uoffset_t off; uoffset_t off;
ECHECK(ParseVector(val.type.VectorType(), &off, field, parent_fieldn)); ECHECK(ParseVector(val.type, &off, field, parent_fieldn));
val.constant = NumToString(off); val.constant = NumToString(off);
break; break;
} }
@@ -1503,6 +1576,9 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; size; for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; size;
size /= 2) { size /= 2) {
// Go through elements in reverse, since we're building the data backwards. // Go through elements in reverse, since we're building the data backwards.
// TODO(derekbailey): this doesn't work when there are Offset64 fields, as
// those have to be built first. So this needs to be changed to iterate over
// Offset64 then Offset32 fields.
for (auto it = field_stack_.rbegin(); for (auto it = field_stack_.rbegin();
it != field_stack_.rbegin() + fieldn_outer; ++it) { it != field_stack_.rbegin() + fieldn_outer; ++it) {
auto &field_value = it->first; auto &field_value = it->first;
@@ -1510,7 +1586,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
if (!struct_def.sortbysize || if (!struct_def.sortbysize ||
size == SizeOf(field_value.type.base_type)) { size == SizeOf(field_value.type.base_type)) {
switch (field_value.type.base_type) { switch (field_value.type.base_type) {
// clang-format off // clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
case BASE_TYPE_ ## ENUM: \ case BASE_TYPE_ ## ENUM: \
builder_.Pad(field->padding); \ builder_.Pad(field->padding); \
@@ -1541,9 +1617,16 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
if (IsStruct(field->value.type)) { \ if (IsStruct(field->value.type)) { \
SerializeStruct(*field->value.type.struct_def, field_value); \ SerializeStruct(*field->value.type.struct_def, field_value); \
} else { \ } else { \
CTYPE val; \ /* Special case for fields that use 64-bit addressing */ \
ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ if(field->offset64) { \
builder_.AddOffset(field_value.offset, val); \ Offset64<void> offset; \
ECHECK(atot(field_value.constant.c_str(), *this, &offset)); \
builder_.AddOffset(field_value.offset, offset); \
} else { \
CTYPE val; \
ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
builder_.AddOffset(field_value.offset, val); \
} \
} \ } \
break; break;
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
@@ -1581,7 +1664,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
} }
template<typename F> template<typename F>
CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) { CheckedError Parser::ParseVectorDelimiters(size_t &count, F body) {
EXPECT('['); EXPECT('[');
for (;;) { for (;;) {
if ((!opts.strict_json || !count) && Is(']')) break; if ((!opts.strict_json || !count) && Is(']')) break;
@@ -1611,10 +1694,11 @@ CheckedError Parser::ParseAlignAttribute(const std::string &align_constant,
NumToString(FLATBUFFERS_MAX_ALIGNMENT)); NumToString(FLATBUFFERS_MAX_ALIGNMENT));
} }
CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue, CheckedError Parser::ParseVector(const Type &vector_type, uoffset_t *ovalue,
FieldDef *field, size_t fieldn) { FieldDef *field, size_t fieldn) {
uoffset_t count = 0; Type type = vector_type.VectorType();
auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError { size_t count = 0;
auto err = ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
Value val; Value val;
val.type = type; val.type = type;
ECHECK(ParseAnyValue(val, field, fieldn, nullptr, count, true)); ECHECK(ParseAnyValue(val, field, fieldn, nullptr, count, true));
@@ -1634,12 +1718,18 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
} }
// TODO Fix using element alignment as size (`elemsize`)! // TODO Fix using element alignment as size (`elemsize`)!
builder_.StartVector(len, elemsize, alignment); if (vector_type.base_type == BASE_TYPE_VECTOR64) {
for (uoffset_t i = 0; i < count; i++) { // TODO(derekbailey): this requires a 64-bit builder.
// builder_.StartVector<Offset64, uoffset64_t>(len, elemsize, alignment);
builder_.StartVector(len, elemsize, alignment);
} else {
builder_.StartVector(len, elemsize, alignment);
}
for (size_t i = 0; i < count; i++) {
// start at the back, since we're building the data backwards. // start at the back, since we're building the data backwards.
auto &val = field_stack_.back().first; auto &val = field_stack_.back().first;
switch (val.type.base_type) { switch (val.type.base_type) {
// clang-format off // clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE,...) \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE,...) \
case BASE_TYPE_ ## ENUM: \ case BASE_TYPE_ ## ENUM: \
if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \
@@ -1657,7 +1747,11 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
} }
builder_.ClearOffsets(); builder_.ClearOffsets();
*ovalue = builder_.EndVector(count); if (vector_type.base_type == BASE_TYPE_VECTOR64) {
*ovalue = builder_.EndVector<uoffset64_t>(count);
} else {
*ovalue = builder_.EndVector(count);
}
if (type.base_type == BASE_TYPE_STRUCT && type.struct_def->has_key) { if (type.base_type == BASE_TYPE_STRUCT && type.struct_def->has_key) {
// We should sort this vector. Find the key first. // We should sort this vector. Find the key first.
@@ -1725,8 +1819,8 @@ CheckedError Parser::ParseArray(Value &array) {
FlatBufferBuilder builder; FlatBufferBuilder builder;
const auto &type = array.type.VectorType(); const auto &type = array.type.VectorType();
auto length = array.type.fixed_length; auto length = array.type.fixed_length;
uoffset_t count = 0; size_t count = 0;
auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError { auto err = ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
stack.emplace_back(Value()); stack.emplace_back(Value());
auto &val = stack.back(); auto &val = stack.back();
val.type = type; val.type = type;
@@ -1977,8 +2071,7 @@ CheckedError Parser::TryTypedValue(const std::string *name, int dtoken,
e.type.base_type = req; e.type.base_type = req;
} else { } else {
return Error(std::string("type mismatch: expecting: ") + return Error(std::string("type mismatch: expecting: ") +
TypeName(e.type.base_type) + TypeName(e.type.base_type) + ", found: " + TypeName(req) +
", found: " + TypeName(req) +
", name: " + (name ? *name : "") + ", value: " + e.constant); ", name: " + (name ? *name : "") + ", value: " + e.constant);
} }
} }
@@ -2595,6 +2688,11 @@ bool Parser::SupportsAdvancedArrayFeatures() const {
IDLOptions::kBinary | IDLOptions::kRust | IDLOptions::kTs)) == 0; IDLOptions::kBinary | IDLOptions::kRust | IDLOptions::kTs)) == 0;
} }
bool Parser::Supports64BitOffsets() const {
return (opts.lang_to_generate &
~(IDLOptions::kCpp | IDLOptions::kJson | IDLOptions::kBinary)) == 0;
}
Namespace *Parser::UniqueNamespace(Namespace *ns) { Namespace *Parser::UniqueNamespace(Namespace *ns) {
for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) { for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
if (ns->components == (*it)->components) { if (ns->components == (*it)->components) {
@@ -3217,10 +3315,9 @@ CheckedError Parser::SkipAnyJsonValue() {
}); });
} }
case '[': { case '[': {
uoffset_t count = 0; size_t count = 0;
return ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError { return ParseVectorDelimiters(
return SkipAnyJsonValue(); count, [&](size_t &) -> CheckedError { return SkipAnyJsonValue(); });
});
} }
case kTokenStringConstant: case kTokenStringConstant:
case kTokenIntegerConstant: case kTokenIntegerConstant:
@@ -3269,8 +3366,8 @@ CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) {
} }
case '[': { case '[': {
auto start = builder->StartVector(); auto start = builder->StartVector();
uoffset_t count = 0; size_t count = 0;
ECHECK(ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError { ECHECK(ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
return ParseFlexBufferValue(builder); return ParseFlexBufferValue(builder);
})); }));
builder->EndVector(start, false, false); builder->EndVector(start, false, false);
@@ -3922,7 +4019,7 @@ Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0, IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0,
// result may be platform-dependent if underlying is float (not double) // result may be platform-dependent if underlying is float (not double)
IsFloat(value.type.base_type) ? d : 0.0, deprecated, IsRequired(), key, IsFloat(value.type.base_type) ? d : 0.0, deprecated, IsRequired(), key,
attr__, docs__, IsOptional(), static_cast<uint16_t>(padding)); attr__, docs__, IsOptional(), static_cast<uint16_t>(padding), offset64);
// TODO: value.constant is almost always "0", we could save quite a bit of // TODO: value.constant is almost always "0", we could save quite a bit of
// space by sharing it. Same for common values of value.type. // space by sharing it. Same for common values of value.type.
} }
@@ -3940,6 +4037,7 @@ bool FieldDef::Deserialize(Parser &parser, const reflection::Field *field) {
presence = FieldDef::MakeFieldPresence(field->optional(), field->required()); presence = FieldDef::MakeFieldPresence(field->optional(), field->required());
padding = field->padding(); padding = field->padding();
key = field->key(); key = field->key();
offset64 = field->offset64();
if (!DeserializeAttributes(parser, field->attributes())) return false; if (!DeserializeAttributes(parser, field->attributes())) return false;
// TODO: this should probably be handled by a separate attribute // TODO: this should probably be handled by a separate attribute
if (attributes.Lookup("flexbuffer")) { if (attributes.Lookup("flexbuffer")) {
@@ -4264,12 +4362,18 @@ std::string Parser::ConformTo(const Parser &base) {
auto field_base = struct_def_base->fields.Lookup(field.name); auto field_base = struct_def_base->fields.Lookup(field.name);
const auto qualified_field_name = qualified_name + "." + field.name; const auto qualified_field_name = qualified_name + "." + field.name;
if (field_base) { if (field_base) {
if (field.value.offset != field_base->value.offset) if (field.value.offset != field_base->value.offset) {
return "offsets differ for field: " + qualified_field_name; return "offsets differ for field: " + qualified_field_name;
if (field.value.constant != field_base->value.constant) }
if (field.value.constant != field_base->value.constant) {
return "defaults differ for field: " + qualified_field_name; return "defaults differ for field: " + qualified_field_name;
if (!EqualByName(field.value.type, field_base->value.type)) }
if (!EqualByName(field.value.type, field_base->value.type)) {
return "types differ for field: " + qualified_field_name; return "types differ for field: " + qualified_field_name;
}
if (field.offset64 != field_base->offset64) {
return "offset types differ for field: " + qualified_field_name;
}
} else { } else {
// Doesn't have to exist, deleting fields is fine. // Doesn't have to exist, deleting fields is fine.
// But we should check if there is a field that has the same offset // But we should check if there is a field that has the same offset

View File

@@ -119,4 +119,4 @@ extension UInt64: Scalar, Verifiable {
public typealias NumericValue = UInt64 public typealias NumericValue = UInt64
} }
public func FlatBuffersVersion_23_5_8() {} public func FlatBuffersVersion_23_5_9() {}

View File

@@ -0,0 +1,8 @@
namespace v1;
table RootTable {
a:float;
b:[uint8];
}
root_type RootTable;

View File

@@ -0,0 +1,219 @@
// 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 == 23 &&
FLATBUFFERS_VERSION_MINOR == 5 &&
FLATBUFFERS_VERSION_REVISION == 9,
"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_

View File

@@ -0,0 +1,9 @@
namespace v2;
table RootTable {
a:float;
b:[uint8];
big_vector:[uint8] (vector64);
}
root_type RootTable;

View File

@@ -0,0 +1,243 @@
// 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 == 23 &&
FLATBUFFERS_VERSION_MINOR == 5 &&
FLATBUFFERS_VERSION_REVISION == 9,
"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_

View File

@@ -0,0 +1,447 @@
#include "offset64_test.h"
#include <stdint.h>
#include <cstdint>
#include <fstream>
#include <limits>
#include <ostream>
#include "evolution/v1_generated.h"
#include "evolution/v2_generated.h"
#include "flatbuffers/base.h"
#include "flatbuffers/buffer.h"
#include "flatbuffers/flatbuffer_builder.h"
#include "flatbuffers/flatbuffers.h"
#include "test_64bit_generated.h"
#include "test_assert.h"
namespace flatbuffers {
namespace tests {
void Offset64Test() {
FlatBufferBuilder64 builder;
const size_t far_vector_size = 1LL << 2;
const size_t big_vector_size = 1LL << 31;
{
// 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);
// Ensure the buffer is big.
TEST_ASSERT(builder.GetSize() > FLATBUFFERS_MAX_BUFFER_SIZE);
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 << 31);
giant_data[2] = 42;
builder.Finish(
v2::CreateRootTableDirect(builder, 1234, &data, &giant_data));
// Ensure the buffer is bigger than the 32-bit size limit for V1.
TEST_ASSERT(builder.GetSize() > FLATBUFFERS_MAX_BUFFER_SIZE);
// 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);
}
} // namespace tests
} // namespace flatbuffers

View File

@@ -0,0 +1,19 @@
#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();
} // namespace tests
} // namespace flatbuffers
#endif // TESTS_64BIT_OFFSET64_TEST_H

View File

@@ -0,0 +1,74 @@
// 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]

BIN
tests/64bit/test_64bit.bfbs Normal file

Binary file not shown.

BIN
tests/64bit/test_64bit.bin Normal file

Binary file not shown.

View File

@@ -0,0 +1,49 @@
struct LeafStruct {
a:int;
b:double;
}
table WrapperTable {
// A normal 32-bit sized vector that could be very far away (64-bit address).
vector:[int8] (offset64);
}
table RootTable {
// A normal 32-bit sized vector, that could be very far away (64-bit address).
far_vector:[ubyte] (offset64);
// An inplace value just to check that vtable offsets are correct.
a:int;
// A normal 32-bit sized string, that could be very far away (64-bit address).
far_string:string (offset64);
// A big 64-bit sized vector, that could be very far away (64-bit address).
big_vector:[ubyte] (vector64);
// A normal 32-bit sized string that is no far away (32-bit address).
near_string:string;
// A big 64-bit sized vector that is a nested flatbuffers (64-bit address).
nested_root:[ubyte] (vector64, nested_flatbuffer: "RootTable");
// A normal 32-bit size vector of structs, that could be very far away
// (64-bit address)
far_struct_vector:[LeafStruct] (offset64);
// A big 64-bit size vector of structs that could be very far away
// (64-bit address)
big_struct_vector:[LeafStruct] (vector64);
// A normal 32-bit size vector of tables. Currently 64-bit vectors don't
// support tables as it would require serializing a table (32-bit) before the
// vector (64-bit), which is not allowed.
//
// This demonstrates how you could have many vectors in the buffer, by
// effectively having a vector of 64-bit vectors. The IDL doesn't support
// nested vecotrs (e.g.: [[type]] ), so going through a wrapper table allows
// this.
many_vectors:[WrapperTable];
}
root_type RootTable;

View File

@@ -0,0 +1,17 @@
{
"far_vector": [1, 2, 3],
"a": 1234,
"far_string": "this is a far string which has a 64-bit offset",
"big_vector": [5, 6, 7, 8],
"near_string": "this is a near string which has a 32-bit offset",
"big_struct_vector": [
{
"a": 12,
"b": 3.456
},
{
"a": 78,
"b": 9.10
}
]
}

View File

@@ -0,0 +1,93 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_TEST64BIT_BFBS_H_
#define FLATBUFFERS_GENERATED_TEST64BIT_BFBS_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 == 5 &&
FLATBUFFERS_VERSION_REVISION == 9,
"Non-compatible flatbuffers version included");
struct RootTableBinarySchema {
static const uint8_t *data() {
// Buffer containing the binary schema.
static const uint8_t bfbsData[1180] = {
0x1C,0x00,0x00,0x00,0x42,0x46,0x42,0x53,0x14,0x00,0x20,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,
0x14,0x00,0x18,0x00,0x00,0x00,0x1C,0x00,0x14,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x2C,0x00,0x00,0x00,
0x20,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x2C,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x60,0x03,0x00,0x00,0x28,0x00,0x00,0x00,0xBC,0x02,0x00,0x00,
0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
0x5C,0x03,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xFD,0xFF,0xFF,0x38,0x00,0x00,0x00,
0x0C,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x09,0x00,0x00,0x00,0x1C,0x02,0x00,0x00,
0x68,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xE0,0x01,0x00,0x00,0xAC,0x00,0x00,0x00,0x2C,0x02,0x00,0x00,
0x1C,0x00,0x00,0x00,0x3C,0x01,0x00,0x00,0xE8,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x52,0x6F,0x6F,0x74,
0x54,0x61,0x62,0x6C,0x65,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x14,0x00,
0x18,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x78,0xFF,0xFF,0xFF,0x00,0x00,0x0E,0x0F,0x02,0x00,0x00,0x00,
0x04,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x6D,0x61,0x6E,0x79,0x5F,0x76,0x65,0x63,0x74,0x6F,0x72,0x73,
0x00,0x00,0x00,0x00,0xA0,0xFE,0xFF,0xFF,0x00,0x00,0x01,0x01,0x07,0x00,0x12,0x00,0x2C,0x00,0x00,0x00,
0x14,0x00,0x00,0x00,0x10,0x00,0x14,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x00,0x00,0x0C,0x00,0x10,0x00,
0x10,0x00,0x00,0x00,0x00,0x00,0x12,0x0F,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
0x11,0x00,0x00,0x00,0x62,0x69,0x67,0x5F,0x73,0x74,0x72,0x75,0x63,0x74,0x5F,0x76,0x65,0x63,0x74,0x6F,
0x72,0x00,0x00,0x00,0xF0,0xFE,0xFF,0xFF,0x00,0x00,0x01,0x01,0x06,0x00,0x10,0x00,0x28,0x00,0x00,0x00,
0x14,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,
0x10,0x00,0x00,0x00,0x00,0x00,0x0E,0x0F,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00,
0x66,0x61,0x72,0x5F,0x73,0x74,0x72,0x75,0x63,0x74,0x5F,0x76,0x65,0x63,0x74,0x6F,0x72,0x00,0x00,0x00,
0x3C,0xFF,0xFF,0xFF,0x00,0x00,0x01,0x01,0x05,0x00,0x0E,0x00,0x18,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
0x80,0xFF,0xFF,0xFF,0x00,0x00,0x12,0x04,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,
0x6E,0x65,0x73,0x74,0x65,0x64,0x5F,0x72,0x6F,0x6F,0x74,0x00,0x1C,0x00,0x14,0x00,0x0C,0x00,0x10,0x00,
0x08,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,
0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x00,0x0C,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
0x90,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x0D,0x01,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x6E,0x65,0x61,0x72,
0x5F,0x73,0x74,0x72,0x69,0x6E,0x67,0x00,0xBC,0xFF,0xFF,0xFF,0x00,0x00,0x01,0x01,0x03,0x00,0x0A,0x00,
0x28,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
0x08,0x00,0x0C,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x12,0x04,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
0x0A,0x00,0x00,0x00,0x62,0x69,0x67,0x5F,0x76,0x65,0x63,0x74,0x6F,0x72,0x00,0x00,0x20,0x00,0x14,0x00,
0x0C,0x00,0x10,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x00,0x08,0x00,
0x14,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x24,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x0D,0x01,0x00,0x00,0x00,
0x0A,0x00,0x00,0x00,0x66,0x61,0x72,0x5F,0x73,0x74,0x72,0x69,0x6E,0x67,0x00,0x00,0xB0,0xFE,0xFF,0xFF,
0x01,0x00,0x06,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x50,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x07,
0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x90,0xFF,0xFF,0xFF,0x01,0x01,0x04,0x00,
0x14,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x70,0xFF,0xFF,0xFF,0x00,0x00,0x0E,0x04,0x01,0x00,0x00,0x00,
0x0A,0x00,0x00,0x00,0x66,0x61,0x72,0x5F,0x76,0x65,0x63,0x74,0x6F,0x72,0x00,0x00,0x14,0x00,0x14,0x00,
0x04,0x00,0x08,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x14,0x00,0x00,0x00,
0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xA8,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
0x38,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x57,0x72,0x61,0x70,0x70,0x65,0x72,0x54,0x61,0x62,0x6C,0x65,
0x00,0x00,0x00,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x20,0x00,0x00,0x00,
0x01,0x01,0x04,0x00,0x24,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x10,0x00,0x0C,0x00,0x06,0x00,0x07,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0E,0x03,0x01,0x00,0x00,0x00,
0x06,0x00,0x00,0x00,0x76,0x65,0x63,0x74,0x6F,0x72,0x00,0x00,0x14,0x00,0x1C,0x00,0x08,0x00,0x0C,0x00,
0x07,0x00,0x10,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
0x38,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
0x10,0x00,0x00,0x00,0x2F,0x2F,0x74,0x65,0x73,0x74,0x5F,0x36,0x34,0x62,0x69,0x74,0x2E,0x66,0x62,0x73,
0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,
0x4C,0x65,0x61,0x66,0x53,0x74,0x72,0x75,0x63,0x74,0x00,0x00,0x0C,0x00,0x10,0x00,0x08,0x00,0x0C,0x00,
0x04,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x28,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
0x10,0x00,0x10,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x00,0x00,
0x00,0x00,0x00,0x0C,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x62,0x00,0x1E,0x00,
0x10,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x24,0x00,0x00,0x00,
0x14,0x00,0x00,0x00,0x10,0x00,0x0C,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x61,0x00,0x00,0x00
};
return bfbsData;
}
static size_t size() {
return 1180;
}
const uint8_t *begin() {
return data();
}
const uint8_t *end() {
return data() + size();
}
};
#endif // FLATBUFFERS_GENERATED_TEST64BIT_BFBS_H_

View File

@@ -0,0 +1,625 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_TEST64BIT_H_
#define FLATBUFFERS_GENERATED_TEST64BIT_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 == 5 &&
FLATBUFFERS_VERSION_REVISION == 9,
"Non-compatible flatbuffers version included");
// For access to the binary schema that produced this file.
#include "test_64bit_bfbs_generated.h"
struct LeafStruct;
struct WrapperTable;
struct WrapperTableBuilder;
struct WrapperTableT;
struct RootTable;
struct RootTableBuilder;
struct RootTableT;
bool operator==(const LeafStruct &lhs, const LeafStruct &rhs);
bool operator!=(const LeafStruct &lhs, const LeafStruct &rhs);
bool operator==(const WrapperTableT &lhs, const WrapperTableT &rhs);
bool operator!=(const WrapperTableT &lhs, const WrapperTableT &rhs);
bool operator==(const RootTableT &lhs, const RootTableT &rhs);
bool operator!=(const RootTableT &lhs, const RootTableT &rhs);
inline const ::flatbuffers::TypeTable *LeafStructTypeTable();
inline const ::flatbuffers::TypeTable *WrapperTableTypeTable();
inline const ::flatbuffers::TypeTable *RootTableTypeTable();
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) LeafStruct FLATBUFFERS_FINAL_CLASS {
private:
int32_t a_;
int32_t padding0__;
double b_;
public:
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
return LeafStructTypeTable();
}
LeafStruct()
: a_(0),
padding0__(0),
b_(0) {
(void)padding0__;
}
LeafStruct(int32_t _a, double _b)
: a_(::flatbuffers::EndianScalar(_a)),
padding0__(0),
b_(::flatbuffers::EndianScalar(_b)) {
(void)padding0__;
}
int32_t a() const {
return ::flatbuffers::EndianScalar(a_);
}
void mutate_a(int32_t _a) {
::flatbuffers::WriteScalar(&a_, _a);
}
double b() const {
return ::flatbuffers::EndianScalar(b_);
}
void mutate_b(double _b) {
::flatbuffers::WriteScalar(&b_, _b);
}
};
FLATBUFFERS_STRUCT_END(LeafStruct, 16);
inline bool operator==(const LeafStruct &lhs, const LeafStruct &rhs) {
return
(lhs.a() == rhs.a()) &&
(lhs.b() == rhs.b());
}
inline bool operator!=(const LeafStruct &lhs, const LeafStruct &rhs) {
return !(lhs == rhs);
}
struct WrapperTableT : public ::flatbuffers::NativeTable {
typedef WrapperTable TableType;
std::vector<int8_t> vector{};
};
struct WrapperTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
typedef WrapperTableT NativeTableType;
typedef WrapperTableBuilder Builder;
typedef RootTableBinarySchema BinarySchema;
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
return WrapperTableTypeTable();
}
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_VECTOR = 4
};
const ::flatbuffers::Vector<int8_t> *vector() const {
return GetPointer64<const ::flatbuffers::Vector<int8_t> *>(VT_VECTOR);
}
::flatbuffers::Vector<int8_t> *mutable_vector() {
return GetPointer64<::flatbuffers::Vector<int8_t> *>(VT_VECTOR);
}
bool Verify(::flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset64(verifier, VT_VECTOR) &&
verifier.VerifyVector(vector()) &&
verifier.EndTable();
}
WrapperTableT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
void UnPackTo(WrapperTableT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
static ::flatbuffers::Offset<WrapperTable> Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const WrapperTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
};
struct WrapperTableBuilder {
typedef WrapperTable Table;
::flatbuffers::FlatBufferBuilder64 &fbb_;
::flatbuffers::uoffset_t start_;
void add_vector(::flatbuffers::Offset64<::flatbuffers::Vector<int8_t>> vector) {
fbb_.AddOffset(WrapperTable::VT_VECTOR, vector);
}
explicit WrapperTableBuilder(::flatbuffers::FlatBufferBuilder64 &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
::flatbuffers::Offset<WrapperTable> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = ::flatbuffers::Offset<WrapperTable>(end);
return o;
}
};
inline ::flatbuffers::Offset<WrapperTable> CreateWrapperTable(
::flatbuffers::FlatBufferBuilder64 &_fbb,
::flatbuffers::Offset64<::flatbuffers::Vector<int8_t>> vector = 0) {
WrapperTableBuilder builder_(_fbb);
builder_.add_vector(vector);
return builder_.Finish();
}
inline ::flatbuffers::Offset<WrapperTable> CreateWrapperTableDirect(
::flatbuffers::FlatBufferBuilder64 &_fbb,
const std::vector<int8_t> *vector = nullptr) {
auto vector__ = vector ? _fbb.CreateVector64<::flatbuffers::Vector>(*vector) : 0;
return CreateWrapperTable(
_fbb,
vector__);
}
::flatbuffers::Offset<WrapperTable> CreateWrapperTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const WrapperTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
struct RootTableT : public ::flatbuffers::NativeTable {
typedef RootTable TableType;
std::vector<uint8_t> far_vector{};
int32_t a = 0;
std::string far_string{};
std::vector<uint8_t> big_vector{};
std::string near_string{};
std::vector<uint8_t> nested_root{};
std::vector<LeafStruct> far_struct_vector{};
std::vector<LeafStruct> big_struct_vector{};
std::vector<std::unique_ptr<WrapperTableT>> many_vectors{};
RootTableT() = default;
RootTableT(const RootTableT &o);
RootTableT(RootTableT&&) FLATBUFFERS_NOEXCEPT = default;
RootTableT &operator=(RootTableT o) FLATBUFFERS_NOEXCEPT;
};
struct RootTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
typedef RootTableT NativeTableType;
typedef RootTableBuilder Builder;
typedef RootTableBinarySchema BinarySchema;
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
return RootTableTypeTable();
}
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_FAR_VECTOR = 4,
VT_A = 6,
VT_FAR_STRING = 8,
VT_BIG_VECTOR = 10,
VT_NEAR_STRING = 12,
VT_NESTED_ROOT = 14,
VT_FAR_STRUCT_VECTOR = 16,
VT_BIG_STRUCT_VECTOR = 18,
VT_MANY_VECTORS = 20
};
const ::flatbuffers::Vector<uint8_t> *far_vector() const {
return GetPointer64<const ::flatbuffers::Vector<uint8_t> *>(VT_FAR_VECTOR);
}
::flatbuffers::Vector<uint8_t> *mutable_far_vector() {
return GetPointer64<::flatbuffers::Vector<uint8_t> *>(VT_FAR_VECTOR);
}
int32_t a() const {
return GetField<int32_t>(VT_A, 0);
}
bool mutate_a(int32_t _a = 0) {
return SetField<int32_t>(VT_A, _a, 0);
}
const ::flatbuffers::String *far_string() const {
return GetPointer64<const ::flatbuffers::String *>(VT_FAR_STRING);
}
::flatbuffers::String *mutable_far_string() {
return GetPointer64<::flatbuffers::String *>(VT_FAR_STRING);
}
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);
}
const ::flatbuffers::String *near_string() const {
return GetPointer<const ::flatbuffers::String *>(VT_NEAR_STRING);
}
::flatbuffers::String *mutable_near_string() {
return GetPointer<::flatbuffers::String *>(VT_NEAR_STRING);
}
const ::flatbuffers::Vector64<uint8_t> *nested_root() const {
return GetPointer64<const ::flatbuffers::Vector64<uint8_t> *>(VT_NESTED_ROOT);
}
::flatbuffers::Vector64<uint8_t> *mutable_nested_root() {
return GetPointer64<::flatbuffers::Vector64<uint8_t> *>(VT_NESTED_ROOT);
}
const RootTable *nested_root_nested_root() const {
const auto _f = nested_root();
return _f ? ::flatbuffers::GetRoot<RootTable>(_f->Data())
: nullptr;
}
const ::flatbuffers::Vector<const LeafStruct *> *far_struct_vector() const {
return GetPointer64<const ::flatbuffers::Vector<const LeafStruct *> *>(VT_FAR_STRUCT_VECTOR);
}
::flatbuffers::Vector<const LeafStruct *> *mutable_far_struct_vector() {
return GetPointer64<::flatbuffers::Vector<const LeafStruct *> *>(VT_FAR_STRUCT_VECTOR);
}
const ::flatbuffers::Vector64<const LeafStruct *> *big_struct_vector() const {
return GetPointer64<const ::flatbuffers::Vector64<const LeafStruct *> *>(VT_BIG_STRUCT_VECTOR);
}
::flatbuffers::Vector64<const LeafStruct *> *mutable_big_struct_vector() {
return GetPointer64<::flatbuffers::Vector64<const LeafStruct *> *>(VT_BIG_STRUCT_VECTOR);
}
const ::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>> *many_vectors() const {
return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>> *>(VT_MANY_VECTORS);
}
::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>> *mutable_many_vectors() {
return GetPointer<::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>> *>(VT_MANY_VECTORS);
}
bool Verify(::flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset64(verifier, VT_FAR_VECTOR) &&
verifier.VerifyVector(far_vector()) &&
VerifyField<int32_t>(verifier, VT_A, 4) &&
VerifyOffset64(verifier, VT_FAR_STRING) &&
verifier.VerifyString(far_string()) &&
VerifyOffset64(verifier, VT_BIG_VECTOR) &&
verifier.VerifyVector(big_vector()) &&
VerifyOffset(verifier, VT_NEAR_STRING) &&
verifier.VerifyString(near_string()) &&
VerifyOffset64(verifier, VT_NESTED_ROOT) &&
verifier.VerifyVector(nested_root()) &&
verifier.VerifyNestedFlatBuffer<RootTable>(nested_root(), nullptr) &&
VerifyOffset64(verifier, VT_FAR_STRUCT_VECTOR) &&
verifier.VerifyVector(far_struct_vector()) &&
VerifyOffset64(verifier, VT_BIG_STRUCT_VECTOR) &&
verifier.VerifyVector(big_struct_vector()) &&
VerifyOffset(verifier, VT_MANY_VECTORS) &&
verifier.VerifyVector(many_vectors()) &&
verifier.VerifyVectorOfTables(many_vectors()) &&
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_far_vector(::flatbuffers::Offset64<::flatbuffers::Vector<uint8_t>> far_vector) {
fbb_.AddOffset(RootTable::VT_FAR_VECTOR, far_vector);
}
void add_a(int32_t a) {
fbb_.AddElement<int32_t>(RootTable::VT_A, a, 0);
}
void add_far_string(::flatbuffers::Offset64<::flatbuffers::String> far_string) {
fbb_.AddOffset(RootTable::VT_FAR_STRING, far_string);
}
void add_big_vector(::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> big_vector) {
fbb_.AddOffset(RootTable::VT_BIG_VECTOR, big_vector);
}
void add_near_string(::flatbuffers::Offset<::flatbuffers::String> near_string) {
fbb_.AddOffset(RootTable::VT_NEAR_STRING, near_string);
}
void add_nested_root(::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> nested_root) {
fbb_.AddOffset(RootTable::VT_NESTED_ROOT, nested_root);
}
void add_far_struct_vector(::flatbuffers::Offset64<::flatbuffers::Vector<const LeafStruct *>> far_struct_vector) {
fbb_.AddOffset(RootTable::VT_FAR_STRUCT_VECTOR, far_struct_vector);
}
void add_big_struct_vector(::flatbuffers::Offset64<::flatbuffers::Vector64<const LeafStruct *>> big_struct_vector) {
fbb_.AddOffset(RootTable::VT_BIG_STRUCT_VECTOR, big_struct_vector);
}
void add_many_vectors(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>>> many_vectors) {
fbb_.AddOffset(RootTable::VT_MANY_VECTORS, many_vectors);
}
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,
::flatbuffers::Offset64<::flatbuffers::Vector<uint8_t>> far_vector = 0,
int32_t a = 0,
::flatbuffers::Offset64<::flatbuffers::String> far_string = 0,
::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> big_vector = 0,
::flatbuffers::Offset<::flatbuffers::String> near_string = 0,
::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> nested_root = 0,
::flatbuffers::Offset64<::flatbuffers::Vector<const LeafStruct *>> far_struct_vector = 0,
::flatbuffers::Offset64<::flatbuffers::Vector64<const LeafStruct *>> big_struct_vector = 0,
::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>>> many_vectors = 0) {
RootTableBuilder builder_(_fbb);
builder_.add_big_struct_vector(big_struct_vector);
builder_.add_nested_root(nested_root);
builder_.add_big_vector(big_vector);
builder_.add_many_vectors(many_vectors);
builder_.add_far_struct_vector(far_struct_vector);
builder_.add_near_string(near_string);
builder_.add_far_string(far_string);
builder_.add_a(a);
builder_.add_far_vector(far_vector);
return builder_.Finish();
}
inline ::flatbuffers::Offset<RootTable> CreateRootTableDirect(
::flatbuffers::FlatBufferBuilder64 &_fbb,
const std::vector<uint8_t> *far_vector = nullptr,
int32_t a = 0,
const char *far_string = nullptr,
const std::vector<uint8_t> *big_vector = nullptr,
const char *near_string = nullptr,
const std::vector<uint8_t> *nested_root = nullptr,
const std::vector<LeafStruct> *far_struct_vector = nullptr,
const std::vector<LeafStruct> *big_struct_vector = nullptr,
const std::vector<::flatbuffers::Offset<WrapperTable>> *many_vectors = nullptr) {
auto far_vector__ = far_vector ? _fbb.CreateVector64<::flatbuffers::Vector>(*far_vector) : 0;
auto far_string__ = far_string ? _fbb.CreateString<::flatbuffers::Offset64>(far_string) : 0;
auto big_vector__ = big_vector ? _fbb.CreateVector64(*big_vector) : 0;
auto nested_root__ = nested_root ? _fbb.CreateVector64(*nested_root) : 0;
auto far_struct_vector__ = far_struct_vector ? _fbb.CreateVectorOfStructs64<::flatbuffers::Vector>(*far_struct_vector) : 0;
auto big_struct_vector__ = big_struct_vector ? _fbb.CreateVectorOfStructs64(*big_struct_vector) : 0;
auto near_string__ = near_string ? _fbb.CreateString(near_string) : 0;
auto many_vectors__ = many_vectors ? _fbb.CreateVector<::flatbuffers::Offset<WrapperTable>>(*many_vectors) : 0;
return CreateRootTable(
_fbb,
far_vector__,
a,
far_string__,
big_vector__,
near_string__,
nested_root__,
far_struct_vector__,
big_struct_vector__,
many_vectors__);
}
::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
inline bool operator==(const WrapperTableT &lhs, const WrapperTableT &rhs) {
return
(lhs.vector == rhs.vector);
}
inline bool operator!=(const WrapperTableT &lhs, const WrapperTableT &rhs) {
return !(lhs == rhs);
}
inline WrapperTableT *WrapperTable::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
auto _o = std::unique_ptr<WrapperTableT>(new WrapperTableT());
UnPackTo(_o.get(), _resolver);
return _o.release();
}
inline void WrapperTable::UnPackTo(WrapperTableT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
(void)_o;
(void)_resolver;
{ auto _e = vector(); if (_e) { _o->vector.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->vector.begin()); } }
}
inline ::flatbuffers::Offset<WrapperTable> WrapperTable::Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const WrapperTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
return CreateWrapperTable(_fbb, _o, _rehasher);
}
inline ::flatbuffers::Offset<WrapperTable> CreateWrapperTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const WrapperTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
(void)_rehasher;
(void)_o;
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder64 *__fbb; const WrapperTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
auto _vector = _o->vector.size() ? _fbb.CreateVector64<::flatbuffers::Vector>(_o->vector) : 0;
return CreateWrapperTable(
_fbb,
_vector);
}
inline bool operator==(const RootTableT &lhs, const RootTableT &rhs) {
return
(lhs.far_vector == rhs.far_vector) &&
(lhs.a == rhs.a) &&
(lhs.far_string == rhs.far_string) &&
(lhs.big_vector == rhs.big_vector) &&
(lhs.near_string == rhs.near_string) &&
(lhs.nested_root == rhs.nested_root) &&
(lhs.far_struct_vector == rhs.far_struct_vector) &&
(lhs.big_struct_vector == rhs.big_struct_vector) &&
(lhs.many_vectors.size() == rhs.many_vectors.size() && std::equal(lhs.many_vectors.cbegin(), lhs.many_vectors.cend(), rhs.many_vectors.cbegin(), [](std::unique_ptr<WrapperTableT> const &a, std::unique_ptr<WrapperTableT> const &b) { return (a == b) || (a && b && *a == *b); }));
}
inline bool operator!=(const RootTableT &lhs, const RootTableT &rhs) {
return !(lhs == rhs);
}
inline RootTableT::RootTableT(const RootTableT &o)
: far_vector(o.far_vector),
a(o.a),
far_string(o.far_string),
big_vector(o.big_vector),
near_string(o.near_string),
nested_root(o.nested_root),
far_struct_vector(o.far_struct_vector),
big_struct_vector(o.big_struct_vector) {
many_vectors.reserve(o.many_vectors.size());
for (const auto &many_vectors_ : o.many_vectors) { many_vectors.emplace_back((many_vectors_) ? new WrapperTableT(*many_vectors_) : nullptr); }
}
inline RootTableT &RootTableT::operator=(RootTableT o) FLATBUFFERS_NOEXCEPT {
std::swap(far_vector, o.far_vector);
std::swap(a, o.a);
std::swap(far_string, o.far_string);
std::swap(big_vector, o.big_vector);
std::swap(near_string, o.near_string);
std::swap(nested_root, o.nested_root);
std::swap(far_struct_vector, o.far_struct_vector);
std::swap(big_struct_vector, o.big_struct_vector);
std::swap(many_vectors, o.many_vectors);
return *this;
}
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 = far_vector(); if (_e) { _o->far_vector.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->far_vector.begin()); } }
{ auto _e = a(); _o->a = _e; }
{ auto _e = far_string(); if (_e) _o->far_string = _e->str(); }
{ auto _e = big_vector(); if (_e) { _o->big_vector.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->big_vector.begin()); } }
{ auto _e = near_string(); if (_e) _o->near_string = _e->str(); }
{ auto _e = nested_root(); if (_e) { _o->nested_root.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->nested_root.begin()); } }
{ auto _e = far_struct_vector(); if (_e) { _o->far_struct_vector.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->far_struct_vector[_i] = *_e->Get(_i); } } else { _o->far_struct_vector.resize(0); } }
{ auto _e = big_struct_vector(); if (_e) { _o->big_struct_vector.resize(_e->size()); for (::flatbuffers::uoffset64_t _i = 0; _i < _e->size(); _i++) { _o->big_struct_vector[_i] = *_e->Get(_i); } } else { _o->big_struct_vector.resize(0); } }
{ auto _e = many_vectors(); if (_e) { _o->many_vectors.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->many_vectors[_i]) { _e->Get(_i)->UnPackTo(_o->many_vectors[_i].get(), _resolver); } else { _o->many_vectors[_i] = std::unique_ptr<WrapperTableT>(_e->Get(_i)->UnPack(_resolver)); }; } } else { _o->many_vectors.resize(0); } }
}
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 _far_vector = _o->far_vector.size() ? _fbb.CreateVector64<::flatbuffers::Vector>(_o->far_vector) : 0;
auto _a = _o->a;
auto _far_string = _o->far_string.empty() ? 0 : _fbb.CreateString<::flatbuffers::Offset64>(_o->far_string);
auto _big_vector = _o->big_vector.size() ? _fbb.CreateVector64(_o->big_vector) : 0;
auto _near_string = _o->near_string.empty() ? 0 : _fbb.CreateString(_o->near_string);
auto _nested_root = _o->nested_root.size() ? _fbb.CreateVector64(_o->nested_root) : 0;
auto _far_struct_vector = _o->far_struct_vector.size() ? _fbb.CreateVectorOfStructs64<::flatbuffers::Vector>(_o->far_struct_vector) : 0;
auto _big_struct_vector = _o->big_struct_vector.size() ? _fbb.CreateVectorOfStructs64(_o->big_struct_vector) : 0;
auto _many_vectors = _o->many_vectors.size() ? _fbb.CreateVector<::flatbuffers::Offset<WrapperTable>> (_o->many_vectors.size(), [](size_t i, _VectorArgs *__va) { return CreateWrapperTable(*__va->__fbb, __va->__o->many_vectors[i].get(), __va->__rehasher); }, &_va ) : 0;
return CreateRootTable(
_fbb,
_far_vector,
_a,
_far_string,
_big_vector,
_near_string,
_nested_root,
_far_struct_vector,
_big_struct_vector,
_many_vectors);
}
inline const ::flatbuffers::TypeTable *LeafStructTypeTable() {
static const ::flatbuffers::TypeCode type_codes[] = {
{ ::flatbuffers::ET_INT, 0, -1 },
{ ::flatbuffers::ET_DOUBLE, 0, -1 }
};
static const int64_t values[] = { 0, 8, 16 };
static const char * const names[] = {
"a",
"b"
};
static const ::flatbuffers::TypeTable tt = {
::flatbuffers::ST_STRUCT, 2, type_codes, nullptr, nullptr, values, names
};
return &tt;
}
inline const ::flatbuffers::TypeTable *WrapperTableTypeTable() {
static const ::flatbuffers::TypeCode type_codes[] = {
{ ::flatbuffers::ET_CHAR, 1, -1 }
};
static const char * const names[] = {
"vector"
};
static const ::flatbuffers::TypeTable tt = {
::flatbuffers::ST_TABLE, 1, type_codes, nullptr, nullptr, nullptr, names
};
return &tt;
}
inline const ::flatbuffers::TypeTable *RootTableTypeTable() {
static const ::flatbuffers::TypeCode type_codes[] = {
{ ::flatbuffers::ET_UCHAR, 1, -1 },
{ ::flatbuffers::ET_INT, 0, -1 },
{ ::flatbuffers::ET_STRING, 0, -1 },
{ ::flatbuffers::ET_UCHAR, 1, -1 },
{ ::flatbuffers::ET_STRING, 0, -1 },
{ ::flatbuffers::ET_UCHAR, 1, -1 },
{ ::flatbuffers::ET_SEQUENCE, 1, 0 },
{ ::flatbuffers::ET_SEQUENCE, 1, 0 },
{ ::flatbuffers::ET_SEQUENCE, 1, 1 }
};
static const ::flatbuffers::TypeFunction type_refs[] = {
LeafStructTypeTable,
WrapperTableTypeTable
};
static const char * const names[] = {
"far_vector",
"a",
"far_string",
"big_vector",
"near_string",
"nested_root",
"far_struct_vector",
"big_struct_vector",
"many_vectors"
};
static const ::flatbuffers::TypeTable tt = {
::flatbuffers::ST_TABLE, 9, type_codes, type_refs, nullptr, nullptr, names
};
return &tt;
}
inline const RootTable *GetRootTable(const void *buf) {
return ::flatbuffers::GetRoot<RootTable>(buf);
}
inline const RootTable *GetSizePrefixedRootTable(const void *buf) {
return ::flatbuffers::GetSizePrefixedRoot<RootTable,::flatbuffers::uoffset64_t>(buf);
}
inline RootTable *GetMutableRootTable(void *buf) {
return ::flatbuffers::GetMutableRoot<RootTable>(buf);
}
inline RootTable *GetMutableSizePrefixedRootTable(void *buf) {
return ::flatbuffers::GetMutableSizePrefixedRoot<RootTable,::flatbuffers::uoffset64_t>(buf);
}
inline bool VerifyRootTableBuffer(
::flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<RootTable>(nullptr);
}
inline bool VerifySizePrefixedRootTableBuffer(
::flatbuffers::Verifier &verifier) {
return verifier.VerifySizePrefixedBuffer<RootTable,::flatbuffers::uoffset64_t>(nullptr);
}
inline void FinishRootTableBuffer(
::flatbuffers::FlatBufferBuilder64 &fbb,
::flatbuffers::Offset<RootTable> root) {
fbb.Finish(root);
}
inline void FinishSizePrefixedRootTableBuffer(
::flatbuffers::FlatBufferBuilder64 &fbb,
::flatbuffers::Offset<RootTable> root) {
fbb.FinishSizePrefixed(root);
}
inline std::unique_ptr<RootTableT> UnPackRootTable(
const void *buf,
const ::flatbuffers::resolver_function_t *res = nullptr) {
return std::unique_ptr<RootTableT>(GetRootTable(buf)->UnPack(res));
}
inline std::unique_ptr<RootTableT> UnPackSizePrefixedRootTable(
const void *buf,
const ::flatbuffers::resolver_function_t *res = nullptr) {
return std::unique_ptr<RootTableT>(GetSizePrefixedRootTable(buf)->UnPack(res));
}
#endif // FLATBUFFERS_GENERATED_TEST64BIT_H_

View File

@@ -2,7 +2,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : Declared by :
]# ]#

View File

@@ -20,6 +20,12 @@ cc_test(
name = "flatbuffers_test", name = "flatbuffers_test",
testonly = 1, testonly = 1,
srcs = [ srcs = [
"64bit/evolution/v1_generated.h",
"64bit/evolution/v2_generated.h",
"64bit/offset64_test.cpp",
"64bit/offset64_test.h",
"64bit/test_64bit_bfbs_generated.h",
"64bit/test_64bit_generated.h",
"alignment_test.cpp", "alignment_test.cpp",
"alignment_test.h", "alignment_test.h",
"alignment_test_generated.h", "alignment_test_generated.h",

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class LongFloatEntry extends Table { public final class LongFloatEntry extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static LongFloatEntry getRootAsLongFloatEntry(ByteBuffer _bb) { return getRootAsLongFloatEntry(_bb, new LongFloatEntry()); } public static LongFloatEntry getRootAsLongFloatEntry(ByteBuffer _bb) { return getRootAsLongFloatEntry(_bb, new LongFloatEntry()); }
public static LongFloatEntry getRootAsLongFloatEntry(ByteBuffer _bb, LongFloatEntry obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static LongFloatEntry getRootAsLongFloatEntry(ByteBuffer _bb, LongFloatEntry obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -44,7 +44,7 @@ class LongFloatEntry : Table() {
return (val_1 - val_2).sign return (val_1 - val_2).sign
} }
companion object { companion object {
fun validateVersion() = Constants.FLATBUFFERS_23_5_8() fun validateVersion() = Constants.FLATBUFFERS_23_5_9()
fun getRootAsLongFloatEntry(_bb: ByteBuffer): LongFloatEntry = getRootAsLongFloatEntry(_bb, LongFloatEntry()) fun getRootAsLongFloatEntry(_bb: ByteBuffer): LongFloatEntry = getRootAsLongFloatEntry(_bb, LongFloatEntry())
fun getRootAsLongFloatEntry(_bb: ByteBuffer, obj: LongFloatEntry): LongFloatEntry { fun getRootAsLongFloatEntry(_bb: ByteBuffer, obj: LongFloatEntry): LongFloatEntry {
_bb.order(ByteOrder.LITTLE_ENDIAN) _bb.order(ByteOrder.LITTLE_ENDIAN)

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class LongFloatMap extends Table { public final class LongFloatMap extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static LongFloatMap getRootAsLongFloatMap(ByteBuffer _bb) { return getRootAsLongFloatMap(_bb, new LongFloatMap()); } public static LongFloatMap getRootAsLongFloatMap(ByteBuffer _bb) { return getRootAsLongFloatMap(_bb, new LongFloatMap()); }
public static LongFloatMap getRootAsLongFloatMap(ByteBuffer _bb, LongFloatMap obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static LongFloatMap getRootAsLongFloatMap(ByteBuffer _bb, LongFloatMap obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -58,7 +58,7 @@ class LongFloatMap : Table() {
} }
} }
companion object { companion object {
fun validateVersion() = Constants.FLATBUFFERS_23_5_8() fun validateVersion() = Constants.FLATBUFFERS_23_5_9()
fun getRootAsLongFloatMap(_bb: ByteBuffer): LongFloatMap = getRootAsLongFloatMap(_bb, LongFloatMap()) fun getRootAsLongFloatMap(_bb: ByteBuffer): LongFloatMap = getRootAsLongFloatMap(_bb, LongFloatMap())
fun getRootAsLongFloatMap(_bb: ByteBuffer, obj: LongFloatMap): LongFloatMap { fun getRootAsLongFloatMap(_bb: ByteBuffer, obj: LongFloatMap): LongFloatMap {
_bb.order(ByteOrder.LITTLE_ENDIAN) _bb.order(ByteOrder.LITTLE_ENDIAN)

View File

@@ -13,7 +13,7 @@ public struct KeywordsInTable : IFlatbufferObject
{ {
private Table __p; private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } } public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_9(); }
public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb) { return GetRootAsKeywordsInTable(_bb, new KeywordsInTable()); } public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb) { return GetRootAsKeywordsInTable(_bb, new KeywordsInTable()); }
public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb, KeywordsInTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb, KeywordsInTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }

View File

@@ -13,7 +13,7 @@ public struct Table2 : IFlatbufferObject
{ {
private Table __p; private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } } public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_9(); }
public static Table2 GetRootAsTable2(ByteBuffer _bb) { return GetRootAsTable2(_bb, new Table2()); } public static Table2 GetRootAsTable2(ByteBuffer _bb) { return GetRootAsTable2(_bb, new Table2()); }
public static Table2 GetRootAsTable2(ByteBuffer _bb, Table2 obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } public static Table2 GetRootAsTable2(ByteBuffer _bb, Table2 obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }

View File

@@ -2,7 +2,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : Declared by :
]# ]#

View File

@@ -3,7 +3,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : //monster_test.fbs Declared by : //monster_test.fbs
Rooting type : MyGame.Example.Monster (//monster_test.fbs) Rooting type : MyGame.Example.Monster (//monster_test.fbs)

View File

@@ -2,7 +2,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : Declared by :
Rooting type : MyGame.Example.Monster () Rooting type : MyGame.Example.Monster ()

View File

@@ -3,7 +3,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : //monster_test.fbs Declared by : //monster_test.fbs
Rooting type : MyGame.Example.Monster (//monster_test.fbs) Rooting type : MyGame.Example.Monster (//monster_test.fbs)

View File

@@ -2,7 +2,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : Declared by :
Rooting type : MyGame.Example.Monster () Rooting type : MyGame.Example.Monster ()

View File

@@ -3,7 +3,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : //monster_test.fbs Declared by : //monster_test.fbs
Rooting type : MyGame.Example.Monster (//monster_test.fbs) Rooting type : MyGame.Example.Monster (//monster_test.fbs)

View File

@@ -2,7 +2,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : Declared by :
Rooting type : MyGame.Example.Monster () Rooting type : MyGame.Example.Monster ()

View File

@@ -3,7 +3,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : //monster_test.fbs Declared by : //monster_test.fbs
Rooting type : MyGame.Example.Monster (//monster_test.fbs) Rooting type : MyGame.Example.Monster (//monster_test.fbs)

View File

@@ -2,7 +2,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : Declared by :
Rooting type : MyGame.Example.Monster () Rooting type : MyGame.Example.Monster ()

View File

@@ -13,7 +13,7 @@ public struct ArrayTable : IFlatbufferObject
{ {
private Table __p; private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } } public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_9(); }
public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb) { return GetRootAsArrayTable(_bb, new ArrayTable()); } public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb) { return GetRootAsArrayTable(_bb, new ArrayTable()); }
public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public static bool ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "ARRT"); } public static bool ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "ARRT"); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class ArrayTable extends Table { public final class ArrayTable extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { Constants.FLATBUFFERS_23_5_9(); }
public static ArrayTable getRootAsArrayTable(ByteBuffer _bb) { return getRootAsArrayTable(_bb, new ArrayTable()); } public static ArrayTable getRootAsArrayTable(ByteBuffer _bb) { return getRootAsArrayTable(_bb, new ArrayTable()); }
public static ArrayTable getRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } public static ArrayTable getRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public static boolean ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "ARRT"); } public static boolean ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "ARRT"); }

View File

@@ -3,7 +3,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : //monster_test.fbs Declared by : //monster_test.fbs
Rooting type : MyGame.Example.Monster (//monster_test.fbs) Rooting type : MyGame.Example.Monster (//monster_test.fbs)

View File

@@ -2,7 +2,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : Declared by :
Rooting type : MyGame.Example.Monster () Rooting type : MyGame.Example.Monster ()

View File

@@ -3,7 +3,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : //monster_test.fbs Declared by : //monster_test.fbs
Rooting type : MyGame.Example.Monster (//monster_test.fbs) Rooting type : MyGame.Example.Monster (//monster_test.fbs)

View File

@@ -2,7 +2,7 @@
Automatically generated by the FlatBuffers compiler, do not modify. Automatically generated by the FlatBuffers compiler, do not modify.
Or modify. I'm a message, not a cop. Or modify. I'm a message, not a cop.
flatc version: 23.5.8 flatc version: 23.5.9
Declared by : Declared by :
Rooting type : MyGame.Example.Monster () Rooting type : MyGame.Example.Monster ()

View File

@@ -14,7 +14,7 @@ public struct Monster : IFlatbufferObject
{ {
private Table __p; private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } } public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_8(); } public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_9(); }
public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); } public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); }
public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public static bool MonsterBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "MONS"); } public static bool MonsterBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "MONS"); }

Some files were not shown because too many files have changed in this diff Show More