You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
5.4 KiB
Solidity
188 lines
5.4 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
|
|
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);
|
|
}
|
|
|
|
// Allocates 'numBytes' bytes in memory. This will prevent the Solidity compiler
|
|
// from using this area of memory. It will also initialize the area by setting
|
|
// each byte to '0'.
|
|
function allocate(uint256 numBytes) internal pure returns (uint256 addr) {
|
|
// Take the current value of the free memory pointer, and update.
|
|
assembly {
|
|
addr := mload(
|
|
/*FREE_MEM_PTR*/
|
|
0x40
|
|
)
|
|
mstore(
|
|
/*FREE_MEM_PTR*/
|
|
0x40,
|
|
add(addr, numBytes)
|
|
)
|
|
}
|
|
uint256 words = (numBytes + WORD_SIZE - 1) / WORD_SIZE;
|
|
for (uint256 i = 0; i < words; i++) {
|
|
assembly {
|
|
mstore(
|
|
add(
|
|
addr,
|
|
mul(
|
|
i,
|
|
/*WORD_SIZE*/
|
|
32
|
|
)
|
|
),
|
|
0
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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
|
|
// Reverse copy to prevent out of memory bound error
|
|
src = src + len;
|
|
dest = dest + len;
|
|
for (; len >= WORD_SIZE; len -= WORD_SIZE) {
|
|
dest -= WORD_SIZE;
|
|
src -= WORD_SIZE;
|
|
|
|
assembly {
|
|
mstore(dest, mload(src))
|
|
}
|
|
}
|
|
|
|
if (len == 0) {
|
|
return;
|
|
}
|
|
|
|
// Copy remaining bytes
|
|
src = src - len;
|
|
dest = dest - len;
|
|
assembly {
|
|
mstore(dest, mload(src))
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
/*
|
|
// Get the byte stored at memory address 'addr' as a 'byte'.
|
|
function toByte(uint addr, uint8 index) internal pure returns (byte b) {
|
|
require(index < WORD_SIZE);
|
|
uint8 n;
|
|
assembly {
|
|
n := byte(index, mload(addr))
|
|
}
|
|
b = byte(n);
|
|
}
|
|
*/
|
|
}
|