mirror of https://github.com/opencv/opencv.git
parent
ca48e217f1
commit
bdff0949bb
28 changed files with 15285 additions and 66 deletions
@ -0,0 +1,202 @@ |
||||
|
||||
Apache License |
||||
Version 2.0, January 2004 |
||||
http://www.apache.org/licenses/ |
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||
|
||||
1. Definitions. |
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, |
||||
and distribution as defined by Sections 1 through 9 of this document. |
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by |
||||
the copyright owner that is granting the License. |
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all |
||||
other entities that control, are controlled by, or are under common |
||||
control with that entity. For the purposes of this definition, |
||||
"control" means (i) the power, direct or indirect, to cause the |
||||
direction or management of such entity, whether by contract or |
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||
outstanding shares, or (iii) beneficial ownership of such entity. |
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity |
||||
exercising permissions granted by this License. |
||||
|
||||
"Source" form shall mean the preferred form for making modifications, |
||||
including but not limited to software source code, documentation |
||||
source, and configuration files. |
||||
|
||||
"Object" form shall mean any form resulting from mechanical |
||||
transformation or translation of a Source form, including but |
||||
not limited to compiled object code, generated documentation, |
||||
and conversions to other media types. |
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or |
||||
Object form, made available under the License, as indicated by a |
||||
copyright notice that is included in or attached to the work |
||||
(an example is provided in the Appendix below). |
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object |
||||
form, that is based on (or derived from) the Work and for which the |
||||
editorial revisions, annotations, elaborations, or other modifications |
||||
represent, as a whole, an original work of authorship. For the purposes |
||||
of this License, Derivative Works shall not include works that remain |
||||
separable from, or merely link (or bind by name) to the interfaces of, |
||||
the Work and Derivative Works thereof. |
||||
|
||||
"Contribution" shall mean any work of authorship, including |
||||
the original version of the Work and any modifications or additions |
||||
to that Work or Derivative Works thereof, that is intentionally |
||||
submitted to Licensor for inclusion in the Work by the copyright owner |
||||
or by an individual or Legal Entity authorized to submit on behalf of |
||||
the copyright owner. For the purposes of this definition, "submitted" |
||||
means any form of electronic, verbal, or written communication sent |
||||
to the Licensor or its representatives, including but not limited to |
||||
communication on electronic mailing lists, source code control systems, |
||||
and issue tracking systems that are managed by, or on behalf of, the |
||||
Licensor for the purpose of discussing and improving the Work, but |
||||
excluding communication that is conspicuously marked or otherwise |
||||
designated in writing by the copyright owner as "Not a Contribution." |
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||
on behalf of whom a Contribution has been received by Licensor and |
||||
subsequently incorporated within the Work. |
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
copyright license to reproduce, prepare Derivative Works of, |
||||
publicly display, publicly perform, sublicense, and distribute the |
||||
Work and such Derivative Works in Source or Object form. |
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
(except as stated in this section) patent license to make, have made, |
||||
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||
where such license applies only to those patent claims licensable |
||||
by such Contributor that are necessarily infringed by their |
||||
Contribution(s) alone or by combination of their Contribution(s) |
||||
with the Work to which such Contribution(s) was submitted. If You |
||||
institute patent litigation against any entity (including a |
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||
or a Contribution incorporated within the Work constitutes direct |
||||
or contributory patent infringement, then any patent licenses |
||||
granted to You under this License for that Work shall terminate |
||||
as of the date such litigation is filed. |
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the |
||||
Work or Derivative Works thereof in any medium, with or without |
||||
modifications, and in Source or Object form, provided that You |
||||
meet the following conditions: |
||||
|
||||
(a) You must give any other recipients of the Work or |
||||
Derivative Works a copy of this License; and |
||||
|
||||
(b) You must cause any modified files to carry prominent notices |
||||
stating that You changed the files; and |
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works |
||||
that You distribute, all copyright, patent, trademark, and |
||||
attribution notices from the Source form of the Work, |
||||
excluding those notices that do not pertain to any part of |
||||
the Derivative Works; and |
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its |
||||
distribution, then any Derivative Works that You distribute must |
||||
include a readable copy of the attribution notices contained |
||||
within such NOTICE file, excluding those notices that do not |
||||
pertain to any part of the Derivative Works, in at least one |
||||
of the following places: within a NOTICE text file distributed |
||||
as part of the Derivative Works; within the Source form or |
||||
documentation, if provided along with the Derivative Works; or, |
||||
within a display generated by the Derivative Works, if and |
||||
wherever such third-party notices normally appear. The contents |
||||
of the NOTICE file are for informational purposes only and |
||||
do not modify the License. You may add Your own attribution |
||||
notices within Derivative Works that You distribute, alongside |
||||
or as an addendum to the NOTICE text from the Work, provided |
||||
that such additional attribution notices cannot be construed |
||||
as modifying the License. |
||||
|
||||
You may add Your own copyright statement to Your modifications and |
||||
may provide additional or different license terms and conditions |
||||
for use, reproduction, or distribution of Your modifications, or |
||||
for any such Derivative Works as a whole, provided Your use, |
||||
reproduction, and distribution of the Work otherwise complies with |
||||
the conditions stated in this License. |
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||
any Contribution intentionally submitted for inclusion in the Work |
||||
by You to the Licensor shall be under the terms and conditions of |
||||
this License, without any additional terms or conditions. |
||||
Notwithstanding the above, nothing herein shall supersede or modify |
||||
the terms of any separate license agreement you may have executed |
||||
with Licensor regarding such Contributions. |
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade |
||||
names, trademarks, service marks, or product names of the Licensor, |
||||
except as required for reasonable and customary use in describing the |
||||
origin of the Work and reproducing the content of the NOTICE file. |
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or |
||||
agreed to in writing, Licensor provides the Work (and each |
||||
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||
implied, including, without limitation, any warranties or conditions |
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||
appropriateness of using or redistributing the Work and assume any |
||||
risks associated with Your exercise of permissions under this License. |
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, |
||||
whether in tort (including negligence), contract, or otherwise, |
||||
unless required by applicable law (such as deliberate and grossly |
||||
negligent acts) or agreed to in writing, shall any Contributor be |
||||
liable to You for damages, including any direct, indirect, special, |
||||
incidental, or consequential damages of any character arising as a |
||||
result of this License or out of the use or inability to use the |
||||
Work (including but not limited to damages for loss of goodwill, |
||||
work stoppage, computer failure or malfunction, or any and all |
||||
other commercial damages or losses), even if such Contributor |
||||
has been advised of the possibility of such damages. |
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing |
||||
the Work or Derivative Works thereof, You may choose to offer, |
||||
and charge a fee for, acceptance of support, warranty, indemnity, |
||||
or other liability obligations and/or rights consistent with this |
||||
License. However, in accepting such obligations, You may act only |
||||
on Your own behalf and on Your sole responsibility, not on behalf |
||||
of any other Contributor, and only if You agree to indemnify, |
||||
defend, and hold each Contributor harmless for any liability |
||||
incurred by, or claims asserted against, such Contributor by reason |
||||
of your accepting any such warranty or additional liability. |
||||
|
||||
END OF TERMS AND CONDITIONS |
||||
|
||||
APPENDIX: How to apply the Apache License to your work. |
||||
|
||||
To apply the Apache License to your work, attach the following |
||||
boilerplate notice, with the fields enclosed by brackets "[]" |
||||
replaced with your own identifying information. (Don't include |
||||
the brackets!) The text should be enclosed in the appropriate |
||||
comment syntax for the file format. We also recommend that a |
||||
file or class name and description of purpose be included on the |
||||
same "printed page" as the copyright notice for easier |
||||
identification within third-party archives. |
||||
|
||||
Copyright [yyyy] [name of copyright owner] |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
@ -0,0 +1 @@ |
||||
Origin: https://github.com/google/flatbuffers/tree/v23.1.21 |
@ -0,0 +1,68 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_ALLOCATOR_H_ |
||||
#define FLATBUFFERS_ALLOCATOR_H_ |
||||
|
||||
#include "flatbuffers/base.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
// Allocator interface. This is flatbuffers-specific and meant only for
|
||||
// `vector_downward` usage.
|
||||
class Allocator { |
||||
public: |
||||
virtual ~Allocator() {} |
||||
|
||||
// Allocate `size` bytes of memory.
|
||||
virtual uint8_t *allocate(size_t size) = 0; |
||||
|
||||
// Deallocate `size` bytes of memory at `p` allocated by this allocator.
|
||||
virtual void deallocate(uint8_t *p, size_t size) = 0; |
||||
|
||||
// Reallocate `new_size` bytes of memory, replacing the old region of size
|
||||
// `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
|
||||
// and is intended specifcally for `vector_downward` use.
|
||||
// `in_use_back` and `in_use_front` indicate how much of `old_size` is
|
||||
// actually in use at each end, and needs to be copied.
|
||||
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size, |
||||
size_t new_size, size_t in_use_back, |
||||
size_t in_use_front) { |
||||
FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows
|
||||
uint8_t *new_p = allocate(new_size); |
||||
memcpy_downward(old_p, old_size, new_p, new_size, in_use_back, |
||||
in_use_front); |
||||
deallocate(old_p, old_size); |
||||
return new_p; |
||||
} |
||||
|
||||
protected: |
||||
// Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
|
||||
// to `new_p` of `new_size`. Only memory of size `in_use_front` and
|
||||
// `in_use_back` will be copied from the front and back of the old memory
|
||||
// allocation.
|
||||
void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p, |
||||
size_t new_size, size_t in_use_back, |
||||
size_t in_use_front) { |
||||
memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back, |
||||
in_use_back); |
||||
memcpy(new_p, old_p, in_use_front); |
||||
} |
||||
}; |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_ALLOCATOR_H_
|
@ -0,0 +1,253 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_ARRAY_H_ |
||||
#define FLATBUFFERS_ARRAY_H_ |
||||
|
||||
#include <memory> |
||||
|
||||
#include "flatbuffers/base.h" |
||||
#include "flatbuffers/stl_emulation.h" |
||||
#include "flatbuffers/vector.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
// This is used as a helper type for accessing arrays.
|
||||
template<typename T, uint16_t length> class Array { |
||||
// 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; |
||||
|
||||
public: |
||||
typedef uint16_t size_type; |
||||
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type; |
||||
typedef VectorConstIterator<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 { |
||||
FLATBUFFERS_ASSERT(i < size()); |
||||
return IndirectHelper<IndirectHelperType>::Read(Data(), i); |
||||
} |
||||
|
||||
return_type operator[](uoffset_t i) const { return Get(i); } |
||||
|
||||
// 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 E.
|
||||
template<typename E> E GetEnum(uoffset_t i) const { |
||||
return static_cast<E>(Get(i)); |
||||
} |
||||
|
||||
const_iterator begin() const { return const_iterator(Data(), 0); } |
||||
const_iterator end() const { return const_iterator(Data(), size()); } |
||||
|
||||
const_reverse_iterator rbegin() const { |
||||
return const_reverse_iterator(end()); |
||||
} |
||||
const_reverse_iterator rend() const { |
||||
return const_reverse_iterator(begin()); |
||||
} |
||||
|
||||
const_iterator cbegin() const { return begin(); } |
||||
const_iterator cend() const { return end(); } |
||||
|
||||
const_reverse_iterator crbegin() const { return rbegin(); } |
||||
const_reverse_iterator crend() const { return rend(); } |
||||
|
||||
// Get a mutable pointer to elements inside this array.
|
||||
// This method used to mutate arrays of structs followed by a @p Mutate
|
||||
// operation. For primitive types use @p Mutate directly.
|
||||
// @warning Assignments and reads to/from the dereferenced pointer are not
|
||||
// automatically converted to the correct endianness.
|
||||
typename flatbuffers::conditional<scalar_tag::value, void, T *>::type |
||||
GetMutablePointer(uoffset_t i) const { |
||||
FLATBUFFERS_ASSERT(i < size()); |
||||
return const_cast<T *>(&data()[i]); |
||||
} |
||||
|
||||
// Change elements if you have a non-const pointer to this object.
|
||||
void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); } |
||||
|
||||
// The raw data in little endian format. Use with care.
|
||||
const uint8_t *Data() const { return data_; } |
||||
|
||||
uint8_t *Data() { return data_; } |
||||
|
||||
// Similarly, but typed, much like std::vector::data
|
||||
const T *data() const { return reinterpret_cast<const T *>(Data()); } |
||||
T *data() { return reinterpret_cast<T *>(Data()); } |
||||
|
||||
// Copy data from a span with endian conversion.
|
||||
// If this Array and the span overlap, the behavior is undefined.
|
||||
void CopyFromSpan(flatbuffers::span<const T, length> src) { |
||||
const auto p1 = reinterpret_cast<const uint8_t *>(src.data()); |
||||
const auto p2 = Data(); |
||||
FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) && |
||||
!(p2 >= p1 && p2 < (p1 + length))); |
||||
(void)p1; |
||||
(void)p2; |
||||
CopyFromSpanImpl(flatbuffers::bool_constant<is_span_observable>(), src); |
||||
} |
||||
|
||||
protected: |
||||
void MutateImpl(flatbuffers::true_type, uoffset_t i, const T &val) { |
||||
FLATBUFFERS_ASSERT(i < size()); |
||||
WriteScalar(data() + i, val); |
||||
} |
||||
|
||||
void MutateImpl(flatbuffers::false_type, uoffset_t i, const T &val) { |
||||
*(GetMutablePointer(i)) = val; |
||||
} |
||||
|
||||
void CopyFromSpanImpl(flatbuffers::true_type, |
||||
flatbuffers::span<const T, length> src) { |
||||
// Use std::memcpy() instead of std::copy() to avoid performance degradation
|
||||
// due to aliasing if T is char or unsigned char.
|
||||
// The size is known at compile time, so memcpy would be inlined.
|
||||
std::memcpy(data(), src.data(), length * sizeof(T)); |
||||
} |
||||
|
||||
// Copy data from flatbuffers::span with endian conversion.
|
||||
void CopyFromSpanImpl(flatbuffers::false_type, |
||||
flatbuffers::span<const T, length> src) { |
||||
for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); } |
||||
} |
||||
|
||||
// This class is only used to access pre-existing data. Don't ever
|
||||
// try to construct these manually.
|
||||
// 'constexpr' allows us to use 'size()' at compile time.
|
||||
// @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
|
||||
// a constructor.
|
||||
#if defined(__cpp_constexpr) |
||||
constexpr Array(); |
||||
#else |
||||
Array(); |
||||
#endif |
||||
|
||||
uint8_t data_[length * sizeof(T)]; |
||||
|
||||
private: |
||||
// This class is a pointer. Copying will therefore create an invalid object.
|
||||
// Private and unimplemented copy constructor.
|
||||
Array(const Array &); |
||||
Array &operator=(const 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> { |
||||
static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T"); |
||||
|
||||
public: |
||||
typedef const void *return_type; |
||||
|
||||
const uint8_t *Data() const { return data_; } |
||||
|
||||
// Make idl_gen_text.cpp::PrintContainer happy.
|
||||
return_type operator[](uoffset_t) const { |
||||
FLATBUFFERS_ASSERT(false); |
||||
return nullptr; |
||||
} |
||||
|
||||
private: |
||||
// This class is only used to access pre-existing data.
|
||||
Array(); |
||||
Array(const Array &); |
||||
Array &operator=(const Array &); |
||||
|
||||
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); |
||||
} |
||||
|
||||
template<typename T, uint16_t length> |
||||
const Array<T, length> &CastToArray(const T (&arr)[length]) { |
||||
return *reinterpret_cast<const Array<T, length> *>(arr); |
||||
} |
||||
|
||||
template<typename E, typename T, uint16_t length> |
||||
Array<E, length> &CastToArrayOfEnum(T (&arr)[length]) { |
||||
static_assert(sizeof(E) == sizeof(T), "invalid enum type E"); |
||||
return *reinterpret_cast<Array<E, length> *>(arr); |
||||
} |
||||
|
||||
template<typename E, typename T, uint16_t length> |
||||
const Array<E, length> &CastToArrayOfEnum(const T (&arr)[length]) { |
||||
static_assert(sizeof(E) == sizeof(T), "invalid enum type E"); |
||||
return *reinterpret_cast<const Array<E, length> *>(arr); |
||||
} |
||||
|
||||
template<typename T, uint16_t length> |
||||
bool operator==(const Array<T, length> &lhs, |
||||
const Array<T, length> &rhs) noexcept { |
||||
return std::addressof(lhs) == std::addressof(rhs) || |
||||
(lhs.size() == rhs.size() && |
||||
std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0); |
||||
} |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_ARRAY_H_
|
@ -0,0 +1,486 @@ |
||||
#ifndef FLATBUFFERS_BASE_H_ |
||||
#define FLATBUFFERS_BASE_H_ |
||||
|
||||
// clang-format off
|
||||
|
||||
// If activate should be declared and included first.
|
||||
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \ |
||||
defined(_MSC_VER) && defined(_DEBUG) |
||||
// The _CRTDBG_MAP_ALLOC inside <crtdbg.h> will replace
|
||||
// calloc/free (etc) to its debug version using #define directives.
|
||||
#define _CRTDBG_MAP_ALLOC |
||||
#include <stdlib.h> |
||||
#include <crtdbg.h> |
||||
// Replace operator new by trace-enabled version.
|
||||
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) |
||||
#define new DEBUG_NEW |
||||
#endif |
||||
|
||||
#if !defined(FLATBUFFERS_ASSERT) |
||||
#include <assert.h> |
||||
#define FLATBUFFERS_ASSERT assert |
||||
#elif defined(FLATBUFFERS_ASSERT_INCLUDE) |
||||
// Include file with forward declaration
|
||||
#include FLATBUFFERS_ASSERT_INCLUDE |
||||
#endif |
||||
|
||||
#ifndef ARDUINO |
||||
#include <cstdint> |
||||
#endif |
||||
|
||||
#include <cstddef> |
||||
#include <cstdlib> |
||||
#include <cstring> |
||||
|
||||
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) && defined(__AVR__) |
||||
#include <utility.h> |
||||
#else |
||||
#include <utility> |
||||
#endif |
||||
|
||||
#include <string> |
||||
#include <type_traits> |
||||
#include <vector> |
||||
#include <set> |
||||
#include <algorithm> |
||||
#include <iterator> |
||||
#include <memory> |
||||
|
||||
#if defined(__unix__) && !defined(FLATBUFFERS_LOCALE_INDEPENDENT) |
||||
#include <unistd.h> |
||||
#endif |
||||
|
||||
#ifdef __ANDROID__ |
||||
#include <android/api-level.h> |
||||
#endif |
||||
|
||||
#if defined(__ICCARM__) |
||||
#include <intrinsics.h> |
||||
#endif |
||||
|
||||
// Note the __clang__ check is needed, because clang presents itself
|
||||
// as an older GNUC compiler (4.2).
|
||||
// Clang 3.3 and later implement all of the ISO C++ 2011 standard.
|
||||
// Clang 3.4 and later implement all of the ISO C++ 2014 standard.
|
||||
// http://clang.llvm.org/cxx_status.html
|
||||
|
||||
// Note the MSVC value '__cplusplus' may be incorrect:
|
||||
// The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L,
|
||||
// indicating (erroneously!) that the compiler conformed to the C++98 Standard.
|
||||
// This value should be correct starting from MSVC2017-15.7-Preview-3.
|
||||
// The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set.
|
||||
// Workaround (for details see MSDN):
|
||||
// Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility.
|
||||
// The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch.
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__) |
||||
#define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) |
||||
#else |
||||
#define FLATBUFFERS_GCC 0 |
||||
#endif |
||||
|
||||
#if defined(__clang__) |
||||
#define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) |
||||
#else |
||||
#define FLATBUFFERS_CLANG 0 |
||||
#endif |
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
#if __cplusplus <= 199711L && \ |
||||
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
||||
(!defined(__GNUC__) || \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400)) |
||||
#error A C++11 compatible compiler with support for the auto typing is \ |
||||
required for FlatBuffers. |
||||
#error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ |
||||
#endif |
||||
|
||||
#if !defined(__clang__) && \ |
||||
defined(__GNUC__) && \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600) |
||||
// Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr
|
||||
// and constexpr keywords. Note the __clang__ check is needed, because clang
|
||||
// presents itself as an older GNUC compiler.
|
||||
#ifndef nullptr_t |
||||
const class nullptr_t { |
||||
public: |
||||
template<class T> inline operator T*() const { return 0; } |
||||
private: |
||||
void operator&() const; |
||||
} nullptr = {}; |
||||
#endif |
||||
#ifndef constexpr |
||||
#define constexpr const |
||||
#endif |
||||
#endif |
||||
|
||||
// The wire format uses a little endian encoding (since that's efficient for
|
||||
// the common platforms).
|
||||
#if defined(__s390x__) |
||||
#define FLATBUFFERS_LITTLEENDIAN 0 |
||||
#endif // __s390x__
|
||||
#if !defined(FLATBUFFERS_LITTLEENDIAN) |
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__) |
||||
#if (defined(__BIG_ENDIAN__) || \ |
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) |
||||
#define FLATBUFFERS_LITTLEENDIAN 0 |
||||
#else |
||||
#define FLATBUFFERS_LITTLEENDIAN 1 |
||||
#endif // __BIG_ENDIAN__
|
||||
#elif defined(_MSC_VER) |
||||
#if defined(_M_PPC) |
||||
#define FLATBUFFERS_LITTLEENDIAN 0 |
||||
#else |
||||
#define FLATBUFFERS_LITTLEENDIAN 1 |
||||
#endif |
||||
#else |
||||
#error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN. |
||||
#endif |
||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
|
||||
#define FLATBUFFERS_VERSION_MAJOR 23 |
||||
#define FLATBUFFERS_VERSION_MINOR 1 |
||||
#define FLATBUFFERS_VERSION_REVISION 21 |
||||
#define FLATBUFFERS_STRING_EXPAND(X) #X |
||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) |
||||
namespace flatbuffers { |
||||
// Returns version as string "MAJOR.MINOR.REVISION".
|
||||
const char* FLATBUFFERS_VERSION(); |
||||
} |
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \ |
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \
|
||||
defined(__clang__) |
||||
#define FLATBUFFERS_FINAL_CLASS final |
||||
#define FLATBUFFERS_OVERRIDE override |
||||
#define FLATBUFFERS_EXPLICIT_CPP11 explicit |
||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t |
||||
#else |
||||
#define FLATBUFFERS_FINAL_CLASS |
||||
#define FLATBUFFERS_OVERRIDE |
||||
#define FLATBUFFERS_EXPLICIT_CPP11 |
||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE |
||||
#endif |
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ |
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
|
||||
(defined(__cpp_constexpr) && __cpp_constexpr >= 200704) |
||||
#define FLATBUFFERS_CONSTEXPR constexpr |
||||
#define FLATBUFFERS_CONSTEXPR_CPP11 constexpr |
||||
#define FLATBUFFERS_CONSTEXPR_DEFINED |
||||
#else |
||||
#define FLATBUFFERS_CONSTEXPR const |
||||
#define FLATBUFFERS_CONSTEXPR_CPP11 |
||||
#endif |
||||
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201402L) || \ |
||||
(defined(__cpp_constexpr) && __cpp_constexpr >= 201304) |
||||
#define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR_CPP11 |
||||
#else |
||||
#define FLATBUFFERS_CONSTEXPR_CPP14 |
||||
#endif |
||||
|
||||
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ |
||||
(defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \
|
||||
defined(__clang__) |
||||
#define FLATBUFFERS_NOEXCEPT noexcept |
||||
#else |
||||
#define FLATBUFFERS_NOEXCEPT |
||||
#endif |
||||
|
||||
// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
|
||||
// private, so be sure to put it at the end or reset access mode explicitly.
|
||||
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \ |
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
|
||||
defined(__clang__) |
||||
#define FLATBUFFERS_DELETE_FUNC(func) func = delete |
||||
#else |
||||
#define FLATBUFFERS_DELETE_FUNC(func) private: func |
||||
#endif |
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ |
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
|
||||
defined(__clang__) |
||||
#define FLATBUFFERS_DEFAULT_DECLARATION |
||||
#endif |
||||
|
||||
// Check if we can use template aliases
|
||||
// Not possible if Microsoft Compiler before 2012
|
||||
// Possible is the language feature __cpp_alias_templates is defined well
|
||||
// Or possible if the C++ std is C+11 or newer
|
||||
#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \ |
||||
|| (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \
|
||||
|| (defined(__cplusplus) && __cplusplus >= 201103L) |
||||
#define FLATBUFFERS_TEMPLATES_ALIASES |
||||
#endif |
||||
|
||||
#ifndef FLATBUFFERS_HAS_STRING_VIEW |
||||
// Only provide flatbuffers::string_view if __has_include can be used
|
||||
// to detect a header that provides an implementation
|
||||
#if defined(__has_include) |
||||
// Check for std::string_view (in c++17)
|
||||
#if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17)) |
||||
#include <string_view> |
||||
namespace flatbuffers { |
||||
typedef std::string_view string_view; |
||||
} |
||||
#define FLATBUFFERS_HAS_STRING_VIEW 1 |
||||
// Check for std::experimental::string_view (in c++14, compiler-dependent)
|
||||
#elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411) |
||||
#include <experimental/string_view> |
||||
namespace flatbuffers { |
||||
typedef std::experimental::string_view string_view; |
||||
} |
||||
#define FLATBUFFERS_HAS_STRING_VIEW 1 |
||||
// Check for absl::string_view
|
||||
#elif __has_include("absl/strings/string_view.h") |
||||
#include "absl/strings/string_view.h" |
||||
namespace flatbuffers { |
||||
typedef absl::string_view string_view; |
||||
} |
||||
#define FLATBUFFERS_HAS_STRING_VIEW 1 |
||||
#endif |
||||
#endif // __has_include
|
||||
#endif // !FLATBUFFERS_HAS_STRING_VIEW
|
||||
|
||||
#ifndef FLATBUFFERS_GENERAL_HEAP_ALLOC_OK |
||||
// Allow heap allocations to be used
|
||||
#define FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 1 |
||||
#endif // !FLATBUFFERS_GENERAL_HEAP_ALLOC_OK
|
||||
|
||||
#ifndef FLATBUFFERS_HAS_NEW_STRTOD |
||||
// Modern (C++11) strtod and strtof functions are available for use.
|
||||
// 1) nan/inf strings as argument of strtod;
|
||||
// 2) hex-float as argument of strtod/strtof.
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \ |
||||
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
|
||||
(defined(__clang__)) |
||||
#define FLATBUFFERS_HAS_NEW_STRTOD 1 |
||||
#endif |
||||
#endif // !FLATBUFFERS_HAS_NEW_STRTOD
|
||||
|
||||
#ifndef FLATBUFFERS_LOCALE_INDEPENDENT |
||||
// Enable locale independent functions {strtof_l, strtod_l,strtoll_l,
|
||||
// strtoull_l}.
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1800) || \ |
||||
(defined(__ANDROID_API__) && __ANDROID_API__>= 21) || \
|
||||
(defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)) && \
|
||||
(!defined(__Fuchsia__) && !defined(__ANDROID_API__)) |
||||
#define FLATBUFFERS_LOCALE_INDEPENDENT 1 |
||||
#else |
||||
#define FLATBUFFERS_LOCALE_INDEPENDENT 0 |
||||
#endif |
||||
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
|
||||
|
||||
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
|
||||
// - __suppress_ubsan__("undefined")
|
||||
// - __suppress_ubsan__("signed-integer-overflow")
|
||||
#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7)) |
||||
#define __suppress_ubsan__(type) __attribute__((no_sanitize(type))) |
||||
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409) |
||||
#define __suppress_ubsan__(type) __attribute__((no_sanitize_undefined)) |
||||
#else |
||||
#define __suppress_ubsan__(type) |
||||
#endif |
||||
|
||||
// This is constexpr function used for checking compile-time constants.
|
||||
// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
|
||||
template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) { |
||||
return !!t; |
||||
} |
||||
|
||||
// Enable C++ attribute [[]] if std:c++17 or higher.
|
||||
#if ((__cplusplus >= 201703L) \ |
||||
|| (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))) |
||||
// All attributes unknown to an implementation are ignored without causing an error.
|
||||
#define FLATBUFFERS_ATTRIBUTE(attr) attr |
||||
|
||||
#define FLATBUFFERS_FALLTHROUGH() [[fallthrough]] |
||||
#else |
||||
#define FLATBUFFERS_ATTRIBUTE(attr) |
||||
|
||||
#if FLATBUFFERS_CLANG >= 30800 |
||||
#define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]] |
||||
#elif FLATBUFFERS_GCC >= 70300 |
||||
#define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]] |
||||
#else |
||||
#define FLATBUFFERS_FALLTHROUGH() |
||||
#endif |
||||
#endif |
||||
|
||||
/// @endcond
|
||||
|
||||
/// @file
|
||||
namespace flatbuffers { |
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
// Our default offset / size type, 32bit on purpose on 64bit systems.
|
||||
// Also, using a consistent offset type maintains compatibility of serialized
|
||||
// offset values between 32bit and 64bit systems.
|
||||
typedef uint32_t uoffset_t; |
||||
|
||||
// Signed offsets for references that can go in both directions.
|
||||
typedef int32_t soffset_t; |
||||
|
||||
// Offset/index used in v-tables, can be changed to uint8_t in
|
||||
// format forks to save a bit of space if desired.
|
||||
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) |
||||
|
||||
// The minimum size buffer that can be a valid flatbuffer.
|
||||
// Includes the offset to the root table (uoffset_t), the offset to the vtable
|
||||
// of the root table (soffset_t), the size of the vtable (uint16_t), and the
|
||||
// size of the referring table (uint16_t).
|
||||
#define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(uoffset_t) + sizeof(soffset_t) + \ |
||||
sizeof(uint16_t) + sizeof(uint16_t) |
||||
|
||||
// We support aligning the contents of buffers up to this size.
|
||||
#ifndef FLATBUFFERS_MAX_ALIGNMENT |
||||
#define FLATBUFFERS_MAX_ALIGNMENT 32 |
||||
#endif |
||||
|
||||
/// @brief The length of a FlatBuffer file header.
|
||||
static const size_t kFileIdentifierLength = 4; |
||||
|
||||
inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) { |
||||
return (min_align <= align) && (align <= (FLATBUFFERS_MAX_ALIGNMENT)) && |
||||
(align & (align - 1)) == 0; // must be power of 2
|
||||
} |
||||
|
||||
#if defined(_MSC_VER) |
||||
#pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized
|
||||
#pragma warning(push) |
||||
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||
#endif |
||||
|
||||
template<typename T> T EndianSwap(T t) { |
||||
#if defined(_MSC_VER) |
||||
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort |
||||
#define FLATBUFFERS_BYTESWAP32 _byteswap_ulong |
||||
#define FLATBUFFERS_BYTESWAP64 _byteswap_uint64 |
||||
#elif defined(__ICCARM__) |
||||
#define FLATBUFFERS_BYTESWAP16 __REV16 |
||||
#define FLATBUFFERS_BYTESWAP32 __REV |
||||
#define FLATBUFFERS_BYTESWAP64(x) \ |
||||
((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U) |
||||
#else |
||||
#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__) |
||||
// __builtin_bswap16 was missing prior to GCC 4.8.
|
||||
#define FLATBUFFERS_BYTESWAP16(x) \ |
||||
static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16)) |
||||
#else |
||||
#define FLATBUFFERS_BYTESWAP16 __builtin_bswap16 |
||||
#endif |
||||
#define FLATBUFFERS_BYTESWAP32 __builtin_bswap32 |
||||
#define FLATBUFFERS_BYTESWAP64 __builtin_bswap64 |
||||
#endif |
||||
if (sizeof(T) == 1) { // Compile-time if-then's.
|
||||
return t; |
||||
} else if (sizeof(T) == 2) { |
||||
union { T t; uint16_t i; } u = { t }; |
||||
u.i = FLATBUFFERS_BYTESWAP16(u.i); |
||||
return u.t; |
||||
} else if (sizeof(T) == 4) { |
||||
union { T t; uint32_t i; } u = { t }; |
||||
u.i = FLATBUFFERS_BYTESWAP32(u.i); |
||||
return u.t; |
||||
} else if (sizeof(T) == 8) { |
||||
union { T t; uint64_t i; } u = { t }; |
||||
u.i = FLATBUFFERS_BYTESWAP64(u.i); |
||||
return u.t; |
||||
} else { |
||||
FLATBUFFERS_ASSERT(0); |
||||
return t; |
||||
} |
||||
} |
||||
|
||||
#if defined(_MSC_VER) |
||||
#pragma warning(pop) |
||||
#endif |
||||
|
||||
|
||||
template<typename T> T EndianScalar(T t) { |
||||
#if FLATBUFFERS_LITTLEENDIAN |
||||
return t; |
||||
#else |
||||
return EndianSwap(t); |
||||
#endif |
||||
} |
||||
|
||||
template<typename T> |
||||
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
||||
__suppress_ubsan__("alignment") |
||||
T ReadScalar(const void *p) { |
||||
return EndianScalar(*reinterpret_cast<const T *>(p)); |
||||
} |
||||
|
||||
// See https://github.com/google/flatbuffers/issues/5950
|
||||
|
||||
#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) |
||||
#pragma GCC diagnostic push |
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow" |
||||
#endif |
||||
|
||||
template<typename T> |
||||
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
||||
__suppress_ubsan__("alignment") |
||||
void WriteScalar(void *p, T t) { |
||||
*reinterpret_cast<T *>(p) = EndianScalar(t); |
||||
} |
||||
|
||||
template<typename T> struct Offset; |
||||
template<typename T> __suppress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) { |
||||
*reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o); |
||||
} |
||||
|
||||
#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) |
||||
#pragma GCC diagnostic pop |
||||
#endif |
||||
|
||||
// Computes how many bytes you'd have to pad to be able to write an
|
||||
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
|
||||
// memory).
|
||||
__suppress_ubsan__("unsigned-integer-overflow") |
||||
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) { |
||||
return ((~buf_size) + 1) & (scalar_size - 1); |
||||
} |
||||
|
||||
// Generic 'operator==' with conditional specialisations.
|
||||
// T e - new value of a scalar field.
|
||||
// T def - default of scalar (is known at compile-time).
|
||||
template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; } |
||||
|
||||
#if defined(FLATBUFFERS_NAN_DEFAULTS) && \ |
||||
defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) |
||||
// Like `operator==(e, def)` with weak NaN if T=(float|double).
|
||||
template<typename T> inline bool IsFloatTheSameAs(T e, T def) { |
||||
return (e == def) || ((def != def) && (e != e)); |
||||
} |
||||
template<> inline bool IsTheSameAs<float>(float e, float def) { |
||||
return IsFloatTheSameAs(e, def); |
||||
} |
||||
template<> inline bool IsTheSameAs<double>(double e, double def) { |
||||
return IsFloatTheSameAs(e, def); |
||||
} |
||||
#endif |
||||
|
||||
// Check 'v' is out of closed range [low; high].
|
||||
// Workaround for GCC warning [-Werror=type-limits]:
|
||||
// comparison is always true due to limited range of data type.
|
||||
template<typename T> |
||||
inline bool IsOutRange(const T &v, const T &low, const T &high) { |
||||
return (v < low) || (high < v); |
||||
} |
||||
|
||||
// Check 'v' is in closed range [low; high].
|
||||
template<typename T> |
||||
inline bool IsInRange(const T &v, const T &low, const T &high) { |
||||
return !IsOutRange(v, low, high); |
||||
} |
||||
|
||||
} // namespace flatbuffers
|
||||
#endif // FLATBUFFERS_BASE_H_
|
@ -0,0 +1,154 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_BUFFER_H_ |
||||
#define FLATBUFFERS_BUFFER_H_ |
||||
|
||||
#include <algorithm> |
||||
|
||||
#include "flatbuffers/base.h" |
||||
|
||||
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; |
||||
Offset() : o(0) {} |
||||
Offset(uoffset_t _o) : o(_o) {} |
||||
Offset<void> Union() const { return Offset<void>(o); } |
||||
bool IsNull() const { return !o; } |
||||
}; |
||||
|
||||
inline void EndianCheck() { |
||||
int endiantest = 1; |
||||
// If this fails, see FLATBUFFERS_LITTLEENDIAN above.
|
||||
FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) == |
||||
FLATBUFFERS_LITTLEENDIAN); |
||||
(void)endiantest; |
||||
} |
||||
|
||||
template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() { |
||||
// clang-format off
|
||||
#ifdef _MSC_VER |
||||
return __alignof(T); |
||||
#else |
||||
#ifndef alignof |
||||
return __alignof__(T); |
||||
#else |
||||
return alignof(T); |
||||
#endif |
||||
#endif |
||||
// clang-format on
|
||||
} |
||||
|
||||
// Lexicographically compare two strings (possibly containing nulls), and
|
||||
// return true if the first is less than the second.
|
||||
static inline bool StringLessThan(const char *a_data, uoffset_t a_size, |
||||
const char *b_data, uoffset_t b_size) { |
||||
const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size)); |
||||
return cmp == 0 ? a_size < b_size : cmp < 0; |
||||
} |
||||
|
||||
// When we read serialized data from memory, in the case of most scalars,
|
||||
// we want to just read T, but in the case of Offset, we want to actually
|
||||
// perform the indirection and return a pointer.
|
||||
// The template specialization below does just that.
|
||||
// It is wrapped in a struct since function templates can't overload on the
|
||||
// return type like this.
|
||||
// The typedef is for the convenience of callers of this function
|
||||
// (avoiding the need for a trailing return decltype)
|
||||
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) { |
||||
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); |
||||
} |
||||
}; |
||||
template<typename T> struct IndirectHelper<Offset<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)); |
||||
} |
||||
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)); |
||||
} |
||||
}; |
||||
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 mutable_return_type Read(uint8_t *p, uoffset_t i) { |
||||
return reinterpret_cast<mutable_return_type>(p + i * sizeof(T)); |
||||
} |
||||
}; |
||||
|
||||
/// @brief Get a pointer to the file_identifier section of the buffer.
|
||||
/// @return Returns a const char pointer to the start of the file_identifier
|
||||
/// characters in the buffer. The returned char * has length
|
||||
/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.
|
||||
/// This function is UNDEFINED for FlatBuffers whose schema does not include
|
||||
/// a file_identifier (likely points at padding or the start of a the root
|
||||
/// vtable).
|
||||
inline const char *GetBufferIdentifier(const void *buf, |
||||
bool size_prefixed = false) { |
||||
return reinterpret_cast<const char *>(buf) + |
||||
((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t)); |
||||
} |
||||
|
||||
// Helper to see if the identifier in a buffer has the expected value.
|
||||
inline bool BufferHasIdentifier(const void *buf, const char *identifier, |
||||
bool size_prefixed = false) { |
||||
return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier, |
||||
flatbuffers::kFileIdentifierLength) == 0; |
||||
} |
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
// Helpers to get a typed pointer to the root object contained in the buffer.
|
||||
template<typename T> T *GetMutableRoot(void *buf) { |
||||
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> 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)); |
||||
} |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_BUFFER_H_
|
@ -0,0 +1,53 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_BUFFER_REF_H_ |
||||
#define FLATBUFFERS_BUFFER_REF_H_ |
||||
|
||||
#include "flatbuffers/base.h" |
||||
#include "flatbuffers/verifier.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
// Convenient way to bundle a buffer and its length, to pass it around
|
||||
// typed by its root.
|
||||
// A BufferRef does not own its buffer.
|
||||
struct BufferRefBase {}; // for std::is_base_of
|
||||
|
||||
template<typename T> struct BufferRef : BufferRefBase { |
||||
BufferRef() : buf(nullptr), len(0), must_free(false) {} |
||||
BufferRef(uint8_t *_buf, uoffset_t _len) |
||||
: buf(_buf), len(_len), must_free(false) {} |
||||
|
||||
~BufferRef() { |
||||
if (must_free) free(buf); |
||||
} |
||||
|
||||
const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); } |
||||
|
||||
bool Verify() { |
||||
Verifier verifier(buf, len); |
||||
return verifier.VerifyBuffer<T>(nullptr); |
||||
} |
||||
|
||||
uint8_t *buf; |
||||
uoffset_t len; |
||||
bool must_free; |
||||
}; |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_BUFFER_REF_H_
|
@ -0,0 +1,64 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_DEFAULT_ALLOCATOR_H_ |
||||
#define FLATBUFFERS_DEFAULT_ALLOCATOR_H_ |
||||
|
||||
#include "flatbuffers/allocator.h" |
||||
#include "flatbuffers/base.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
// DefaultAllocator uses new/delete to allocate memory regions
|
||||
class DefaultAllocator : public Allocator { |
||||
public: |
||||
uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE { |
||||
return new uint8_t[size]; |
||||
} |
||||
|
||||
void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; } |
||||
|
||||
static void dealloc(void *p, size_t) { delete[] static_cast<uint8_t *>(p); } |
||||
}; |
||||
|
||||
// These functions allow for a null allocator to mean use the default allocator,
|
||||
// as used by DetachedBuffer and vector_downward below.
|
||||
// This is to avoid having a statically or dynamically allocated default
|
||||
// allocator, or having to move it between the classes that may own it.
|
||||
inline uint8_t *Allocate(Allocator *allocator, size_t size) { |
||||
return allocator ? allocator->allocate(size) |
||||
: DefaultAllocator().allocate(size); |
||||
} |
||||
|
||||
inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) { |
||||
if (allocator) |
||||
allocator->deallocate(p, size); |
||||
else |
||||
DefaultAllocator().deallocate(p, size); |
||||
} |
||||
|
||||
inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p, |
||||
size_t old_size, size_t new_size, |
||||
size_t in_use_back, size_t in_use_front) { |
||||
return allocator ? allocator->reallocate_downward(old_p, old_size, new_size, |
||||
in_use_back, in_use_front) |
||||
: DefaultAllocator().reallocate_downward( |
||||
old_p, old_size, new_size, in_use_back, in_use_front); |
||||
} |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_DEFAULT_ALLOCATOR_H_
|
@ -0,0 +1,114 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_DETACHED_BUFFER_H_ |
||||
#define FLATBUFFERS_DETACHED_BUFFER_H_ |
||||
|
||||
#include "flatbuffers/allocator.h" |
||||
#include "flatbuffers/base.h" |
||||
#include "flatbuffers/default_allocator.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
// DetachedBuffer is a finished flatbuffer memory region, detached from its
|
||||
// builder. The original memory region and allocator are also stored so that
|
||||
// the DetachedBuffer can manage the memory lifetime.
|
||||
class DetachedBuffer { |
||||
public: |
||||
DetachedBuffer() |
||||
: allocator_(nullptr), |
||||
own_allocator_(false), |
||||
buf_(nullptr), |
||||
reserved_(0), |
||||
cur_(nullptr), |
||||
size_(0) {} |
||||
|
||||
DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf, |
||||
size_t reserved, uint8_t *cur, size_t sz) |
||||
: allocator_(allocator), |
||||
own_allocator_(own_allocator), |
||||
buf_(buf), |
||||
reserved_(reserved), |
||||
cur_(cur), |
||||
size_(sz) {} |
||||
|
||||
DetachedBuffer(DetachedBuffer &&other) noexcept |
||||
: allocator_(other.allocator_), |
||||
own_allocator_(other.own_allocator_), |
||||
buf_(other.buf_), |
||||
reserved_(other.reserved_), |
||||
cur_(other.cur_), |
||||
size_(other.size_) { |
||||
other.reset(); |
||||
} |
||||
|
||||
DetachedBuffer &operator=(DetachedBuffer &&other) noexcept { |
||||
if (this == &other) return *this; |
||||
|
||||
destroy(); |
||||
|
||||
allocator_ = other.allocator_; |
||||
own_allocator_ = other.own_allocator_; |
||||
buf_ = other.buf_; |
||||
reserved_ = other.reserved_; |
||||
cur_ = other.cur_; |
||||
size_ = other.size_; |
||||
|
||||
other.reset(); |
||||
|
||||
return *this; |
||||
} |
||||
|
||||
~DetachedBuffer() { destroy(); } |
||||
|
||||
const uint8_t *data() const { return cur_; } |
||||
|
||||
uint8_t *data() { return cur_; } |
||||
|
||||
size_t size() const { return size_; } |
||||
|
||||
// These may change access mode, leave these at end of public section
|
||||
FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other)); |
||||
FLATBUFFERS_DELETE_FUNC( |
||||
DetachedBuffer &operator=(const DetachedBuffer &other)); |
||||
|
||||
protected: |
||||
Allocator *allocator_; |
||||
bool own_allocator_; |
||||
uint8_t *buf_; |
||||
size_t reserved_; |
||||
uint8_t *cur_; |
||||
size_t size_; |
||||
|
||||
inline void destroy() { |
||||
if (buf_) Deallocate(allocator_, buf_, reserved_); |
||||
if (own_allocator_ && allocator_) { delete allocator_; } |
||||
reset(); |
||||
} |
||||
|
||||
inline void reset() { |
||||
allocator_ = nullptr; |
||||
own_allocator_ = false; |
||||
buf_ = nullptr; |
||||
reserved_ = 0; |
||||
cur_ = nullptr; |
||||
size_ = 0; |
||||
} |
||||
}; |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_DETACHED_BUFFER_H_
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,272 @@ |
||||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_H_ |
||||
#define FLATBUFFERS_H_ |
||||
|
||||
#include <algorithm> |
||||
|
||||
// TODO: These includes are for mitigating the pains of users editing their
|
||||
// source because they relied on flatbuffers.h to include everything for them.
|
||||
#include "flatbuffers/array.h" |
||||
#include "flatbuffers/base.h" |
||||
#include "flatbuffers/buffer.h" |
||||
#include "flatbuffers/buffer_ref.h" |
||||
#include "flatbuffers/detached_buffer.h" |
||||
#include "flatbuffers/flatbuffer_builder.h" |
||||
#include "flatbuffers/stl_emulation.h" |
||||
#include "flatbuffers/string.h" |
||||
#include "flatbuffers/struct.h" |
||||
#include "flatbuffers/table.h" |
||||
#include "flatbuffers/vector.h" |
||||
#include "flatbuffers/vector_downward.h" |
||||
#include "flatbuffers/verifier.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
/// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
|
||||
/// it is the opposite transformation of GetRoot().
|
||||
/// This may be useful if you want to pass on a root and have the recipient
|
||||
/// delete the buffer afterwards.
|
||||
inline const uint8_t *GetBufferStartFromRootPointer(const void *root) { |
||||
auto table = reinterpret_cast<const Table *>(root); |
||||
auto vtable = table->GetVTable(); |
||||
// Either the vtable is before the root or after the root.
|
||||
auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root)); |
||||
// Align to at least sizeof(uoffset_t).
|
||||
start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) & |
||||
~(sizeof(uoffset_t) - 1)); |
||||
// Additionally, there may be a file_identifier in the buffer, and the root
|
||||
// offset. The buffer may have been aligned to any size between
|
||||
// sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
|
||||
// Sadly, the exact alignment is only known when constructing the buffer,
|
||||
// since it depends on the presence of values with said alignment properties.
|
||||
// So instead, we simply look at the next uoffset_t values (root,
|
||||
// file_identifier, and alignment padding) to see which points to the root.
|
||||
// None of the other values can "impersonate" the root since they will either
|
||||
// be 0 or four ASCII characters.
|
||||
static_assert(flatbuffers::kFileIdentifierLength == sizeof(uoffset_t), |
||||
"file_identifier is assumed to be the same size as uoffset_t"); |
||||
for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1; |
||||
possible_roots; possible_roots--) { |
||||
start -= sizeof(uoffset_t); |
||||
if (ReadScalar<uoffset_t>(start) + start == |
||||
reinterpret_cast<const uint8_t *>(root)) |
||||
return start; |
||||
} |
||||
// We didn't find the root, either the "root" passed isn't really a root,
|
||||
// or the buffer is corrupt.
|
||||
// Assert, because calling this function with bad data may cause reads
|
||||
// outside of buffer boundaries.
|
||||
FLATBUFFERS_ASSERT(false); |
||||
return nullptr; |
||||
} |
||||
|
||||
/// @brief This return the prefixed size of a FlatBuffer.
|
||||
inline uoffset_t GetPrefixedSize(const uint8_t *buf) { |
||||
return ReadScalar<uoffset_t>(buf); |
||||
} |
||||
|
||||
// Base class for native objects (FlatBuffer data de-serialized into native
|
||||
// C++ data structures).
|
||||
// Contains no functionality, purely documentative.
|
||||
struct NativeTable {}; |
||||
|
||||
/// @brief Function types to be used with resolving hashes into objects and
|
||||
/// back again. The resolver gets a pointer to a field inside an object API
|
||||
/// object that is of the type specified in the schema using the attribute
|
||||
/// `cpp_type` (it is thus important whatever you write to this address
|
||||
/// matches that type). The value of this field is initially null, so you
|
||||
/// may choose to implement a delayed binding lookup using this function
|
||||
/// if you wish. The resolver does the opposite lookup, for when the object
|
||||
/// is being serialized again.
|
||||
typedef uint64_t hash_value_t; |
||||
typedef std::function<void(void **pointer_adr, hash_value_t hash)> |
||||
resolver_function_t; |
||||
typedef std::function<hash_value_t(void *pointer)> rehasher_function_t; |
||||
|
||||
// Helper function to test if a field is present, using any of the field
|
||||
// enums in the generated code.
|
||||
// `table` must be a generated table type. Since this is a template parameter,
|
||||
// this is not typechecked to be a subclass of Table, so beware!
|
||||
// Note: this function will return false for fields equal to the default
|
||||
// value, since they're not stored in the buffer (unless force_defaults was
|
||||
// used).
|
||||
template<typename T> |
||||
bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) { |
||||
// Cast, since Table is a private baseclass of any table types.
|
||||
return reinterpret_cast<const Table *>(table)->CheckField( |
||||
static_cast<voffset_t>(field)); |
||||
} |
||||
|
||||
// Utility function for reverse lookups on the EnumNames*() functions
|
||||
// (in the generated C++ code)
|
||||
// names must be NULL terminated.
|
||||
inline int LookupEnum(const char **names, const char *name) { |
||||
for (const char **p = names; *p; p++) |
||||
if (!strcmp(*p, name)) return static_cast<int>(p - names); |
||||
return -1; |
||||
} |
||||
|
||||
// These macros allow us to layout a struct with a guarantee that they'll end
|
||||
// up looking the same on different compilers and platforms.
|
||||
// It does this by disallowing the compiler to do any padding, and then
|
||||
// does padding itself by inserting extra padding fields that make every
|
||||
// element aligned to its own size.
|
||||
// Additionally, it manually sets the alignment of the struct as a whole,
|
||||
// which is typically its largest element, or a custom size set in the schema
|
||||
// by the force_align attribute.
|
||||
// These are used in the generated code only.
|
||||
|
||||
// clang-format off
|
||||
#if defined(_MSC_VER) |
||||
#define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ |
||||
__pragma(pack(1)) \
|
||||
struct __declspec(align(alignment)) |
||||
#define FLATBUFFERS_STRUCT_END(name, size) \ |
||||
__pragma(pack()) \
|
||||
static_assert(sizeof(name) == size, "compiler breaks packing rules") |
||||
#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__) |
||||
#define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ |
||||
_Pragma("pack(1)") \
|
||||
struct __attribute__((aligned(alignment))) |
||||
#define FLATBUFFERS_STRUCT_END(name, size) \ |
||||
_Pragma("pack()") \
|
||||
static_assert(sizeof(name) == size, "compiler breaks packing rules") |
||||
#else |
||||
#error Unknown compiler, please define structure alignment macros |
||||
#endif |
||||
// clang-format on
|
||||
|
||||
// Minimal reflection via code generation.
|
||||
// Besides full-fat reflection (see reflection.h) and parsing/printing by
|
||||
// loading schemas (see idl.h), we can also have code generation for minimal
|
||||
// reflection data which allows pretty-printing and other uses without needing
|
||||
// a schema or a parser.
|
||||
// Generate code with --reflect-types (types only) or --reflect-names (names
|
||||
// also) to enable.
|
||||
// See minireflect.h for utilities using this functionality.
|
||||
|
||||
// These types are organized slightly differently as the ones in idl.h.
|
||||
enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM }; |
||||
|
||||
// Scalars have the same order as in idl.h
|
||||
// clang-format off
|
||||
#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \ |
||||
ET(ET_UTYPE) \
|
||||
ET(ET_BOOL) \
|
||||
ET(ET_CHAR) \
|
||||
ET(ET_UCHAR) \
|
||||
ET(ET_SHORT) \
|
||||
ET(ET_USHORT) \
|
||||
ET(ET_INT) \
|
||||
ET(ET_UINT) \
|
||||
ET(ET_LONG) \
|
||||
ET(ET_ULONG) \
|
||||
ET(ET_FLOAT) \
|
||||
ET(ET_DOUBLE) \
|
||||
ET(ET_STRING) \
|
||||
ET(ET_SEQUENCE) // See SequenceType.
|
||||
|
||||
enum ElementaryType { |
||||
#define FLATBUFFERS_ET(E) E, |
||||
FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) |
||||
#undef FLATBUFFERS_ET |
||||
}; |
||||
|
||||
inline const char * const *ElementaryTypeNames() { |
||||
static const char * const names[] = { |
||||
#define FLATBUFFERS_ET(E) #E, |
||||
FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) |
||||
#undef FLATBUFFERS_ET |
||||
}; |
||||
return names; |
||||
} |
||||
// clang-format on
|
||||
|
||||
// Basic type info cost just 16bits per field!
|
||||
// We're explicitly defining the signedness since the signedness of integer
|
||||
// bitfields is otherwise implementation-defined and causes warnings on older
|
||||
// GCC compilers.
|
||||
struct TypeCode { |
||||
// ElementaryType
|
||||
unsigned short base_type : 4; |
||||
// Either vector (in table) or array (in struct)
|
||||
unsigned short is_repeating : 1; |
||||
// Index into type_refs below, or -1 for none.
|
||||
signed short sequence_ref : 11; |
||||
}; |
||||
|
||||
static_assert(sizeof(TypeCode) == 2, "TypeCode"); |
||||
|
||||
struct TypeTable; |
||||
|
||||
// Signature of the static method present in each type.
|
||||
typedef const TypeTable *(*TypeFunction)(); |
||||
|
||||
struct TypeTable { |
||||
SequenceType st; |
||||
size_t num_elems; // of type_codes, values, names (but not type_refs).
|
||||
const TypeCode *type_codes; // num_elems count
|
||||
const TypeFunction *type_refs; // less than num_elems entries (see TypeCode).
|
||||
const int16_t *array_sizes; // less than num_elems entries (see TypeCode).
|
||||
const int64_t *values; // Only set for non-consecutive enum/union or structs.
|
||||
const char *const *names; // Only set if compiled with --reflect-names.
|
||||
}; |
||||
|
||||
// String which identifies the current version of FlatBuffers.
|
||||
inline const char *flatbuffers_version_string() { |
||||
return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "." |
||||
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "." |
||||
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION); |
||||
} |
||||
|
||||
// clang-format off
|
||||
#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\ |
||||
inline E operator | (E lhs, E rhs){\
|
||||
return E(T(lhs) | T(rhs));\
|
||||
}\
|
||||
inline E operator & (E lhs, E rhs){\
|
||||
return E(T(lhs) & T(rhs));\
|
||||
}\
|
||||
inline E operator ^ (E lhs, E rhs){\
|
||||
return E(T(lhs) ^ T(rhs));\
|
||||
}\
|
||||
inline E operator ~ (E lhs){\
|
||||
return E(~T(lhs));\
|
||||
}\
|
||||
inline E operator |= (E &lhs, E rhs){\
|
||||
lhs = lhs | rhs;\
|
||||
return lhs;\
|
||||
}\
|
||||
inline E operator &= (E &lhs, E rhs){\
|
||||
lhs = lhs & rhs;\
|
||||
return lhs;\
|
||||
}\
|
||||
inline E operator ^= (E &lhs, E rhs){\
|
||||
lhs = lhs ^ rhs;\
|
||||
return lhs;\
|
||||
}\
|
||||
inline bool operator !(E rhs) \
|
||||
{\
|
||||
return !bool(T(rhs)); \
|
||||
} |
||||
/// @endcond
|
||||
} // namespace flatbuffers
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // FLATBUFFERS_H_
|
@ -0,0 +1,510 @@ |
||||
/*
|
||||
* Copyright 2017 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_STL_EMULATION_H_ |
||||
#define FLATBUFFERS_STL_EMULATION_H_ |
||||
|
||||
// clang-format off
|
||||
#include "flatbuffers/base.h" |
||||
|
||||
#include <string> |
||||
#include <type_traits> |
||||
#include <vector> |
||||
#include <memory> |
||||
#include <limits> |
||||
|
||||
#ifndef FLATBUFFERS_USE_STD_OPTIONAL |
||||
// Detect C++17 compatible compiler.
|
||||
// __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201703L) \ |
||||
|| (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) |
||||
#define FLATBUFFERS_USE_STD_OPTIONAL 1 |
||||
#else |
||||
#define FLATBUFFERS_USE_STD_OPTIONAL 0 |
||||
#endif // (defined(__cplusplus) && __cplusplus >= 201703L) ...
|
||||
#endif // FLATBUFFERS_USE_STD_OPTIONAL
|
||||
|
||||
#if FLATBUFFERS_USE_STD_OPTIONAL |
||||
#include <optional> |
||||
#endif |
||||
|
||||
// The __cpp_lib_span is the predefined feature macro.
|
||||
#if defined(FLATBUFFERS_USE_STD_SPAN) |
||||
#include <span> |
||||
#elif defined(__cpp_lib_span) && defined(__has_include) |
||||
#if __has_include(<span>) |
||||
#include <array> |
||||
#include <span> |
||||
#define FLATBUFFERS_USE_STD_SPAN |
||||
#endif |
||||
#else |
||||
// Disable non-trivial ctors if FLATBUFFERS_SPAN_MINIMAL defined.
|
||||
#if !defined(FLATBUFFERS_TEMPLATES_ALIASES) |
||||
#define FLATBUFFERS_SPAN_MINIMAL |
||||
#else |
||||
// Enable implicit construction of a span<T,N> from a std::array<T,N>.
|
||||
#include <array> |
||||
#endif |
||||
#endif // defined(FLATBUFFERS_USE_STD_SPAN)
|
||||
|
||||
// This header provides backwards compatibility for older versions of the STL.
|
||||
namespace flatbuffers { |
||||
|
||||
#if defined(FLATBUFFERS_TEMPLATES_ALIASES) |
||||
template <typename T> |
||||
using numeric_limits = std::numeric_limits<T>; |
||||
#else |
||||
template <typename T> class numeric_limits : |
||||
public std::numeric_limits<T> {}; |
||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
|
||||
#if defined(FLATBUFFERS_TEMPLATES_ALIASES) |
||||
template <typename T> using is_scalar = std::is_scalar<T>; |
||||
template <typename T, typename U> using is_same = std::is_same<T,U>; |
||||
template <typename T> using is_floating_point = std::is_floating_point<T>; |
||||
template <typename T> using is_unsigned = std::is_unsigned<T>; |
||||
template <typename T> using is_enum = std::is_enum<T>; |
||||
template <typename T> using make_unsigned = std::make_unsigned<T>; |
||||
template<bool B, class T, class F> |
||||
using conditional = std::conditional<B, T, F>; |
||||
template<class T, T v> |
||||
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 |
||||
// MSVC 2010 doesn't support C++11 aliases.
|
||||
template <typename T> struct is_scalar : public std::is_scalar<T> {}; |
||||
template <typename T, typename U> struct is_same : public std::is_same<T,U> {}; |
||||
template <typename T> struct is_floating_point : |
||||
public std::is_floating_point<T> {}; |
||||
template <typename T> struct is_unsigned : public std::is_unsigned<T> {}; |
||||
template <typename T> struct is_enum : public std::is_enum<T> {}; |
||||
template <typename T> struct make_unsigned : public std::make_unsigned<T> {}; |
||||
template<bool B, class T, class F> |
||||
struct conditional : public std::conditional<B, T, F> {}; |
||||
template<class T, T v> |
||||
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)
|
||||
|
||||
#if defined(FLATBUFFERS_TEMPLATES_ALIASES) |
||||
template <class T> using unique_ptr = std::unique_ptr<T>; |
||||
#else |
||||
// MSVC 2010 doesn't support C++11 aliases.
|
||||
// We're manually "aliasing" the class here as we want to bring unique_ptr
|
||||
// into the flatbuffers namespace. We have unique_ptr in the flatbuffers
|
||||
// namespace we have a completely independent implementation (see below)
|
||||
// for C++98 STL implementations.
|
||||
template <class T> class unique_ptr : public std::unique_ptr<T> { |
||||
public: |
||||
unique_ptr() {} |
||||
explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {} |
||||
unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); } |
||||
unique_ptr(unique_ptr&& u) { *this = std::move(u); } |
||||
unique_ptr& operator=(std::unique_ptr<T>&& u) { |
||||
std::unique_ptr<T>::reset(u.release()); |
||||
return *this; |
||||
} |
||||
unique_ptr& operator=(unique_ptr&& u) { |
||||
std::unique_ptr<T>::reset(u.release()); |
||||
return *this; |
||||
} |
||||
unique_ptr& operator=(T* p) { |
||||
return std::unique_ptr<T>::operator=(p); |
||||
} |
||||
}; |
||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
|
||||
#if FLATBUFFERS_USE_STD_OPTIONAL |
||||
template<class T> |
||||
using Optional = std::optional<T>; |
||||
using nullopt_t = std::nullopt_t; |
||||
inline constexpr nullopt_t nullopt = std::nullopt; |
||||
|
||||
#else |
||||
// Limited implementation of Optional<T> type for a scalar T.
|
||||
// This implementation limited by trivial types compatible with
|
||||
// std::is_arithmetic<T> or std::is_enum<T> type traits.
|
||||
|
||||
// A tag to indicate an empty flatbuffers::optional<T>.
|
||||
struct nullopt_t { |
||||
explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {} |
||||
}; |
||||
|
||||
#if defined(FLATBUFFERS_CONSTEXPR_DEFINED) |
||||
namespace internal { |
||||
template <class> struct nullopt_holder { |
||||
static constexpr nullopt_t instance_ = nullopt_t(0); |
||||
}; |
||||
template<class Dummy> |
||||
constexpr nullopt_t nullopt_holder<Dummy>::instance_; |
||||
} |
||||
static constexpr const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_; |
||||
|
||||
#else |
||||
namespace internal { |
||||
template <class> struct nullopt_holder { |
||||
static const nullopt_t instance_; |
||||
}; |
||||
template<class Dummy> |
||||
const nullopt_t nullopt_holder<Dummy>::instance_ = nullopt_t(0); |
||||
} |
||||
static const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_; |
||||
|
||||
#endif |
||||
|
||||
template<class T> |
||||
class Optional FLATBUFFERS_FINAL_CLASS { |
||||
// Non-scalar 'T' would extremely complicated Optional<T>.
|
||||
// Use is_scalar<T> checking because flatbuffers flatbuffers::is_arithmetic<T>
|
||||
// isn't implemented.
|
||||
static_assert(flatbuffers::is_scalar<T>::value, "unexpected type T"); |
||||
|
||||
public: |
||||
~Optional() {} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT |
||||
: value_(), has_value_(false) {} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT |
||||
: value_(), has_value_(false) {} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT |
||||
: value_(val), has_value_(true) {} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT |
||||
: value_(other.value_), has_value_(other.has_value_) {} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT { |
||||
value_ = other.value_; |
||||
has_value_ = other.has_value_; |
||||
return *this; |
||||
} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT { |
||||
value_ = T(); |
||||
has_value_ = false; |
||||
return *this; |
||||
} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT { |
||||
value_ = val; |
||||
has_value_ = true; |
||||
return *this; |
||||
} |
||||
|
||||
void reset() FLATBUFFERS_NOEXCEPT { |
||||
*this = nullopt; |
||||
} |
||||
|
||||
void swap(Optional &other) FLATBUFFERS_NOEXCEPT { |
||||
std::swap(value_, other.value_); |
||||
std::swap(has_value_, other.has_value_); |
||||
} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT { |
||||
return has_value_; |
||||
} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT { |
||||
return has_value_; |
||||
} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT { |
||||
return value_; |
||||
} |
||||
|
||||
const T& value() const { |
||||
FLATBUFFERS_ASSERT(has_value()); |
||||
return value_; |
||||
} |
||||
|
||||
T value_or(T default_value) const FLATBUFFERS_NOEXCEPT { |
||||
return has_value() ? value_ : default_value; |
||||
} |
||||
|
||||
private: |
||||
T value_; |
||||
bool has_value_; |
||||
}; |
||||
|
||||
template<class T> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& opt, nullopt_t) FLATBUFFERS_NOEXCEPT { |
||||
return !opt; |
||||
} |
||||
template<class T> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional<T>& opt) FLATBUFFERS_NOEXCEPT { |
||||
return !opt; |
||||
} |
||||
|
||||
template<class T, class U> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT { |
||||
return static_cast<bool>(lhs) && (*lhs == rhs); |
||||
} |
||||
|
||||
template<class T, class U> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT { |
||||
return static_cast<bool>(rhs) && (lhs == *rhs); |
||||
} |
||||
|
||||
template<class T, class U> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT { |
||||
return static_cast<bool>(lhs) != static_cast<bool>(rhs) |
||||
? false |
||||
: !static_cast<bool>(lhs) ? false : (*lhs == *rhs); |
||||
} |
||||
#endif // FLATBUFFERS_USE_STD_OPTIONAL
|
||||
|
||||
|
||||
// Very limited and naive partial implementation of C++20 std::span<T,Extent>.
|
||||
#if defined(FLATBUFFERS_USE_STD_SPAN) |
||||
inline constexpr std::size_t dynamic_extent = std::dynamic_extent; |
||||
template<class T, std::size_t Extent = std::dynamic_extent> |
||||
using span = std::span<T, Extent>; |
||||
|
||||
#else // !defined(FLATBUFFERS_USE_STD_SPAN)
|
||||
FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast<std::size_t>(-1); |
||||
|
||||
// Exclude this code if MSVC2010 or non-STL Android is active.
|
||||
// The non-STL Android doesn't have `std::is_convertible` required for SFINAE.
|
||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL) |
||||
namespace internal { |
||||
// This is SFINAE helper class for checking of a common condition:
|
||||
// > This overload only participates in overload resolution
|
||||
// > Check whether a pointer to an array of From can be converted
|
||||
// > to a pointer to an array of To.
|
||||
// This helper is used for checking of 'From -> const From'.
|
||||
template<class To, std::size_t Extent, class From, std::size_t N> |
||||
struct is_span_convertible { |
||||
using type = |
||||
typename std::conditional<std::is_convertible<From (*)[], To (*)[]>::value |
||||
&& (Extent == dynamic_extent || N == Extent), |
||||
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)
|
||||
|
||||
// T - element type; must be a complete type that is not an abstract
|
||||
// class type.
|
||||
// Extent - the number of elements in the sequence, or dynamic.
|
||||
template<class T, std::size_t Extent = dynamic_extent> |
||||
class span FLATBUFFERS_FINAL_CLASS { |
||||
public: |
||||
typedef T element_type; |
||||
typedef T& reference; |
||||
typedef const T& const_reference; |
||||
typedef T* pointer; |
||||
typedef const T* const_pointer; |
||||
typedef std::size_t size_type; |
||||
|
||||
static FLATBUFFERS_CONSTEXPR size_type extent = Extent; |
||||
|
||||
// Returns the number of elements in the span.
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 size_type size() const FLATBUFFERS_NOEXCEPT { |
||||
return count_; |
||||
} |
||||
|
||||
// Returns the size of the sequence in bytes.
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 |
||||
size_type size_bytes() const FLATBUFFERS_NOEXCEPT { |
||||
return size() * sizeof(element_type); |
||||
} |
||||
|
||||
// Checks if the span is empty.
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 bool empty() const FLATBUFFERS_NOEXCEPT { |
||||
return size() == 0; |
||||
} |
||||
|
||||
// Returns a pointer to the beginning of the sequence.
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 pointer data() const FLATBUFFERS_NOEXCEPT { |
||||
return data_; |
||||
} |
||||
|
||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL) |
||||
using Iterator = internal::SpanIterator<T>; |
||||
|
||||
Iterator begin() const { return Iterator(data()); } |
||||
Iterator end() const { return Iterator(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 { |
||||
return data()[idx]; |
||||
} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 span(const span &other) FLATBUFFERS_NOEXCEPT |
||||
: data_(other.data_), count_(other.count_) {} |
||||
|
||||
FLATBUFFERS_CONSTEXPR_CPP14 span &operator=(const span &other) |
||||
FLATBUFFERS_NOEXCEPT { |
||||
data_ = other.data_; |
||||
count_ = other.count_; |
||||
} |
||||
|
||||
// Limited implementation of
|
||||
// `template <class It> constexpr std::span(It first, size_type count);`.
|
||||
//
|
||||
// Constructs a span that is a view over the range [first, first + count);
|
||||
// the resulting span has: data() == first and size() == count.
|
||||
// The behavior is undefined if [first, first + count) is not a valid range,
|
||||
// or if (extent != flatbuffers::dynamic_extent && count != extent).
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 |
||||
explicit span(pointer first, size_type count) FLATBUFFERS_NOEXCEPT |
||||
: data_ (Extent == dynamic_extent ? first : (Extent == count ? first : nullptr)), |
||||
count_(Extent == dynamic_extent ? count : (Extent == count ? Extent : 0)) { |
||||
// Make span empty if the count argument is incompatible with span<T,N>.
|
||||
} |
||||
|
||||
// Exclude this code if MSVC2010 is active. The MSVC2010 isn't C++11
|
||||
// compliant, it doesn't support default template arguments for functions.
|
||||
#if defined(FLATBUFFERS_SPAN_MINIMAL) |
||||
FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr), |
||||
count_(0) { |
||||
static_assert(extent == 0 || extent == dynamic_extent, "invalid span"); |
||||
} |
||||
|
||||
#else |
||||
// Constructs an empty span whose data() == nullptr and size() == 0.
|
||||
// This overload only participates in overload resolution if
|
||||
// extent == 0 || extent == flatbuffers::dynamic_extent.
|
||||
// A dummy template argument N is need dependency for SFINAE.
|
||||
template<std::size_t N = 0, |
||||
typename internal::is_span_convertible<element_type, Extent, element_type, (N - N)>::type = 0> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr), |
||||
count_(0) { |
||||
static_assert(extent == 0 || extent == dynamic_extent, "invalid span"); |
||||
} |
||||
|
||||
// Constructs a span that is a view over the array arr; the resulting span
|
||||
// has size() == N and data() == std::data(arr). These overloads only
|
||||
// participate in overload resolution if
|
||||
// extent == std::dynamic_extent || N == extent is true and
|
||||
// std::remove_pointer_t<decltype(std::data(arr))>(*)[]
|
||||
// is convertible to element_type (*)[].
|
||||
template<std::size_t N, |
||||
typename internal::is_span_convertible<element_type, Extent, element_type, N>::type = 0> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT |
||||
: data_(arr), count_(N) {} |
||||
|
||||
template<class U, std::size_t N, |
||||
typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT |
||||
: data_(arr.data()), count_(N) {} |
||||
|
||||
//template<class U, std::size_t N,
|
||||
// int = 0>
|
||||
//FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
|
||||
// : data_(arr.data()), count_(N) {}
|
||||
|
||||
template<class U, std::size_t N, |
||||
typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT |
||||
: data_(arr.data()), count_(N) {} |
||||
|
||||
// Converting constructor from another span s;
|
||||
// the resulting span has size() == s.size() and data() == s.data().
|
||||
// This overload only participates in overload resolution
|
||||
// if extent == std::dynamic_extent || N == extent is true and U (*)[]
|
||||
// is convertible to element_type (*)[].
|
||||
template<class U, std::size_t N, |
||||
typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span<U, N> &s) FLATBUFFERS_NOEXCEPT |
||||
: span(s.data(), s.size()) { |
||||
} |
||||
|
||||
#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
|
||||
|
||||
private: |
||||
// This is a naive implementation with 'count_' member even if (Extent != dynamic_extent).
|
||||
pointer const data_; |
||||
size_type count_; |
||||
}; |
||||
#endif // defined(FLATBUFFERS_USE_STD_SPAN)
|
||||
|
||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL) |
||||
template<class ElementType, std::size_t Extent> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 |
||||
flatbuffers::span<ElementType, Extent> make_span(ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT { |
||||
return span<ElementType, Extent>(arr); |
||||
} |
||||
|
||||
template<class ElementType, std::size_t Extent> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 |
||||
flatbuffers::span<const ElementType, Extent> make_span(const ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT { |
||||
return span<const ElementType, Extent>(arr); |
||||
} |
||||
|
||||
template<class ElementType, std::size_t Extent> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 |
||||
flatbuffers::span<ElementType, Extent> make_span(std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT { |
||||
return span<ElementType, Extent>(arr); |
||||
} |
||||
|
||||
template<class ElementType, std::size_t Extent> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 |
||||
flatbuffers::span<const ElementType, Extent> make_span(const std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT { |
||||
return span<const ElementType, Extent>(arr); |
||||
} |
||||
|
||||
template<class ElementType, std::size_t Extent> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 |
||||
flatbuffers::span<ElementType, dynamic_extent> make_span(ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT { |
||||
return span<ElementType, dynamic_extent>(first, count); |
||||
} |
||||
|
||||
template<class ElementType, std::size_t Extent> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 |
||||
flatbuffers::span<const ElementType, dynamic_extent> make_span(const ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT { |
||||
return span<const ElementType, dynamic_extent>(first, count); |
||||
} |
||||
#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_STL_EMULATION_H_
|
@ -0,0 +1,64 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_STRING_H_ |
||||
#define FLATBUFFERS_STRING_H_ |
||||
|
||||
#include "flatbuffers/base.h" |
||||
#include "flatbuffers/vector.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
struct String : public Vector<char> { |
||||
const char *c_str() const { return reinterpret_cast<const char *>(Data()); } |
||||
std::string str() const { return std::string(c_str(), size()); } |
||||
|
||||
// clang-format off
|
||||
#ifdef FLATBUFFERS_HAS_STRING_VIEW |
||||
flatbuffers::string_view string_view() const { |
||||
return flatbuffers::string_view(c_str(), size()); |
||||
} |
||||
#endif // FLATBUFFERS_HAS_STRING_VIEW
|
||||
// clang-format on
|
||||
|
||||
bool operator<(const String &o) const { |
||||
return StringLessThan(this->data(), this->size(), o.data(), o.size()); |
||||
} |
||||
}; |
||||
|
||||
// Convenience function to get std::string from a String returning an empty
|
||||
// string on null pointer.
|
||||
static inline std::string GetString(const String *str) { |
||||
return str ? str->str() : ""; |
||||
} |
||||
|
||||
// Convenience function to get char* from a String returning an empty string on
|
||||
// null pointer.
|
||||
static inline const char *GetCstring(const String *str) { |
||||
return str ? str->c_str() : ""; |
||||
} |
||||
|
||||
#ifdef FLATBUFFERS_HAS_STRING_VIEW |
||||
// Convenience function to get string_view from a String returning an empty
|
||||
// string_view on null pointer.
|
||||
static inline flatbuffers::string_view GetStringView(const String *str) { |
||||
return str ? str->string_view() : flatbuffers::string_view(); |
||||
} |
||||
#endif // FLATBUFFERS_HAS_STRING_VIEW
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_STRING_H_
|
@ -0,0 +1,53 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_STRUCT_H_ |
||||
#define FLATBUFFERS_STRUCT_H_ |
||||
|
||||
#include "flatbuffers/base.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
// "structs" are flat structures that do not have an offset table, thus
|
||||
// always have all members present and do not support forwards/backwards
|
||||
// compatible extensions.
|
||||
|
||||
class Struct FLATBUFFERS_FINAL_CLASS { |
||||
public: |
||||
template<typename T> T GetField(uoffset_t o) const { |
||||
return ReadScalar<T>(&data_[o]); |
||||
} |
||||
|
||||
template<typename T> T GetStruct(uoffset_t o) const { |
||||
return reinterpret_cast<T>(&data_[o]); |
||||
} |
||||
|
||||
const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; } |
||||
uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; } |
||||
|
||||
private: |
||||
// private constructor & copy constructor: you obtain instances of this
|
||||
// class by pointing to existing data only
|
||||
Struct(); |
||||
Struct(const Struct &); |
||||
Struct &operator=(const Struct &); |
||||
|
||||
uint8_t data_[1]; |
||||
}; |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_STRUCT_H_
|
@ -0,0 +1,168 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_TABLE_H_ |
||||
#define FLATBUFFERS_TABLE_H_ |
||||
|
||||
#include "flatbuffers/base.h" |
||||
#include "flatbuffers/verifier.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
// "tables" use an offset table (possibly shared) that allows fields to be
|
||||
// omitted and added at will, but uses an extra indirection to read.
|
||||
class Table { |
||||
public: |
||||
const uint8_t *GetVTable() const { |
||||
return data_ - ReadScalar<soffset_t>(data_); |
||||
} |
||||
|
||||
// This gets the field offset for any of the functions below it, or 0
|
||||
// if the field was not present.
|
||||
voffset_t GetOptionalFieldOffset(voffset_t field) const { |
||||
// The vtable offset is always at the start.
|
||||
auto vtable = GetVTable(); |
||||
// The first element is the size of the vtable (fields + type id + itself).
|
||||
auto vtsize = ReadScalar<voffset_t>(vtable); |
||||
// If the field we're accessing is outside the vtable, we're reading older
|
||||
// data, so it's the same as if the offset was 0 (not present).
|
||||
return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0; |
||||
} |
||||
|
||||
template<typename T> T GetField(voffset_t field, T defaultval) const { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval; |
||||
} |
||||
|
||||
template<typename P> P GetPointer(voffset_t field) { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
auto p = data_ + field_offset; |
||||
return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p)) |
||||
: nullptr; |
||||
} |
||||
template<typename P> P GetPointer(voffset_t field) const { |
||||
return const_cast<Table *>(this)->GetPointer<P>(field); |
||||
} |
||||
|
||||
template<typename P> P GetStruct(voffset_t field) const { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
auto p = const_cast<uint8_t *>(data_ + field_offset); |
||||
return field_offset ? reinterpret_cast<P>(p) : nullptr; |
||||
} |
||||
|
||||
template<typename Raw, typename Face> |
||||
flatbuffers::Optional<Face> GetOptional(voffset_t field) const { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
auto p = data_ + field_offset; |
||||
return field_offset ? Optional<Face>(static_cast<Face>(ReadScalar<Raw>(p))) |
||||
: Optional<Face>(); |
||||
} |
||||
|
||||
template<typename T> bool SetField(voffset_t field, T val, T def) { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
if (!field_offset) return IsTheSameAs(val, def); |
||||
WriteScalar(data_ + field_offset, val); |
||||
return true; |
||||
} |
||||
template<typename T> bool SetField(voffset_t field, T val) { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
if (!field_offset) return false; |
||||
WriteScalar(data_ + field_offset, val); |
||||
return true; |
||||
} |
||||
|
||||
bool SetPointer(voffset_t field, const uint8_t *val) { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
if (!field_offset) return false; |
||||
WriteScalar(data_ + field_offset, |
||||
static_cast<uoffset_t>(val - (data_ + field_offset))); |
||||
return true; |
||||
} |
||||
|
||||
uint8_t *GetAddressOf(voffset_t field) { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
return field_offset ? data_ + field_offset : nullptr; |
||||
} |
||||
const uint8_t *GetAddressOf(voffset_t field) const { |
||||
return const_cast<Table *>(this)->GetAddressOf(field); |
||||
} |
||||
|
||||
bool CheckField(voffset_t field) const { |
||||
return GetOptionalFieldOffset(field) != 0; |
||||
} |
||||
|
||||
// Verify the vtable of this table.
|
||||
// Call this once per table, followed by VerifyField once per field.
|
||||
bool VerifyTableStart(Verifier &verifier) const { |
||||
return verifier.VerifyTableStart(data_); |
||||
} |
||||
|
||||
// Verify a particular field.
|
||||
template<typename T> |
||||
bool VerifyField(const Verifier &verifier, voffset_t field, |
||||
size_t align) const { |
||||
// Calling GetOptionalFieldOffset should be safe now thanks to
|
||||
// VerifyTable().
|
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
// Check the actual field.
|
||||
return !field_offset || verifier.VerifyField<T>(data_, field_offset, align); |
||||
} |
||||
|
||||
// VerifyField for required fields.
|
||||
template<typename T> |
||||
bool VerifyFieldRequired(const Verifier &verifier, voffset_t field, |
||||
size_t align) const { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
return verifier.Check(field_offset != 0) && |
||||
verifier.VerifyField<T>(data_, field_offset, align); |
||||
} |
||||
|
||||
// Versions for offsets.
|
||||
bool VerifyOffset(const Verifier &verifier, voffset_t field) const { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
return !field_offset || verifier.VerifyOffset(data_, field_offset); |
||||
} |
||||
|
||||
bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
return verifier.Check(field_offset != 0) && |
||||
verifier.VerifyOffset(data_, field_offset); |
||||
} |
||||
|
||||
private: |
||||
// private constructor & copy constructor: you obtain instances of this
|
||||
// class by pointing to existing data only
|
||||
Table(); |
||||
Table(const Table &other); |
||||
Table &operator=(const Table &); |
||||
|
||||
uint8_t data_[1]; |
||||
}; |
||||
|
||||
// This specialization allows avoiding warnings like:
|
||||
// MSVC C4800: type: forcing value to bool 'true' or 'false'.
|
||||
template<> |
||||
inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>( |
||||
voffset_t field) const { |
||||
auto field_offset = GetOptionalFieldOffset(field); |
||||
auto p = data_ + field_offset; |
||||
return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0) |
||||
: Optional<bool>(); |
||||
} |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_TABLE_H_
|
@ -0,0 +1,393 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_VECTOR_H_ |
||||
#define FLATBUFFERS_VECTOR_H_ |
||||
|
||||
#include "flatbuffers/base.h" |
||||
#include "flatbuffers/buffer.h" |
||||
#include "flatbuffers/stl_emulation.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
struct String; |
||||
|
||||
// An STL compatible iterator implementation for Vector below, effectively
|
||||
// calling Get() for every element.
|
||||
template<typename T, typename IT, typename Data = uint8_t *> |
||||
struct VectorIterator { |
||||
typedef std::random_access_iterator_tag iterator_category; |
||||
typedef IT value_type; |
||||
typedef ptrdiff_t difference_type; |
||||
typedef IT *pointer; |
||||
typedef IT &reference; |
||||
|
||||
VectorIterator(Data data, uoffset_t i) |
||||
: data_(data + IndirectHelper<T>::element_stride * i) {} |
||||
VectorIterator(const VectorIterator &other) : data_(other.data_) {} |
||||
VectorIterator() : data_(nullptr) {} |
||||
|
||||
VectorIterator &operator=(const VectorIterator &other) { |
||||
data_ = other.data_; |
||||
return *this; |
||||
} |
||||
|
||||
VectorIterator &operator=(VectorIterator &&other) { |
||||
data_ = other.data_; |
||||
return *this; |
||||
} |
||||
|
||||
bool operator==(const VectorIterator &other) const { |
||||
return data_ == other.data_; |
||||
} |
||||
|
||||
bool operator<(const VectorIterator &other) const { |
||||
return data_ < other.data_; |
||||
} |
||||
|
||||
bool operator!=(const VectorIterator &other) const { |
||||
return data_ != other.data_; |
||||
} |
||||
|
||||
difference_type operator-(const VectorIterator &other) const { |
||||
return (data_ - other.data_) / IndirectHelper<T>::element_stride; |
||||
} |
||||
|
||||
// Note: return type is incompatible with the standard
|
||||
// `reference operator*()`.
|
||||
IT operator*() const { return IndirectHelper<T>::Read(data_, 0); } |
||||
|
||||
// Note: return type is incompatible with the standard
|
||||
// `pointer operator->()`.
|
||||
IT operator->() const { return IndirectHelper<T>::Read(data_, 0); } |
||||
|
||||
VectorIterator &operator++() { |
||||
data_ += IndirectHelper<T>::element_stride; |
||||
return *this; |
||||
} |
||||
|
||||
VectorIterator operator++(int) { |
||||
VectorIterator temp(data_, 0); |
||||
data_ += IndirectHelper<T>::element_stride; |
||||
return temp; |
||||
} |
||||
|
||||
VectorIterator operator+(const uoffset_t &offset) const { |
||||
return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, |
||||
0); |
||||
} |
||||
|
||||
VectorIterator &operator+=(const uoffset_t &offset) { |
||||
data_ += offset * IndirectHelper<T>::element_stride; |
||||
return *this; |
||||
} |
||||
|
||||
VectorIterator &operator--() { |
||||
data_ -= IndirectHelper<T>::element_stride; |
||||
return *this; |
||||
} |
||||
|
||||
VectorIterator operator--(int) { |
||||
VectorIterator temp(data_, 0); |
||||
data_ -= IndirectHelper<T>::element_stride; |
||||
return temp; |
||||
} |
||||
|
||||
VectorIterator operator-(const uoffset_t &offset) const { |
||||
return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, |
||||
0); |
||||
} |
||||
|
||||
VectorIterator &operator-=(const uoffset_t &offset) { |
||||
data_ -= offset * IndirectHelper<T>::element_stride; |
||||
return *this; |
||||
} |
||||
|
||||
private: |
||||
Data data_; |
||||
}; |
||||
|
||||
template<typename T, typename IT> |
||||
using VectorConstIterator = VectorIterator<T, IT, const uint8_t *>; |
||||
|
||||
template<typename Iterator> |
||||
struct VectorReverseIterator : public std::reverse_iterator<Iterator> { |
||||
explicit VectorReverseIterator(Iterator iter) |
||||
: std::reverse_iterator<Iterator>(iter) {} |
||||
|
||||
// Note: return type is incompatible with the standard
|
||||
// `reference operator*()`.
|
||||
typename Iterator::value_type operator*() const { |
||||
auto tmp = std::reverse_iterator<Iterator>::current; |
||||
return *--tmp; |
||||
} |
||||
|
||||
// Note: return type is incompatible with the standard
|
||||
// `pointer operator->()`.
|
||||
typename Iterator::value_type operator->() const { |
||||
auto tmp = std::reverse_iterator<Iterator>::current; |
||||
return *--tmp; |
||||
} |
||||
}; |
||||
|
||||
// This is used as a helper type for accessing vectors.
|
||||
// Vector::data() assumes the vector elements start after the length field.
|
||||
template<typename T> class Vector { |
||||
public: |
||||
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type> |
||||
iterator; |
||||
typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type> |
||||
const_iterator; |
||||
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.
|
||||
FLATBUFFERS_ATTRIBUTE([[deprecated("use size() instead")]]) |
||||
uoffset_t Length() const { return size(); } |
||||
|
||||
typedef typename IndirectHelper<T>::return_type return_type; |
||||
typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type; |
||||
typedef return_type value_type; |
||||
|
||||
return_type Get(uoffset_t i) const { |
||||
FLATBUFFERS_ASSERT(i < size()); |
||||
return IndirectHelper<T>::Read(Data(), i); |
||||
} |
||||
|
||||
return_type operator[](uoffset_t i) const { return Get(i); } |
||||
|
||||
// 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 E.
|
||||
template<typename E> E GetEnum(uoffset_t i) const { |
||||
return static_cast<E>(Get(i)); |
||||
} |
||||
|
||||
// If this a vector of unions, this does the cast for you. There's no check
|
||||
// to make sure this is the right type!
|
||||
template<typename U> const U *GetAs(uoffset_t i) const { |
||||
return reinterpret_cast<const U *>(Get(i)); |
||||
} |
||||
|
||||
// If this a vector of unions, this does the cast for you. There's no check
|
||||
// to make sure this is actually a string!
|
||||
const String *GetAsString(uoffset_t i) const { |
||||
return reinterpret_cast<const String *>(Get(i)); |
||||
} |
||||
|
||||
const void *GetStructFromOffset(size_t o) const { |
||||
return reinterpret_cast<const void *>(Data() + o); |
||||
} |
||||
|
||||
iterator begin() { return iterator(Data(), 0); } |
||||
const_iterator begin() const { return const_iterator(Data(), 0); } |
||||
|
||||
iterator end() { return iterator(Data(), size()); } |
||||
const_iterator end() const { return const_iterator(Data(), size()); } |
||||
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); } |
||||
const_reverse_iterator rbegin() const { |
||||
return const_reverse_iterator(end()); |
||||
} |
||||
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); } |
||||
const_reverse_iterator rend() const { |
||||
return const_reverse_iterator(begin()); |
||||
} |
||||
|
||||
const_iterator cbegin() const { return begin(); } |
||||
|
||||
const_iterator cend() const { return end(); } |
||||
|
||||
const_reverse_iterator crbegin() const { return rbegin(); } |
||||
|
||||
const_reverse_iterator crend() const { return rend(); } |
||||
|
||||
// Change elements if you have a non-const pointer to this object.
|
||||
// Scalars only. See reflection.h, and the documentation.
|
||||
void Mutate(uoffset_t i, const T &val) { |
||||
FLATBUFFERS_ASSERT(i < size()); |
||||
WriteScalar(data() + i, val); |
||||
} |
||||
|
||||
// Change an element of a vector of tables (or strings).
|
||||
// "val" points to the new table/string, as you can obtain from
|
||||
// e.g. reflection::AddFlatBuffer().
|
||||
void MutateOffset(uoffset_t i, const uint8_t *val) { |
||||
FLATBUFFERS_ASSERT(i < size()); |
||||
static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types"); |
||||
WriteScalar(data() + i, |
||||
static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t)))); |
||||
} |
||||
|
||||
// Get a mutable pointer to tables/strings inside this vector.
|
||||
mutable_return_type GetMutableObject(uoffset_t i) const { |
||||
FLATBUFFERS_ASSERT(i < size()); |
||||
return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i)); |
||||
} |
||||
|
||||
// The raw data in little endian format. Use with care.
|
||||
const uint8_t *Data() const { |
||||
return reinterpret_cast<const uint8_t *>(&length_ + 1); |
||||
} |
||||
|
||||
uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); } |
||||
|
||||
// Similarly, but typed, much like std::vector::data
|
||||
const T *data() const { return reinterpret_cast<const T *>(Data()); } |
||||
T *data() { return reinterpret_cast<T *>(Data()); } |
||||
|
||||
template<typename K> return_type LookupByKey(K key) const { |
||||
void *search_result = std::bsearch( |
||||
&key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>); |
||||
|
||||
if (!search_result) { |
||||
return nullptr; // Key not found.
|
||||
} |
||||
|
||||
const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result); |
||||
|
||||
return IndirectHelper<T>::Read(element, 0); |
||||
} |
||||
|
||||
template<typename K> mutable_return_type MutableLookupByKey(K key) { |
||||
return const_cast<mutable_return_type>(LookupByKey(key)); |
||||
} |
||||
|
||||
protected: |
||||
// This class is only used to access pre-existing data. Don't ever
|
||||
// try to construct these manually.
|
||||
Vector(); |
||||
|
||||
uoffset_t length_; |
||||
|
||||
private: |
||||
// This class is a pointer. Copying will therefore create an invalid object.
|
||||
// Private and unimplemented copy constructor.
|
||||
Vector(const Vector &); |
||||
Vector &operator=(const Vector &); |
||||
|
||||
template<typename K> static int KeyCompare(const void *ap, const void *bp) { |
||||
const K *key = reinterpret_cast<const K *>(ap); |
||||
const uint8_t *data = reinterpret_cast<const uint8_t *>(bp); |
||||
auto table = IndirectHelper<T>::Read(data, 0); |
||||
|
||||
// std::bsearch compares with the operands transposed, so we negate the
|
||||
// result here.
|
||||
return -table->KeyCompareWithValue(*key); |
||||
} |
||||
}; |
||||
|
||||
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)); |
||||
} |
||||
|
||||
// Convenient helper functions to get a span of any vector, regardless
|
||||
// of whether it is null or not (the field is not set).
|
||||
template<class U> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> *ptr) |
||||
FLATBUFFERS_NOEXCEPT { |
||||
static_assert(Vector<U>::is_span_observable, |
||||
"wrong type U, only LE-scalar, or byte types are allowed"); |
||||
return ptr ? make_span(*ptr) : span<U>(); |
||||
} |
||||
|
||||
template<class U> |
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span( |
||||
const Vector<U> *ptr) FLATBUFFERS_NOEXCEPT { |
||||
static_assert(Vector<U>::is_span_observable, |
||||
"wrong type U, only LE-scalar, or byte types are allowed"); |
||||
return ptr ? make_span(*ptr) : span<const 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 { |
||||
public: |
||||
uoffset_t size() const { return EndianScalar(length_); } |
||||
|
||||
const uint8_t *Data() const { |
||||
return reinterpret_cast<const uint8_t *>(&length_ + 1); |
||||
} |
||||
uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); } |
||||
|
||||
protected: |
||||
VectorOfAny(); |
||||
|
||||
uoffset_t length_; |
||||
|
||||
private: |
||||
VectorOfAny(const VectorOfAny &); |
||||
VectorOfAny &operator=(const VectorOfAny &); |
||||
}; |
||||
|
||||
template<typename T, typename U> |
||||
Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) { |
||||
static_assert(std::is_base_of<T, U>::value, "Unrelated types"); |
||||
return reinterpret_cast<Vector<Offset<T>> *>(ptr); |
||||
} |
||||
|
||||
template<typename T, typename U> |
||||
const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) { |
||||
static_assert(std::is_base_of<T, U>::value, "Unrelated types"); |
||||
return reinterpret_cast<const Vector<Offset<T>> *>(ptr); |
||||
} |
||||
|
||||
// Convenient helper function to get the length of any vector, regardless
|
||||
// of whether it is null or not (the field is not set).
|
||||
template<typename T> static inline size_t VectorLength(const Vector<T> *v) { |
||||
return v ? v->size() : 0; |
||||
} |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_VERIFIER_H_
|
@ -0,0 +1,273 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_ |
||||
#define FLATBUFFERS_VECTOR_DOWNWARD_H_ |
||||
|
||||
#include <algorithm> |
||||
|
||||
#include "flatbuffers/base.h" |
||||
#include "flatbuffers/default_allocator.h" |
||||
#include "flatbuffers/detached_buffer.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
// This is a minimal replication of std::vector<uint8_t> functionality,
|
||||
// except growing from higher to lower addresses. i.e. push_back() inserts data
|
||||
// in the lowest address in the vector.
|
||||
// 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.
|
||||
// Essentially, this supports 2 std::vectors in a single buffer.
|
||||
class vector_downward { |
||||
public: |
||||
explicit vector_downward(size_t initial_size, Allocator *allocator, |
||||
bool own_allocator, size_t buffer_minalign) |
||||
: allocator_(allocator), |
||||
own_allocator_(own_allocator), |
||||
initial_size_(initial_size), |
||||
buffer_minalign_(buffer_minalign), |
||||
reserved_(0), |
||||
size_(0), |
||||
buf_(nullptr), |
||||
cur_(nullptr), |
||||
scratch_(nullptr) {} |
||||
|
||||
vector_downward(vector_downward &&other) noexcept |
||||
// clang-format on
|
||||
: allocator_(other.allocator_), |
||||
own_allocator_(other.own_allocator_), |
||||
initial_size_(other.initial_size_), |
||||
buffer_minalign_(other.buffer_minalign_), |
||||
reserved_(other.reserved_), |
||||
size_(other.size_), |
||||
buf_(other.buf_), |
||||
cur_(other.cur_), |
||||
scratch_(other.scratch_) { |
||||
// No change in other.allocator_
|
||||
// No change in other.initial_size_
|
||||
// No change in other.buffer_minalign_
|
||||
other.own_allocator_ = false; |
||||
other.reserved_ = 0; |
||||
other.buf_ = nullptr; |
||||
other.cur_ = nullptr; |
||||
other.scratch_ = nullptr; |
||||
} |
||||
|
||||
vector_downward &operator=(vector_downward &&other) noexcept { |
||||
// Move construct a temporary and swap idiom
|
||||
vector_downward temp(std::move(other)); |
||||
swap(temp); |
||||
return *this; |
||||
} |
||||
|
||||
~vector_downward() { |
||||
clear_buffer(); |
||||
clear_allocator(); |
||||
} |
||||
|
||||
void reset() { |
||||
clear_buffer(); |
||||
clear(); |
||||
} |
||||
|
||||
void clear() { |
||||
if (buf_) { |
||||
cur_ = buf_ + reserved_; |
||||
} else { |
||||
reserved_ = 0; |
||||
cur_ = nullptr; |
||||
} |
||||
size_ = 0; |
||||
clear_scratch(); |
||||
} |
||||
|
||||
void clear_scratch() { scratch_ = buf_; } |
||||
|
||||
void clear_allocator() { |
||||
if (own_allocator_ && allocator_) { delete allocator_; } |
||||
allocator_ = nullptr; |
||||
own_allocator_ = false; |
||||
} |
||||
|
||||
void clear_buffer() { |
||||
if (buf_) Deallocate(allocator_, buf_, reserved_); |
||||
buf_ = nullptr; |
||||
} |
||||
|
||||
// Relinquish the pointer to the caller.
|
||||
uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) { |
||||
auto *buf = buf_; |
||||
allocated_bytes = reserved_; |
||||
offset = static_cast<size_t>(cur_ - buf_); |
||||
|
||||
// release_raw only relinquishes the buffer ownership.
|
||||
// Does not deallocate or reset the allocator. Destructor will do that.
|
||||
buf_ = nullptr; |
||||
clear(); |
||||
return buf; |
||||
} |
||||
|
||||
// Relinquish the pointer to the caller.
|
||||
DetachedBuffer release() { |
||||
// allocator ownership (if any) is transferred to DetachedBuffer.
|
||||
DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_, |
||||
size()); |
||||
if (own_allocator_) { |
||||
allocator_ = nullptr; |
||||
own_allocator_ = false; |
||||
} |
||||
buf_ = nullptr; |
||||
clear(); |
||||
return fb; |
||||
} |
||||
|
||||
size_t ensure_space(size_t len) { |
||||
FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_); |
||||
if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); } |
||||
// Beyond this, signed offsets may not have enough range:
|
||||
// (FlatBuffers > 2GB not supported).
|
||||
FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE); |
||||
return len; |
||||
} |
||||
|
||||
inline uint8_t *make_space(size_t len) { |
||||
if (len) { |
||||
ensure_space(len); |
||||
cur_ -= len; |
||||
size_ += static_cast<uoffset_t>(len); |
||||
} |
||||
return cur_; |
||||
} |
||||
|
||||
// Returns nullptr if using the DefaultAllocator.
|
||||
Allocator *get_custom_allocator() { return allocator_; } |
||||
|
||||
inline uoffset_t size() const { return size_; } |
||||
|
||||
uoffset_t scratch_size() const { |
||||
return static_cast<uoffset_t>(scratch_ - buf_); |
||||
} |
||||
|
||||
size_t capacity() const { return reserved_; } |
||||
|
||||
uint8_t *data() const { |
||||
FLATBUFFERS_ASSERT(cur_); |
||||
return cur_; |
||||
} |
||||
|
||||
uint8_t *scratch_data() const { |
||||
FLATBUFFERS_ASSERT(buf_); |
||||
return buf_; |
||||
} |
||||
|
||||
uint8_t *scratch_end() const { |
||||
FLATBUFFERS_ASSERT(scratch_); |
||||
return scratch_; |
||||
} |
||||
|
||||
uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; } |
||||
|
||||
void push(const uint8_t *bytes, size_t num) { |
||||
if (num > 0) { memcpy(make_space(num), bytes, num); } |
||||
} |
||||
|
||||
// Specialized version of push() that avoids memcpy call for small data.
|
||||
template<typename T> void push_small(const T &little_endian_t) { |
||||
make_space(sizeof(T)); |
||||
*reinterpret_cast<T *>(cur_) = little_endian_t; |
||||
} |
||||
|
||||
template<typename T> void scratch_push_small(const T &t) { |
||||
ensure_space(sizeof(T)); |
||||
*reinterpret_cast<T *>(scratch_) = t; |
||||
scratch_ += sizeof(T); |
||||
} |
||||
|
||||
// fill() is most frequently called with small byte counts (<= 4),
|
||||
// which is why we're using loops rather than calling memset.
|
||||
void fill(size_t zero_pad_bytes) { |
||||
make_space(zero_pad_bytes); |
||||
for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0; |
||||
} |
||||
|
||||
// Version for when we know the size is larger.
|
||||
// Precondition: zero_pad_bytes > 0
|
||||
void fill_big(size_t zero_pad_bytes) { |
||||
memset(make_space(zero_pad_bytes), 0, zero_pad_bytes); |
||||
} |
||||
|
||||
void pop(size_t bytes_to_remove) { |
||||
cur_ += bytes_to_remove; |
||||
size_ -= static_cast<uoffset_t>(bytes_to_remove); |
||||
} |
||||
|
||||
void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; } |
||||
|
||||
void swap(vector_downward &other) { |
||||
using std::swap; |
||||
swap(allocator_, other.allocator_); |
||||
swap(own_allocator_, other.own_allocator_); |
||||
swap(initial_size_, other.initial_size_); |
||||
swap(buffer_minalign_, other.buffer_minalign_); |
||||
swap(reserved_, other.reserved_); |
||||
swap(size_, other.size_); |
||||
swap(buf_, other.buf_); |
||||
swap(cur_, other.cur_); |
||||
swap(scratch_, other.scratch_); |
||||
} |
||||
|
||||
void swap_allocator(vector_downward &other) { |
||||
using std::swap; |
||||
swap(allocator_, other.allocator_); |
||||
swap(own_allocator_, other.own_allocator_); |
||||
} |
||||
|
||||
private: |
||||
// You shouldn't really be copying instances of this class.
|
||||
FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &)); |
||||
FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &)); |
||||
|
||||
Allocator *allocator_; |
||||
bool own_allocator_; |
||||
size_t initial_size_; |
||||
size_t buffer_minalign_; |
||||
size_t reserved_; |
||||
uoffset_t size_; |
||||
uint8_t *buf_; |
||||
uint8_t *cur_; // Points at location between empty (below) and used (above).
|
||||
uint8_t *scratch_; // Points to the end of the scratchpad in use.
|
||||
|
||||
void reallocate(size_t len) { |
||||
auto old_reserved = reserved_; |
||||
auto old_size = size(); |
||||
auto old_scratch_size = scratch_size(); |
||||
reserved_ += |
||||
(std::max)(len, old_reserved ? old_reserved / 2 : initial_size_); |
||||
reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1); |
||||
if (buf_) { |
||||
buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_, |
||||
old_size, old_scratch_size); |
||||
} else { |
||||
buf_ = Allocate(allocator_, reserved_); |
||||
} |
||||
cur_ = buf_ + reserved_ - old_size; |
||||
scratch_ = buf_ + old_scratch_size; |
||||
} |
||||
}; |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_VECTOR_DOWNWARD_H_
|
@ -0,0 +1,317 @@ |
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#ifndef FLATBUFFERS_VERIFIER_H_ |
||||
#define FLATBUFFERS_VERIFIER_H_ |
||||
|
||||
#include "flatbuffers/base.h" |
||||
#include "flatbuffers/vector.h" |
||||
|
||||
namespace flatbuffers { |
||||
|
||||
// Helper class to verify the integrity of a FlatBuffer
|
||||
class Verifier FLATBUFFERS_FINAL_CLASS { |
||||
public: |
||||
struct Options { |
||||
// The maximum nesting of tables and vectors before we call it invalid.
|
||||
uoffset_t max_depth = 64; |
||||
// The maximum number of tables we will verify before we call it invalid.
|
||||
uoffset_t max_tables = 1000000; |
||||
// If true, verify all data is aligned.
|
||||
bool check_alignment = true; |
||||
// If true, run verifier on nested flatbuffers
|
||||
bool check_nested_flatbuffers = true; |
||||
}; |
||||
|
||||
explicit Verifier(const uint8_t *const buf, const size_t buf_len, |
||||
const Options &opts) |
||||
: buf_(buf), size_(buf_len), opts_(opts) { |
||||
FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE); |
||||
} |
||||
|
||||
// Deprecated API, please construct with Verifier::Options.
|
||||
Verifier(const uint8_t *const buf, const size_t buf_len, |
||||
const uoffset_t max_depth = 64, const uoffset_t max_tables = 1000000, |
||||
const bool check_alignment = true) |
||||
: Verifier(buf, buf_len, [&] { |
||||
Options opts; |
||||
opts.max_depth = max_depth; |
||||
opts.max_tables = max_tables; |
||||
opts.check_alignment = check_alignment; |
||||
return opts; |
||||
}()) {} |
||||
|
||||
// Central location where any verification failures register.
|
||||
bool Check(const bool ok) const { |
||||
// clang-format off
|
||||
#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE |
||||
FLATBUFFERS_ASSERT(ok); |
||||
#endif |
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE |
||||
if (!ok) |
||||
upper_bound_ = 0; |
||||
#endif |
||||
// clang-format on
|
||||
return ok; |
||||
} |
||||
|
||||
// Verify any range within the buffer.
|
||||
bool Verify(const size_t elem, const size_t elem_len) const { |
||||
// clang-format off
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE |
||||
auto upper_bound = elem + elem_len; |
||||
if (upper_bound_ < upper_bound) |
||||
upper_bound_ = upper_bound; |
||||
#endif |
||||
// clang-format on
|
||||
return Check(elem_len < size_ && elem <= size_ - elem_len); |
||||
} |
||||
|
||||
bool VerifyAlignment(const size_t elem, const size_t align) const { |
||||
return Check((elem & (align - 1)) == 0 || !opts_.check_alignment); |
||||
} |
||||
|
||||
// Verify a range indicated by sizeof(T).
|
||||
template<typename T> bool Verify(const size_t elem) const { |
||||
return VerifyAlignment(elem, sizeof(T)) && Verify(elem, sizeof(T)); |
||||
} |
||||
|
||||
bool VerifyFromPointer(const uint8_t *const p, const size_t len) { |
||||
return Verify(static_cast<size_t>(p - buf_), len); |
||||
} |
||||
|
||||
// Verify relative to a known-good base pointer.
|
||||
bool VerifyFieldStruct(const uint8_t *const base, const voffset_t elem_off, |
||||
const size_t elem_len, const size_t align) const { |
||||
const auto f = static_cast<size_t>(base - buf_) + elem_off; |
||||
return VerifyAlignment(f, align) && Verify(f, elem_len); |
||||
} |
||||
|
||||
template<typename T> |
||||
bool VerifyField(const uint8_t *const base, const voffset_t elem_off, |
||||
const size_t align) const { |
||||
const auto f = static_cast<size_t>(base - buf_) + elem_off; |
||||
return VerifyAlignment(f, align) && Verify(f, sizeof(T)); |
||||
} |
||||
|
||||
// Verify a pointer (may be NULL) of a table type.
|
||||
template<typename T> bool VerifyTable(const T *const table) { |
||||
return !table || table->Verify(*this); |
||||
} |
||||
|
||||
// Verify a pointer (may be NULL) of any vector type.
|
||||
template<typename T> bool VerifyVector(const Vector<T> *const vec) const { |
||||
return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec), |
||||
sizeof(T)); |
||||
} |
||||
|
||||
// Verify a pointer (may be NULL) of a vector to struct.
|
||||
template<typename T> |
||||
bool VerifyVector(const Vector<const T *> *const vec) const { |
||||
return VerifyVector(reinterpret_cast<const Vector<T> *>(vec)); |
||||
} |
||||
|
||||
// Verify a pointer (may be NULL) to string.
|
||||
bool VerifyString(const String *const str) const { |
||||
size_t end; |
||||
return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str), |
||||
1, &end) && |
||||
Verify(end, 1) && // Must have terminator
|
||||
Check(buf_[end] == '\0')); // Terminating byte must be 0.
|
||||
} |
||||
|
||||
// Common code between vectors and strings.
|
||||
bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size, |
||||
size_t *const end = nullptr) const { |
||||
const auto veco = static_cast<size_t>(vec - buf_); |
||||
// Check we can read the size field.
|
||||
if (!Verify<uoffset_t>(veco)) return false; |
||||
// Check the whole array. If this is a string, the byte past the array must
|
||||
// be 0.
|
||||
const auto size = ReadScalar<uoffset_t>(vec); |
||||
const auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size; |
||||
if (!Check(size < max_elems)) |
||||
return false; // Protect against byte_size overflowing.
|
||||
const auto byte_size = sizeof(size) + elem_size * size; |
||||
if (end) *end = veco + byte_size; |
||||
return Verify(veco, byte_size); |
||||
} |
||||
|
||||
// Special case for string contents, after the above has been called.
|
||||
bool VerifyVectorOfStrings(const Vector<Offset<String>> *const vec) const { |
||||
if (vec) { |
||||
for (uoffset_t i = 0; i < vec->size(); i++) { |
||||
if (!VerifyString(vec->Get(i))) return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
// Special case for table contents, after the above has been called.
|
||||
template<typename T> |
||||
bool VerifyVectorOfTables(const Vector<Offset<T>> *const vec) { |
||||
if (vec) { |
||||
for (uoffset_t i = 0; i < vec->size(); i++) { |
||||
if (!vec->Get(i)->Verify(*this)) return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
__suppress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart( |
||||
const uint8_t *const table) { |
||||
// Check the vtable offset.
|
||||
const auto tableo = static_cast<size_t>(table - buf_); |
||||
if (!Verify<soffset_t>(tableo)) return false; |
||||
// This offset may be signed, but doing the subtraction unsigned always
|
||||
// gives the result we want.
|
||||
const auto vtableo = |
||||
tableo - static_cast<size_t>(ReadScalar<soffset_t>(table)); |
||||
// Check the vtable size field, then check vtable fits in its entirety.
|
||||
if (!(VerifyComplexity() && Verify<voffset_t>(vtableo) && |
||||
VerifyAlignment(ReadScalar<voffset_t>(buf_ + vtableo), |
||||
sizeof(voffset_t)))) |
||||
return false; |
||||
const auto vsize = ReadScalar<voffset_t>(buf_ + vtableo); |
||||
return Check((vsize & 1) == 0) && Verify(vtableo, vsize); |
||||
} |
||||
|
||||
template<typename T> |
||||
bool VerifyBufferFromStart(const char *const identifier, const size_t start) { |
||||
// Buffers have to be of some size to be valid. The reason it is a runtime
|
||||
// check instead of static_assert, is that nested flatbuffers go through
|
||||
// this call and their size is determined at runtime.
|
||||
if (!Check(size_ >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false; |
||||
|
||||
// If an identifier is provided, check that we have a buffer
|
||||
if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) && |
||||
BufferHasIdentifier(buf_ + start, identifier)))) { |
||||
return false; |
||||
} |
||||
|
||||
// Call T::Verify, which must be in the generated code for this type.
|
||||
const auto o = VerifyOffset(start); |
||||
return Check(o != 0) && |
||||
reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this) |
||||
// clang-format off
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE |
||||
&& GetComputedSize() |
||||
#endif |
||||
; |
||||
// clang-format on
|
||||
} |
||||
|
||||
template<typename T> |
||||
bool VerifyNestedFlatBuffer(const Vector<uint8_t> *const buf, |
||||
const char *const identifier) { |
||||
// Caller opted out of this.
|
||||
if (!opts_.check_nested_flatbuffers) return true; |
||||
|
||||
// An empty buffer is OK as it indicates not present.
|
||||
if (!buf) return true; |
||||
|
||||
// If there is a nested buffer, it must be greater than the min size.
|
||||
if (!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false; |
||||
|
||||
Verifier nested_verifier(buf->data(), buf->size()); |
||||
return nested_verifier.VerifyBuffer<T>(identifier); |
||||
} |
||||
|
||||
// Verify this whole buffer, starting with root type T.
|
||||
template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); } |
||||
|
||||
template<typename T> bool VerifyBuffer(const char *const identifier) { |
||||
return VerifyBufferFromStart<T>(identifier, 0); |
||||
} |
||||
|
||||
template<typename T> |
||||
bool VerifySizePrefixedBuffer(const char *const identifier) { |
||||
return Verify<uoffset_t>(0U) && |
||||
Check(ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t)) && |
||||
VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t)); |
||||
} |
||||
|
||||
uoffset_t VerifyOffset(const size_t start) const { |
||||
if (!Verify<uoffset_t>(start)) return 0; |
||||
const auto o = ReadScalar<uoffset_t>(buf_ + start); |
||||
// May not point to itself.
|
||||
if (!Check(o != 0)) return 0; |
||||
// Can't wrap around / buffers are max 2GB.
|
||||
if (!Check(static_cast<soffset_t>(o) >= 0)) return 0; |
||||
// Must be inside the buffer to create a pointer from it (pointer outside
|
||||
// buffer is UB).
|
||||
if (!Verify(start + o, 1)) return 0; |
||||
return o; |
||||
} |
||||
|
||||
uoffset_t VerifyOffset(const uint8_t *const base, |
||||
const voffset_t start) const { |
||||
return VerifyOffset(static_cast<size_t>(base - buf_) + start); |
||||
} |
||||
|
||||
// Called at the start of a table to increase counters measuring data
|
||||
// structure depth and amount, and possibly bails out with false if limits set
|
||||
// by the constructor have been hit. Needs to be balanced with EndTable().
|
||||
bool VerifyComplexity() { |
||||
depth_++; |
||||
num_tables_++; |
||||
return Check(depth_ <= opts_.max_depth && num_tables_ <= opts_.max_tables); |
||||
} |
||||
|
||||
// Called at the end of a table to pop the depth count.
|
||||
bool EndTable() { |
||||
depth_--; |
||||
return true; |
||||
} |
||||
|
||||
// Returns the message size in bytes
|
||||
size_t GetComputedSize() const { |
||||
// clang-format off
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE |
||||
uintptr_t size = upper_bound_; |
||||
// Align the size to uoffset_t
|
||||
size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1); |
||||
return (size > size_) ? 0 : size; |
||||
#else |
||||
// Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
|
||||
(void)upper_bound_; |
||||
FLATBUFFERS_ASSERT(false); |
||||
return 0; |
||||
#endif |
||||
// clang-format on
|
||||
} |
||||
|
||||
std::vector<uint8_t> *GetFlexReuseTracker() { return flex_reuse_tracker_; } |
||||
|
||||
void SetFlexReuseTracker(std::vector<uint8_t> *const rt) { |
||||
flex_reuse_tracker_ = rt; |
||||
} |
||||
|
||||
private: |
||||
const uint8_t *buf_; |
||||
const size_t size_; |
||||
const Options opts_; |
||||
|
||||
mutable size_t upper_bound_ = 0; |
||||
|
||||
uoffset_t depth_ = 0; |
||||
uoffset_t num_tables_ = 0; |
||||
std::vector<uint8_t> *flex_reuse_tracker_ = nullptr; |
||||
}; |
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_VERIFIER_H_
|
@ -0,0 +1,19 @@ |
||||
if(WITH_FLATBUFFERS) |
||||
set(HAVE_FLATBUFFERS 1) |
||||
set(flatbuffers_VERSION "23.1.21") |
||||
ocv_install_3rdparty_licenses(flatbuffers "${OpenCV_SOURCE_DIR}/3rdparty/flatbuffers/LICENSE.txt") |
||||
ocv_add_external_target(flatbuffers "${OpenCV_SOURCE_DIR}/3rdparty/flatbuffers/include" "" "HAVE_FLATBUFFERS=1") |
||||
set(CUSTOM_STATUS_flatbuffers " Flatbuffers:" "builtin/3rdparty (${flatbuffers_VERSION})") |
||||
endif() |
||||
|
||||
if(WITH_FLATBUFFERS OR HAVE_FLATBUFFERS) |
||||
list(APPEND CUSTOM_STATUS flatbuffers) |
||||
|
||||
if(HAVE_FLATBUFFERS) |
||||
if(NOT CUSTOM_STATUS_flatbuffers) |
||||
list(APPEND CUSTOM_STATUS_flatbuffers " Flatbuffers:" "${flatbuffers_VERSION}") |
||||
endif() |
||||
else() |
||||
list(APPEND CUSTOM_STATUS_flatbuffers " Flatbuffers:" "NO") |
||||
endif() |
||||
endif() |
@ -1,15 +0,0 @@ |
||||
set(HAVE_FLATBUFFERS FALSE) |
||||
|
||||
if(NOT WITH_FLATBUFFERS) |
||||
return() |
||||
endif() |
||||
|
||||
list(APPEND CUSTOM_STATUS flatbuffers) |
||||
|
||||
find_package(flatbuffers QUIET) |
||||
if(flatbuffers_FOUND) |
||||
set(HAVE_FLATBUFFERS 1) |
||||
list(APPEND CUSTOM_STATUS_flatbuffers " FlatBuffers:" "${flatbuffers_VERSION}") |
||||
else() |
||||
list(APPEND CUSTOM_STATUS_flatbuffers " FlatBuffers:" "NO") |
||||
endif() |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue