Skip to content

Commit

Permalink
Added strrstr, sha3_substring
Browse files Browse the repository at this point in the history
  • Loading branch information
Arachnid committed Apr 17, 2016
1 parent 7201bb0 commit 26bc1fa
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 5 deletions.
53 changes: 48 additions & 5 deletions StringUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ contract StringUtils {
}

/**
* @dev Finds an occurrence of a substring in a string, returning its index,
* or -1 if the substring is not found.
* @dev Finds the first occurrence of a substring in a string, returning its
* index, or -1 if the substring is not found.
* @param haystack The string to search.
* @param needle The string to look for.
* @param idx The string index at which to start searching.
Expand All @@ -52,7 +52,7 @@ contract StringUtils {
assembly {
hash := sha3(add(needle, 32), needleSize)
}
for(; idx <= bytes(haystack).length - needleSize; idx++) {
for (; idx <= bytes(haystack).length - needleSize; idx++) {
bytes32 testHash;
assembly {
testHash := sha3(add(add(haystack, idx), 32), needleSize)
Expand All @@ -63,6 +63,34 @@ contract StringUtils {
return -1;
}

/**
* @dev Finds the last occurrence of a substring in a string, returning its
* index, or -1 if the substring is not found.
* @param haystack The string to search.
* @param needle The string to look for.
* @param idx The string index at which to start searching.
* @return The index of the first character of the substring, or -1 if not
* found.
*/
function strrstr(string haystack, string needle, uint idx) internal
returns (int)
{
uint needleSize = bytes(needle).length;
bytes32 hash;
assembly {
hash := sha3(add(needle, 32), needleSize)
}
for (int i = int(idx); i >= 0; i--) {
bytes32 testHash;
assembly {
testHash := sha3(add(add(haystack, i), 32), needleSize)
}
if (hash == testHash)
return i;
}
return -1;
}

/**
* @dev Copies part of one string into another. If the requested range
* extends past the end of the source or target strings, the range will
Expand Down Expand Up @@ -134,11 +162,26 @@ contract StringUtils {
* @param str The string to return the length of.
* @return The length of the string, in characters.
*/
function strchrlen(string str) internal returns (uint len) {
function strchrlen(string str) internal returns (uint len) {
bytes memory strdata = bytes(str);
for (uint i = 0; i < strdata.length; i++)
// Don't count continuation bytes, of the form 0b10xxxxxx
if (strdata[i] & 0xC0 != 0x80)
len += 1;
}
}

/**
* @dev Cheaply computes the SHA3 hash of a substring.
* @param str The string to hash (part of).
* @param idx The start index for the section to hash.
* @param len The number of bytes to hash.
* @return The SHA3 sum of the selected substring.
*/
function sha3_substring(string str, uint idx, uint len)
internal returns (bytes32 ret)
{
assembly {
ret := sha3(add(add(str, 32), idx), len)
}
}
}
15 changes: 15 additions & 0 deletions StringUtils_test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ contract StringUtilsTest is Test, StringUtils {
assertEq(strcmp(a, b), 0);
}

function assertEq(bytes32 a, bytes32 b) {
assertEq(uint(a), uint(b));
}

function testStrcmp() logs_gas {
assertEq(sign(strcmp("foobie", "foobie")), 0);
assertEq(sign(strcmp("foobie", "foobif")), -1);
Expand All @@ -33,6 +37,13 @@ contract StringUtilsTest is Test, StringUtils {
assertEq(strstr("ABC ABCDAB ABCDABCDABDE", "ABCDABD", 0), 15);
}

function testStrrstr() logs_gas {
assertEq(strrstr("abracadabra", "bra", 8), 8);
assertEq(strrstr("abracadabra", "bra", 7), 1);
assertEq(strrstr("abracadabra", "rab", 11), -1);
assertEq(strrstr("ABC ABCDAB ABCDABCDABDE", "ABCDABD", 16), 15);
}

function testStrncpy() logs_gas {
string memory target = "0123456789";

Expand Down Expand Up @@ -72,4 +83,8 @@ contract StringUtilsTest is Test, StringUtils {
assertEq(strchrlen("foobar"), 6);
assertEq(strchrlen("I ♥ ethereum"), 12);
}

function testSha3Substring() logs_gas {
assertEq(sha3_substring("Hello, world!", 7, 5), sha3("world"));
}
}

0 comments on commit 26bc1fa

Please sign in to comment.