jcc-solidity-utils
Version:
jcc solidity utils
608 lines • 2.06 MB
JSON
{
"contractName": "StringUtils",
"abi": [],
"metadata": "{\"compiler\":{\"version\":\"0.4.24+commit.e67f0147\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"/Users/chtian/Documents/01_work/01_develope/jcc/jcc-solidity-utils/contracts/utils/StringUtils.sol\":\"StringUtils\"},\"evmVersion\":\"byzantium\",\"libraries\":{},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"/Users/chtian/Documents/01_work/01_develope/jcc/jcc-solidity-utils/contracts/utils/StringUtils.sol\":{\"keccak256\":\"0xc19208b7c3ff461890e9fd7ff239c8117091c6a09dda4fc3a24131abc49f0a22\",\"urls\":[\"bzzr://1e827a43f7437be23fca88c994e91a20f80f613043089aeacc54ddd2d92910ed\"]}},\"version\":1}",
"bytecode": "0x604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820ee17f9c564e383bc569f172c888e3e6bb30a9aa29e27b0d920d5926d44c9cae50029",
"deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820ee17f9c564e383bc569f172c888e3e6bb30a9aa29e27b0d920d5926d44c9cae50029",
"sourceMap": "2109:21569:35:-;;132:2:-1;166:7;155:9;146:7;137:37;252:7;246:14;243:1;238:23;232:4;229:33;270:1;265:20;;;;222:63;;265:20;274:9;222:63;;298:9;295:1;288:20;328:4;319:7;311:22;352:7;343;336:24",
"deployedSourceMap": "2109:21569:35:-;;;;;;;;",
"source": "/*\n * @title String & slice utility library for Solidity contracts.\n * @author Nick Johnson <arachnid@notdot.net>\n *\n * @dev Functionality in this library is largely implemented using an\n * abstraction called a 'slice'. A slice represents a part of a string -\n * anything from the entire string to a single character, or even no\n * characters at all (a 0-length slice). Since a slice only has to specify\n * an offset and a length, copying and manipulating slices is a lot less\n * expensive than copying and manipulating the strings they reference.\n *\n * To further reduce gas costs, most functions on slice that need to return\n * a slice modify the original one instead of allocating a new one; for\n * instance, `s.split(\".\")` will return the text up to the first '.',\n * modifying s to only contain the remainder of the string after the '.'.\n * In situations where you do not want to modify the original slice, you\n * can make a copy first with `.copy()`, for example:\n * `s.copy().split(\".\")`. Try and avoid using this idiom in loops; since\n * Solidity has no memory management, it will result in allocating many\n * short-lived slices that are later discarded.\n *\n * Functions that return two slices come in two versions: a non-allocating\n * version that takes the second slice as an argument, modifying it in\n * place, and an allocating version that allocates and returns the second\n * slice; see `nextRune` for example.\n *\n * Functions that have to copy string data will return strings rather than\n * slices; these can be cast back to slices for further processing if\n * required.\n *\n * For convenience, some functions are provided with non-modifying\n * variants that create a new slice and return both; for instance,\n * `s.splitNew('.')` leaves s unmodified, and returns two values\n * corresponding to the left and right parts of the string.\n */\n\npragma solidity >=0.4.24;\n\n/**\n * @dev Utility library of string.\n * see also: https://github.com/Arachnid/solidity-stringutils\n */\nlibrary StringUtils {\n struct slice {\n uint256 _len;\n uint256 _ptr;\n }\n\n function memcpy(\n uint256 dest,\n uint256 src,\n uint256 len\n ) private pure {\n // Copy word-length chunks while possible\n for (; len >= 32; len -= 32) {\n assembly {\n mstore(dest, mload(src))\n }\n dest += 32;\n src += 32;\n }\n\n // Copy remaining bytes\n uint256 mask = 256**(32 - len) - 1;\n assembly {\n let srcpart := and(mload(src), not(mask))\n let destpart := and(mload(dest), mask)\n mstore(dest, or(destpart, srcpart))\n }\n }\n\n /*\n * @dev Returns a slice containing the entire string.\n * @param self The string to make a slice from.\n * @return A newly allocated slice containing the entire string.\n */\n function toSlice(string memory self) internal pure returns (slice memory) {\n uint256 ptr;\n assembly {\n ptr := add(self, 0x20)\n }\n return slice(bytes(self).length, ptr);\n }\n\n /*\n * @dev Returns the length of a null-terminated bytes32 string.\n * @param self The value to find the length of.\n * @return The length of the string, from 0 to 32.\n */\n function len(bytes32 self) internal pure returns (uint256) {\n uint256 ret;\n if (self == 0) return 0;\n if (self & 0xffffffffffffffffffffffffffffffff == 0) {\n ret += 16;\n self = bytes32(uint256(self) / 0x100000000000000000000000000000000);\n }\n if (self & 0xffffffffffffffff == 0) {\n ret += 8;\n self = bytes32(uint256(self) / 0x10000000000000000);\n }\n if (self & 0xffffffff == 0) {\n ret += 4;\n self = bytes32(uint256(self) / 0x100000000);\n }\n if (self & 0xffff == 0) {\n ret += 2;\n self = bytes32(uint256(self) / 0x10000);\n }\n if (self & 0xff == 0) {\n ret += 1;\n }\n return 32 - ret;\n }\n\n /*\n * @dev Returns a slice containing the entire bytes32, interpreted as a\n * null-terminated utf-8 string.\n * @param self The bytes32 value to convert to a slice.\n * @return A new slice containing the value of the input argument up to the\n * first null.\n */\n function toSliceB32(bytes32 self) internal pure returns (slice memory ret) {\n // Allocate space for `self` in memory, copy it there, and point ret at it\n assembly {\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, 0x20))\n mstore(ptr, self)\n mstore(add(ret, 0x20), ptr)\n }\n ret._len = len(self);\n }\n\n /*\n * @dev Returns a new slice containing the same data as the current slice.\n * @param self The slice to copy.\n * @return A new slice containing the same data as `self`.\n */\n function copy(slice memory self) internal pure returns (slice memory) {\n return slice(self._len, self._ptr);\n }\n\n /*\n * @dev Copies a slice to a new string.\n * @param self The slice to copy.\n * @return A newly allocated string containing the slice's text.\n */\n function toString(slice memory self) internal pure returns (string memory) {\n string memory ret = new string(self._len);\n uint256 retptr;\n assembly {\n retptr := add(ret, 32)\n }\n\n memcpy(retptr, self._ptr, self._len);\n return ret;\n }\n\n /*\n * @dev Returns the length in runes of the slice. Note that this operation\n * takes time proportional to the length of the slice; avoid using it\n * in loops, and call `slice.empty()` if you only need to know whether\n * the slice is empty or not.\n * @param self The slice to operate on.\n * @return The length of the slice in runes.\n */\n function len(slice memory self) internal pure returns (uint256 l) {\n // Starting at ptr-31 means the LSB will be the byte we care about\n uint256 ptr = self._ptr - 31;\n uint256 end = ptr + self._len;\n for (l = 0; ptr < end; l++) {\n uint8 b;\n assembly {\n b := and(mload(ptr), 0xFF)\n }\n if (b < 0x80) {\n ptr += 1;\n } else if (b < 0xE0) {\n ptr += 2;\n } else if (b < 0xF0) {\n ptr += 3;\n } else if (b < 0xF8) {\n ptr += 4;\n } else if (b < 0xFC) {\n ptr += 5;\n } else {\n ptr += 6;\n }\n }\n }\n\n /*\n * @dev Returns true if the slice is empty (has a length of 0).\n * @param self The slice to operate on.\n * @return True if the slice is empty, False otherwise.\n */\n function empty(slice memory self) internal pure returns (bool) {\n return self._len == 0;\n }\n\n /*\n * @dev Returns a positive number if `other` comes lexicographically after\n * `self`, a negative number if it comes before, or zero if the\n * contents of the two slices are equal. Comparison is done per-rune,\n * on unicode codepoints.\n * @param self The first slice to compare.\n * @param other The second slice to compare.\n * @return The result of the comparison.\n */\n function compare(slice memory self, slice memory other)\n internal\n pure\n returns (int256)\n {\n uint256 shortest = self._len;\n if (other._len < self._len) shortest = other._len;\n\n uint256 selfptr = self._ptr;\n uint256 otherptr = other._ptr;\n for (uint256 idx = 0; idx < shortest; idx += 32) {\n uint256 a;\n uint256 b;\n assembly {\n a := mload(selfptr)\n b := mload(otherptr)\n }\n if (a != b) {\n // Mask out irrelevant bytes and check again\n uint256 mask = uint256(-1); // 0xffff...\n if (shortest < 32) {\n mask = ~(2**(8 * (32 - shortest + idx)) - 1);\n }\n uint256 diff = (a & mask) - (b & mask);\n if (diff != 0) return int256(diff);\n }\n selfptr += 32;\n otherptr += 32;\n }\n return int256(self._len) - int256(other._len);\n }\n\n /*\n * @dev Returns true if the two slices contain the same text.\n * @param self The first slice to compare.\n * @param self The second slice to compare.\n * @return True if the slices are equal, false otherwise.\n */\n function equals(slice memory self, slice memory other)\n internal\n pure\n returns (bool)\n {\n return compare(self, other) == 0;\n }\n\n /*\n * @dev Extracts the first rune in the slice into `rune`, advancing the\n * slice to point to the next rune and returning `self`.\n * @param self The slice to operate on.\n * @param rune The slice that will contain the first rune.\n * @return `rune`.\n */\n function nextRune(slice memory self, slice memory rune)\n internal\n pure\n returns (slice memory)\n {\n rune._ptr = self._ptr;\n\n if (self._len == 0) {\n rune._len = 0;\n return rune;\n }\n\n uint256 l;\n uint256 b;\n // Load the first byte of the rune into the LSBs of b\n assembly {\n b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF)\n }\n if (b < 0x80) {\n l = 1;\n } else if (b < 0xE0) {\n l = 2;\n } else if (b < 0xF0) {\n l = 3;\n } else {\n l = 4;\n }\n\n // Check for truncated codepoints\n if (l > self._len) {\n rune._len = self._len;\n self._ptr += self._len;\n self._len = 0;\n return rune;\n }\n\n self._ptr += l;\n self._len -= l;\n rune._len = l;\n return rune;\n }\n\n /*\n * @dev Returns the first rune in the slice, advancing the slice to point\n * to the next rune.\n * @param self The slice to operate on.\n * @return A slice containing only the first rune from `self`.\n */\n function nextRune(slice memory self)\n internal\n pure\n returns (slice memory ret)\n {\n nextRune(self, ret);\n }\n\n /*\n * @dev Returns the number of the first codepoint in the slice.\n * @param self The slice to operate on.\n * @return The number of the first codepoint in the slice.\n */\n function ord(slice memory self) internal pure returns (uint256 ret) {\n if (self._len == 0) {\n return 0;\n }\n\n uint256 word;\n uint256 length;\n uint256 divisor = 2**248;\n\n // Load the rune into the MSBs of b\n assembly {\n word := mload(mload(add(self, 32)))\n }\n uint256 b = word / divisor;\n if (b < 0x80) {\n ret = b;\n length = 1;\n } else if (b < 0xE0) {\n ret = b & 0x1F;\n length = 2;\n } else if (b < 0xF0) {\n ret = b & 0x0F;\n length = 3;\n } else {\n ret = b & 0x07;\n length = 4;\n }\n\n // Check for truncated codepoints\n if (length > self._len) {\n return 0;\n }\n\n for (uint256 i = 1; i < length; i++) {\n divisor = divisor / 256;\n b = (word / divisor) & 0xFF;\n if (b & 0xC0 != 0x80) {\n // Invalid UTF-8 sequence\n return 0;\n }\n ret = (ret * 64) | (b & 0x3F);\n }\n\n return ret;\n }\n\n /*\n * @dev Returns the keccak-256 hash of the slice.\n * @param self The slice to hash.\n * @return The hash of the slice.\n */\n function keccak(slice memory self) internal pure returns (bytes32 ret) {\n assembly {\n ret := keccak256(mload(add(self, 32)), mload(self))\n }\n }\n\n /*\n * @dev Returns true if `self` starts with `needle`.\n * @param self The slice to operate on.\n * @param needle The slice to search for.\n * @return True if the slice starts with the provided text, false otherwise.\n */\n function startsWith(slice memory self, slice memory needle)\n internal\n pure\n returns (bool)\n {\n if (self._len < needle._len) {\n return false;\n }\n\n if (self._ptr == needle._ptr) {\n return true;\n }\n\n bool equal;\n assembly {\n let length := mload(needle)\n let selfptr := mload(add(self, 0x20))\n let needleptr := mload(add(needle, 0x20))\n equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\n }\n return equal;\n }\n\n /*\n * @dev If `self` starts with `needle`, `needle` is removed from the\n * beginning of `self`. Otherwise, `self` is unmodified.\n * @param self The slice to operate on.\n * @param needle The slice to search for.\n * @return `self`\n */\n function beyond(slice memory self, slice memory needle)\n internal\n pure\n returns (slice memory)\n {\n if (self._len < needle._len) {\n return self;\n }\n\n bool equal = true;\n if (self._ptr != needle._ptr) {\n assembly {\n let length := mload(needle)\n let selfptr := mload(add(self, 0x20))\n let needleptr := mload(add(needle, 0x20))\n equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\n }\n }\n\n if (equal) {\n self._len -= needle._len;\n self._ptr += needle._len;\n }\n\n return self;\n }\n\n /*\n * @dev Returns true if the slice ends with `needle`.\n * @param self The slice to operate on.\n * @param needle The slice to search for.\n * @return True if the slice starts with the provided text, false otherwise.\n */\n function endsWith(slice memory self, slice memory needle)\n internal\n pure\n returns (bool)\n {\n if (self._len < needle._len) {\n return false;\n }\n\n uint256 selfptr = self._ptr + self._len - needle._len;\n\n if (selfptr == needle._ptr) {\n return true;\n }\n\n bool equal;\n assembly {\n let length := mload(needle)\n let needleptr := mload(add(needle, 0x20))\n equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\n }\n\n return equal;\n }\n\n /*\n * @dev If `self` ends with `needle`, `needle` is removed from the\n * end of `self`. Otherwise, `self` is unmodified.\n * @param self The slice to operate on.\n * @param needle The slice to search for.\n * @return `self`\n */\n function until(slice memory self, slice memory needle)\n internal\n pure\n returns (slice memory)\n {\n if (self._len < needle._len) {\n return self;\n }\n\n uint256 selfptr = self._ptr + self._len - needle._len;\n bool equal = true;\n if (selfptr != needle._ptr) {\n assembly {\n let length := mload(needle)\n let needleptr := mload(add(needle, 0x20))\n equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\n }\n }\n\n if (equal) {\n self._len -= needle._len;\n }\n\n return self;\n }\n\n // Returns the memory address of the first byte of the first occurrence of\n // `needle` in `self`, or the first byte after `self` if not found.\n function findPtr(\n uint256 selflen,\n uint256 selfptr,\n uint256 needlelen,\n uint256 needleptr\n ) private pure returns (uint256) {\n uint256 ptr = selfptr;\n uint256 idx;\n\n if (needlelen <= selflen) {\n if (needlelen <= 32) {\n bytes32 mask = bytes32(~(2**(8 * (32 - needlelen)) - 1));\n\n bytes32 needledata;\n assembly {\n needledata := and(mload(needleptr), mask)\n }\n\n uint256 end = selfptr + selflen - needlelen;\n bytes32 ptrdata;\n assembly {\n ptrdata := and(mload(ptr), mask)\n }\n\n while (ptrdata != needledata) {\n if (ptr >= end) return selfptr + selflen;\n ptr++;\n assembly {\n ptrdata := and(mload(ptr), mask)\n }\n }\n return ptr;\n } else {\n // For long needles, use hashing\n bytes32 hash;\n assembly {\n hash := keccak256(needleptr, needlelen)\n }\n\n for (idx = 0; idx <= selflen - needlelen; idx++) {\n bytes32 testHash;\n assembly {\n testHash := keccak256(ptr, needlelen)\n }\n if (hash == testHash) return ptr;\n ptr += 1;\n }\n }\n }\n return selfptr + selflen;\n }\n\n // Returns the memory address of the first byte after the last occurrence of\n // `needle` in `self`, or the address of `self` if not found.\n function rfindPtr(\n uint256 selflen,\n uint256 selfptr,\n uint256 needlelen,\n uint256 needleptr\n ) private pure returns (uint256) {\n uint256 ptr;\n\n if (needlelen <= selflen) {\n if (needlelen <= 32) {\n bytes32 mask = bytes32(~(2**(8 * (32 - needlelen)) - 1));\n\n bytes32 needledata;\n assembly {\n needledata := and(mload(needleptr), mask)\n }\n\n ptr = selfptr + selflen - needlelen;\n bytes32 ptrdata;\n assembly {\n ptrdata := and(mload(ptr), mask)\n }\n\n while (ptrdata != needledata) {\n if (ptr <= selfptr) return selfptr;\n ptr--;\n assembly {\n ptrdata := and(mload(ptr), mask)\n }\n }\n return ptr + needlelen;\n } else {\n // For long needles, use hashing\n bytes32 hash;\n assembly {\n hash := keccak256(needleptr, needlelen)\n }\n ptr = selfptr + (selflen - needlelen);\n while (ptr >= selfptr) {\n bytes32 testHash;\n assembly {\n testHash := keccak256(ptr, needlelen)\n }\n if (hash == testHash) return ptr + needlelen;\n ptr -= 1;\n }\n }\n }\n return selfptr;\n }\n\n /*\n * @dev Modifies `self` to contain everything from the first occurrence of\n * `needle` to the end of the slice. `self` is set to the empty slice\n * if `needle` is not found.\n * @param self The slice to search and modify.\n * @param needle The text to search for.\n * @return `self`.\n */\n function find(slice memory self, slice memory needle)\n internal\n pure\n returns (slice memory)\n {\n uint256 ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);\n self._len -= ptr - self._ptr;\n self._ptr = ptr;\n return self;\n }\n\n /*\n * @dev Modifies `self` to contain the part of the string from the start of\n * `self` to the end of the first occurrence of `needle`. If `needle`\n * is not found, `self` is set to the empty slice.\n * @param self The slice to search and modify.\n * @param needle The text to search for.\n * @return `self`.\n */\n function rfind(slice memory self, slice memory needle)\n internal\n pure\n returns (slice memory)\n {\n uint256 ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);\n self._len = ptr - self._ptr;\n return self;\n }\n\n /*\n * @dev Splits the slice, setting `self` to everything after the first\n * occurrence of `needle`, and `token` to everything before it. If\n * `needle` does not occur in `self`, `self` is set to the empty slice,\n * and `token` is set to the entirety of `self`.\n * @param self The slice to split.\n * @param needle The text to search for in `self`.\n * @param token An output parameter to which the first token is written.\n * @return `token`.\n */\n function split(\n slice memory self,\n slice memory needle,\n slice memory token\n ) internal pure returns (slice memory) {\n uint256 ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);\n token._ptr = self._ptr;\n token._len = ptr - self._ptr;\n if (ptr == self._ptr + self._len) {\n // Not found\n self._len = 0;\n } else {\n self._len -= token._len + needle._len;\n self._ptr = ptr + needle._len;\n }\n return token;\n }\n\n /*\n * @dev Splits the slice, setting `self` to everything after the first\n * occurrence of `needle`, and returning everything before it. If\n * `needle` does not occur in `self`, `self` is set to the empty slice,\n * and the entirety of `self` is returned.\n * @param self The slice to split.\n * @param needle The text to search for in `self`.\n * @return The part of `self` up to the first occurrence of `delim`.\n */\n function split(slice memory self, slice memory needle)\n internal\n pure\n returns (slice memory token)\n {\n split(self, needle, token);\n }\n\n /*\n * @dev Splits the slice, setting `self` to everything before the last\n * occurrence of `needle`, and `token` to everything after it. If\n * `needle` does not occur in `self`, `self` is set to the empty slice,\n * and `token` is set to the entirety of `self`.\n * @param self The slice to split.\n * @param needle The text to search for in `self`.\n * @param token An output parameter to which the first token is written.\n * @return `token`.\n */\n function rsplit(\n slice memory self,\n slice memory needle,\n slice memory token\n ) internal pure returns (slice memory) {\n uint256 ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);\n token._ptr = ptr;\n token._len = self._len - (ptr - self._ptr);\n if (ptr == self._ptr) {\n // Not found\n self._len = 0;\n } else {\n self._len -= token._len + needle._len;\n }\n return token;\n }\n\n /*\n * @dev Splits the slice, setting `self` to everything before the last\n * occurrence of `needle`, and returning everything after it. If\n * `needle` does not occur in `self`, `self` is set to the empty slice,\n * and the entirety of `self` is returned.\n * @param self The slice to split.\n * @param needle The text to search for in `self`.\n * @return The part of `self` after the last occurrence of `delim`.\n */\n function rsplit(slice memory self, slice memory needle)\n internal\n pure\n returns (slice memory token)\n {\n rsplit(self, needle, token);\n }\n\n /*\n * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`.\n * @param self The slice to search.\n * @param needle The text to search for in `self`.\n * @return The number of occurrences of `needle` found in `self`.\n */\n function count(slice memory self, slice memory needle)\n internal\n pure\n returns (uint256 cnt)\n {\n uint256 ptr =\n findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len;\n while (ptr <= self._ptr + self._len) {\n cnt++;\n ptr =\n findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) +\n needle._len;\n }\n }\n\n /*\n * @dev Returns True if `self` contains `needle`.\n * @param self The slice to search.\n * @param needle The text to search for in `self`.\n * @return True if `needle` is found in `self`, false otherwise.\n */\n function contains(slice memory self, slice memory needle)\n internal\n pure\n returns (bool)\n {\n return\n rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr;\n }\n\n /*\n * @dev Returns a newly allocated string containing the concatenation of\n * `self` and `other`.\n * @param self The first slice to concatenate.\n * @param other The second slice to concatenate.\n * @return The concatenation of the two strings.\n */\n function concat(slice memory self, slice memory other)\n internal\n pure\n returns (string memory)\n {\n string memory ret = new string(self._len + other._len);\n uint256 retptr;\n assembly {\n retptr := add(ret, 32)\n }\n memcpy(retptr, self._ptr, self._len);\n memcpy(retptr + self._len, other._ptr, other._len);\n return ret;\n }\n\n /*\n * @dev Joins an array of slices, using `self` as a delimiter, returning a\n * newly allocated string.\n * @param self The delimiter to use.\n * @param parts A list of slices to join.\n * @return A newly allocated string containing all the slices in `parts`,\n * joined with `self`.\n */\n function join(slice memory self, slice[] memory parts)\n internal\n pure\n returns (string memory)\n {\n if (parts.length == 0) return \"\";\n\n uint256 length = self._len * (parts.length - 1);\n for (uint256 i = 0; i < parts.length; i++) length += parts[i]._len;\n\n string memory ret = new string(length);\n uint256 retptr;\n assembly {\n retptr := add(ret, 32)\n }\n\n for (i = 0; i < parts.length; i++) {\n memcpy(retptr, parts[i]._ptr, parts[i]._len);\n retptr += parts[i]._len;\n if (i < parts.length - 1) {\n memcpy(retptr, self._ptr, self._len);\n retptr += self._len;\n }\n }\n\n return ret;\n }\n}\n",
"sourcePath": "/Users/chtian/Documents/01_work/01_develope/jcc/jcc-solidity-utils/contracts/utils/StringUtils.sol",
"ast": {
"absolutePath": "/Users/chtian/Documents/01_work/01_develope/jcc/jcc-solidity-utils/contracts/utils/StringUtils.sol",
"exportedSymbols": {
"StringUtils": [
9026
]
},
"id": 9027,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 7333,
"literals": [
"solidity",
">=",
"0.4",
".24"
],
"nodeType": "PragmaDirective",
"src": "1977:25:35"
},
{
"baseContracts": [],
"contractDependencies": [],
"contractKind": "library",
"documentation": "@dev Utility library of string.\nsee also: https://github.com/Arachnid/solidity-stringutils",
"fullyImplemented": true,
"id": 9026,
"linearizedBaseContracts": [
9026
],
"name": "StringUtils",
"nodeType": "ContractDefinition",
"nodes": [
{
"canonicalName": "StringUtils.slice",
"id": 7338,
"members": [
{
"constant": false,
"id": 7335,
"name": "_len",
"nodeType": "VariableDeclaration",
"scope": 7338,
"src": "2152:12:35",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 7334,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "2152:7:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value": null,
"visibility": "internal"
},
{
"constant": false,
"id": 7337,
"name": "_ptr",
"nodeType": "VariableDeclaration",
"scope": 7338,
"src": "2170:12:35",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 7336,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "2170:7:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value": null,
"visibility": "internal"
}
],
"name": "slice",
"nodeType": "StructDefinition",
"scope": 9026,
"src": "2133:54:35",
"visibility": "public"
},
{
"body": {
"id": 7377,
"nodeType": "Block",
"src": "2276:410:35",
"statements": [
{
"body": {
"id": 7363,
"nodeType": "Block",
"src": "2357:100:35",
"statements": [
{
"externalReferences": [
{
"dest": {
"declaration": 7340,
"isOffset": false,
"isSlot": false,
"src": "2391:4:35",
"valueSize": 1
}
},
{
"src": {
"declaration": 7342,
"isOffset": false,
"isSlot": false,
"src": "2403:3:35",
"valueSize": 1
}
}
],
"id": 7354,
"nodeType": "InlineAssembly",
"operations": "{\n mstore(dest, mload(src))\n}",
"src": "2365:62:35"
},
{
"expression": {
"argumentTypes": null,
"id": 7357,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"argumentTypes": null,
"id": 7355,
"name": "dest",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 7340,
"src": "2423:4:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "+=",
"rightHandSide": {
"argumentTypes": null,
"hexValue": "3332",
"id": 7356,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "2431:2:35",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_32_by_1",
"typeString": "int_const 32"
},
"value": "32"
},
"src": "2423:10:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 7358,
"nodeType": "ExpressionStatement",
"src": "2423:10:35"
},
{
"expression": {
"argumentTypes": null,
"id": 7361,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"argumentTypes": null,
"id": 7359,
"name": "src",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 7342,
"src": "2441:3:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "+=",
"rightHandSide": {
"argumentTypes": null,
"hexValue": "3332",
"id": 7360,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "2448:2:35",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_32_by_1",
"typeString": "int_const 32"
},
"value": "32"
},
"src": "2441:9:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 7362,
"nodeType": "ExpressionStatement",
"src": "2441:9:35"
}
]
},
"condition": {
"argumentTypes": null,
"commonType": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 7349,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"id": 7347,
"name": "len",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 7344,
"src": "2335:3:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "BinaryOperation",
"operator": ">=",
"rightExpression": {
"argumentTypes": null,
"hexValue": "3332",
"id": 7348,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "2342:2:35",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_32_by_1",
"typeString": "int_const 32"
},
"value": "32"
},
"src": "2335:9:35",
"typeDescriptions": {
"typeIdentifier": "t_bool",
"typeString": "bool"
}
},
"id": 7364,
"initializationExpression": null,
"loopExpression": {
"expression": {
"argumentTypes": null,
"id": 7352,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"argumentTypes": null,
"id": 7350,
"name": "len",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 7344,
"src": "2346:3:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "-=",
"rightHandSide": {
"argumentTypes": null,
"hexValue": "3332",
"id": 7351,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "2353:2:35",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_32_by_1",
"typeString": "int_const 32"
},
"value": "32"
},
"src": "2346:9:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 7353,
"nodeType": "ExpressionStatement",
"src": "2346:9:35"
},
"nodeType": "ForStatement",
"src": "2328:129:35"
},
{
"assignments": [
7366
],
"declarations": [
{
"constant": false,
"id": 7366,
"name": "mask",
"nodeType": "VariableDeclaration",
"scope": 7378,
"src": "2491:12:35",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName": {
"id": 7365,
"name": "uint256",
"nodeType": "ElementaryTypeName",
"src": "2491:7:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value": null,
"visibility": "internal"
}
],
"id": 7375,
"initialValue": {
"argumentTypes": null,
"commonType": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 7374,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"commonType": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 7372,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"hexValue": "323536",
"id": 7367,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "2506:3:35",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_256_by_1",
"typeString": "int_const 256"
},
"value": "256"
},
"nodeType": "BinaryOperation",
"operator": "**",
"rightExpression": {
"argumentTypes": null,
"components": [
{
"argumentTypes": null,
"commonType": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 7370,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"hexValue": "3332",
"id": 7368,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "2512:2:35",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_32_by_1",
"typeString": "int_const 32"
},
"value": "32"
},
"nodeType": "BinaryOperation",
"operator": "-",
"rightExpression": {
"argumentTypes": null,
"id": 7369,
"name": "len",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 7344,
"src": "2517:3:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "2512:8:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}
],
"id": 7371,
"isConstant": false,
"isInlineArray": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "TupleExpression",
"src": "2511:10:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "2506:15:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "BinaryOperation",
"operator": "-",
"rightExpression": {
"argumentTypes": null,
"hexValue": "31",
"id": 7373,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "2524:1:35",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
},
"value": "1"
},
"src": "2506:19:35",
"typeDescriptions": {
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "VariableDeclarationStatement",
"src": "2491:34:35"
},
{
"externalReferences": [
{
"src": {
"declaration": 7342,
"isOffset": false,
"isSlot": false,
"src": "2573:3:35",
"valueSize": 1
}
},
{
"mask": {
"declaration": 7366,
"isOffset": false,
"isSlot": false,
"src": "2583:4:35",
"valueSize": 1
}
},
{
"dest": {
"declaration": 7340,
"isOffset": false,
"isSlot": false,
"src": "2622:4:35",
"valueSize": 1
}
},
{
"mask": {
"declaration": 7366,
"isOffset": false,
"isSlot": false,
"src": "2629:4:35",
"valueSize": 1
}
},
{
"dest": {
"declaration": 7340,
"isOffset": false,
"isSlot": false,
"src": "2648:4:35",
"valueSize": 1
}
}
],
"id": 7376,
"nodeType": "InlineAssembly",
"operations": "{\n let srcpart := and(mload(src), not(mask))\n let destpart := and(mload(dest), mask)\n mstore(dest, or(destpart, srcpart))\n}",
"src": "2531:155:35"
}
]
},
"documentation": null,
"id": 7378,
"implemented": true,
"isConstructor": false,
"isDeclaredConst": true,
"modifiers": [],
"name": "memcpy",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 7345,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 7340,
"name": "dest",
"nodeType": "VariableDeclaration",
"scope": 7378,
"src": "2212:12:35",
"stateVariable": false,
"storageLocation": "de