blob: f90ccdef7575cefc647730d1cb1e208486623303 [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:
46 Table(std::span<uint8_t> buffer, ResizeableObject *parent)
47 : ResizeableObject(buffer, parent) {}
48 Table(std::span<uint8_t> buffer, Allocator *allocator)
49 : ResizeableObject(buffer, allocator) {}
50 Table(std::span<uint8_t> buffer, ::std::unique_ptr<Allocator> allocator)
51 : ResizeableObject(buffer, ::std::move(allocator)) {}
52 Table(Table &&) = default;
53 virtual ~Table() {}
54 virtual size_t FixedVtableOffset() const = 0;
55 virtual size_t VtableSize() const = 0;
56 virtual size_t InlineTableSize() const = 0;
57 virtual size_t OffsetDataStart() const = 0;
58 size_t AbsoluteOffsetOffset() const override { return 0; }
59 void PopulateVtable() {
60 // Zero out everything up to the start of the sub-messages/tables, which are
61 // responsible for doing their own memory initialization.
62 internal::ClearSpan(internal::GetSubSpan(buffer_, 0, OffsetDataStart()));
63 // Set the offset to the start of the vtable (points backwards, hence the
64 // sign inversion).
65 Set<soffset_t>(0, -FixedVtableOffset());
66 // First element of the vtable is the size of the table.
67 Set<voffset_t>(FixedVtableOffset(), VtableSize());
68 // Second element of the vtable is the size of the inlined data (not really
69 // used by anything...).
70 Set<voffset_t>(FixedVtableOffset() + sizeof(voffset_t), InlineTableSize());
71 }
72
73 template <typename T>
74 void SetField(size_t absolute_offset, size_t vtable_offset, const T &value) {
75 Set<T>(absolute_offset, value);
76 CHECK_EQ(0u, (absolute_offset + reinterpret_cast<size_t>(buffer_.data())) %
77 alignof(T));
78 Set<voffset_t>(FixedVtableOffset() + vtable_offset, absolute_offset);
79 }
80
81 void ClearField(size_t absolute_offset, size_t inline_size,
82 size_t vtable_offset) {
83 // TODO: Remove/account for any excess allocated memory.
84 internal::ClearSpan(
85 internal::GetSubSpan(buffer_, absolute_offset, inline_size));
86 Set<voffset_t>(FixedVtableOffset() + vtable_offset, 0);
87 }
88
89 template <typename T>
90 const T &Get(size_t absolute_offset) const {
91 return *reinterpret_cast<const T *>(buffer_.data() + absolute_offset);
92 }
93
94 template <typename T>
95 T *MutableGet(size_t absolute_offset) {
96 return reinterpret_cast<T *>(buffer_.data() + absolute_offset);
97 }
98
99 template <typename T>
100 T *GetMutableFlatbuffer() {
101 return reinterpret_cast<T *>(buffer_.data());
102 }
103
104 template <typename T>
105 const T *GetFlatbuffer() const {
106 return reinterpret_cast<const T *>(buffer_.data());
107 }
108
109 private:
110 template <typename T>
111 void Set(size_t absolute_offset, const T &value) {
112 *reinterpret_cast<T *>(buffer_.data() + absolute_offset) = value;
113 }
114};
115
116} // namespace aos::fbs
117#endif // AOS_FLATBUFFERS_STATIC_TABLE_H_