Submission d4c9d10d...

ChallengeHex decoder
Submitterricmoo.firefly.eth
Submitted at2018-11-01
Gas used1050503
pragma solidity 0.4.24;

contract HexDecoder {
    function decode(string input) pure public returns(bytes output) {
        bytes memory inp = bytes(input);
        uint length = inp.length;

        output = new bytes(length / 2);

        uint offset = 0;
        uint outputOffset = 0;
        while (offset < length) {

            uint chunkLength = length - offset;
            if (chunkLength > 32) { chunkLength = 32; }

            uint chunk = 0;
            for (uint i = 0; i < chunkLength; i++) {
                chunk *= 256;
                chunk |= uint(inp[offset + i]);
            }

            // "Number 0" (Alpha 9) For letters (0x40 set) put 0x90 in the slot, otherwise 0
            uint n0 = chunk;
            n0 &= 0x5050505050505050505050505050505050505050505050505050505050505050;
            n0 += 0x5050505050505050505050505050505050505050505050505050505050505050;
            n0 &= 0x9090909090909090909090909090909090909090909090909090909090909090;
            n0 /= 16;

            // Move the data over 1 nibble
            //chunk *= 16;

            // Take the lowest nibble from each ascii character (upper nibble since we shifted)
            // 0-9: already the correct value
            // A-F: add 9 to the value to offset A (1) -> 10, etc
            chunk &= 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f;
            chunk += n0;

            chunk = (chunk | (chunk / 0x10));

            for (uint j = chunkLength / 2; j != 0; j--) {
                output[outputOffset + j - 1] = byte(chunk);
                chunk /= 0x10000;
            }

            offset += chunkLength;
            outputOffset += 16;
        }
    }
}