Submission 3473c1fc...
contract HexDecoder {
function decode(string /* input */) pure public returns(bytes) {
assembly {
// WARNING! This is NOT safe. For the purpose of this contest I
// am assuming the ABI pointer to the dynamic slot is
// 32, but that is not, in general, safe to assume
let offset := 68
let length := calldataload(36)
let end := add(68, length)
// Output length
length := div(length, 2)
// Allocate memory for the response
let output := mload(0x40)
let outputLength := and(add(length, 95), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0)
let outOffset := add(output, 64)
// Should do this, to update free-memory pointer, but since we aren't using any Solidity
// this is safe to leave
//mstore(0x40, add(output, outputLength))
// Pointer to the dynamic slot for the bytes
mstore(output, 0x20)
// Length of the bytes (half the length)
mstore(add(output, 32), length)
let data := calldataload(offset)
for { } lt(offset, end) { } {
//data := calldataload(offset)
// For letters, the 7th bit is high; n0 is 0x90 for letters 0x00 for numbers
let n0 := and(data, 0x4040404040404040404040404040404040404040404040404040404040404040)
n0 := or(add(n0, n0), div(n0, 4))
// Move the data over 1 nibble
data := mul(data, 0x10)
// Take the lowest nibble from each ascii character (upper nibble since we shifted)
// 0-9: already the correct value
// A-F: add 9 to the value to offset A (1) -> 10, etc
data := and(data, 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0)
data := add(n0, data)
// Shift all nibbles over to the left and odd nibbles into their neighbour
// (odd bytes become junk)
data := or(data, mul(data, 0x10))
// Remove the spaces in the output by chunking
data := and(data, 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00)
data := or(data, mul(data, 0x100))
data := and(data, 0xffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000)
data := or(data, mul(data, 0x10000))
data := and(data, 0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000)
data := or(data, mul(data, 0x100000000))
data := and(data, 0xffffffffffffffff0000000000000000ffffffffffffffff0000000000000000)
data := or(data, mul(data, 0x10000000000000000))
mstore(outOffset, data)
outOffset := add(outOffset, 16)
offset := add(offset, 0x20)
data := calldataload(offset)
}
return(output, outputLength)
}
}
}