Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FlatBuffers 64 for C++ #7935

Merged
merged 62 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
1f53a53
First working hack of adding 64-bit. Don't judge :)
dbaileychess Jan 26, 2023
0033e15
Made vector_downward work on 64 bit types
dbaileychess Jan 26, 2023
a91e67d
vector_downward uses size_t, added offset64 to reflection
dbaileychess Jan 26, 2023
8a4b283
cleaned up adding offset64 in parser
dbaileychess Jan 27, 2023
00a5c35
Add C++ testing skeleton for 64-bit
dbaileychess Jan 27, 2023
b08d3ed
working test for CreateVector64
dbaileychess Jan 27, 2023
e396b34
working >2 GiB buffers
dbaileychess Jan 27, 2023
44b9b91
support for large strings
dbaileychess Jan 28, 2023
d02a187
simplified CreateString<> to just provide the offset type
dbaileychess Jan 28, 2023
a00d388
generalize CreateVector template
dbaileychess Feb 2, 2023
7add255
update test_64.afb due to upstream format change
dbaileychess Feb 2, 2023
9ef353a
Added Vector64 type, which is just an alias for vector ATM
dbaileychess Feb 3, 2023
1ca9995
Switch to Offset64 for Vector64
dbaileychess Feb 4, 2023
181ba16
Update for reflection bfbs output change
dbaileychess Feb 5, 2023
c130cd2
Starting to add support for vector64 type in C++
dbaileychess Feb 5, 2023
e90f0a5
made a generic CreateVector that can handle different offsets and vec…
dbaileychess Feb 6, 2023
35d1df0
Support for 32-vector with 64-addressing
dbaileychess Feb 6, 2023
b76bfa0
Vector64 basic builder + tests working
dbaileychess Feb 6, 2023
6d310d6
basic support for json vector64 support
dbaileychess Feb 6, 2023
2a4014b
renamed fields in test_64bit.fbs to better reflect their use
dbaileychess Feb 6, 2023
f597385
working C++ vector64 builder
dbaileychess Feb 6, 2023
e63aff9
Apply --annotate-sparse-vector to 64-bit tests
dbaileychess Feb 7, 2023
3935ce4
Enable Vector64 for --annotate-sparse-vectors
dbaileychess Feb 7, 2023
5175a82
Merged from upstream
dbaileychess Mar 15, 2023
aa96cb6
Add `near_string` field for testing 32-bit offsets alongside
dbaileychess Mar 15, 2023
1cce400
keep track of where the 32-bit and 64-bit regions are for flatbufferb…
dbaileychess Mar 16, 2023
59d84e4
move template<> outside class body for GCC
dbaileychess Mar 16, 2023
574be24
update run.sh to build and run tests
dbaileychess Apr 26, 2023
eeb3347
basic assertion for adding 64-bit offset at the wrong time
dbaileychess Apr 27, 2023
b8b9bfc
started to separate `FlatBufferBuilder` into two classes, 1 64-bit aw…
dbaileychess Apr 27, 2023
eddc21e
add test for nested flatbuffer vector64, fix bug in alignment of big …
dbaileychess Apr 28, 2023
b459abf
fixed CreateDirect method by iterating by Offset64 first
dbaileychess Apr 28, 2023
5d355f3
internal refactoring of flatbufferbuilder
dbaileychess Apr 28, 2023
c9aaff3
block not supported languages in the parser from using 64-bit
dbaileychess Apr 28, 2023
3ae01bd
evolution tests for adding a vector64 field
dbaileychess Apr 28, 2023
3f0e2ed
conformity tests for adding/removing offset64 attributes
dbaileychess Apr 28, 2023
0830233
ensure test is for a big buffer
dbaileychess Apr 28, 2023
2421d33
add parser error tests for `offset64` and `vector64` attributes
dbaileychess Apr 28, 2023
490dac5
add missing static that GCC only complains about
dbaileychess Apr 28, 2023
99c4700
remove stdint-uintn.h header that gets automatically added
dbaileychess Apr 28, 2023
fa456d5
move 64-bit CalculateOffset internal
dbaileychess Apr 28, 2023
3e7bbf9
fixed return size of EndVector
dbaileychess Apr 28, 2023
f3ba945
various fixes on windows
dbaileychess Apr 29, 2023
cae57e3
add SizeT to vector_downward
dbaileychess Apr 29, 2023
b28d0e9
minimze range of size changes in vector and builder
dbaileychess Apr 30, 2023
a75b3fb
reworked how tracking if 64-offsets are added
dbaileychess May 1, 2023
6d7a8fe
Add ReturnT to EndVector
dbaileychess May 2, 2023
b51a18d
small cleanups
dbaileychess May 2, 2023
38e98d1
remove need for second Array definition
dbaileychess May 2, 2023
699b618
combine IndirectHelpers into one definition
dbaileychess May 2, 2023
2cc133b
started support for vector of struct
dbaileychess May 2, 2023
46f2068
Support for 32/64-vectors of structs + Offset64
dbaileychess May 2, 2023
d2641a3
small cleanups
dbaileychess May 2, 2023
d075a35
add verification for vector64
dbaileychess May 2, 2023
040cea8
add sized prefix for 64-bit buffers
dbaileychess May 2, 2023
cb64fef
add fuzzer for 64-bit
dbaileychess May 3, 2023
66c8059
add example of adding many vectors using a wrapper table
dbaileychess May 4, 2023
e7f1afe
run the new -bfbs-gen-embed logic on the 64-bit tests
dbaileychess May 4, 2023
6e52dbb
remove run.sh and fix cmakelist issue
dbaileychess May 5, 2023
b3e3fad
fixed bazel rules
dbaileychess May 5, 2023
46a0ea8
fixed some PR comments
dbaileychess May 8, 2023
1ac0550
add 64-bit tests to cmakelist
dbaileychess May 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ set(FlatBuffers_Tests_SRCS
tests/native_type_test_impl.cpp
tests/alignment_test.h
tests/alignment_test.cpp
tests/64bit/offset64_test.h
tests/64bit/offset64_test.cpp
include/flatbuffers/code_generators.h
src/code_generators.cpp
)
Expand Down Expand Up @@ -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_type_test.fbs "${FLATC_OPT}")
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)
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
Expand Down
7 changes: 5 additions & 2 deletions include/flatbuffers/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef FLATBUFFERS_ARRAY_H_
#define FLATBUFFERS_ARRAY_H_

