Submission 8506d454...

ChallengeHex decoder
Submitterhyszeth.eth
Submitted at2018-57-26
Gas used1167931
/**
 * 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) {
        uint inputLen = bytes(input).length;
        if(inputLen == 0) return output;

        // Assumption: all competition inputs are multiples of 2 (this assumption saves gas)
        output = new bytes(inputLen / 2); // +1 because we need to round up
        uint j = 0;
        uint8 left;
        uint8 right;
        for(uint i = 0; i + 1 < inputLen; i += 2) {
            // Get half-bytes
            left = getHalfOfByte(uint8(bytes(input)[i]));
            right = getHalfOfByte(uint8(bytes(input)[i+1]));
            // Combine left & right into one whole byte
            output[j++] = byte(left * 16 + right);
        }
    }

    function getHalfOfByte(uint8 hexLetter) internal pure returns (uint8) {
        // We do conversions based on UTF8 byte representations
        // 0x3A=UTF8(9)+1 and 0x47 = UTF8(F)+1 (see https://en.wikipedia.org/wiki/UTF-8)
        // Decode left half of byte
        uint8 byte0 = uint8(byte('0'));
        uint8 byteBigA = (uint8(byte('A')) - 10);
        uint8 byteSmallA = (uint8(byte('a')) - 10);
        if(hexLetter < 0x3A) {
            // 0-9
            return hexLetter - byte0;
        } else if(hexLetter < 0x47) {
            // A-F
            return hexLetter - byteBigA;
        }
        // a-f
        return hexLetter - byteSmallA;
    }
}