#pragma once 
 | 
#include <stdint.h> 
 | 
#include "xxhash.h" 
 | 
  
 | 
namespace il2cpp 
 | 
{ 
 | 
namespace utils 
 | 
{ 
 | 
    class MemoryUtils 
 | 
    { 
 | 
    public: 
 | 
        IL2CPP_NO_INLINE inline static int MemoryCompareByteByByte(const uint8_t* left, const uint8_t* right, size_t size) 
 | 
        { 
 | 
            for (size_t i = 0; i < size; i++) 
 | 
            { 
 | 
                uint8_t leftItem = left[i]; 
 | 
                uint8_t rightItem = right[i]; 
 | 
  
 | 
                if (leftItem != rightItem) 
 | 
                { 
 | 
                    if (leftItem < rightItem) 
 | 
                        return -1; 
 | 
  
 | 
                    return 1; 
 | 
                } 
 | 
            } 
 | 
  
 | 
            return 0; 
 | 
        } 
 | 
  
 | 
        inline static int MemoryCompare(const void* left, const void* right, size_t size) 
 | 
        { 
 | 
            const uint8_t* leftBytes = static_cast<const uint8_t*>(left); 
 | 
            const uint8_t* rightBytes = static_cast<const uint8_t*>(right); 
 | 
            ptrdiff_t leftUnalignedByteCount = (reinterpret_cast<intptr_t>(leftBytes + 3) & ~3) - reinterpret_cast<intptr_t>(leftBytes); 
 | 
            ptrdiff_t rightUnalignedByteCount = (reinterpret_cast<intptr_t>(rightBytes + 3) & ~3) - reinterpret_cast<intptr_t>(rightBytes); 
 | 
  
 | 
            // Memory is aligned differently, so the best we can do is byte by byte comparison 
 | 
            if (leftUnalignedByteCount != rightUnalignedByteCount) 
 | 
                return MemoryCompareByteByByte(leftBytes, rightBytes, size); 
 | 
  
 | 
            // Memory is aligned at same size of 4 boundaries, but the start is not at size of 4 alignment 
 | 
            // In this case, we will scan first unaligned number of bytes and then continue with scanning multiples of 4 
 | 
            if (leftUnalignedByteCount != 0) 
 | 
            { 
 | 
                int unalignedMemoryCompare = MemoryCompareByteByByte(leftBytes, rightBytes, leftUnalignedByteCount); 
 | 
                if (unalignedMemoryCompare != 0) 
 | 
                    return unalignedMemoryCompare; 
 | 
  
 | 
                leftBytes += leftUnalignedByteCount; 
 | 
                rightBytes += leftUnalignedByteCount; 
 | 
                size -= leftUnalignedByteCount; 
 | 
            } 
 | 
  
 | 
            size_t count4 = size / 4; 
 | 
            for (size_t i = 0; i < count4; i++) 
 | 
            { 
 | 
                uint32_t leftItem = reinterpret_cast<const uint32_t*>(leftBytes)[i]; 
 | 
                uint32_t rightItem = reinterpret_cast<const uint32_t*>(rightBytes)[i]; 
 | 
  
 | 
                if (leftItem != rightItem) 
 | 
                { 
 | 
                    if (leftItem < rightItem) 
 | 
                        return -1; 
 | 
  
 | 
                    return 1; 
 | 
                } 
 | 
            } 
 | 
  
 | 
            size_t offset = count4 * 4; 
 | 
            return MemoryCompareByteByByte(leftBytes + offset, rightBytes + offset, size - offset); 
 | 
        } 
 | 
  
 | 
        inline static void* MemorySet(void* targetMemory, int value, size_t size) 
 | 
        { 
 | 
            uint8_t* ptr = static_cast<uint8_t*>(targetMemory); 
 | 
            for (size_t i = 0; i != size; i++) 
 | 
            { 
 | 
                ptr[i] = static_cast<uint8_t>(value); 
 | 
            } 
 | 
  
 | 
            return targetMemory; 
 | 
        } 
 | 
  
 | 
        inline static void MemoryCopyByteByByte(uint8_t* target, const uint8_t* source, size_t size) 
 | 
        { 
 | 
            for (size_t i = 0; i < size; i++) 
 | 
                target[i] = source[i]; 
 | 
        } 
 | 
  
 | 
        inline static void* MemoryCopy(void* target, const void* source, size_t size) 
 | 
        { 
 | 
            uint8_t* targetBytes = static_cast<uint8_t*>(target); 
 | 
            const uint8_t* sourceBytes = static_cast<const uint8_t*>(source); 
 | 
            ptrdiff_t targetUnalignedByteCount = (reinterpret_cast<intptr_t>(targetBytes + 3) & ~3) - reinterpret_cast<intptr_t>(targetBytes); 
 | 
            ptrdiff_t sourceUnalignedByteCount = (reinterpret_cast<intptr_t>(sourceBytes + 3) & ~3) - reinterpret_cast<intptr_t>(sourceBytes); 
 | 
  
 | 
            // Memory is aligned differently, so the best we can do is byte by byte copy 
 | 
            if (targetUnalignedByteCount != sourceUnalignedByteCount) 
 | 
            { 
 | 
                MemoryCopyByteByByte(targetBytes, sourceBytes, size); 
 | 
                return targetBytes; 
 | 
            } 
 | 
  
 | 
            // Memory is aligned at same size of 4 boundaries, but the start is not at size of 4 alignment 
 | 
            // In this case, we will copy first unaligned number of bytes and then continue with copying multiples of 4 
 | 
            if (targetUnalignedByteCount != 0) 
 | 
            { 
 | 
                MemoryCopyByteByByte(targetBytes, sourceBytes, targetUnalignedByteCount); 
 | 
  
 | 
                targetBytes += targetUnalignedByteCount; 
 | 
                sourceBytes += targetUnalignedByteCount; 
 | 
                size -= targetUnalignedByteCount; 
 | 
            } 
 | 
  
 | 
            size_t count4 = size / 4; 
 | 
  
 | 
            const uint32_t* source32 = reinterpret_cast<const uint32_t*>(sourceBytes); 
 | 
            uint32_t* target32 = reinterpret_cast<uint32_t*>(targetBytes); 
 | 
  
 | 
            for (size_t i = 0; i < count4; i++) 
 | 
                target32[i] = source32[i]; 
 | 
  
 | 
            size_t offset = count4 * 4; 
 | 
            MemoryCopyByteByByte(targetBytes + offset, sourceBytes + offset, size - offset); 
 | 
  
 | 
            return target; 
 | 
        } 
 | 
  
 | 
        template<typename T> 
 | 
        static int32_t MemCmpRef(T* left, T* right) 
 | 
        { 
 | 
            return MemoryCompare(left, right, sizeof(T)); 
 | 
        } 
 | 
  
 | 
#if IL2CPP_TINY 
 | 
        template<typename T> 
 | 
        static int32_t MemHashRef(T* val) 
 | 
        { 
 | 
            return XXH32(val, sizeof(T), 0x8f37154b); 
 | 
        } 
 | 
  
 | 
#endif 
 | 
    }; 
 | 
#define DECL_MEMCMP_NUM(typ) template<> inline int32_t MemoryUtils::MemCmpRef<typ>(typ* left, typ* right) { return (*right > *left) ? -1 : (*right < *left) ? 1 : 0; } 
 | 
    DECL_MEMCMP_NUM(int8_t) 
 | 
    DECL_MEMCMP_NUM(int16_t) 
 | 
    DECL_MEMCMP_NUM(int32_t) 
 | 
    DECL_MEMCMP_NUM(int64_t) 
 | 
    DECL_MEMCMP_NUM(uint8_t) 
 | 
    DECL_MEMCMP_NUM(uint16_t) 
 | 
    DECL_MEMCMP_NUM(uint32_t) 
 | 
    DECL_MEMCMP_NUM(uint64_t) 
 | 
    // don't think this will give the right result for NaNs and such 
 | 
    DECL_MEMCMP_NUM(float) 
 | 
    DECL_MEMCMP_NUM(double) 
 | 
#undef DECL_MEMCMP_NUM 
 | 
  
 | 
#define DECL_MEMHASH_NUM(typ) template<> inline int32_t MemoryUtils::MemHashRef(typ* val) { return (int32_t)(*val); } 
 | 
    DECL_MEMHASH_NUM(int8_t) 
 | 
    DECL_MEMHASH_NUM(int16_t) 
 | 
    DECL_MEMHASH_NUM(int32_t) 
 | 
    DECL_MEMHASH_NUM(uint8_t) 
 | 
    DECL_MEMHASH_NUM(uint16_t) 
 | 
    DECL_MEMHASH_NUM(uint32_t) 
 | 
    DECL_MEMHASH_NUM(float) 
 | 
#undef DECL_MEMHASH_NUM 
 | 
  
 | 
    template<> inline int32_t MemoryUtils::MemHashRef(int64_t* val) { int64_t k = *val; return (int32_t)(k & 0xffffffff) ^ (int32_t)((k >> 32) & 0xffffffff); } 
 | 
    template<> inline int32_t MemoryUtils::MemHashRef(uint64_t* val) { return MemHashRef(reinterpret_cast<int64_t*>(val)); } 
 | 
    template<> inline int32_t MemoryUtils::MemHashRef(double* val) { return MemHashRef(reinterpret_cast<int64_t*>(val)); } 
 | 
} // namespace utils 
 | 
} // namespace il2cpp 
 |