forked from ethereum/solidity-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMemory.sol
136 lines (121 loc) · 4.64 KB
/
Memory.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
pragma solidity ^0.4.16;
pragma experimental "v0.5.0";
pragma experimental "ABIEncoderV2";
library Memory {
// Size of a word, in bytes.
uint internal constant WORD_SIZE = 32;
// Size of the header of a 'bytes' array.
uint internal constant BYTES_HEADER_SIZE = 32;
// Address of the free memory pointer.
uint 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(uint addr, uint addr2, uint 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(uint addr, uint len, bytes memory bts) internal pure returns (bool equal) {
require(bts.length >= len);
uint 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(uint numBytes) internal pure returns (uint 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))
}
uint words = (numBytes + WORD_SIZE - 1) / WORD_SIZE;
for (uint 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(uint src, uint dest, uint 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
uint 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 (uint 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 (uint 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 (uint addr, uint 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(uint addr, uint len) internal pure returns (bytes memory bts) {
bts = new bytes(len);
uint 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(uint addr) internal pure returns (uint n) {
assembly {
n := mload(addr)
}
}
// Get the word stored at memory address 'addr' as a 'bytes32'.
function toBytes32(uint 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);
}
*/
}