[C++] add make_span for Array<T,N> (#6663)
* [C++] Add make_span for Array<T,N> and Vector<T> * [C++] Add tests for make_span<T,N>(Array<T,N>) * [C++] Add span iterators * [C++] Checked span iterator (MSVC) * Fix review notes
This commit is contained in:
parent
bd37e67ac0
commit
22498cf3a9
|
@ -259,6 +259,12 @@ template<typename T> class Vector {
|
|||
typedef VectorReverseIterator<iterator> reverse_iterator;
|
||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
|
||||
scalar_tag;
|
||||
|
||||
static FLATBUFFERS_CONSTEXPR bool is_span_observable =
|
||||
scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1);
|
||||
|
||||
uoffset_t size() const { return EndianScalar(length_); }
|
||||
|
||||
// Deprecated: use size(). Here for backwards compatibility.
|
||||
|
@ -394,6 +400,38 @@ template<typename T> class Vector {
|
|||
}
|
||||
};
|
||||
|
||||
template<class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> &vec)
|
||||
FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::is_span_observable,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return span<U>(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
template<class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
|
||||
const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::is_span_observable,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return span<const U>(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
template<class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t> make_bytes_span(
|
||||
Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::scalar_tag::value,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return span<uint8_t>(vec.Data(), vec.size() * sizeof(U));
|
||||
}
|
||||
|
||||
template<class U>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t> make_bytes_span(
|
||||
const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Vector<U>::scalar_tag::value,
|
||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
||||
return span<const uint8_t>(vec.Data(), vec.size() * sizeof(U));
|
||||
}
|
||||
|
||||
// Represent a vector much like the template above, but in this case we
|
||||
// don't know what the element types are (used with reflection.h).
|
||||
class VectorOfAny {
|
||||
|
@ -437,10 +475,9 @@ template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
|
|||
|
||||
// This is used as a helper type for accessing arrays.
|
||||
template<typename T, uint16_t length> class Array {
|
||||
typedef
|
||||
typename flatbuffers::integral_constant<bool,
|
||||
flatbuffers::is_scalar<T>::value>
|
||||
scalar_tag;
|
||||
// Array<T> can carry only POD data types (scalars or structs).
|
||||
typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
|
||||
scalar_tag;
|
||||
typedef
|
||||
typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
|
||||
IndirectHelperType;
|
||||
|
@ -451,6 +488,11 @@ template<typename T, uint16_t length> class Array {
|
|||
typedef VectorIterator<T, return_type> const_iterator;
|
||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
// If T is a LE-scalar or a struct (!scalar_tag::value).
|
||||
static FLATBUFFERS_CONSTEXPR bool is_span_observable =
|
||||
(scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1)) ||
|
||||
!scalar_tag::value;
|
||||
|
||||
FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
|
||||
|
||||
return_type Get(uoffset_t i) const {
|
||||
|
@ -515,26 +557,20 @@ template<typename T, uint16_t length> class Array {
|
|||
!(p2 >= p1 && p2 < (p1 + length)));
|
||||
(void)p1;
|
||||
(void)p2;
|
||||
|
||||
CopyFromSpanImpl(
|
||||
flatbuffers::integral_constant < bool,
|
||||
!scalar_tag::value || sizeof(T) == 1 || FLATBUFFERS_LITTLEENDIAN > (),
|
||||
src);
|
||||
CopyFromSpanImpl(flatbuffers::bool_constant<is_span_observable>(), src);
|
||||
}
|
||||
|
||||
protected:
|
||||
void MutateImpl(flatbuffers::integral_constant<bool, true>, uoffset_t i,
|
||||
const T &val) {
|
||||
void MutateImpl(flatbuffers::true_type, uoffset_t i, const T &val) {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
WriteScalar(data() + i, val);
|
||||
}
|
||||
|
||||
void MutateImpl(flatbuffers::integral_constant<bool, false>, uoffset_t i,
|
||||
const T &val) {
|
||||
void MutateImpl(flatbuffers::false_type, uoffset_t i, const T &val) {
|
||||
*(GetMutablePointer(i)) = val;
|
||||
}
|
||||
|
||||
void CopyFromSpanImpl(flatbuffers::integral_constant<bool, true>,
|
||||
void CopyFromSpanImpl(flatbuffers::true_type,
|
||||
flatbuffers::span<const T, length> src) {
|
||||
// Use std::memcpy() instead of std::copy() to avoid preformance degradation
|
||||
// due to aliasing if T is char or unsigned char.
|
||||
|
@ -543,7 +579,7 @@ template<typename T, uint16_t length> class Array {
|
|||
}
|
||||
|
||||
// Copy data from flatbuffers::span with endian conversion.
|
||||
void CopyFromSpanImpl(flatbuffers::integral_constant<bool, false>,
|
||||
void CopyFromSpanImpl(flatbuffers::false_type,
|
||||
flatbuffers::span<const T, length> src) {
|
||||
for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); }
|
||||
}
|
||||
|
@ -593,8 +629,43 @@ template<typename T, uint16_t length> class Array<Offset<T>, length> {
|
|||
uint8_t data_[1];
|
||||
};
|
||||
|
||||
template<class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U, N> make_span(Array<U, N> &arr)
|
||||
FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(
|
||||
Array<U, N>::is_span_observable,
|
||||
"wrong type U, only plain struct, LE-scalar, or byte types are allowed");
|
||||
return span<U, N>(arr.data(), N);
|
||||
}
|
||||
|
||||
template<class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U, N> make_span(
|
||||
const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(
|
||||
Array<U, N>::is_span_observable,
|
||||
"wrong type U, only plain struct, LE-scalar, or byte types are allowed");
|
||||
return span<const U, N>(arr.data(), N);
|
||||
}
|
||||
|
||||
template<class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t, sizeof(U) * N>
|
||||
make_bytes_span(Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Array<U, N>::is_span_observable,
|
||||
"internal error, Array<T> might hold only scalars or structs");
|
||||
return span<uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
|
||||
}
|
||||
|
||||
template<class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t, sizeof(U) * N>
|
||||
make_bytes_span(const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Array<U, N>::is_span_observable,
|
||||
"internal error, Array<T> might hold only scalars or structs");
|
||||
return span<const uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
|
||||
}
|
||||
|
||||
// Cast a raw T[length] to a raw flatbuffers::Array<T, length>
|
||||
// without endian conversion. Use with care.
|
||||
// TODO: move these Cast-methods to `internal` namespace.
|
||||
template<typename T, uint16_t length>
|
||||
Array<T, length> &CastToArray(T (&arr)[length]) {
|
||||
return *reinterpret_cast<Array<T, length> *>(arr);
|
||||
|
|
|
@ -166,6 +166,8 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
|||
using integral_constant = std::integral_constant<T, v>;
|
||||
template <bool B>
|
||||
using bool_constant = integral_constant<bool, B>;
|
||||
using true_type = std::true_type;
|
||||
using false_type = std::false_type;
|
||||
#else
|
||||
// Map C++ TR1 templates defined by stlport.
|
||||
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
|
||||
|
@ -191,6 +193,8 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
|||
using integral_constant = std::tr1::integral_constant<T, v>;
|
||||
template <bool B>
|
||||
using bool_constant = integral_constant<bool, B>;
|
||||
using true_type = bool_constant<true>;
|
||||
using false_type = bool_constant<false>;
|
||||
#endif // !FLATBUFFERS_CPP98_STL
|
||||
#else
|
||||
// MSVC 2010 doesn't support C++11 aliases.
|
||||
|
@ -207,6 +211,8 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
|||
struct integral_constant : public std::integral_constant<T, v> {};
|
||||
template <bool B>
|
||||
struct bool_constant : public integral_constant<bool, B> {};
|
||||
typedef bool_constant<true> true_type;
|
||||
typedef bool_constant<false> false_type;
|
||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
|
@ -495,6 +501,32 @@ namespace internal {
|
|||
int, void>::type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct SpanIterator {
|
||||
// TODO: upgrade to std::random_access_iterator_tag.
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = typename std::remove_cv<T>::type;
|
||||
using reference = T&;
|
||||
using pointer = T*;
|
||||
|
||||
// Convince MSVC compiler that this iterator is trusted (it is verified).
|
||||
#ifdef _MSC_VER
|
||||
using _Unchecked_type = pointer;
|
||||
#endif // _MSC_VER
|
||||
|
||||
SpanIterator(pointer ptr) : ptr_(ptr) {}
|
||||
reference operator*() const { return *ptr_; }
|
||||
pointer operator->() { return ptr_; }
|
||||
SpanIterator& operator++() { ptr_++; return *this; }
|
||||
SpanIterator operator++(int) { auto tmp = *this; ++(*this); return tmp; }
|
||||
|
||||
friend bool operator== (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ == rhs.ptr_; }
|
||||
friend bool operator!= (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ != rhs.ptr_; }
|
||||
|
||||
private:
|
||||
pointer ptr_;
|
||||
};
|
||||
} // namespace internal
|
||||
#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
|
||||
|
||||
|
@ -534,6 +566,17 @@ class span FLATBUFFERS_FINAL_CLASS {
|
|||
return data_;
|
||||
}
|
||||
|
||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL)
|
||||
using Iterator = internal::SpanIterator<T>;
|
||||
using ConstIterator = internal::SpanIterator<const T>;
|
||||
|
||||
Iterator begin() const { return Iterator(data()); }
|
||||
Iterator end() const { return Iterator(data() + size()); }
|
||||
|
||||
ConstIterator cbegin() const { return ConstIterator(data()); }
|
||||
ConstIterator cend() const { return ConstIterator(data() + size()); }
|
||||
#endif
|
||||
|
||||
// Returns a reference to the idx-th element of the sequence.
|
||||
// The behavior is undefined if the idx is greater than or equal to size().
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const {
|
||||
|
@ -627,47 +670,46 @@ class span FLATBUFFERS_FINAL_CLASS {
|
|||
pointer const data_;
|
||||
const size_type count_;
|
||||
};
|
||||
|
||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL)
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<U, N> make_span(U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
|
||||
return span<U, N>(arr);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<const U, N> make_span(const U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
|
||||
return span<const U, N>(arr);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<U, N> make_span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
return span<U, N>(arr);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<const U, N> make_span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
return span<const U, N>(arr);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<U, dynamic_extent> make_span(U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
|
||||
return span<U, dynamic_extent>(first, count);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<const U, dynamic_extent> make_span(const U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
|
||||
return span<const U, dynamic_extent>(first, count);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // defined(FLATBUFFERS_USE_STD_SPAN)
|
||||
|
||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL)
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<U, N> make_span(U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
|
||||
return span<U, N>(arr);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<const U, N> make_span(const U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
|
||||
return span<const U, N>(arr);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<U, N> make_span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
return span<U, N>(arr);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<const U, N> make_span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
return span<const U, N>(arr);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<U, dynamic_extent> make_span(U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
|
||||
return span<U, dynamic_extent>(first, count);
|
||||
}
|
||||
|
||||
template<class U, std::size_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11
|
||||
flatbuffers::span<const U, dynamic_extent> make_span(const U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
|
||||
return span<const U, dynamic_extent>(first, count);
|
||||
}
|
||||
#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_STL_EMULATION_H_
|
||||
|
|
102
tests/test.cpp
102
tests/test.cpp
|
@ -3499,9 +3499,9 @@ void FlatbuffersSpanTest() {
|
|||
void FlatbuffersSpanTest() {}
|
||||
#endif
|
||||
|
||||
void FixedLengthArrayTest() {
|
||||
// VS10 does not support typed enums, exclude from tests
|
||||
// VS10 does not support typed enums, exclude from tests
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||
void FixedLengthArrayTest() {
|
||||
// Generate an ArrayTable containing one ArrayStruct.
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
MyGame::Example::NestedStruct nStruct0(MyGame::Example::TestEnum::B);
|
||||
|
@ -3535,10 +3535,10 @@ void FixedLengthArrayTest() {
|
|||
aStruct.mutable_d()->Mutate(1, nStruct1);
|
||||
auto aTable = MyGame::Example::CreateArrayTable(fbb, &aStruct);
|
||||
MyGame::Example::FinishArrayTableBuffer(fbb, aTable);
|
||||
|
||||
// Verify correctness of the ArrayTable.
|
||||
flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
|
||||
MyGame::Example::VerifyArrayTableBuffer(verifier);
|
||||
TEST_ASSERT(MyGame::Example::VerifyArrayTableBuffer(verifier));
|
||||
// Do test.
|
||||
auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
|
||||
auto mArStruct = p->mutable_a();
|
||||
TEST_NOTNULL(mArStruct);
|
||||
|
@ -3548,10 +3548,10 @@ void FixedLengthArrayTest() {
|
|||
TEST_NOTNULL(mArStruct->mutable_b());
|
||||
TEST_NOTNULL(mArStruct->mutable_d());
|
||||
TEST_NOTNULL(mArStruct->mutable_f());
|
||||
mArStruct->mutable_b()->Mutate(14, -14);
|
||||
TEST_EQ(mArStruct->a(), 2);
|
||||
TEST_EQ(mArStruct->b()->size(), 15);
|
||||
TEST_EQ(mArStruct->b()->Get(aStruct.b()->size() - 1), -14);
|
||||
mArStruct->mutable_b()->Mutate(14, -14);
|
||||
TEST_EQ(mArStruct->b()->Get(14), -14);
|
||||
TEST_EQ(mArStruct->c(), 12);
|
||||
TEST_NOTNULL(mArStruct->d()->Get(0));
|
||||
TEST_NOTNULL(mArStruct->d()->Get(0)->a());
|
||||
|
@ -3603,8 +3603,10 @@ void FixedLengthArrayTest() {
|
|||
# endif
|
||||
(void)ap;
|
||||
for (size_t i = 0; i < arr_size; ++i) { TEST_EQ(non_zero_memory[i], 0); }
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void FixedLengthArrayTest() {}
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||
|
||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL) && \
|
||||
(!defined(_MSC_VER) || _MSC_VER >= 1700)
|
||||
|
@ -3689,9 +3691,9 @@ void NativeTypeTest() {
|
|||
}
|
||||
}
|
||||
|
||||
void FixedLengthArrayJsonTest(bool binary) {
|
||||
// VS10 does not support typed enums, exclude from tests
|
||||
// VS10 does not support typed enums, exclude from tests
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||
void FixedLengthArrayJsonTest(bool binary) {
|
||||
// load FlatBuffer schema (.fbs) and JSON from disk
|
||||
std::string schemafile;
|
||||
std::string jsonfile;
|
||||
|
@ -3748,11 +3750,86 @@ void FixedLengthArrayJsonTest(bool binary) {
|
|||
parserGen.builder_.GetBufferPointer(),
|
||||
parserOrg.builder_.GetSize()),
|
||||
0);
|
||||
#else
|
||||
(void)binary;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedLengthArraySpanTest() {
|
||||
// load FlatBuffer schema (.fbs) and JSON from disk
|
||||
std::string schemafile;
|
||||
std::string jsonfile;
|
||||
TEST_EQ(flatbuffers::LoadFile((test_data_path + "arrays_test.fbs").c_str(),
|
||||
false, &schemafile),
|
||||
true);
|
||||
TEST_EQ(flatbuffers::LoadFile((test_data_path + "arrays_test.golden").c_str(),
|
||||
false, &jsonfile),
|
||||
true);
|
||||
|
||||
// parse schema first, so we can use it to parse the data after
|
||||
flatbuffers::Parser parser;
|
||||
TEST_EQ(parser.Parse(schemafile.c_str()), true);
|
||||
TEST_EQ(parser.Parse(jsonfile.c_str()), true);
|
||||
auto &fbb = parser.builder_;
|
||||
auto verifier = flatbuffers::Verifier(fbb.GetBufferPointer(), fbb.GetSize());
|
||||
TEST_EQ(true, VerifyArrayTableBuffer(verifier));
|
||||
|
||||
auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
|
||||
TEST_NOTNULL(p);
|
||||
auto table_struct = p->mutable_a();
|
||||
TEST_NOTNULL(table_struct);
|
||||
TEST_EQ(2, table_struct->d()->size());
|
||||
TEST_NOTNULL(table_struct->d());
|
||||
TEST_NOTNULL(table_struct->mutable_d());
|
||||
// test array of structs
|
||||
auto const_d = flatbuffers::make_span(*table_struct->d());
|
||||
auto mutable_d = flatbuffers::make_span(*table_struct->mutable_d());
|
||||
TEST_EQ(2, const_d.size());
|
||||
TEST_EQ(2, mutable_d.size());
|
||||
TEST_ASSERT(const_d[0] == mutable_d[0]);
|
||||
TEST_ASSERT(const_d[1] == mutable_d[1]);
|
||||
mutable_d[0] = const_d[0]; // mutate
|
||||
// test scalars
|
||||
auto &const_nested = const_d[0];
|
||||
auto &mutable_nested = mutable_d[0];
|
||||
static_assert(sizeof(MyGame::Example::TestEnum) == sizeof(uint8_t),
|
||||
"TestEnum's underlaying type must by byte");
|
||||
TEST_NOTNULL(const_nested.d());
|
||||
TEST_NOTNULL(mutable_nested.d());
|
||||
{
|
||||
flatbuffers::span<const MyGame::Example::TestEnum, 2> const_d_c =
|
||||
flatbuffers::make_span(*const_nested.c());
|
||||
auto mutable_d_c = flatbuffers::make_span(*mutable_nested.mutable_c());
|
||||
TEST_EQ(2, const_d_c.size());
|
||||
TEST_EQ(2, mutable_d_c.size());
|
||||
TEST_EQ(MyGame::Example::TestEnum::C, const_d_c[0]);
|
||||
TEST_EQ(MyGame::Example::TestEnum::B, const_d_c[1]);
|
||||
TEST_ASSERT(mutable_d_c.end() == std::copy(const_d_c.cbegin(),
|
||||
const_d_c.cend(),
|
||||
mutable_d_c.begin()));
|
||||
TEST_ASSERT(
|
||||
std::equal(const_d_c.cbegin(), const_d_c.cend(), mutable_d_c.cbegin()));
|
||||
}
|
||||
// test little endian array of int32
|
||||
# if FLATBUFFERS_LITTLEENDIAN
|
||||
{
|
||||
flatbuffers::span<const int32_t, 2> const_d_a =
|
||||
flatbuffers::make_span(*const_nested.a());
|
||||
auto mutable_d_a = flatbuffers::make_span(*mutable_nested.mutable_a());
|
||||
TEST_EQ(2, const_d_a.size());
|
||||
TEST_EQ(2, mutable_d_a.size());
|
||||
TEST_EQ(-1, const_d_a[0]);
|
||||
TEST_EQ(2, const_d_a[1]);
|
||||
TEST_ASSERT(mutable_d_a.end() == std::copy(const_d_a.cbegin(),
|
||||
const_d_a.cend(),
|
||||
mutable_d_a.begin()));
|
||||
TEST_ASSERT(
|
||||
std::equal(const_d_a.cbegin(), const_d_a.cend(), mutable_d_a.cbegin()));
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#else
|
||||
void FixedLengthArrayJsonTest(bool /*binary*/) {}
|
||||
void FixedLengthArraySpanTest() {}
|
||||
#endif
|
||||
|
||||
void TestEmbeddedBinarySchema() {
|
||||
// load JSON from disk
|
||||
std::string jsonfile;
|
||||
|
@ -4147,6 +4224,7 @@ int FlatBufferTests() {
|
|||
ParseIncorrectMonsterJsonTest();
|
||||
FlexBuffersFloatingPointTest();
|
||||
FlatbuffersIteratorsTest();
|
||||
FixedLengthArraySpanTest();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue