blob: e9619a7e63fe772cdbdfda88f48d7acddff9839d [file] [log] [blame]
James Kuszmaulf5eb4682023-09-22 17:16:59 -07001#ifndef AOS_FLATBUFFERS_STATIC_TABLE_H_
2#define AOS_FLATBUFFERS_STATIC_TABLE_H_
3#include <algorithm>
4#include <span>
5
6#include "flatbuffers/base.h"
7#include "glog/logging.h"
8
9#include "aos/flatbuffers/base.h"
10namespace aos::fbs {
11
12// This Table object is used as the parent class to the generated code for every
13// flatbuffer table that we generate code for.
14// This object primarily serves to provide some useful common methods for
15// mutating the flatbuffer memory.
16//
17// Every table will be aligned to the greatest alignment of all of its members
18// and its size will be equal to a multiple of the alignment. Each table shall
19// have the following layout: [vtable offset; inline data with padding; vtable;
20// padding; table/vector data with padding]
21class Table : public ResizeableObject {
22 public:
23 // Prints out a debug string of the raw flatbuffer memory. Does not currently
24 // do anything intelligent ot traverse down into the subobjects of the
25 // flatbuffer (if you want that, then use the flatbuffer binary
26 // annotator---this code mostly exists for debugging the static flatbuffers
27 // implementation itself).
28 std::string SerializationDebugString() const {
29 std::stringstream str;
30 str << "Size: " << buffer_.size() << " alignment: " << Alignment() << "\n";
31 str << "Observed Vtable offset " << Get<soffset_t>(0) << "\n";
32 str << "Inline Size " << InlineTableSize() << " Inline Bytes:\n";
33 internal::DebugBytes(internal::GetSubSpan(buffer_, 4, InlineTableSize()),
34 str);
35 str << "Vtable offset " << FixedVtableOffset() << " Vtable size "
36 << VtableSize() << " Vtable contents:\n";
37 internal::DebugBytes(
38 internal::GetSubSpan(buffer_, FixedVtableOffset(), VtableSize()), str);
39 str << "Offset data offset " << OffsetDataStart() << "\n";
40 // Actual contents can be big; don't print them out until we run into a
41 // situation where we need to debug that.
42 return str.str();
43 }
44
45 protected:
James Kuszmaula75cd7c2023-12-07 15:52:51 -080046 static constexpr size_t kMinAlign = alignof(uoffset_t);
47
James Kuszmaulf5eb4682023-09-22 17:16:59 -070048 Table(std::span<uint8_t> buffer, ResizeableObject *parent)
49 : ResizeableObject(buffer, parent) {}
50 Table(std::span<uint8_t> buffer, Allocator *allocator)
51 : ResizeableObject(buffer, allocator) {}
52 Table(std::span<uint8_t> buffer, ::std::unique_ptr<Allocator> allocator)
53 : ResizeableObject(buffer, ::std::move(allocator)) {}
54 Table(Table &&) = default;
55 virtual ~Table() {}
56 virtual size_t FixedVtableOffset() const = 0;
57 virtual size_t VtableSize() const = 0;
58 virtual size_t InlineTableSize() const = 0;
59 virtual size_t OffsetDataStart() const = 0;
60 size_t AbsoluteOffsetOffset() const override { return 0; }
61 void PopulateVtable() {
62 // Zero out everything up to the start of the sub-messages/tables, which are
63 // responsible for doing their own memory initialization.
64 internal::ClearSpan(internal::GetSubSpan(buffer_, 0, OffsetDataStart()));
65 // Set the offset to the start of the vtable (points backwards, hence the
66 // sign inversion).
67 Set<soffset_t>(0, -FixedVtableOffset());
68 // First element of the vtable is the size of the table.
69 Set<voffset_t>(FixedVtableOffset(), VtableSize());
70 // Second element of the vtable is the size of the inlined data (not really
71 // used by anything...).
72 Set<voffset_t>(FixedVtableOffset() + sizeof(voffset_t), InlineTableSize());
73 }
74
75 template <typename T>
76 void SetField(size_t absolute_offset, size_t vtable_offset, const T &value) {
77 Set<T>(absolute_offset, value);
78 CHECK_EQ(0u, (absolute_offset + reinterpret_cast<size_t>(buffer_.data())) %
79 alignof(T));
80 Set<voffset_t>(FixedVtableOffset() + vtable_offset, absolute_offset);
81 }
82
83 void ClearField(size_t absolute_offset, size_t inline_size,
84 size_t vtable_offset) {
85 // TODO: Remove/account for any excess allocated memory.
86 internal::ClearSpan(
87 internal::GetSubSpan(buffer_, absolute_offset, inline_size));
88 Set<voffset_t>(FixedVtableOffset() + vtable_offset, 0);
89 }
90
91 template <typename T>
92 const T &Get(size_t absolute_offset) const {
93 return *reinterpret_cast<const T *>(buffer_.data() + absolute_offset);
94 }
95
96 template <typename T>
97 T *MutableGet(size_t absolute_offset) {
98 return reinterpret_cast<T *>(buffer_.data() + absolute_offset);
99 }
100
101 template <typename T>
102 T *GetMutableFlatbuffer() {
103 return reinterpret_cast<T *>(buffer_.data());
104 }
105
106 template <typename T>
107 const T *GetFlatbuffer() const {
108 return reinterpret_cast<const T *>(buffer_.data());
109 }
110
111 private:
112 template <typename T>
113 void Set(size_t absolute_offset, const T &value) {
114 *reinterpret_cast<T *>(buffer_.data() + absolute_offset) = value;
115 }
116};
117
118} // namespace aos::fbs
119#endif // AOS_FLATBUFFERS_STATIC_TABLE_H_