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