UNPKG

witnet-solidity-bridge

Version:

Witnet Solidity Bridge contracts for EVM-compatible chains

521 lines (520 loc) 1.18 MB
{ "contractName": "Slices", "abi": [], "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project:/contracts/libs/Slices.sol\":\"Slices\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"project:/contracts/libs/Slices.sol\":{\"keccak256\":\"0x9d046fa558be922c9625a1fdc470f6e68b3c9b5745b6185cb4a4fc59181fa006\",\"license\":\"APACHE-2.0\",\"urls\":[\"bzz-raw://ab19ba09faf83aaa92947f0a0907f6522be89279a9a1b0e53d5393a23085947d\",\"dweb:/ipfs/QmeE9MwhpSFNTwyqDFpMFjftrJKR1edBhLjV3bdKQQHUVm\"]}},\"version\":1}", "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122034fe14c8b25328bfcb02b0c149122aee94eb93ae34a50ac29bfcd2381db3577464736f6c63430008190033", "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122034fe14c8b25328bfcb02b0c149122aee94eb93ae34a50ac29bfcd2381db3577464736f6c63430008190033", "immutableReferences": {}, "generatedSources": [], "deployedGeneratedSources": [], "sourceMap": "2090:24418:63:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;2090:24418:63;;;;;;;;;;;;;;;;;", "deployedSourceMap": "2090:24418:63:-:0;;;;;;;;", "source": "// SPDX-License-Identifier: APACHE-2.0\r\n\r\npragma solidity >=0.8.0 <0.9.0;\r\n\r\n/*\r\n * @title String & Slice utility library for Solidity contracts.\r\n * @author Nick Johnson <arachnid@notdot.net>\r\n *\r\n * @dev Functionality in this library is largely implemented using an\r\n * abstraction called a 'Slice'. A Slice represents a part of a string -\r\n * anything from the entire string to a single character, or even no\r\n * characters at all (a 0-length Slice). Since a Slice only has to specify\r\n * an offset and a length, copying and manipulating slices is a lot less\r\n * expensive than copying and manipulating the strings they reference.\r\n *\r\n * To further reduce gas costs, most functions on Slice that need to return\r\n * a Slice modify the original one instead of allocating a new one; for\r\n * instance, `s.split(\".\")` will return the text up to the first '.',\r\n * modifying s to only contain the remainder of the string after the '.'.\r\n * In situations where you do not want to modify the original Slice, you\r\n * can make a copy first with `.copy()`, for example:\r\n * `s.copy().split(\".\")`. Try and avoid using this idiom in loops; since\r\n * Solidity has no memory management, it will result in allocating many\r\n * short-lived slices that are later discarded.\r\n *\r\n * Functions that return two slices come in two versions: a non-allocating\r\n * version that takes the second Slice as an argument, modifying it in\r\n * place, and an allocating version that allocates and returns the second\r\n * Slice; see `nextRune` for example.\r\n *\r\n * Functions that have to copy string data will return strings rather than\r\n * slices; these can be cast back to slices for further processing if\r\n * required.\r\n *\r\n * For convenience, some functions are provided with non-modifying\r\n * variants that create a new Slice and return both; for instance,\r\n * `s.splitNew('.')` leaves s unmodified, and returns two values\r\n * corresponding to the left and right parts of the string.\r\n */\r\n\r\nlibrary Slices {\r\n \r\n struct Slice {\r\n uint _len;\r\n uint _ptr;\r\n }\r\n\r\n function _memcpy(uint _dest, uint _src, uint _len) private pure {\r\n // Copy word-length chunks while possible\r\n for(; _len >= 32; _len -= 32) {\r\n assembly {\r\n mstore(_dest, mload(_src))\r\n }\r\n _dest += 32;\r\n _src += 32;\r\n }\r\n\r\n // Copy remaining bytes\r\n uint _mask = type(uint).max;\r\n if (_len > 0) {\r\n _mask = 256 ** (32 - _len) - 1;\r\n }\r\n assembly {\r\n let srcpart := and(mload(_src), not(_mask))\r\n let destpart := and(mload(_dest), _mask)\r\n mstore(_dest, or(destpart, srcpart))\r\n }\r\n }\r\n\r\n /*\r\n * @dev Returns a Slice containing the entire string.\r\n * @param self The string to make a Slice from.\r\n * @return A newly allocated Slice containing the entire string.\r\n */\r\n function toSlice(string memory self) internal pure returns (Slice memory) {\r\n uint ptr;\r\n assembly {\r\n ptr := add(self, 0x20)\r\n }\r\n return Slice(bytes(self).length, ptr);\r\n }\r\n\r\n /*\r\n * @dev Returns the length of a null-terminated bytes32 string.\r\n * @param self The value to find the length of.\r\n * @return The length of the string, from 0 to 32.\r\n */\r\n function len(bytes32 self) internal pure returns (uint) {\r\n uint ret;\r\n if (self == 0)\r\n return 0;\r\n if (uint(self) & type(uint128).max == 0) {\r\n ret += 16;\r\n self = bytes32(uint(self) / 0x100000000000000000000000000000000);\r\n }\r\n if (uint(self) & type(uint64).max == 0) {\r\n ret += 8;\r\n self = bytes32(uint(self) / 0x10000000000000000);\r\n }\r\n if (uint(self) & type(uint32).max == 0) {\r\n ret += 4;\r\n self = bytes32(uint(self) / 0x100000000);\r\n }\r\n if (uint(self) & type(uint16).max == 0) {\r\n ret += 2;\r\n self = bytes32(uint(self) / 0x10000);\r\n }\r\n if (uint(self) & type(uint8).max == 0) {\r\n ret += 1;\r\n }\r\n return 32 - ret;\r\n }\r\n\r\n /*\r\n * @dev Returns a Slice containing the entire bytes32, interpreted as a\r\n * null-terminated utf-8 string.\r\n * @param self The bytes32 value to convert to a Slice.\r\n * @return A new Slice containing the value of the input argument up to the\r\n * first null.\r\n */\r\n function toSliceB32(bytes32 self) internal pure returns (Slice memory ret) {\r\n // Allocate space for `self` in memory, copy it there, and point ret at it\r\n assembly {\r\n let ptr := mload(0x40)\r\n mstore(0x40, add(ptr, 0x20))\r\n mstore(ptr, self)\r\n mstore(add(ret, 0x20), ptr)\r\n }\r\n ret._len = len(self);\r\n }\r\n\r\n /*\r\n * @dev Returns a new Slice containing the same data as the current Slice.\r\n * @param self The Slice to copy.\r\n * @return A new Slice containing the same data as `self`.\r\n */\r\n function copy(Slice memory self) internal pure returns (Slice memory) {\r\n return Slice(self._len, self._ptr);\r\n }\r\n\r\n /*\r\n * @dev Copies a Slice to a new string.\r\n * @param self The Slice to copy.\r\n * @return A newly allocated string containing the Slice's text.\r\n */\r\n function toString(Slice memory self) internal pure returns (string memory) {\r\n string memory ret = new string(self._len);\r\n uint retptr;\r\n assembly { retptr := add(ret, 32) }\r\n\r\n _memcpy(retptr, self._ptr, self._len);\r\n return ret;\r\n }\r\n\r\n /*\r\n * @dev Returns the length in runes of the Slice. Note that this operation\r\n * takes time proportional to the length of the Slice; avoid using it\r\n * in loops, and call `Slice.empty()` if you only need to know whether\r\n * the Slice is empty or not.\r\n * @param self The Slice to operate on.\r\n * @return The length of the Slice in runes.\r\n */\r\n function len(Slice memory self) internal pure returns (uint _l) {\r\n // Starting at ptr-31 means the LSB will be the byte we care about\r\n uint ptr = self._ptr - 31;\r\n uint end = ptr + self._len;\r\n for (_l = 0; ptr < end; _l++) {\r\n uint8 b;\r\n assembly { b := and(mload(ptr), 0xFF) }\r\n if (b < 0x80) {\r\n ptr += 1;\r\n } else if(b < 0xE0) {\r\n ptr += 2;\r\n } else if(b < 0xF0) {\r\n ptr += 3;\r\n } else if(b < 0xF8) {\r\n ptr += 4;\r\n } else if(b < 0xFC) {\r\n ptr += 5;\r\n } else {\r\n ptr += 6;\r\n }\r\n }\r\n }\r\n\r\n /*\r\n * @dev Returns true if the Slice is empty (has a length of 0).\r\n * @param self The Slice to operate on.\r\n * @return True if the Slice is empty, False otherwise.\r\n */\r\n function empty(Slice memory self) internal pure returns (bool) {\r\n return self._len == 0;\r\n }\r\n\r\n /*\r\n * @dev Returns a positive number if `other` comes lexicographically after\r\n * `self`, a negative number if it comes before, or zero if the\r\n * contents of the two slices are equal. Comparison is done per-rune,\r\n * on unicode codepoints.\r\n * @param self The first Slice to compare.\r\n * @param other The second Slice to compare.\r\n * @return The result of the comparison.\r\n */\r\n function compare(Slice memory self, Slice memory other) internal pure returns (int) {\r\n uint shortest = self._len;\r\n if (other._len < self._len)\r\n shortest = other._len;\r\n\r\n uint selfptr = self._ptr;\r\n uint otherptr = other._ptr;\r\n for (uint idx = 0; idx < shortest; idx += 32) {\r\n uint a;\r\n uint b;\r\n assembly {\r\n a := mload(selfptr)\r\n b := mload(otherptr)\r\n }\r\n if (a != b) {\r\n // Mask out irrelevant bytes and check again\r\n uint mask = type(uint).max; // 0xffff...\r\n if(shortest < 32) {\r\n mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);\r\n }\r\n unchecked {\r\n uint diff = (a & mask) - (b & mask);\r\n if (diff != 0)\r\n return int(diff);\r\n }\r\n }\r\n selfptr += 32;\r\n otherptr += 32;\r\n }\r\n return int(self._len) - int(other._len);\r\n }\r\n\r\n /*\r\n * @dev Returns true if the two slices contain the same text.\r\n * @param self The first Slice to compare.\r\n * @param self The second Slice to compare.\r\n * @return True if the slices are equal, false otherwise.\r\n */\r\n function equals(Slice memory self, Slice memory other) internal pure returns (bool) {\r\n return compare(self, other) == 0;\r\n }\r\n\r\n /*\r\n * @dev Extracts the first rune in the Slice into `rune`, advancing the\r\n * Slice to point to the next rune and returning `self`.\r\n * @param self The Slice to operate on.\r\n * @param rune The Slice that will contain the first rune.\r\n * @return `rune`.\r\n */\r\n function nextRune(Slice memory self, Slice memory rune) internal pure returns (Slice memory) {\r\n rune._ptr = self._ptr;\r\n\r\n if (self._len == 0) {\r\n rune._len = 0;\r\n return rune;\r\n }\r\n\r\n uint _l;\r\n uint _b;\r\n // Load the first byte of the rune into the LSBs of _b\r\n assembly { _b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) }\r\n if (_b < 0x80) {\r\n _l = 1;\r\n } else if(_b < 0xE0) {\r\n _l = 2;\r\n } else if(_b < 0xF0) {\r\n _l = 3;\r\n } else {\r\n _l = 4;\r\n }\r\n\r\n // Check for truncated codepoints\r\n if (_l > self._len) {\r\n rune._len = self._len;\r\n self._ptr += self._len;\r\n self._len = 0;\r\n return rune;\r\n }\r\n\r\n self._ptr += _l;\r\n self._len -= _l;\r\n rune._len = _l;\r\n return rune;\r\n }\r\n\r\n /*\r\n * @dev Returns the first rune in the Slice, advancing the Slice to point\r\n * to the next rune.\r\n * @param self The Slice to operate on.\r\n * @return A Slice containing only the first rune from `self`.\r\n */\r\n function nextRune(Slice memory self) internal pure returns (Slice memory ret) {\r\n nextRune(self, ret);\r\n }\r\n\r\n /*\r\n * @dev Returns the number of the first codepoint in the Slice.\r\n * @param self The Slice to operate on.\r\n * @return The number of the first codepoint in the Slice.\r\n */\r\n function ord(Slice memory self) internal pure returns (uint ret) {\r\n if (self._len == 0) {\r\n return 0;\r\n }\r\n\r\n uint word;\r\n uint length;\r\n uint divisor = 2 ** 248;\r\n\r\n // Load the rune into the MSBs of b\r\n assembly { word:= mload(mload(add(self, 32))) }\r\n uint b = word / divisor;\r\n if (b < 0x80) {\r\n ret = b;\r\n length = 1;\r\n } else if(b < 0xE0) {\r\n ret = b & 0x1F;\r\n length = 2;\r\n } else if(b < 0xF0) {\r\n ret = b & 0x0F;\r\n length = 3;\r\n } else {\r\n ret = b & 0x07;\r\n length = 4;\r\n }\r\n\r\n // Check for truncated codepoints\r\n if (length > self._len) {\r\n return 0;\r\n }\r\n\r\n for (uint i = 1; i < length; i++) {\r\n divisor = divisor / 256;\r\n b = (word / divisor) & 0xFF;\r\n if (b & 0xC0 != 0x80) {\r\n // Invalid UTF-8 sequence\r\n return 0;\r\n }\r\n ret = (ret * 64) | (b & 0x3F);\r\n }\r\n\r\n return ret;\r\n }\r\n\r\n /*\r\n * @dev Returns the keccak-256 hash of the Slice.\r\n * @param self The Slice to hash.\r\n * @return The hash of the Slice.\r\n */\r\n function keccak(Slice memory self) internal pure returns (bytes32 ret) {\r\n assembly {\r\n ret := keccak256(mload(add(self, 32)), mload(self))\r\n }\r\n }\r\n\r\n /*\r\n * @dev Returns true if `self` starts with `needle`.\r\n * @param self The Slice to operate on.\r\n * @param needle The Slice to search for.\r\n * @return True if the Slice starts with the provided text, false otherwise.\r\n */\r\n function startsWith(Slice memory self, Slice memory needle) internal pure returns (bool) {\r\n if (self._len < needle._len) {\r\n return false;\r\n }\r\n\r\n if (self._ptr == needle._ptr) {\r\n return true;\r\n }\r\n\r\n bool equal;\r\n assembly {\r\n let length := mload(needle)\r\n let selfptr := mload(add(self, 0x20))\r\n let needleptr := mload(add(needle, 0x20))\r\n equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\r\n }\r\n return equal;\r\n }\r\n\r\n /*\r\n * @dev If `self` starts with `needle`, `needle` is removed from the\r\n * beginning of `self`. Otherwise, `self` is unmodified.\r\n * @param self The Slice to operate on.\r\n * @param needle The Slice to search for.\r\n * @return `self`\r\n */\r\n function beyond(Slice memory self, Slice memory needle) internal pure returns (Slice memory) {\r\n if (self._len < needle._len) {\r\n return self;\r\n }\r\n\r\n bool equal = true;\r\n if (self._ptr != needle._ptr) {\r\n assembly {\r\n let length := mload(needle)\r\n let selfptr := mload(add(self, 0x20))\r\n let needleptr := mload(add(needle, 0x20))\r\n equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\r\n }\r\n }\r\n\r\n if (equal) {\r\n self._len -= needle._len;\r\n self._ptr += needle._len;\r\n }\r\n\r\n return self;\r\n }\r\n\r\n /*\r\n * @dev Returns true if the Slice ends with `needle`.\r\n * @param self The Slice to operate on.\r\n * @param needle The Slice to search for.\r\n * @return True if the Slice starts with the provided text, false otherwise.\r\n */\r\n function endsWith(Slice memory self, Slice memory needle) internal pure returns (bool) {\r\n if (self._len < needle._len) {\r\n return false;\r\n }\r\n\r\n uint selfptr = self._ptr + self._len - needle._len;\r\n\r\n if (selfptr == needle._ptr) {\r\n return true;\r\n }\r\n\r\n bool equal;\r\n assembly {\r\n let length := mload(needle)\r\n let needleptr := mload(add(needle, 0x20))\r\n equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\r\n }\r\n\r\n return equal;\r\n }\r\n\r\n /*\r\n * @dev If `self` ends with `needle`, `needle` is removed from the\r\n * end of `self`. Otherwise, `self` is unmodified.\r\n * @param self The Slice to operate on.\r\n * @param needle The Slice to search for.\r\n * @return `self`\r\n */\r\n function until(Slice memory self, Slice memory needle) internal pure returns (Slice memory) {\r\n if (self._len < needle._len) {\r\n return self;\r\n }\r\n\r\n uint selfptr = self._ptr + self._len - needle._len;\r\n bool equal = true;\r\n if (selfptr != needle._ptr) {\r\n assembly {\r\n let length := mload(needle)\r\n let needleptr := mload(add(needle, 0x20))\r\n equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\r\n }\r\n }\r\n\r\n if (equal) {\r\n self._len -= needle._len;\r\n }\r\n\r\n return self;\r\n }\r\n\r\n // Returns the memory address of the first byte of the first occurrence of\r\n // `needle` in `self`, or the first byte after `self` if not found.\r\n function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {\r\n uint ptr = selfptr;\r\n uint idx;\r\n\r\n if (needlelen <= selflen) {\r\n if (needlelen <= 32) {\r\n bytes32 mask;\r\n if (needlelen > 0) {\r\n mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));\r\n }\r\n\r\n bytes32 needledata;\r\n assembly { needledata := and(mload(needleptr), mask) }\r\n\r\n uint end = selfptr + selflen - needlelen;\r\n bytes32 ptrdata;\r\n assembly { ptrdata := and(mload(ptr), mask) }\r\n\r\n while (ptrdata != needledata) {\r\n if (ptr >= end)\r\n return selfptr + selflen;\r\n ptr++;\r\n assembly { ptrdata := and(mload(ptr), mask) }\r\n }\r\n return ptr;\r\n } else {\r\n // For long needles, use hashing\r\n bytes32 hash;\r\n assembly { hash := keccak256(needleptr, needlelen) }\r\n\r\n for (idx = 0; idx <= selflen - needlelen; idx++) {\r\n bytes32 testHash;\r\n assembly { testHash := keccak256(ptr, needlelen) }\r\n if (hash == testHash)\r\n return ptr;\r\n ptr += 1;\r\n }\r\n }\r\n }\r\n return selfptr + selflen;\r\n }\r\n\r\n // Returns the memory address of the first byte after the last occurrence of\r\n // `needle` in `self`, or the address of `self` if not found.\r\n function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {\r\n uint ptr;\r\n\r\n if (needlelen <= selflen) {\r\n if (needlelen <= 32) {\r\n bytes32 mask;\r\n if (needlelen > 0) {\r\n mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));\r\n }\r\n\r\n bytes32 needledata;\r\n assembly { needledata := and(mload(needleptr), mask) }\r\n\r\n ptr = selfptr + selflen - needlelen;\r\n bytes32 ptrdata;\r\n assembly { ptrdata := and(mload(ptr), mask) }\r\n\r\n while (ptrdata != needledata) {\r\n if (ptr <= selfptr)\r\n return selfptr;\r\n ptr--;\r\n assembly { ptrdata := and(mload(ptr), mask) }\r\n }\r\n return ptr + needlelen;\r\n } else {\r\n // For long needles, use hashing\r\n bytes32 hash;\r\n assembly { hash := keccak256(needleptr, needlelen) }\r\n ptr = selfptr + (selflen - needlelen);\r\n while (ptr >= selfptr) {\r\n bytes32 testHash;\r\n assembly { testHash := keccak256(ptr, needlelen) }\r\n if (hash == testHash)\r\n return ptr + needlelen;\r\n ptr -= 1;\r\n }\r\n }\r\n }\r\n return selfptr;\r\n }\r\n\r\n /*\r\n * @dev Modifies `self` to contain everything from the first occurrence of\r\n * `needle` to the end of the Slice. `self` is set to the empty Slice\r\n * if `needle` is not found.\r\n * @param self The Slice to search and modify.\r\n * @param needle The text to search for.\r\n * @return `self`.\r\n */\r\n function find(Slice memory self, Slice memory needle) internal pure returns (Slice memory) {\r\n uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);\r\n self._len -= ptr - self._ptr;\r\n self._ptr = ptr;\r\n return self;\r\n }\r\n\r\n /*\r\n * @dev Modifies `self` to contain the part of the string from the start of\r\n * `self` to the end of the first occurrence of `needle`. If `needle`\r\n * is not found, `self` is set to the empty Slice.\r\n * @param self The Slice to search and modify.\r\n * @param needle The text to search for.\r\n * @return `self`.\r\n */\r\n function rfind(Slice memory self, Slice memory needle) internal pure returns (Slice memory) {\r\n uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);\r\n self._len = ptr - self._ptr;\r\n return self;\r\n }\r\n\r\n /*\r\n * @dev Splits the Slice, setting `self` to everything after the first\r\n * occurrence of `needle`, and `token` to everything before it. If\r\n * `needle` does not occur in `self`, `self` is set to the empty Slice,\r\n * and `token` is set to the entirety of `self`.\r\n * @param self The Slice to split.\r\n * @param needle The text to search for in `self`.\r\n * @param token An output parameter to which the first token is written.\r\n * @return `token`.\r\n */\r\n function split(Slice memory self, Slice memory needle, Slice memory token) internal pure returns (Slice memory) {\r\n uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);\r\n token._ptr = self._ptr;\r\n token._len = ptr - self._ptr;\r\n if (ptr == self._ptr + self._len) {\r\n // Not found\r\n self._len = 0;\r\n } else {\r\n self._len -= token._len + needle._len;\r\n self._ptr = ptr + needle._len;\r\n }\r\n return token;\r\n }\r\n\r\n /*\r\n * @dev Splits the Slice, setting `self` to everything after the first\r\n * occurrence of `needle`, and returning everything before it. If\r\n * `needle` does not occur in `self`, `self` is set to the empty Slice,\r\n * and the entirety of `self` is returned.\r\n * @param self The Slice to split.\r\n * @param needle The text to search for in `self`.\r\n * @return The part of `self` up to the first occurrence of `delim`.\r\n */\r\n function split(Slice memory self, Slice memory needle) internal pure returns (Slice memory token) {\r\n split(self, needle, token);\r\n }\r\n\r\n /*\r\n * @dev Splits the Slice, setting `self` to everything before the last\r\n * occurrence of `needle`, and `token` to everything after it. If\r\n * `needle` does not occur in `self`, `self` is set to the empty Slice,\r\n * and `token` is set to the entirety of `self`.\r\n * @param self The Slice to split.\r\n * @param needle The text to search for in `self`.\r\n * @param token An output parameter to which the first token is written.\r\n * @return `token`.\r\n */\r\n function rsplit(Slice memory self, Slice memory needle, Slice memory token) internal pure returns (Slice memory) {\r\n uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);\r\n token._ptr = ptr;\r\n token._len = self._len - (ptr - self._ptr);\r\n if (ptr == self._ptr) {\r\n // Not found\r\n self._len = 0;\r\n } else {\r\n self._len -= token._len + needle._len;\r\n }\r\n return token;\r\n }\r\n\r\n /*\r\n * @dev Splits the Slice, setting `self` to everything before the last\r\n * occurrence of `needle`, and returning everything after it. If\r\n * `needle` does not occur in `self`, `self` is set to the empty Slice,\r\n * and the entirety of `self` is returned.\r\n * @param self The Slice to split.\r\n * @param needle The text to search for in `self`.\r\n * @return The part of `self` after the last occurrence of `delim`.\r\n */\r\n function rsplit(Slice memory self, Slice memory needle) internal pure returns (Slice memory token) {\r\n rsplit(self, needle, token);\r\n }\r\n\r\n /*\r\n * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`.\r\n * @param self The Slice to search.\r\n * @param needle The text to search for in `self`.\r\n * @return The number of occurrences of `needle` found in `self`.\r\n */\r\n function count(Slice memory self, Slice memory needle) internal pure returns (uint cnt) {\r\n uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len;\r\n while (ptr <= self._ptr + self._len) {\r\n cnt++;\r\n ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len;\r\n }\r\n }\r\n\r\n /*\r\n * @dev Returns True if `self` contains `needle`.\r\n * @param self The Slice to search.\r\n * @param needle The text to search for in `self`.\r\n * @return True if `needle` is found in `self`, false otherwise.\r\n */\r\n function contains(Slice memory self, Slice memory needle) internal pure returns (bool) {\r\n return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr;\r\n }\r\n\r\n /*\r\n * @dev Returns a newly allocated string containing the concatenation of\r\n * `self` and `other`.\r\n * @param self The first Slice to concatenate.\r\n * @param other The second Slice to concatenate.\r\n * @return The concatenation of the two strings.\r\n */\r\n function concat(Slice memory self, Slice memory other) internal pure returns (string memory) {\r\n string memory ret = new string(self._len + other._len);\r\n uint retptr;\r\n assembly { retptr := add(ret, 32) }\r\n _memcpy(retptr, self._ptr, self._len);\r\n _memcpy(retptr + self._len, other._ptr, other._len);\r\n return ret;\r\n }\r\n\r\n /*\r\n * @dev Joins an array of slices, using `self` as a delimiter, returning a\r\n * newly allocated string.\r\n * @param self The delimiter to use.\r\n * @param parts A list of slices to join.\r\n * @return A newly allocated string containing all the slices in `parts`,\r\n * joined with `self`.\r\n */\r\n function join(Slice memory self, Slice[] memory parts) internal pure returns (string memory) {\r\n if (parts.length == 0)\r\n return \"\";\r\n\r\n uint length = self._len * (parts.length - 1);\r\n for(uint i = 0; i < parts.length; i++)\r\n length += parts[i]._len;\r\n\r\n string memory ret = new string(length);\r\n uint retptr;\r\n assembly { retptr := add(ret, 32) }\r\n\r\n for(uint i = 0; i < parts.length; i++) {\r\n _memcpy(retptr, parts[i]._ptr, parts[i]._len);\r\n retptr += parts[i]._len;\r\n if (i < parts.length - 1) {\r\n _memcpy(retptr, self._ptr, self._len);\r\n retptr += self._len;\r\n }\r\n }\r\n\r\n return ret;\r\n }\r\n}", "sourcePath": "C:\\Users\\guill\\github\\witnet\\witnet-solidity-bridge\\contracts\\libs\\Slices.sol", "ast": { "absolutePath": "project:/contracts/libs/Slices.sol", "exportedSymbols": { "Slices": [ 15980 ] }, "id": 15981, "license": "APACHE-2.0", "nodeType": "SourceUnit", "nodes": [ { "id": 14151, "literals": [ "solidity", ">=", "0.8", ".0", "<", "0.9", ".0" ], "nodeType": "PragmaDirective", "src": "42:31:63" }, { "abstract": false, "baseContracts": [], "canonicalName": "Slices", "contractDependencies": [], "contractKind": "library", "fullyImplemented": true, "id": 15980, "linearizedBaseContracts": [ 15980 ], "name": "Slices", "nameLocation": "2098:6:63", "nodeType": "ContractDefinition", "nodes": [ { "canonicalName": "Slices.Slice", "id": 14156, "members": [ { "constant": false, "id": 14153, "mutability": "mutable", "name": "_len", "nameLocation": "2147:4:63", "nodeType": "VariableDeclaration", "scope": 14156, "src": "2142:9:63", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "typeName": { "id": 14152, "name": "uint", "nodeType": "ElementaryTypeName", "src": "2142:4:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "visibility": "internal" }, { "constant": false, "id": 14155, "mutability": "mutable", "name": "_ptr", "nameLocation": "2167:4:63", "nodeType": "VariableDeclaration", "scope": 14156, "src": "2162:9:63", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "typeName": { "id": 14154, "name": "uint", "nodeType": "ElementaryTypeName", "src": "2162:4:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "visibility": "internal" } ], "name": "Slice", "nameLocation": "2125:5:63", "nodeType": "StructDefinition", "scope": 15980, "src": "2118:61:63", "visibility": "public" }, { "body": { "id": 14208, "nodeType": "Block", "src": "2251:591:63", "statements": [ { "body": { "id": 14181, "nodeType": "Block", "src": "2343:146:63", "statements": [ { "AST": { "nativeSrc": "2367:60:63", "nodeType": "YulBlock", "src": "2367:60:63", "statements": [ { "expression": { "arguments": [ { "name": "_dest", "nativeSrc": "2393:5:63", "nodeType": "YulIdentifier", "src": "2393:5:63" }, { "arguments": [ { "name": "_src", "nativeSrc": "2406:4:63", "nodeType": "YulIdentifier", "src": "2406:4:63" } ], "functionName": { "name": "mload", "nativeSrc": "2400:5:63", "nodeType": "YulIdentifier", "src": "2400:5:63" }, "nativeSrc": "2400:11:63", "nodeType": "YulFunctionCall", "src": "2400:11:63" } ], "functionName": { "name": "mstore", "nativeSrc": "2386:6:63", "nodeType": "YulIdentifier", "src": "2386:6:63" }, "nativeSrc": "2386:26:63", "nodeType": "YulFunctionCall", "src": "2386:26:63" }, "nativeSrc": "2386:26:63", "nodeType": "YulExpressionStatement", "src": "2386:26:63" } ] }, "evmVersion": "paris", "externalReferences": [ { "declaration": 14158, "isOffset": false, "isSlot": false, "src": "2393:5:63", "valueSize": 1 }, { "declaration": 14160, "isOffset": false, "isSlot": false, "src": "2406:4:63", "valueSize": 1 } ], "id": 14172, "nodeType": "InlineAssembly", "src": "2358:69:63" }, { "expression": { "id": 14175, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "leftHandSide": { "id": 14173, "name": "_dest", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 14158, "src": "2441:5:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "Assignment", "operator": "+=", "rightHandSide": { "hexValue": "3332", "id": 14174, "isConstant": false, "isLValue": false, "isPure": true, "kind": "number", "lValueRequested": false, "nodeType": "Literal", "src": "2450:2:63", "typeDescriptions": { "typeIdentifier": "t_rational_32_by_1", "typeString": "int_const 32" }, "value": "32" }, "src": "2441:11:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "id": 14176, "nodeType": "ExpressionStatement", "src": "2441:11:63" }, { "expression": { "id": 14179, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "leftHandSide": { "id": 14177, "name": "_src", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 14160, "src": "2467:4:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "Assignment", "operator": "+=", "rightHandSide": { "hexValue": "3332", "id": 14178, "isConstant": false, "isLValue": false, "isPure": true, "kind": "number", "lValueRequested": false, "nodeType": "Literal", "src": "2475:2:63", "typeDescriptions": { "typeIdentifier": "t_rational_32_by_1", "typeString": "int_const 32" }, "value": "32" }, "src": "2467:10:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "id": 14180, "nodeType": "ExpressionStatement", "src": "2467:10:63" } ] }, "condition": { "commonType": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "id": 14167, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "leftExpression": { "id": 14165, "name": "_len", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 14162, "src": "2319:4:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "BinaryOperation", "operator": ">=", "rightExpression": { "hexValue": "3332", "id": 14166, "isConstant": false, "isLValue": false, "isPure": true, "kind": "number", "lValueRequested": false, "nodeType": "Literal", "src": "2327:2:63", "typeDescriptions": { "typeIdentifier": "t_rational_32_by_1", "typeString": "int_const 32" }, "value": "32" }, "src": "2319:10:63", "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } }, "id": 14182, "isSimpleCounterLoop": false, "loopExpression": { "expression": { "id": 14170, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "leftHandSide": { "id": 14168, "name": "_len", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 14162, "src": "2331:4:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "Assignment", "operator": "-=", "rightHandSide": { "hexValue": "3332", "id": 14169, "isConstant": false, "isLValue": false, "isPure": true, "kind": "number", "lValueRequested": false, "nodeType": "Literal", "src": "2339:2:63", "typeDescriptions": { "typeIdentifier": "t_rational_32_by_1", "typeString": "int_const 32" }, "value": "32" }, "src": "2331:10:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "id": 14171, "nodeType": "ExpressionStatement", "src": "2331:10:63" }, "nodeType": "ForStatement", "src": "2313:176:63" }, { "assignments": [ 14184 ], "declarations": [ { "constant": false, "id": 14184, "mutability": "mutable", "name": "_mask", "nameLocation": "2539:5:63", "nodeType": "VariableDeclaration", "scope": 14208, "src": "2534:10:63", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "typeName": { "id": 14183, "name": "uint", "nodeType": "ElementaryTypeName", "src": "2534:4:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "visibility": "internal" } ], "id": 14190, "initialValue": { "expression": { "arguments": [ { "id": 14187, "isConstant": false, "isLValue": false, "isPure": true, "lValueRequested": false, "nodeType": "ElementaryTypeNameExpression", "src": "2552:4:63", "typeDescriptions": { "typeIdentifier": "t_type$_t_uint256_$", "typeString": "type(uint256)" }, "typeName": { "id": 14186, "name": "uint", "nodeType": "ElementaryTypeName", "src": "2552:4:63", "typeDescriptions": {} } } ], "expression": { "argumentTypes": [ { "typeIdentifier": "t_type$_t_uint256_$", "typeString": "type(uint256)" } ], "id": 14185, "name": "type", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 4294967269, "src": "2547:4:63", "typeDescriptions": { "typeIdentifier": "t_function_metatype_pure$__$returns$__$", "typeString": "function () pure" } }, "id": 14188, "isConstant": false, "isLValue": false, "isPure": true, "kind": "functionCall", "lValueRequested": false, "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "2547:10:63", "tryCall": false, "typeDescriptions": { "typeIdentifier": "t_magic_meta_type_t_uint256", "typeString": "type(uint256)" } }, "id": 14189, "isConstant": false, "isLValue": false, "isPure": true, "lValueRequested": false, "memberLocation": "2558:3:63", "memberName": "max", "nodeType": "MemberAccess", "src": "2547:14:63", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "VariableDeclarationStatement", "src": "2534:27:63" }, { "condition": { "commonType": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "id": 14193, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "leftExpression": { "id": 14191, "name": "_len",