I'm trying to process structures which are contained in a file mapping. One of the challenges I'm facing is that some structures have pointers which need a function to get the correct value. It's important that the layout and size of the structure stay the same, and I'm using c++20.
My current solution is as follows. I have a private data structure, and store the member offsets in a public subclass. The template factory method uses this array of offsets to fix up any pointers.
struct _Data {
uint32_t flags;
uint64_t ptr1;
uint64_t ptr2;
};
struct Data : public {
constexpr static std::size_t PTRS[] = {
offsetof(_Data, ptr1),
offsetof(_Data, ptr2)
};
};
template <class T> T GetStructure(uint64_t addr) {
// Converts the "virtual address" to a pointer in the file mapping
T temp = *(T *)context.translateAddr(addr);
for (auto offset : T::PTRS) {
uint64_t *member = (uint8_t *)temp + offset;
*member = context.getPointer(addr + offset);
}
return temp;
}
I found a similar question here dealing with serialization, which also stores metadata about members in a list.
My main gripe with my solution is how I need to split a definition into two structures. It would be great if I could contain everything within its own definition.
Other solutions I thought were,
- Somehow "mark" a member in a way the factory method can detect.
- Using a function to return a vector of offsets. This would solve the two definitions problem, but I'm concerned about the performance of constantly calling a function and return a vector.
- Using a constexpr function to return a
std::array
. Faster than returning a vector for sure, but probably slower than a constexpr list like the one shown above. - I can make a separate templated function which returns a a vector of offsets given the structure, but this seems to combine worst of both worlds.