Submission f0fedcfb...

ChallengeHex decoder
Submitterricmoo.firefly.eth
Submitted at2018-50-26
Gas used41017
/**
 * This file is part of the 1st Solidity Gas Golfing Contest.
 *
 * This work is licensed under Creative Commons Attribution ShareAlike 3.0.
 * https://creativecommons.org/licenses/by-sa/3.0/
 *
 * Author: Richard Moore <[email protected]>
 * Date: May 23, 2018
 */


pragma solidity 0.4.24;

contract HexDecoder {

    /**
     * @dev Decodes a hex-encoded input string, returning it in binary.
     *
     * Input strings may be of any length, but will always be a multiple of two
     * bytes long, and will not contain any non-hexadecimal characters.
     *
     * @param input The hex-encoded input.
     * @return The decoded output.
     */

    function decode(string input) pure public returns(bytes output) {
        output = bytes(input);

        assembly {
          let offset := add(output, 32)
          let length := mload(output)
          let end := add(offset, length)

          // The output length is half the input length
          mstore(output, div(length, 2))

          let outOffset := offset
          for { } lt(offset, end) { } {

            let data := mload(offset)

            // For letters, the 7th bit is high; create 9 if set
            let n0 := and(0x4040404040404040404040404040404040404040404040404040404040404040, data)
            n0 := or(div(n0, 8), div(n0, 64))

            // Take the lowest nibble from each ascii character
            // 0-9: already the correct value
            // A-F: add 9 to the value to offset A (1) -> 10, etc
            data := and(0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f, data)
            data := add(n0, data)

            // Shift all nibbles over to the left and odd nibbles into their neighbour
            // (odd bytes become junk)
            data := or(mul(data, 16), mul(data, 256))

            // 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)
          }
        }
    }
}