@@ -4,52 +4,31 @@ pragma solidity 0.4.19;
44library BytesLib {
55 function concat (bytes memory _preBytes , bytes memory _postBytes ) internal pure returns (bytes ) {
66 bytes memory tempBytes;
7-
7+
88 assembly {
9- // Get a location of some free memory and store it in tempBytes as
10- // Solidity does for memory variables.
119 tempBytes := mload (0x40 )
1210
13- // Store the length of the first bytes array at the beginning of
14- // the memory for tempBytes.
1511 let length := mload (_preBytes)
1612 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+
2114 let mc := add (tempBytes, 0x20 )
22- // Stop copying when the memory counter reaches the length of the
23- // first bytes array.
2415 let end := add (mc, length)
25-
16+
2617 for {
27- // Initialize a copy counter to the start of the _preBytes data,
28- // 32 bytes into its memory.
2918 let cc := add (_preBytes, 0x20 )
3019 } lt (mc, end) {
31- // Increase both counters by 32 bytes each iteration.
3220 mc := add (mc, 0x20 )
3321 cc := add (cc, 0x20 )
3422 } {
35- // Write the _preBytes data into the tempBytes memory 32 bytes
36- // at a time.
3723 mstore (mc, mload (cc))
3824 }
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+
4326 length := mload (_postBytes)
4427 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+
4829 mc := end
49- // Stop copying when the memory counter reaches the new combined
50- // length of the arrays.
5130 end := add (mc, length)
52-
31+
5332 for {
5433 let cc := add (_postBytes, 0x20 )
5534 } lt (mc, end) {
@@ -58,35 +37,21 @@ library BytesLib {
5837 } {
5938 mstore (mc, mload (cc))
6039 }
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 )))
7246 }
73-
47+
7448 return tempBytes;
7549 }
76-
50+
7751 function concatStorage (bytes storage _preBytes , bytes memory _postBytes ) internal {
7852 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
8254 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.
9055 let slength := div (and (fslot, sub (mul (0x100 , iszero (and (fslot, 1 ))), 1 )), 2 )
9156 let mlength := mload (_postBytes)
9257 let newlength := add (slength, mlength)
@@ -95,15 +60,13 @@ library BytesLib {
9560 // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
9661 switch add (lt (slength, 32 ), lt (newlength, 32 ))
9762 case 2 {
98- // Since the new array still fits in the slot, we just need to
99- // update the contents of the slot.
10063 // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
10164 sstore (
10265 _preBytes_slot,
10366 // all the modifications to the slot are inside this
10467 // next block
10568 add (
106- // we can just add to the slot contents because the
69+ // we can just add to the slot contents because the
10770 // bytes we want to change are the LSBs
10871 fslot,
10972 add (
@@ -126,29 +89,18 @@ library BytesLib {
12689 )
12790 }
12891 case 1 {
129- // The stored value fits in the slot, but the combined value
130- // will exceed it.
13192 // get the keccak hash to get the contents of the array
13293 mstore (0x0 , _preBytes_slot)
13394 let sc := add (keccak256 (0x0 , 0x20 ), div (slength, 32 ))
134-
95+
13596 // save new length
13697 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+
14799 let submod := sub (32 , slength)
148100 let mc := add (_postBytes, submod)
149101 let end := add (add (_postBytes, 0x20 ), mlength)
150102 let mask := sub (exp (0x100 , submod), 1 )
151-
103+
152104 sstore (
153105 sc,
154106 add (
@@ -159,8 +111,8 @@ library BytesLib {
159111 and (mload (mc), mask)
160112 )
161113 )
162-
163- for {
114+
115+ for {
164116 mc := add (mc, 0x20 )
165117 sc := add (sc, 1 )
166118 } lt (mc, end) {
@@ -173,23 +125,20 @@ library BytesLib {
173125 default {
174126 // get the keccak hash to get the contents of the array
175127 mstore (0x0 , _preBytes_slot)
176- // Start copying to the last used word of the stored array.
177128 let sc := add (keccak256 (0x0 , 0x20 ), div (slength, 32 ))
178-
129+
179130 // save new length
180131 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+
184133 let slengthmod := mod (slength, 32 )
185134 let submod := sub (32 , slengthmod)
186135 let mc := add (_postBytes, submod)
187136 let end := add (mc, mlength)
188137 let mask := sub (exp (0x100 , submod), 1 )
189-
138+
190139 sstore (sc, add (sload (sc), and (mload (mc), mask)))
191-
192- for {
140+
141+ for {
193142 mc := add (mc, 0x20 )
194143 } lt (mc, end) {
195144 sc := add (sc, 1 )
@@ -200,32 +149,22 @@ library BytesLib {
200149 }
201150 }
202151 }
203-
152+
204153 function slice (bytes _bytes , uint _start , uint _length ) internal pure returns (bytes ) {
205154 require (_bytes.length >= (_start + _length));
206-
155+
207156 bytes memory tempBytes;
208-
157+
209158 assembly {
210159 switch iszero (_length)
211160 case 0 {
212- // Get a location of some free memory and store it in tempBytes as
213- // Solidity does for memory variables.
214161 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+
224163 let lengthmod := and (_length, 31 )
225-
164+
226165 let mc := add (tempBytes, lengthmod)
227166 let end := add (mc, _length)
228-
167+
229168 for {
230169 let cc := add (add (_bytes, lengthmod), _start)
231170 } lt (mc, end) {
@@ -234,9 +173,9 @@ library BytesLib {
234173 } {
235174 mstore (mc, mload (cc))
236175 }
237-
176+
238177 mstore (tempBytes, _length)
239-
178+
240179 //update free-memory pointer
241180 //allocating the array padded to 32 bytes like the compiler does now
242181 mstore (0x40 , and (add (mc, 31 ), not (31 )))
@@ -248,29 +187,29 @@ library BytesLib {
248187 mstore (0x40 , add (tempBytes, 0x20 ))
249188 }
250189 }
251-
190+
252191 return tempBytes;
253192 }
254-
193+
255194 function toAddress (bytes _bytes , uint _start ) internal pure returns (address ) {
256195 require (_bytes.length >= (_start + 20 ));
257196 address tempAddress;
258-
197+
259198 assembly {
260199 tempAddress := div (mload (add (add (_bytes, 0x20 ), _start)), 0x1000000000000000000000000 )
261200 }
262-
201+
263202 return tempAddress;
264203 }
265-
204+
266205 function toUint (bytes _bytes , uint _start ) internal pure returns (uint256 ) {
267206 require (_bytes.length >= (_start + 32 ));
268207 uint256 tempUint;
269-
208+
270209 assembly {
271210 tempUint := mload (add (add (_bytes, 0x20 ), _start))
272211 }
273-
212+
274213 return tempUint;
275214 }
276215
@@ -283,7 +222,7 @@ library BytesLib {
283222 // if lengths don't match the arrays are not equal
284223 switch eq (length, mload (_postBytes))
285224 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
287226 // no said feature for inline assembly loops
288227 // cb = 1 - don't breaker
289228 // cb = 0 - break
@@ -323,7 +262,6 @@ library BytesLib {
323262 assembly {
324263 // we know _preBytes_offset is 0
325264 let fslot := sload (_preBytes_slot)
326- // Decode the length of the stored array like in concatStorage().
327265 let slength := div (and (fslot, sub (mul (0x100 , iszero (and (fslot, 1 ))), 1 )), 2 )
328266 let mlength := mload (_postBytes)
329267
@@ -345,7 +283,7 @@ library BytesLib {
345283 }
346284 }
347285 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
349287 // no said feature for inline assembly loops
350288 // cb = 1 - don't breaker
351289 // cb = 0 - break
@@ -354,7 +292,7 @@ library BytesLib {
354292 // get the keccak hash to get the contents of the array
355293 mstore (0x0 , _preBytes_slot)
356294 let sc := keccak256 (0x0 , 0x20 )
357-
295+
358296 let mc := add (_postBytes, 0x20 )
359297 let end := add (mc, mlength)
360298
0 commit comments