library StringUtil {
    /*
     * 字符串连接
     */
    function concat(string memory self, string memory str) pure public returns(string memory) {
        bytes memory selfBytes = bytes(self);
        bytes memory strBytes = bytes(str);
        
        uint selfLen = selfBytes.length;
        uint strLen = strBytes.length;
        
        if (selfLen == 0 && strLen == 0) {
            return self;
        } else if (selfLen == 0) {
            return str;
        } else if (strLen == 0) {
            return self;
        }
        
        uint length = selfLen + strLen;
        bytes memory temp = new bytes(length);
        uint index = 0;
        for (uint i = 0 ; i < selfLen ; i++) {
            temp[index++] = selfBytes[i];
        }
        for (uint i = 0 ; i < strLen ; i++) {
            temp[index++] = strBytes[i];
        }
        
        return string(temp);
    }
    
    /*
     * 字符串比较，self>str => 1，self<str => -1，self=str => 0
     */
    function compare(string memory self, string memory str) pure public returns(int) {
        bytes memory selfBytes = bytes(self);
        bytes memory strBytes = bytes(str);
        
        uint selfLen = selfBytes.length;
        uint strLen = strBytes.length;
        
        uint minLen = selfLen;
        if (selfLen > strLen) {
            minLen = strLen;
        }
        
        for (uint i = 0 ; i < minLen ; i++) {
            if (selfBytes[i] < strBytes[i]) {
                return -1;
            } else if (selfBytes[i] > strBytes[i]) {
                return 1;
            }
        }
        
        if (selfLen < strLen) {
            return -1;
        } else if (selfLen > strLen) {
            return 1;
        }
        
        return 0;
    }
    
    /*
     * 字符串是否相同  
     */
    function equals(string memory self, string memory str) pure public returns(bool) {
        return compare(self, str) == 0;
    }

    /*
     *  获取子字符串第一次出现的位置下标
     */
    function indexOf(string memory self, string memory str) pure public returns(int) {
        bytes memory selfBytes = bytes(self);
        bytes memory strBytes = bytes(str);
        
        uint selfLen = selfBytes.length;
        uint strLen = strBytes.length;
        
        if (selfLen < 1 || strLen < 1 || selfLen < strLen) {
            return -1;
        }
        
        if (selfLen > 2 ** 128 - 1) {
            return -1;
        }
        
        uint index = 0;
        for (uint i = 0 ; i < selfLen ; i++) {
            if (selfBytes[i] == strBytes[0]) {
                index = 1;
                while (index < strLen && (i + index) < selfLen && selfBytes[i + index] == strBytes[index]) {
                    index++;
                }
                
                if (index == strLen) {
                    return int(i);
                }
            }
        }
        
        return -1;
    }
    
    /*
     *   将uint256转成字符串 
     */
    function fromUint256(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        uint256 index = digits - 1;
        temp = value;
        while (temp != 0) {
            buffer[index--] = byte(uint8(48 + temp % 10));
            temp /= 10;
        }
        return string(buffer);
    }
}
function compare(string memory self, string memory str) pure public returns(int) {
    bytes memory selfBytes = bytes(self);
    bytes memory strBytes = bytes(str);
        
    uint selfLen = selfBytes.length;
    uint strLen = strBytes.length;
        
    uint minLen = selfLen;
    if (selfLen > strLen) {
        minLen = strLen;
    }
        
    for (uint i = 0 ; i < minLen ; i++) {
        if (selfBytes[i] < strBytes[i]) {
            return -1;
        } else if (selfBytes[i] > strBytes[i]) {
            return 1;
        }
    }
        
    if (selfLen < strLen) {
        return -1;
    } else if (selfLen > strLen) {
        return 1;
    }
        
    return 0;
}

/*
 * 字符串比较，self>str => 1，self<str => -1，self=str => 0
 */