blob: a7f96d12ab00f9080437872c36b09ffaca0850b6 [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;
Austin Schuhf8440852024-05-31 10:46:50 -070020// table/vector data with padding]
21//
22// Within the table/vector data with padding section, there will be a chunk of
23// memory for the data associated with each sub-table/vector of the table.
24// That memory will start with some padding and then the memory actually
25// allocated to the table/vector in question will start at said
26// sub-table/vector's individual alignment.
James Kuszmaulf5eb4682023-09-22 17:16:59 -070027class Table : public ResizeableObject {
28 public:
29 // Prints out a debug string of the raw flatbuffer memory. Does not currently
30 // do anything intelligent ot traverse down into the subobjects of the
31 // flatbuffer (if you want that, then use the flatbuffer binary
32 // annotator---this code mostly exists for debugging the static flatbuffers
33 // implementation itself).
34 std::string SerializationDebugString() const {
35 std::stringstream str;
36 str << "Size: " << buffer_.size() << " alignment: " << Alignment() << "\n";
37 str << "Observed Vtable offset " << Get<soffset_t>(0) << "\n";
38 str << "Inline Size " << InlineTableSize() << " Inline Bytes:\n";
39 internal::DebugBytes(internal::GetSubSpan(buffer_, 4, InlineTableSize()),
40 str);
41 str << "Vtable offset " << FixedVtableOffset() << " Vtable size "
42 << VtableSize() << " Vtable contents:\n";
43 internal::DebugBytes(
44 internal::GetSubSpan(buffer_, FixedVtableOffset(), VtableSize()), str);
45 str << "Offset data offset " << OffsetDataStart() << "\n";
46 // Actual contents can be big; don't print them out until we run into a
47 // situation where we need to debug that.
48 return str.str();
49 }
50
51 protected:
James Kuszmaula75cd7c2023-12-07 15:52:51 -080052 static constexpr size_t kMinAlign = alignof(uoffset_t);
53
James Kuszmaulf5eb4682023-09-22 17:16:59 -070054 Table(std::span<uint8_t> buffer, ResizeableObject *parent)
55 : ResizeableObject(buffer, parent) {}
56 Table(std::span<uint8_t> buffer, Allocator *allocator)
57 : ResizeableObject(buffer, allocator) {}
58 Table(std::span<uint8_t> buffer, ::std::unique_ptr<Allocator> allocator)
59 : ResizeableObject(buffer, ::std::move(allocator)) {}
60 Table(Table &&) = default;
61 virtual ~Table() {}
62 virtual size_t FixedVtableOffset() const = 0;
63 virtual size_t VtableSize() const = 0;
64 virtual size_t InlineTableSize() const = 0;
65 virtual size_t OffsetDataStart() const = 0;
James Kuszmaulf5eb4682023-09-22 17:16:59 -070066 void PopulateVtable() {
67 // Zero out everything up to the start of the sub-messages/tables, which are
68 // responsible for doing their own memory initialization.
69 internal::ClearSpan(internal::GetSubSpan(buffer_, 0, OffsetDataStart()));
70 // Set the offset to the start of the vtable (points backwards, hence the
71 // sign inversion).
72 Set<soffset_t>(0, -FixedVtableOffset());
73 // First element of the vtable is the size of the table.
74 Set<voffset_t>(FixedVtableOffset(), VtableSize());
75 // Second element of the vtable is the size of the inlined data (not really
76 // used by anything...).
77 Set<voffset_t>(FixedVtableOffset() + sizeof(voffset_t), InlineTableSize());
78 }
79
80 template <typename T>
81 void SetField(size_t absolute_offset, size_t vtable_offset, const T &value) {
82 Set<T>(absolute_offset, value);
83 CHECK_EQ(0u, (absolute_offset + reinterpret_cast<size_t>(buffer_.data())) %
84 alignof(T));
85 Set<voffset_t>(FixedVtableOffset() + vtable_offset, absolute_offset);
86 }
87
88 void ClearField(size_t absolute_offset, size_t inline_size,
89 size_t vtable_offset) {
90 // TODO: Remove/account for any excess allocated memory.
91 internal::ClearSpan(
92 internal::GetSubSpan(buffer_, absolute_offset, inline_size));
93 Set<voffset_t>(FixedVtableOffset() + vtable_offset, 0);
94 }
95
96 template <typename T>
97 const T &Get(size_t absolute_offset) const {
98 return *reinterpret_cast<const T *>(buffer_.data() + absolute_offset);
99 }
100
101 template <typename T>
102 T *MutableGet(size_t absolute_offset) {
103 return reinterpret_cast<T *>(buffer_.data() + absolute_offset);
104 }
105
106 template <typename T>
107 T *GetMutableFlatbuffer() {
108 return reinterpret_cast<T *>(buffer_.data());
109 }
110
111 template <typename T>
112 const T *GetFlatbuffer() const {
113 return reinterpret_cast<const T *>(buffer_.data());
114 }
115
116 private:
117 template <typename T>
118 void Set(size_t absolute_offset, const T &value) {
119 *reinterpret_cast<T *>(buffer_.data() + absolute_offset) = value;
120 }
121};
122
123} // namespace aos::fbs
124#endif // AOS_FLATBUFFERS_STATIC_TABLE_H_