#include <cstdint>
#include <memory>

#include "flatbuffers/base.h"
Expand All @@ -37,7 +38,7 @@ template<typename T, uint16_t length> class Array {
public:
typedef uint16_t size_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;

// If T is a LE-scalar or a struct (!scalar_tag::value).
Expand Down Expand Up @@ -158,11 +159,13 @@ template<typename T, uint16_t length> class Array {

// Specialization for Array[struct] with access using Offset<void> pointer.
// 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");

public:
typedef const void *return_type;
typedef uint16_t size_type;

const uint8_t *Data() const { return data_; }

Expand Down
6 changes: 5 additions & 1 deletion include/flatbuffers/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <vector>
#include <set>
#include <algorithm>
#include <limits>
#include <iterator>
#include <memory>

Expand Down Expand Up @@ -323,9 +324,11 @@ namespace flatbuffers {
// Also, using a consistent offset type maintains compatibility of serialized
// offset values between 32bit and 64bit systems.
typedef uint32_t uoffset_t;
typedef uint64_t uoffset64_t;

// Signed offsets for references that can go in both directions.
typedef int32_t soffset_t;
typedef int64_t soffset64_t;

// Offset/index used in v-tables, can be changed to uint8_t in
// format forks to save a bit of space if desired.
Expand All @@ -334,7 +337,8 @@ typedef uint16_t voffset_t;
typedef uintmax_t largest_scalar_t;

// 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.
// Includes the offset to the root table (uoffset_t), the offset to the vtable
Expand Down
93 changes: 69 additions & 24 deletions include/flatbuffers/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,33 @@ namespace flatbuffers {

// Wrapper for uoffset_t to allow safe template specialization.
// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
template<typename T> struct Offset {
uoffset_t o;
template<typename T = void> struct Offset {
// The type of offset to use.
typedef uoffset_t offset_type;

offset_type o;
Offset() : o(0) {}
Offset(uoffset_t _o) : o(_o) {}
Offset<void> Union() const { return Offset<void>(o); }
Offset(const offset_type _o) : o(_o) {}
Offset<> Union() 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() {
int endiantest = 1;
// If this fails, see FLATBUFFERS_LITTLEENDIAN above.
Expand Down Expand Up @@ -75,35 +94,59 @@ template<typename T> struct IndirectHelper {
typedef T return_type;
typedef T mutable_return_type;
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) {
dbaileychess marked this conversation as resolved.
Show resolved Hide resolved
return EndianScalar((reinterpret_cast<const T *>(p))[i]);
}
static return_type Read(uint8_t *p, uoffset_t i) {
return Read(const_cast<const uint8_t *>(p), i);
static mutable_return_type Read(uint8_t *p, const size_t 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 T *mutable_return_type;
static const size_t element_stride = sizeof(uoffset_t);
static return_type Read(const uint8_t *p, uoffset_t i) {
p += i * sizeof(uoffset_t);
return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
typedef typename OffsetT<T>::offset_type offset_type;
static const offset_type element_stride = sizeof(offset_type);

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) {
p += i * sizeof(uoffset_t);
return reinterpret_cast<mutable_return_type>(p + ReadScalar<uoffset_t>(p));
static mutable_return_type Read(uint8_t *const p, const offset_type i) {
// Offsets are relative to themselves, so first update the pointer to
// 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 *> {
typedef const T *return_type;
typedef T *mutable_return_type;
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) {
return reinterpret_cast<mutable_return_type>(p + i * sizeof(T));
static mutable_return_type Read(uint8_t *const p, const size_t i) {
// Structs are stored inline, relative to the first struct pointer.
return reinterpret_cast<mutable_return_type>(p + i * element_stride);
}
};

Expand All @@ -130,23 +173,25 @@ inline bool BufferHasIdentifier(const void *buf, const char *identifier,
/// @cond FLATBUFFERS_INTERNAL
// Helpers to get a typed pointer to the root object contained in the buffer.
template<typename T> T *GetMutableRoot(void *buf) {
if (!buf) return nullptr;
EndianCheck();
return reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>(buf) +
EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
}

template<typename T> T *GetMutableSizePrefixedRoot(void *buf) {
return GetMutableRoot<T>(reinterpret_cast<uint8_t *>(buf) +
sizeof(uoffset_t));
template<typename T, typename SizeT = uoffset_t>
T *GetMutableSizePrefixedRoot(void *buf) {
return GetMutableRoot<T>(reinterpret_cast<uint8_t *>(buf) + sizeof(SizeT));
}

template<typename T> const T *GetRoot(const void *buf) {
return GetMutableRoot<T>(const_cast<void *>(buf));
}

template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
template<typename T, typename SizeT = uoffset_t>
const T *GetSizePrefixedRoot(const void *buf) {
return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(SizeT));
}

} // namespace flatbuffers
Expand Down
Loading