// Copyright 2011-2020 Molecular Matters GmbH, all rights reserved. #pragma once #if LC_VERSION == 1 // BEGIN EPIC MOD #include "CoreTypes.h" // END EPIC MOD #include namespace pointer { // BEGIN EPIC MOD template T As(void* anyPointer); template T As(const void* anyPointer); // END EPIC MOD template T AsInteger(const void* anyPointer) { // unfortunately, conversion from pointers to integers is implementation-defined, which is sign-extended in MSVC and GCC. // this means that e.g. converting directly from void* to uint64_t would sign-extend on 32-bit, which is not what we want. // in order to convert without sign-extension on both 32-bit and 64-bit targets, we need to go via uintptr_t first. return static_cast(reinterpret_cast(anyPointer)); } template To FromInteger(From integer) { // widen integer to width of pointer type first before converting to pointer return reinterpret_cast(static_cast(integer)); } template T AlignBottom(void* anyPointer, size_t alignment) { union { void* as_void; uintptr_t as_uintptr_t; }; as_void = anyPointer; const size_t mask = alignment - 1u; as_uintptr_t &= ~mask; return As(as_void); } template T AlignBottom(const void* anyPointer, size_t alignment) { union { const void* as_void; uintptr_t as_uintptr_t; }; as_void = anyPointer; const size_t mask = alignment - 1u; as_uintptr_t &= ~mask; return As(as_void); } template T AlignTop(void* anyPointer, size_t alignment) { union { void* as_void; uintptr_t as_uintptr_t; }; as_void = anyPointer; const size_t mask = alignment - 1u; as_uintptr_t += mask; as_uintptr_t &= ~mask; return As(as_void); } template T AlignTop(const void* anyPointer, size_t alignment) { union { const void* as_void; uintptr_t as_uintptr_t; }; as_void = anyPointer; const size_t mask = alignment - 1u; as_uintptr_t += mask; as_uintptr_t &= ~mask; return As(as_void); } template T As(void* anyPointer) { // only a check for pointer-type needed here. // T can point to const or non-const type. static_assert(std::is_pointer::value == true, "Expected pointer type"); union { void* as_void; T as_T; }; as_void = anyPointer; return as_T; } template T As(const void* anyPointer) { static_assert(std::is_pointer::value == true, "Expected pointer type"); // enforce T being a pointer to const elements static_assert(std::is_const::type>::value == true, "Wrong cv-qualifiers"); union { const void* as_void; T as_T; }; as_void = anyPointer; return as_T; } template T Offset(void* anyPointer, U howManyBytes) { static_assert(std::is_pointer::value == true, "Expected pointer type"); return As((As(anyPointer) + howManyBytes)); } template T Offset(const void* anyPointer, U howManyBytes) { static_assert(std::is_pointer::value == true, "Expected pointer type"); return As((As(anyPointer) + howManyBytes)); } template T Displacement(const void* from, const void* to) { static_assert(std::is_pointer::value == false, "Expected value type"); return static_cast(As(to) - As(from)); } } #endif // LC_VERSION