Submission 0165e532...

ChallengeHex decoder
Submitterwicketh.eth
Submitted at2018-40-08
Gas used1362251
pragma solidity ^0.4.23;

contract HexDecoder {

    uint256 constant lowNibs = 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F;
    uint256 constant bit1 = 0x0101010101010101010101010101010101010101010101010101010101010101;
    uint256 constant byten1 = 0x0FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF0;
    uint256 constant byten2 = 0x0FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000;
    uint256 constant byten3 = 0x0FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF0000000;
    uint256 constant byten4 = 0x0FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF000000000000000;
    
    uint256 constant f1 = 0x11;
    uint256 constant f2 = 0x101;
    uint256 constant f3 = 0x10001;
    uint256 constant f4 = 0x100000001;
    uint256 constant f5 = 0x100000000000000010;
    
    function decode(string input)
        public pure
        returns(bytes output)
    {
        uint256 ol = bytes(input).length / 2;
        output = new bytes(ol);
        uint256 i = 0;
        uint256 j = 0;
        if (ol > 15) {
            for (; i < ol - 15; ) {
                
                uint256 B = read32(bytes(input), j);
                j += 32;
                
                // SWAR convert hex to nibbles
                B = (B & lowNibs) + (9 * ((B / 64) & bit1));
                
                // SWAR shuffle nibbles to left
                B = (B * f1) & byten1;
                B = (B * f2) & byten2;
                B = (B * f3) & byten3;
                B = (B * f4) & byten4;
                B =  B * f5;
                
                // Write to output
                write16(output, i, bytes16(bytes32(B)));
                i += 16;
            }
        }
        for (; i < ol; ) {
            uint8 a = uint8(read1(bytes(input), j++));
            uint8 b = uint8(read1(bytes(input), j++));
            a = (a & 0xf) + ((a / 64) * 9);
            b = (b & 0xf) + ((b / 64) * 9);
            output[i++] = byte((a << 4) | b);
        }
    }
    
    function read32(bytes memory input, uint256 j)
        internal pure
        returns (uint256)
    {
        // Load input block
        uint256 B;
                  B |= read1(input, j     );
        B *= 256; B |= read1(input, j +  1);
        B *= 256; B |= read1(input, j +  2);
        B *= 256; B |= read1(input, j +  3);
        B *= 256; B |= read1(input, j +  4);
        B *= 256; B |= read1(input, j +  5);
        B *= 256; B |= read1(input, j +  6);
        B *= 256; B |= read1(input, j +  7);
        B *= 256; B |= read1(input, j +  8);
        B *= 256; B |= read1(input, j +  9);
        B *= 256; B |= read1(input, j + 10);
        B *= 256; B |= read1(input, j + 11);
        B *= 256; B |= read1(input, j + 12);
        B *= 256; B |= read1(input, j + 13);
        B *= 256; B |= read1(input, j + 14);
        B *= 256; B |= read1(input, j + 15);
        B *= 256; B |= read1(input, j + 16);
        B *= 256; B |= read1(input, j + 17);
        B *= 256; B |= read1(input, j + 18);
        B *= 256; B |= read1(input, j + 19);
        B *= 256; B |= read1(input, j + 20);
        B *= 256; B |= read1(input, j + 21);
        B *= 256; B |= read1(input, j + 22);
        B *= 256; B |= read1(input, j + 23);
        B *= 256; B |= read1(input, j + 24);
        B *= 256; B |= read1(input, j + 25);
        B *= 256; B |= read1(input, j + 26);
        B *= 256; B |= read1(input, j + 27);
        B *= 256; B |= read1(input, j + 28);
        B *= 256; B |= read1(input, j + 29);
        B *= 256; B |= read1(input, j + 30);
        B *= 256; B |= read1(input, j + 31);
        return B;
    }
    
    function read1(bytes memory input, uint256 i)
        internal pure
        returns (uint256)
    {
        return uint256(bytes(input)[i]);
    }
    
    function write16(bytes memory output, uint256 i, bytes16 out)
        internal pure
    {
        output[i     ] = out[ 0];
        output[i +  1] = out[ 1];
        output[i +  2] = out[ 2];
        output[i +  3] = out[ 3];
        output[i +  4] = out[ 4];
        output[i +  5] = out[ 5];
        output[i +  6] = out[ 6];
        output[i +  7] = out[ 7];
        output[i +  8] = out[ 8];
        output[i +  9] = out[ 9];
        output[i + 10] = out[10];
        output[i + 11] = out[11];
        output[i + 12] = out[12];
        output[i + 13] = out[13];
        output[i + 14] = out[14];
        output[i + 15] = out[15];
    }
}