Submission d214e10c...

ChallengeHex decoder
Submitter0xabcdef0db461f2f...
Submitted at2018-28-31
Gas used427367
/**
 * 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/
 */

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) public pure returns(bytes output) {
        bytes memory input_bytes = bytes(input);
        uint output_length = input_bytes.length / 2;
        bytes memory output_bytes = new bytes(output_length);
        if (output_length < 96) {
            decode_less(input_bytes, output_bytes);
        } else {
            decode_more(input_bytes, output_bytes);
        }
        return output_bytes;
    }

    function decode_less(bytes memory input_bytes, bytes memory output_bytes) internal pure {
        byte tmpByte;
        uint tmpUint;
        assembly {
            let inptr := add(input_bytes, 0x20)
            let outptr := add(output_bytes, 0x20)
            let outlen := mload(output_bytes)
            let outptrEnd := add(outptr, outlen)
            let tmp
            for { } lt(outptr, outptrEnd) { } {

                tmpByte := mload(add(inptr, 1))
                mstore(0x1f, tmpByte)
                tmp := mload(0x0)

                switch add(lt(tmp, 58), lt(tmp, 71))
                case 2 { tmp := sub(tmp, 48)}
                case 1 { tmp := sub(tmp, 55)}
                default { tmp := sub(tmp, 87)}

                tmpUint := tmp

                tmpByte := mload(inptr)
                mstore(0x1f, tmpByte)
                tmp := mload(0x0)

                tmp := add(tmpUint, mul(tmp, 16))

                switch add(lt(tmp, 928), lt(tmp, 1136))
                case 2 { tmp := sub(tmp, 768)}
                case 1 { tmp := sub(tmp, 880)}
                default { tmp := sub(tmp, 1392)}

                tmpUint := tmp

                mstore8(outptr, tmpUint)

                inptr := add(inptr, 0x2)
                outptr := add(outptr, 0x1)
            }
        }
    }

    function decode_more(bytes memory input_bytes, bytes memory output_bytes) internal pure {
        uint[103] memory dict = [
            uint(0),
             0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
             0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
             0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
           0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9,   0,   0,   0,   0,   0,   0,   0,
           0xa, 0xb, 0xc, 0xd, 0xe, 0xf,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
             0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
           0xa, 0xb, 0xc, 0xd, 0xe, 0xf];
        byte tmpByte;
        uint tmpUint;
        assembly {
            let inptr := add(input_bytes, 0x20)
            let outptr := add(output_bytes, 0x20)
            let outlen := mload(output_bytes)
            let outptrEnd := add(outptr, outlen)
            for { } lt(outptr, outptrEnd) { } {

                tmpByte:= mload(inptr)
                mstore(0x1f, tmpByte)

                tmpUint := mul(mload(add(dict, mul(0x20, mload(0x0)))), 16)
                inptr := add(inptr, 0x1)

                tmpByte:= mload(inptr)
                mstore(0x1f, tmpByte)

                tmpUint := add(tmpUint, mload(add(dict, mul(0x20, mload(0x0)))))
                inptr := add(inptr, 0x1)

                mstore8(outptr, tmpUint)

                outptr := add(outptr, 0x1)
            }
        }
    }
}