Submission 45e9d68a...

ChallengeString search
Submitter0x888888417655103...
Submitted at2018-53-30
Gas used57906
pragma solidity 0.4.24;

contract IndexOf {
    function indexOf(
        string haystack,
        string needle
    ) public pure returns(int) {

        assembly {

            let hsLen := calldataload(0x44)
            let nLen := calldataload(add(calldataload(0x24), 0x04))

            if iszero(nLen) {
                mstore(0x40, 0x0000000000000000000000000000000000000000000000000000000000000000)
                return(0x40, 0x20)
            }

            if lt(hsLen, nLen) {
                mstore(0x40, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
                return(0x40, 0x20)
            }

            function findOne(hsBegin, hsEnd, nByte) {
                for { let idx := hsBegin }
                    lt(idx, hsEnd)
                    { idx := add(idx, 0x1) } {
                    if eq(nByte,
                          and(
                              calldataload(idx),
                              0xff00000000000000000000000000000000000000000000000000000000000000)) {
                        mstore(0x20, sub(idx, hsBegin))
                        idx := hsEnd
                    }
                }
            }

            function findFew(hsBegin, hsEnd, nUint, nMask) {
                for { let idx := hsBegin }
                    lt(idx, hsEnd)
                    { idx := add(idx, 0x1) } {
                    if eq(nUint, and(calldataload(idx), nMask)) {
                        mstore(0x20, sub(idx, hsBegin))
                        idx := hsEnd
                    }
                }
            }

            function findUint(hsBegin, hsEnd, nUint) {
                for { let idx := hsBegin }
                    lt(idx, hsEnd)
                    { idx := add(idx, 0x1) } {
                    if eq(nUint, calldataload(idx)) {
                        mstore(0x20, sub(idx, hsBegin))
                        idx := hsEnd
                    }
                }
            }

            function findMuch(hsBegin, hsEnd, nBegin, _nLen) {
                let nLeft := mod(_nLen, 0x20)
                let nEnd := sub(add(nBegin, _nLen), nLeft)
                let nUint := calldataload(nBegin)
                for { let idx := hsBegin }
                    lt(idx, hsEnd)
                    { idx := add(idx, 0x1) } {
                    if eq(nUint, calldataload(idx)) {
                        let idx2 := add(nBegin, 0x20)
                        let idx3 := idx
                        for { } lt(idx2, nEnd) { } {
                            idx3 := add(idx3, 0x20)
                            switch eq(calldataload(idx2), calldataload(idx3))
                            case 1 { idx2 := add(idx2, 0x20) }
                            default { idx2 := add(nEnd, 0x01) }
                        }
                        if eq(idx2, nEnd) {
                            switch iszero(nLeft)
                            case 1 {
                                mstore(0x20, sub(idx, hsBegin))
                                idx := hsEnd
                            }
                            default {
                                if eq(
                                    calldataload(idx2),
                                    and(
                                        calldataload(add(idx3, 0x20)),
                                        not(
                                            sub(
                                                exp(0x02, mul(0x08, nLeft)),
                                                0x01)))) {
                                    mstore(0x20, sub(idx, hsBegin))
                                    idx := hsEnd
                                }
                            }
                        }
                    }
                }
            }

            mstore(0x20, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
            switch nLen
            case 1 {
                findOne(
                    0x64,
                    add(0x64, hsLen),
                    calldataload(add(calldataload(0x24), 0x24)))
            }
            case 32 {
                findUint(
                    0x64,
                    sub(add(0x64, hsLen), 0x1f),
                    calldataload(add(calldataload(0x24), 0x24)))
            }
            default {
                if lt(nLen, 32) {
                    findFew(
                        0x64,
                        sub(add(0x64, hsLen), sub(nLen, 0x01)),
                        calldataload(add(calldataload(0x24), 0x24)),
                        not(
                            sub(
                                exp(
                                    0x02,
                                    mul(0x08, nLen)),
                                0x01)))
                    return(0x20, 0x20)
                }
                findMuch(
                    0x64,
                    sub(add(0x64, hsLen), sub(nLen, 0x01)),
                    add(calldataload(0x24), 0x24),
                    nLen)
            }
            return(0x20, 0x20)
        }
    }
}