1#pragma once
2
3#include <cstring>
4
5#include <basis/seadTypes.h>
6
7namespace sead
8{
9// This does not actually seem to exist in Nintendo's sead, but for convenience reasons and to
10// easily avoid UB let's pretend this exists.
11namespace BitUtil
12{
13inline void* addOffset(const void* ptr, intptr_t offset)
14{
15 return reinterpret_cast<void*>(uintptr_t(ptr) + offset);
16}
17
18// Convenience function to avoid UB.
19// Nintendo appears to perform type punning, but we care about UB.
20template <typename To, typename From>
21inline To bitCast(From value)
22{
23 static_assert(sizeof(To) == sizeof(From), "To and From must have the same size");
24 To result;
25 std::memcpy(&result, &value, sizeof(value));
26 return result;
27}
28
29// Convenience function to avoid UB.
30// Nintendo appears to perform type punning, but we care about UB.
31template <typename To>
32inline To bitCastPtr(const void* value, intptr_t offset = 0)
33{
34 To result;
35 std::memcpy(&result, addOffset(ptr: value, offset), sizeof(To));
36 return result;
37}
38
39// Convenience function to avoid UB.
40// Nintendo appears to perform type punning, but we care about UB.
41template <typename To, typename From>
42inline void bitCastWrite(const From& value, To* ptr)
43{
44 static_assert(sizeof(To) == sizeof(From), "To and From must have the same size");
45 std::memcpy(ptr, &value, sizeof(To));
46}
47} // namespace BitUtil
48} // namespace sead
49