blob: c16746442de269c494d62dddcdc0a777f3c3db95 [file] [log] [blame]
Austin Schuh09d7ffa2019-10-03 23:43:34 -07001#ifndef AOS_FLATBUFFER_MERGE_H_
2#define AOS_FLATBUFFER_MERGE_H_
3
4#include <cstddef>
5#include <string>
6
7#include "flatbuffers/flatbuffers.h"
8
Philipp Schrader790cb542023-07-05 21:06:52 -07009#include "aos/flatbuffers.h"
10
Austin Schuh09d7ffa2019-10-03 23:43:34 -070011namespace aos {
12
Austin Schuhe93d8642019-10-13 15:27:07 -070013// Merges 2 flat buffers with the provided type table into the builder. Returns
14// the offset to the flatbuffers.
15// One or both of t1 and t2 must be non-null. If one is null, this method
Austin Schuh48d10d62022-10-16 22:19:23 -070016// copies instead of merging.
Austin Schuhe93d8642019-10-13 15:27:07 -070017flatbuffers::Offset<flatbuffers::Table> MergeFlatBuffers(
18 const flatbuffers::TypeTable *typetable, const flatbuffers::Table *t1,
19 const flatbuffers::Table *t2, flatbuffers::FlatBufferBuilder *fbb);
Austin Schuh09d7ffa2019-10-03 23:43:34 -070020
21template <class T>
Austin Schuhe93d8642019-10-13 15:27:07 -070022inline flatbuffers::Offset<T> MergeFlatBuffers(
Austin Schuhadd6eb32020-11-09 21:24:26 -080023 const flatbuffers::Table *t1, const flatbuffers::Table *t2,
24 flatbuffers::FlatBufferBuilder *fbb) {
Austin Schuhe93d8642019-10-13 15:27:07 -070025 return MergeFlatBuffers(T::MiniReflectTypeTable(), t1, t2, fbb).o;
26}
27
28template <class T>
Austin Schuh40485ed2019-10-26 21:51:44 -070029inline aos::FlatbufferDetachedBuffer<T> MergeFlatBuffers(const T *fb1,
30 const T *fb2) {
James Kuszmaulf3a3be22020-01-04 12:12:00 -080031 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -080032 fbb.ForceDefaults(true);
Austin Schuh12417a02021-02-07 22:44:24 -080033 fbb.DedupVtables(false);
James Kuszmaulf3a3be22020-01-04 12:12:00 -080034 fbb.Finish(MergeFlatBuffers<T>(
35 reinterpret_cast<const flatbuffers::Table *>(fb1),
36 reinterpret_cast<const flatbuffers::Table *>(fb2), &fbb));
37 return aos::FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -070038}
39
40template <class T>
Austin Schuhe6958212020-10-19 11:48:14 -070041inline flatbuffers::Offset<T> MergeFlatBuffers(
42 const T *fb1, const T *fb2, flatbuffers::FlatBufferBuilder *fbb) {
43 return MergeFlatBuffers<T>(reinterpret_cast<const flatbuffers::Table *>(fb1),
44 reinterpret_cast<const flatbuffers::Table *>(fb2),
45 fbb);
46}
47
Austin Schuhadd6eb32020-11-09 21:24:26 -080048template <class T>
49inline aos::FlatbufferDetachedBuffer<T> MergeFlatBuffers(
50 const aos::Flatbuffer<T> &fb1, const aos::Flatbuffer<T> &fb2) {
51 return aos::FlatbufferDetachedBuffer<T>(
52 MergeFlatBuffers<T>(&fb1.message(), &fb2.message()));
53}
54
Austin Schuh4b5c22a2020-11-30 22:58:43 -080055template <class T>
56inline flatbuffers::Offset<T> MergeFlatBuffers(
57 const aos::Flatbuffer<T> &fb1, const aos::Flatbuffer<T> &fb2,
58 flatbuffers::FlatBufferBuilder *fbb) {
59 return MergeFlatBuffers<T>(
60 reinterpret_cast<const flatbuffers::Table *>(&fb1.message()),
61 reinterpret_cast<const flatbuffers::Table *>(&fb2.message()), fbb);
62}
63
Austin Schuha4fc60f2020-11-01 23:06:47 -080064// Copies a flatbuffer by walking the tree and copying all the pieces. This
65// converts DAGs to trees.
Austin Schuhe6958212020-10-19 11:48:14 -070066template <class T>
Austin Schuha4fc60f2020-11-01 23:06:47 -080067inline flatbuffers::Offset<T> RecursiveCopyFlatBuffer(
Austin Schuhe93d8642019-10-13 15:27:07 -070068 const T *t1, flatbuffers::FlatBufferBuilder *fbb) {
69 return MergeFlatBuffers<T>(reinterpret_cast<const flatbuffers::Table *>(t1),
70 nullptr, fbb);
71}
72
Austin Schuha4fc60f2020-11-01 23:06:47 -080073// Copies a flatbuffer by finding the extents of the memory using the typetable
74// and copying the containing memory. This doesn't allocate memory, and
75// preserves DAGs.
76flatbuffers::Offset<flatbuffers::Table> CopyFlatBuffer(
77 const flatbuffers::Table *t1, const flatbuffers::TypeTable *typetable,
78 flatbuffers::FlatBufferBuilder *fbb);
79
80template <class T>
81inline flatbuffers::Offset<T> CopyFlatBuffer(
82 const T *t1, flatbuffers::FlatBufferBuilder *fbb) {
83 return flatbuffers::Offset<T>(
84 CopyFlatBuffer(reinterpret_cast<const flatbuffers::Table *>(t1),
85 T::MiniReflectTypeTable(), fbb)
86 .o);
87}
88
89template <class T>
90inline flatbuffers::Offset<T> CopyFlatBuffer(
91 const Flatbuffer<T> &t1, flatbuffers::FlatBufferBuilder *fbb) {
92 return flatbuffers::Offset<T>(
93 CopyFlatBuffer(
94 reinterpret_cast<const flatbuffers::Table *>(&t1.message()),
95 T::MiniReflectTypeTable(), fbb)
96 .o);
97}
98
Austin Schuhadd6eb32020-11-09 21:24:26 -080099namespace flatbuffer_merge_internal {
100
101inline flatbuffers::uoffset_t DoBlindCopyFlatBuffer(
102 const void *message, absl::Span<const uint8_t> span,
103 flatbuffers::FlatBufferBuilder *fbb) {
Austin Schuha4fc60f2020-11-01 23:06:47 -0800104 // Enforce 8 byte alignment so anything inside the flatbuffer can be read.
105 fbb->Align(sizeof(flatbuffers::largest_scalar_t));
106
107 // We don't know how much of the start of the flatbuffer is padding. The
108 // safest thing to do from an alignment point of view (without looking inside)
109 // is to copy the initial offset and leave it as dead space.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800110 fbb->PushBytes(span.data(), span.size());
111 // Then, compute the offset from the back by computing the distance from the
112 // front to the start of the message.
Austin Schuha4fc60f2020-11-01 23:06:47 -0800113 return fbb->GetSize() -
Austin Schuhadd6eb32020-11-09 21:24:26 -0800114 static_cast<flatbuffers::uoffset_t>(
115 reinterpret_cast<const uint8_t *>(message) - span.data());
116}
117
118} // namespace flatbuffer_merge_internal
119
120// Copies a flatbuffer by copying all the data without looking inside and
121// pointing inside it.
122template <class T>
123inline flatbuffers::Offset<T> BlindCopyFlatBuffer(
124 const NonSizePrefixedFlatbuffer<T> &t,
125 flatbuffers::FlatBufferBuilder *fbb) {
126 return flatbuffer_merge_internal::DoBlindCopyFlatBuffer(&t.message(),
127 t.span(), fbb);
128}
129
130// Copies a flatbuffer by copying all the data without looking inside and
131// pointing inside it.
132template <class T>
133inline flatbuffers::Offset<T> BlindCopyFlatBuffer(
134 const SizePrefixedFlatbuffer<T> &t, flatbuffers::FlatBufferBuilder *fbb) {
135 return flatbuffer_merge_internal::DoBlindCopyFlatBuffer(&t.message(),
136 t.span(), fbb);
Austin Schuha4fc60f2020-11-01 23:06:47 -0800137}
138
Austin Schuhe93d8642019-10-13 15:27:07 -0700139template <class T>
Austin Schuhcbe9d5a2020-11-01 23:25:23 -0800140inline flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<T>>>
Austin Schuh5c255aa2020-11-05 18:32:46 -0800141RecursiveCopyVectorTable(const flatbuffers::Vector<flatbuffers::Offset<T>> *t1,
142 flatbuffers::FlatBufferBuilder *fbb) {
Austin Schuhcbe9d5a2020-11-01 23:25:23 -0800143 if (t1 == nullptr) {
144 return 0;
145 }
146 std::vector<flatbuffers::Offset<T>> v;
147 for (const T *t : *t1) {
Austin Schuh5c255aa2020-11-05 18:32:46 -0800148 v.emplace_back(RecursiveCopyFlatBuffer(t, fbb));
Austin Schuhcbe9d5a2020-11-01 23:25:23 -0800149 }
150 return fbb->CreateVector(v);
151}
152
153inline flatbuffers::Offset<
154 flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
155CopyVectorSharedString(
156 const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *t1,
157 flatbuffers::FlatBufferBuilder *fbb) {
158 if (t1 == nullptr) {
159 return 0;
160 }
161 std::vector<flatbuffers::Offset<flatbuffers::String>> v;
162 for (const flatbuffers::String *t : *t1) {
163 v.emplace_back(fbb->CreateSharedString(t));
164 }
165 return fbb->CreateVector(v);
166}
167
168template <class T>
Austin Schuh40485ed2019-10-26 21:51:44 -0700169inline FlatbufferDetachedBuffer<T> CopyFlatBuffer(const T *t) {
Austin Schuhe93d8642019-10-13 15:27:07 -0700170 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -0800171 fbb.ForceDefaults(true);
Austin Schuh12417a02021-02-07 22:44:24 -0800172 fbb.DedupVtables(false);
Austin Schuhe93d8642019-10-13 15:27:07 -0700173 fbb.Finish(CopyFlatBuffer<T>(t, &fbb));
Austin Schuh40485ed2019-10-26 21:51:44 -0700174 return FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -0700175}
176
Austin Schuha4fc60f2020-11-01 23:06:47 -0800177template <class T>
178inline FlatbufferDetachedBuffer<T> RecursiveCopyFlatBuffer(const T *t) {
179 flatbuffers::FlatBufferBuilder fbb;
180 fbb.ForceDefaults(true);
Austin Schuh12417a02021-02-07 22:44:24 -0800181 fbb.DedupVtables(false);
Austin Schuha4fc60f2020-11-01 23:06:47 -0800182 fbb.Finish(RecursiveCopyFlatBuffer<T>(t, &fbb));
183 return FlatbufferDetachedBuffer<T>(fbb.Release());
184}
185
Austin Schuh30d7db92020-01-26 16:45:47 -0800186// Compares 2 flatbuffers. Returns true if they match, false otherwise.
187bool CompareFlatBuffer(const flatbuffers::TypeTable *typetable,
188 const flatbuffers::Table *t1,
189 const flatbuffers::Table *t2);
190
191template <class T>
192inline bool CompareFlatBuffer(const T *t1, const T *t2) {
193 return CompareFlatBuffer(T::MiniReflectTypeTable(),
194 reinterpret_cast<const flatbuffers::Table *>(t1),
195 reinterpret_cast<const flatbuffers::Table *>(t2));
196}
197
Austin Schuh97789fc2020-08-01 14:42:45 -0700198template <class T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800199inline bool CompareFlatBuffer(const aos::NonSizePrefixedFlatbuffer<T> &t1,
200 const aos::NonSizePrefixedFlatbuffer<T> &t2) {
201 return t1.span() == t2.span();
202}
203
204template <class T>
205inline bool CompareFlatBuffer(const aos::SizePrefixedFlatbuffer<T> &t1,
206 const aos::SizePrefixedFlatbuffer<T> &t2) {
Austin Schuh97789fc2020-08-01 14:42:45 -0700207 return t1.span() == t2.span();
208}
209
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700210} // namespace aos
211
212#endif // AOS_FLATBUFFER_MERGE_H_