blob: 4d2d395455ed05eb4248301cce22530f932a4df9 [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
Austin Schuhe93d8642019-10-13 15:27:07 -07007#include "aos/flatbuffers.h"
Austin Schuh09d7ffa2019-10-03 23:43:34 -07008#include "flatbuffers/flatbuffers.h"
9
10namespace aos {
11
Austin Schuhe93d8642019-10-13 15:27:07 -070012// Merges 2 flat buffers with the provided type table into the builder. Returns
13// the offset to the flatbuffers.
14// One or both of t1 and t2 must be non-null. If one is null, this method
Austin Schuh48d10d62022-10-16 22:19:23 -070015// copies instead of merging.
Austin Schuhe93d8642019-10-13 15:27:07 -070016flatbuffers::Offset<flatbuffers::Table> MergeFlatBuffers(
17 const flatbuffers::TypeTable *typetable, const flatbuffers::Table *t1,
18 const flatbuffers::Table *t2, flatbuffers::FlatBufferBuilder *fbb);
Austin Schuh09d7ffa2019-10-03 23:43:34 -070019
20template <class T>
Austin Schuhe93d8642019-10-13 15:27:07 -070021inline flatbuffers::Offset<T> MergeFlatBuffers(
Austin Schuhadd6eb32020-11-09 21:24:26 -080022 const flatbuffers::Table *t1, const flatbuffers::Table *t2,
23 flatbuffers::FlatBufferBuilder *fbb) {
Austin Schuhe93d8642019-10-13 15:27:07 -070024 return MergeFlatBuffers(T::MiniReflectTypeTable(), t1, t2, fbb).o;
25}
26
27template <class T>
Austin Schuh40485ed2019-10-26 21:51:44 -070028inline aos::FlatbufferDetachedBuffer<T> MergeFlatBuffers(const T *fb1,
29 const T *fb2) {
James Kuszmaulf3a3be22020-01-04 12:12:00 -080030 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -080031 fbb.ForceDefaults(true);
Austin Schuh12417a02021-02-07 22:44:24 -080032 fbb.DedupVtables(false);
James Kuszmaulf3a3be22020-01-04 12:12:00 -080033 fbb.Finish(MergeFlatBuffers<T>(
34 reinterpret_cast<const flatbuffers::Table *>(fb1),
35 reinterpret_cast<const flatbuffers::Table *>(fb2), &fbb));
36 return aos::FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -070037}
38
39template <class T>
Austin Schuhe6958212020-10-19 11:48:14 -070040inline flatbuffers::Offset<T> MergeFlatBuffers(
41 const T *fb1, const T *fb2, flatbuffers::FlatBufferBuilder *fbb) {
42 return MergeFlatBuffers<T>(reinterpret_cast<const flatbuffers::Table *>(fb1),
43 reinterpret_cast<const flatbuffers::Table *>(fb2),
44 fbb);
45}
46
Austin Schuhadd6eb32020-11-09 21:24:26 -080047template <class T>
48inline aos::FlatbufferDetachedBuffer<T> MergeFlatBuffers(
49 const aos::Flatbuffer<T> &fb1, const aos::Flatbuffer<T> &fb2) {
50 return aos::FlatbufferDetachedBuffer<T>(
51 MergeFlatBuffers<T>(&fb1.message(), &fb2.message()));
52}
53
Austin Schuh4b5c22a2020-11-30 22:58:43 -080054template <class T>
55inline flatbuffers::Offset<T> MergeFlatBuffers(
56 const aos::Flatbuffer<T> &fb1, const aos::Flatbuffer<T> &fb2,
57 flatbuffers::FlatBufferBuilder *fbb) {
58 return MergeFlatBuffers<T>(
59 reinterpret_cast<const flatbuffers::Table *>(&fb1.message()),
60 reinterpret_cast<const flatbuffers::Table *>(&fb2.message()), fbb);
61}
62
Austin Schuha4fc60f2020-11-01 23:06:47 -080063// Copies a flatbuffer by walking the tree and copying all the pieces. This
64// converts DAGs to trees.
Austin Schuhe6958212020-10-19 11:48:14 -070065template <class T>
Austin Schuha4fc60f2020-11-01 23:06:47 -080066inline flatbuffers::Offset<T> RecursiveCopyFlatBuffer(
Austin Schuhe93d8642019-10-13 15:27:07 -070067 const T *t1, flatbuffers::FlatBufferBuilder *fbb) {
68 return MergeFlatBuffers<T>(reinterpret_cast<const flatbuffers::Table *>(t1),
69 nullptr, fbb);
70}
71
Austin Schuha4fc60f2020-11-01 23:06:47 -080072// Copies a flatbuffer by finding the extents of the memory using the typetable
73// and copying the containing memory. This doesn't allocate memory, and
74// preserves DAGs.
75flatbuffers::Offset<flatbuffers::Table> CopyFlatBuffer(
76 const flatbuffers::Table *t1, const flatbuffers::TypeTable *typetable,
77 flatbuffers::FlatBufferBuilder *fbb);
78
79template <class T>
80inline flatbuffers::Offset<T> CopyFlatBuffer(
81 const T *t1, flatbuffers::FlatBufferBuilder *fbb) {
82 return flatbuffers::Offset<T>(
83 CopyFlatBuffer(reinterpret_cast<const flatbuffers::Table *>(t1),
84 T::MiniReflectTypeTable(), fbb)
85 .o);
86}
87
88template <class T>
89inline flatbuffers::Offset<T> CopyFlatBuffer(
90 const Flatbuffer<T> &t1, flatbuffers::FlatBufferBuilder *fbb) {
91 return flatbuffers::Offset<T>(
92 CopyFlatBuffer(
93 reinterpret_cast<const flatbuffers::Table *>(&t1.message()),
94 T::MiniReflectTypeTable(), fbb)
95 .o);
96}
97
Austin Schuhadd6eb32020-11-09 21:24:26 -080098namespace flatbuffer_merge_internal {
99
100inline flatbuffers::uoffset_t DoBlindCopyFlatBuffer(
101 const void *message, absl::Span<const uint8_t> span,
102 flatbuffers::FlatBufferBuilder *fbb) {
Austin Schuha4fc60f2020-11-01 23:06:47 -0800103 // Enforce 8 byte alignment so anything inside the flatbuffer can be read.
104 fbb->Align(sizeof(flatbuffers::largest_scalar_t));
105
106 // We don't know how much of the start of the flatbuffer is padding. The
107 // safest thing to do from an alignment point of view (without looking inside)
108 // is to copy the initial offset and leave it as dead space.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800109 fbb->PushBytes(span.data(), span.size());
110 // Then, compute the offset from the back by computing the distance from the
111 // front to the start of the message.
Austin Schuha4fc60f2020-11-01 23:06:47 -0800112 return fbb->GetSize() -
Austin Schuhadd6eb32020-11-09 21:24:26 -0800113 static_cast<flatbuffers::uoffset_t>(
114 reinterpret_cast<const uint8_t *>(message) - span.data());
115}
116
117} // namespace flatbuffer_merge_internal
118
119// Copies a flatbuffer by copying all the data without looking inside and
120// pointing inside it.
121template <class T>
122inline flatbuffers::Offset<T> BlindCopyFlatBuffer(
123 const NonSizePrefixedFlatbuffer<T> &t,
124 flatbuffers::FlatBufferBuilder *fbb) {
125 return flatbuffer_merge_internal::DoBlindCopyFlatBuffer(&t.message(),
126 t.span(), fbb);
127}
128
129// Copies a flatbuffer by copying all the data without looking inside and
130// pointing inside it.
131template <class T>
132inline flatbuffers::Offset<T> BlindCopyFlatBuffer(
133 const SizePrefixedFlatbuffer<T> &t, flatbuffers::FlatBufferBuilder *fbb) {
134 return flatbuffer_merge_internal::DoBlindCopyFlatBuffer(&t.message(),
135 t.span(), fbb);
Austin Schuha4fc60f2020-11-01 23:06:47 -0800136}
137
Austin Schuhe93d8642019-10-13 15:27:07 -0700138template <class T>
Austin Schuhcbe9d5a2020-11-01 23:25:23 -0800139inline flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<T>>>
Austin Schuh5c255aa2020-11-05 18:32:46 -0800140RecursiveCopyVectorTable(const flatbuffers::Vector<flatbuffers::Offset<T>> *t1,
141 flatbuffers::FlatBufferBuilder *fbb) {
Austin Schuhcbe9d5a2020-11-01 23:25:23 -0800142 if (t1 == nullptr) {
143 return 0;
144 }
145 std::vector<flatbuffers::Offset<T>> v;
146 for (const T *t : *t1) {
Austin Schuh5c255aa2020-11-05 18:32:46 -0800147 v.emplace_back(RecursiveCopyFlatBuffer(t, fbb));
Austin Schuhcbe9d5a2020-11-01 23:25:23 -0800148 }
149 return fbb->CreateVector(v);
150}
151
152inline flatbuffers::Offset<
153 flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>
154CopyVectorSharedString(
155 const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *t1,
156 flatbuffers::FlatBufferBuilder *fbb) {
157 if (t1 == nullptr) {
158 return 0;
159 }
160 std::vector<flatbuffers::Offset<flatbuffers::String>> v;
161 for (const flatbuffers::String *t : *t1) {
162 v.emplace_back(fbb->CreateSharedString(t));
163 }
164 return fbb->CreateVector(v);
165}
166
167template <class T>
Austin Schuh40485ed2019-10-26 21:51:44 -0700168inline FlatbufferDetachedBuffer<T> CopyFlatBuffer(const T *t) {
Austin Schuhe93d8642019-10-13 15:27:07 -0700169 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -0800170 fbb.ForceDefaults(true);
Austin Schuh12417a02021-02-07 22:44:24 -0800171 fbb.DedupVtables(false);
Austin Schuhe93d8642019-10-13 15:27:07 -0700172 fbb.Finish(CopyFlatBuffer<T>(t, &fbb));
Austin Schuh40485ed2019-10-26 21:51:44 -0700173 return FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -0700174}
175
Austin Schuha4fc60f2020-11-01 23:06:47 -0800176template <class T>
177inline FlatbufferDetachedBuffer<T> RecursiveCopyFlatBuffer(const T *t) {
178 flatbuffers::FlatBufferBuilder fbb;
179 fbb.ForceDefaults(true);
Austin Schuh12417a02021-02-07 22:44:24 -0800180 fbb.DedupVtables(false);
Austin Schuha4fc60f2020-11-01 23:06:47 -0800181 fbb.Finish(RecursiveCopyFlatBuffer<T>(t, &fbb));
182 return FlatbufferDetachedBuffer<T>(fbb.Release());
183}
184
Austin Schuh30d7db92020-01-26 16:45:47 -0800185// Compares 2 flatbuffers. Returns true if they match, false otherwise.
186bool CompareFlatBuffer(const flatbuffers::TypeTable *typetable,
187 const flatbuffers::Table *t1,
188 const flatbuffers::Table *t2);
189
190template <class T>
191inline bool CompareFlatBuffer(const T *t1, const T *t2) {
192 return CompareFlatBuffer(T::MiniReflectTypeTable(),
193 reinterpret_cast<const flatbuffers::Table *>(t1),
194 reinterpret_cast<const flatbuffers::Table *>(t2));
195}
196
Austin Schuh97789fc2020-08-01 14:42:45 -0700197template <class T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800198inline bool CompareFlatBuffer(const aos::NonSizePrefixedFlatbuffer<T> &t1,
199 const aos::NonSizePrefixedFlatbuffer<T> &t2) {
200 return t1.span() == t2.span();
201}
202
203template <class T>
204inline bool CompareFlatBuffer(const aos::SizePrefixedFlatbuffer<T> &t1,
205 const aos::SizePrefixedFlatbuffer<T> &t2) {
Austin Schuh97789fc2020-08-01 14:42:45 -0700206 return t1.span() == t2.span();
207}
208
Austin Schuh09d7ffa2019-10-03 23:43:34 -0700209} // namespace aos
210
211#endif // AOS_FLATBUFFER_MERGE_H_