Submission f7040700...

ChallengeHex decoder
Submittersggc.yuetloo.eth
Submitted at2018-49-05
Gas used1716706
/**
 * This contract was a modified version of the original from 
 * https://github.com/arachnid/sggc.git
 *
 * 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) {
        output = new bytes(bytes(input).length / 2);

        uint j= 0;
        uint len = output.length;
        uint lastPiece = len - (len%16);
        for(uint i = 0; i < lastPiece; ) {
           uint v = uint(bytes(input)[j]);
           v = (v* 256) | uint(bytes(input)[j+1]);
           v = (v* 256) | uint(bytes(input)[j+2]);
           v = (v* 256) | uint(bytes(input)[j+3]);
           v = (v* 256) | uint(bytes(input)[j+4]);
           v = (v* 256) | uint(bytes(input)[j+5]);
           v = (v* 256) | uint(bytes(input)[j+6]);
           v = (v* 256) | uint(bytes(input)[j+7]);
           v = (v* 256) | uint(bytes(input)[j+8]);
           v = (v* 256) | uint(bytes(input)[j+9]);
           v = (v* 256) | uint(bytes(input)[j+10]);
           v = (v* 256) | uint(bytes(input)[j+11]);
           v = (v* 256) | uint(bytes(input)[j+12]);
           v = (v* 256) | uint(bytes(input)[j+13]);
           v = (v* 256) | uint(bytes(input)[j+14]);
           v = (v* 256) | uint(bytes(input)[j+15]);
           v = (v* 256) | uint(bytes(input)[j+16]);
           v = (v* 256) | uint(bytes(input)[j+17]);
           v = (v* 256) | uint(bytes(input)[j+18]);
           v = (v* 256) | uint(bytes(input)[j+19]);
           v = (v* 256) | uint(bytes(input)[j+20]);
           v = (v* 256) | uint(bytes(input)[j+21]);
           v = (v* 256) | uint(bytes(input)[j+22]);
           v = (v* 256) | uint(bytes(input)[j+23]);
           v = (v* 256) | uint(bytes(input)[j+24]);
           v = (v* 256) | uint(bytes(input)[j+25]);
           v = (v* 256) | uint(bytes(input)[j+26]);
           v = (v* 256) | uint(bytes(input)[j+27]);
           v = (v* 256) | uint(bytes(input)[j+28]);
           v = (v* 256) | uint(bytes(input)[j+29]);
           v = (v* 256) | uint(bytes(input)[j+30]);
           v = (v* 256) | uint(bytes(input)[j+31]);
           j += 32;

           // parallel mapping formula: lower byte + (9 for A...F)
           v =     (v & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f) + 
              ((((((v & 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0)/16 )) & 
                        0x0505050505050505050505050505050505050505050505050505050505050505) + 
                        0x0505050505050505050505050505050505050505050505050505050505050505) & 
                        0x0909090909090909090909090909090909090909090909090909090909090909);
           v = ( v/16 ) | v ;
           
           i += 16;
           output[i-1]   = byte( v);
           v /= 0x10000;
           output[i-2]   = byte( v);
           v /= 0x10000;
           output[i-3]   = byte( v);
           v /= 0x10000;
           output[i-4]   = byte( v);
           v /= 0x10000;
           output[i-5]   = byte( v);
           v /= 0x10000;
           output[i-6]   = byte( v);
           v /= 0x10000;
           output[i-7]   = byte( v);
           v /= 0x10000;
           output[i-8]   = byte( v);
           v /= 0x10000;
           output[i-9]   = byte( v);
           v /= 0x10000;
           output[i-10]   = byte( v);
           v /= 0x10000;
           output[i-11]   = byte( v);
           v /= 0x10000;
           output[i-12]   = byte( v);
           v /= 0x10000;
           output[i-13]   = byte( v);
           v /= 0x10000;
           output[i-14]   = byte( v);
           v /= 0x10000;
           output[i-15]   = byte( v);
           v /= 0x10000;
           output[i-16]   = byte( v);
        }

        for(; i < len; ++i)
        {
           v = uint(bytes(input)[j]);
           uint m = uint(bytes(input)[j+1]);
           j +=2;
           output[i] = byte(((v < 0x40? (v &0xf) : (v & 0xf) + 9)*16) |
                             ( m < 0x40? (m &0xf) : (m & 0xf) + 9));
        }
    }
}