// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; library Memory { // Size of a word, in bytes. uint256 internal constant WORD_SIZE = 32; // Size of the header of a 'bytes' array. uint256 internal constant BYTES_HEADER_SIZE = 32; // Address of the free memory pointer. uint256 internal constant FREE_MEM_PTR = 0x40; // Compares the 'len' bytes starting at address 'addr' in memory with the 'len' // bytes starting at 'addr2'. // Returns 'true' if the bytes are the same, otherwise 'false'. function equals(uint256 addr, uint256 addr2, uint256 len) internal pure returns (bool equal) { assembly { equal := eq(keccak256(addr, len), keccak256(addr2, len)) } } // Compares the 'len' bytes starting at address 'addr' in memory with the bytes stored in // 'bts'. It is allowed to set 'len' to a lower value then 'bts.length', in which case only // the first 'len' bytes will be compared. // Requires that 'bts.length >= len' function equals(uint256 addr, uint256 len, bytes memory bts) internal pure returns (bool equal) { require(bts.length >= len); uint256 addr2; assembly { addr2 := add(bts, /*BYTES_HEADER_SIZE*/ 32) } return equals(addr, addr2, len); } function compareStrings(string memory a, string memory b) internal pure returns (bool) { return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)))); } // Copy 'len' bytes from memory address 'src', to address 'dest'. // This function does not check the or destination, it only copies // the bytes. function copy(uint256 src, uint256 dest, uint256 len) internal pure { // Copy word-length chunks while possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } dest += WORD_SIZE; src += WORD_SIZE; } // Copy remaining bytes uint256 mask; unchecked { mask = 256 ** (WORD_SIZE - len) - 1; } assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } // Returns a memory pointer to the provided bytes array. function ptr(bytes memory bts) internal pure returns (uint256 addr) { assembly { addr := bts } } // Returns a memory pointer to the data portion of the provided bytes array. function dataPtr(bytes memory bts) internal pure returns (uint256 addr) { assembly { addr := add(bts, /*BYTES_HEADER_SIZE*/ 32) } } // This function does the same as 'dataPtr(bytes memory)', but will also return the // length of the provided bytes array. function fromBytes(bytes memory bts) internal pure returns (uint256 addr, uint256 len) { len = bts.length; assembly { addr := add(bts, /*BYTES_HEADER_SIZE*/ 32) } } // Creates a 'bytes memory' variable from the memory address 'addr', with the // length 'len'. The function will allocate new memory for the bytes array, and // the 'len bytes starting at 'addr' will be copied into that new memory. function toBytes(uint256 addr, uint256 len) internal pure returns (bytes memory bts) { bts = new bytes(len); uint256 btsptr; assembly { btsptr := add(bts, /*BYTES_HEADER_SIZE*/ 32) } copy(addr, btsptr, len); } // Get the word stored at memory address 'addr' as a 'uint'. function toUint(uint256 addr) internal pure returns (uint256 n) { assembly { n := mload(addr) } } // Get the word stored at memory address 'addr' as a 'bytes32'. function toBytes32(uint256 addr) internal pure returns (bytes32 bts) { assembly { bts := mload(addr) } } }