@@ -4,52 +4,31 @@ pragma solidity 0.4.19;
4
4
library BytesLib {
5
5
function concat (bytes memory _preBytes , bytes memory _postBytes ) internal pure returns (bytes ) {
6
6
bytes memory tempBytes;
7
-
7
+
8
8
assembly {
9
- // Get a location of some free memory and store it in tempBytes as
10
- // Solidity does for memory variables.
11
9
tempBytes := mload (0x40 )
12
10
13
- // Store the length of the first bytes array at the beginning of
14
- // the memory for tempBytes.
15
11
let length := mload (_preBytes)
16
12
mstore (tempBytes, length)
17
-
18
- // Maintain a memory counter for the current write location in the
19
- // temp bytes array by adding the 32 bytes for the array length to
20
- // the starting location.
13
+
21
14
let mc := add (tempBytes, 0x20 )
22
- // Stop copying when the memory counter reaches the length of the
23
- // first bytes array.
24
15
let end := add (mc, length)
25
-
16
+
26
17
for {
27
- // Initialize a copy counter to the start of the _preBytes data,
28
- // 32 bytes into its memory.
29
18
let cc := add (_preBytes, 0x20 )
30
19
} lt (mc, end) {
31
- // Increase both counters by 32 bytes each iteration.
32
20
mc := add (mc, 0x20 )
33
21
cc := add (cc, 0x20 )
34
22
} {
35
- // Write the _preBytes data into the tempBytes memory 32 bytes
36
- // at a time.
37
23
mstore (mc, mload (cc))
38
24
}
39
-
40
- // Add the length of _postBytes to the current length of tempBytes
41
- // and store it as the new length in the first 32 bytes of the
42
- // tempBytes memory.
25
+
43
26
length := mload (_postBytes)
44
27
mstore (tempBytes, add (length, mload (tempBytes)))
45
-
46
- // Move the memory counter back from a multiple of 0x20 to the
47
- // actual end of the _preBytes data.
28
+
48
29
mc := end
49
- // Stop copying when the memory counter reaches the new combined
50
- // length of the arrays.
51
30
end := add (mc, length)
52
-
31
+
53
32
for {
54
33
let cc := add (_postBytes, 0x20 )
55
34
} lt (mc, end) {
@@ -58,35 +37,21 @@ library BytesLib {
58
37
} {
59
38
mstore (mc, mload (cc))
60
39
}
61
-
62
- // Update the free-memory pointer by padding our last write location
63
- // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
64
- // next 32 byte block, then round down to the nearest multiple of
65
- // 32. If second array's length is a multiple of 32, mc will equal
66
- // end after it's been copied. Add one before rounding down
67
- // to leave a blank 32 bytes.
68
- mstore (0x40 , and (
69
- add (add (end, iszero (sub (mc, end))), 31 ),
70
- not (31 ) // Round down to the nearest 32 bytes.
71
- ))
40
+
41
+ //update free-memory pointer
42
+ //allocating the array padded to 32 bytes like the compiler does now
43
+ //make an additional check for a resulting zero-length array:
44
+ // if (sub - end == 0) then end = end + 1
45
+ mstore (0x40 , and (add (add (end, iszero (sub (mc, end))), 31 ), not (31 )))
72
46
}
73
-
47
+
74
48
return tempBytes;
75
49
}
76
-
50
+
77
51
function concatStorage (bytes storage _preBytes , bytes memory _postBytes ) internal {
78
52
assembly {
79
- // Read the first 32 bytes of _preBytes storage, which is the length
80
- // of the array. (We don't need to use the offset into the slot
81
- // because arrays use the entire slot.)
53
+ // we know _preBytes_offset is 0
82
54
let fslot := sload (_preBytes_slot)
83
- // Arrays of 31 bytes or less have an even value in their slot,
84
- // while longer arrays have an odd value. The actual length is
85
- // the slot divided by two for odd values, and the lowest order
86
- // byte divided by two for even values.
87
- // If the slot is even, bitwise and the slot with 255 and divide by
88
- // two to get the length. If the slot is odd, bitwise and the slot
89
- // with -1 and divide by two.
90
55
let slength := div (and (fslot, sub (mul (0x100 , iszero (and (fslot, 1 ))), 1 )), 2 )
91
56
let mlength := mload (_postBytes)
92
57
let newlength := add (slength, mlength)
@@ -95,15 +60,13 @@ library BytesLib {
95
60
// v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
96
61
switch add (lt (slength, 32 ), lt (newlength, 32 ))
97
62
case 2 {
98
- // Since the new array still fits in the slot, we just need to
99
- // update the contents of the slot.
100
63
// uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
101
64
sstore (
102
65
_preBytes_slot,
103
66
// all the modifications to the slot are inside this
104
67
// next block
105
68
add (
106
- // we can just add to the slot contents because the
69
+ // we can just add to the slot contents because the
107
70
// bytes we want to change are the LSBs
108
71
fslot,
109
72
add (
@@ -126,29 +89,18 @@ library BytesLib {
126
89
)
127
90
}
128
91
case 1 {
129
- // The stored value fits in the slot, but the combined value
130
- // will exceed it.
131
92
// get the keccak hash to get the contents of the array
132
93
mstore (0x0 , _preBytes_slot)
133
94
let sc := add (keccak256 (0x0 , 0x20 ), div (slength, 32 ))
134
-
95
+
135
96
// save new length
136
97
sstore (_preBytes_slot, add (mul (newlength, 2 ), 1 ))
137
-
138
- // The contents of the _postBytes array start 32 bytes into
139
- // the structure. Our first read should obtain the `submod`
140
- // bytes that can fit into the unused space in the last word
141
- // of the stored array. To get this, we read 32 bytes starting
142
- // from `submod`, so the data we read overlaps with the array
143
- // contents by `submod` bytes. Masking the lowest-order
144
- // `submod` bytes allows us to add that value directly to the
145
- // stored value.
146
-
98
+
147
99
let submod := sub (32 , slength)
148
100
let mc := add (_postBytes, submod)
149
101
let end := add (add (_postBytes, 0x20 ), mlength)
150
102
let mask := sub (exp (0x100 , submod), 1 )
151
-
103
+
152
104
sstore (
153
105
sc,
154
106
add (
@@ -159,8 +111,8 @@ library BytesLib {
159
111
and (mload (mc), mask)
160
112
)
161
113
)
162
-
163
- for {
114
+
115
+ for {
164
116
mc := add (mc, 0x20 )
165
117
sc := add (sc, 1 )
166
118
} lt (mc, end) {
@@ -173,23 +125,20 @@ library BytesLib {
173
125
default {
174
126
// get the keccak hash to get the contents of the array
175
127
mstore (0x0 , _preBytes_slot)
176
- // Start copying to the last used word of the stored array.
177
128
let sc := add (keccak256 (0x0 , 0x20 ), div (slength, 32 ))
178
-
129
+
179
130
// save new length
180
131
sstore (_preBytes_slot, add (mul (newlength, 2 ), 1 ))
181
-
182
- // Copy over the first `submod` bytes of the new data as in
183
- // case 1 above.
132
+
184
133
let slengthmod := mod (slength, 32 )
185
134
let submod := sub (32 , slengthmod)
186
135
let mc := add (_postBytes, submod)
187
136
let end := add (mc, mlength)
188
137
let mask := sub (exp (0x100 , submod), 1 )
189
-
138
+
190
139
sstore (sc, add (sload (sc), and (mload (mc), mask)))
191
-
192
- for {
140
+
141
+ for {
193
142
mc := add (mc, 0x20 )
194
143
} lt (mc, end) {
195
144
sc := add (sc, 1 )
@@ -200,32 +149,22 @@ library BytesLib {
200
149
}
201
150
}
202
151
}
203
-
152
+
204
153
function slice (bytes _bytes , uint _start , uint _length ) internal pure returns (bytes ) {
205
154
require (_bytes.length >= (_start + _length));
206
-
155
+
207
156
bytes memory tempBytes;
208
-
157
+
209
158
assembly {
210
159
switch iszero (_length)
211
160
case 0 {
212
- // Get a location of some free memory and store it in tempBytes as
213
- // Solidity does for memory variables.
214
161
tempBytes := mload (0x40 )
215
-
216
- // The first word of the slice result is potentially a partial
217
- // word read from the original array. To read it, we calculate
218
- // the length of that partial word and start copying that many
219
- // bytes into the array. The first word we copy will start with
220
- // data we don't care about, but the last `lengthmod` bytes will
221
- // land at the beginning of the contents of the new array. When
222
- // we're done copying, we overwrite the full first word with
223
- // the actual length of the slice.
162
+
224
163
let lengthmod := and (_length, 31 )
225
-
164
+
226
165
let mc := add (tempBytes, lengthmod)
227
166
let end := add (mc, _length)
228
-
167
+
229
168
for {
230
169
let cc := add (add (_bytes, lengthmod), _start)
231
170
} lt (mc, end) {
@@ -234,9 +173,9 @@ library BytesLib {
234
173
} {
235
174
mstore (mc, mload (cc))
236
175
}
237
-
176
+
238
177
mstore (tempBytes, _length)
239
-
178
+
240
179
//update free-memory pointer
241
180
//allocating the array padded to 32 bytes like the compiler does now
242
181
mstore (0x40 , and (add (mc, 31 ), not (31 )))
@@ -248,29 +187,29 @@ library BytesLib {
248
187
mstore (0x40 , add (tempBytes, 0x20 ))
249
188
}
250
189
}
251
-
190
+
252
191
return tempBytes;
253
192
}
254
-
193
+
255
194
function toAddress (bytes _bytes , uint _start ) internal pure returns (address ) {
256
195
require (_bytes.length >= (_start + 20 ));
257
196
address tempAddress;
258
-
197
+
259
198
assembly {
260
199
tempAddress := div (mload (add (add (_bytes, 0x20 ), _start)), 0x1000000000000000000000000 )
261
200
}
262
-
201
+
263
202
return tempAddress;
264
203
}
265
-
204
+
266
205
function toUint (bytes _bytes , uint _start ) internal pure returns (uint256 ) {
267
206
require (_bytes.length >= (_start + 32 ));
268
207
uint256 tempUint;
269
-
208
+
270
209
assembly {
271
210
tempUint := mload (add (add (_bytes, 0x20 ), _start))
272
211
}
273
-
212
+
274
213
return tempUint;
275
214
}
276
215
@@ -283,7 +222,7 @@ library BytesLib {
283
222
// if lengths don't match the arrays are not equal
284
223
switch eq (length, mload (_postBytes))
285
224
case 1 {
286
- // cb is a circuit breaker in the for loop since there's
225
+ // cb is a circuit breaker in the for loop since there's
287
226
// no said feature for inline assembly loops
288
227
// cb = 1 - don't breaker
289
228
// cb = 0 - break
@@ -323,7 +262,6 @@ library BytesLib {
323
262
assembly {
324
263
// we know _preBytes_offset is 0
325
264
let fslot := sload (_preBytes_slot)
326
- // Decode the length of the stored array like in concatStorage().
327
265
let slength := div (and (fslot, sub (mul (0x100 , iszero (and (fslot, 1 ))), 1 )), 2 )
328
266
let mlength := mload (_postBytes)
329
267
@@ -345,7 +283,7 @@ library BytesLib {
345
283
}
346
284
}
347
285
default {
348
- // cb is a circuit breaker in the for loop since there's
286
+ // cb is a circuit breaker in the for loop since there's
349
287
// no said feature for inline assembly loops
350
288
// cb = 1 - don't breaker
351
289
// cb = 0 - break
@@ -354,7 +292,7 @@ library BytesLib {
354
292
// get the keccak hash to get the contents of the array
355
293
mstore (0x0 , _preBytes_slot)
356
294
let sc := keccak256 (0x0 , 0x20 )
357
-
295
+
358
296
let mc := add (_postBytes, 0x20 )
359
297
let end := add (mc, mlength)
360
298
0 commit comments