Arrays.sol 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v5.0.0) (utils/Arrays.sol)
  3. // This file was procedurally generated from scripts/generate/templates/Arrays.js.
  4. pragma solidity ^0.8.20;
  5. import {StorageSlot} from "./StorageSlot.sol";
  6. import {Math} from "./math/Math.sol";
  7. /**
  8. * @dev Collection of functions related to array types.
  9. */
  10. library Arrays {
  11. using StorageSlot for bytes32;
  12. /**
  13. * @dev Sort an array of bytes32 (in memory) following the provided comparator function.
  14. *
  15. * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
  16. * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
  17. *
  18. * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
  19. * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
  20. * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
  21. * consume more gas than is available in a block, leading to potential DoS.
  22. */
  23. function sort(
  24. bytes32[] memory array,
  25. function(bytes32, bytes32) pure returns (bool) comp
  26. ) internal pure returns (bytes32[] memory) {
  27. _quickSort(_begin(array), _end(array), comp);
  28. return array;
  29. }
  30. /**
  31. * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.
  32. */
  33. function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {
  34. sort(array, _defaultComp);
  35. return array;
  36. }
  37. /**
  38. * @dev Sort an array of address (in memory) following the provided comparator function.
  39. *
  40. * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
  41. * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
  42. *
  43. * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
  44. * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
  45. * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
  46. * consume more gas than is available in a block, leading to potential DoS.
  47. */
  48. function sort(
  49. address[] memory array,
  50. function(address, address) pure returns (bool) comp
  51. ) internal pure returns (address[] memory) {
  52. sort(_castToBytes32Array(array), _castToBytes32Comp(comp));
  53. return array;
  54. }
  55. /**
  56. * @dev Variant of {sort} that sorts an array of address in increasing order.
  57. */
  58. function sort(address[] memory array) internal pure returns (address[] memory) {
  59. sort(_castToBytes32Array(array), _defaultComp);
  60. return array;
  61. }
  62. /**
  63. * @dev Sort an array of uint256 (in memory) following the provided comparator function.
  64. *
  65. * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
  66. * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
  67. *
  68. * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
  69. * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
  70. * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
  71. * consume more gas than is available in a block, leading to potential DoS.
  72. */
  73. function sort(
  74. uint256[] memory array,
  75. function(uint256, uint256) pure returns (bool) comp
  76. ) internal pure returns (uint256[] memory) {
  77. sort(_castToBytes32Array(array), _castToBytes32Comp(comp));
  78. return array;
  79. }
  80. /**
  81. * @dev Variant of {sort} that sorts an array of uint256 in increasing order.
  82. */
  83. function sort(uint256[] memory array) internal pure returns (uint256[] memory) {
  84. sort(_castToBytes32Array(array), _defaultComp);
  85. return array;
  86. }
  87. /**
  88. * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops
  89. * at end (exclusive). Sorting follows the `comp` comparator.
  90. *
  91. * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.
  92. *
  93. * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should
  94. * be used only if the limits are within a memory array.
  95. */
  96. function _quickSort(uint256 begin, uint256 end, function(bytes32, bytes32) pure returns (bool) comp) private pure {
  97. unchecked {
  98. if (end - begin < 0x40) return;
  99. // Use first element as pivot
  100. bytes32 pivot = _mload(begin);
  101. // Position where the pivot should be at the end of the loop
  102. uint256 pos = begin;
  103. for (uint256 it = begin + 0x20; it < end; it += 0x20) {
  104. if (comp(_mload(it), pivot)) {
  105. // If the value stored at the iterator's position comes before the pivot, we increment the
  106. // position of the pivot and move the value there.
  107. pos += 0x20;
  108. _swap(pos, it);
  109. }
  110. }
  111. _swap(begin, pos); // Swap pivot into place
  112. _quickSort(begin, pos, comp); // Sort the left side of the pivot
  113. _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot
  114. }
  115. }
  116. /**
  117. * @dev Pointer to the memory location of the first element of `array`.
  118. */
  119. function _begin(bytes32[] memory array) private pure returns (uint256 ptr) {
  120. /// @solidity memory-safe-assembly
  121. assembly {
  122. ptr := add(array, 0x20)
  123. }
  124. }
  125. /**
  126. * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word
  127. * that comes just after the last element of the array.
  128. */
  129. function _end(bytes32[] memory array) private pure returns (uint256 ptr) {
  130. unchecked {
  131. return _begin(array) + array.length * 0x20;
  132. }
  133. }
  134. /**
  135. * @dev Load memory word (as a bytes32) at location `ptr`.
  136. */
  137. function _mload(uint256 ptr) private pure returns (bytes32 value) {
  138. assembly {
  139. value := mload(ptr)
  140. }
  141. }
  142. /**
  143. * @dev Swaps the elements memory location `ptr1` and `ptr2`.
  144. */
  145. function _swap(uint256 ptr1, uint256 ptr2) private pure {
  146. assembly {
  147. let value1 := mload(ptr1)
  148. let value2 := mload(ptr2)
  149. mstore(ptr1, value2)
  150. mstore(ptr2, value1)
  151. }
  152. }
  153. /// @dev Comparator for sorting arrays in increasing order.
  154. function _defaultComp(bytes32 a, bytes32 b) private pure returns (bool) {
  155. return a < b;
  156. }
  157. /// @dev Helper: low level cast address memory array to uint256 memory array
  158. function _castToBytes32Array(address[] memory input) private pure returns (bytes32[] memory output) {
  159. assembly {
  160. output := input
  161. }
  162. }
  163. /// @dev Helper: low level cast uint256 memory array to uint256 memory array
  164. function _castToBytes32Array(uint256[] memory input) private pure returns (bytes32[] memory output) {
  165. assembly {
  166. output := input
  167. }
  168. }
  169. /// @dev Helper: low level cast address comp function to bytes32 comp function
  170. function _castToBytes32Comp(
  171. function(address, address) pure returns (bool) input
  172. ) private pure returns (function(bytes32, bytes32) pure returns (bool) output) {
  173. assembly {
  174. output := input
  175. }
  176. }
  177. /// @dev Helper: low level cast uint256 comp function to bytes32 comp function
  178. function _castToBytes32Comp(
  179. function(uint256, uint256) pure returns (bool) input
  180. ) private pure returns (function(bytes32, bytes32) pure returns (bool) output) {
  181. assembly {
  182. output := input
  183. }
  184. }
  185. /**
  186. * @dev Searches a sorted `array` and returns the first index that contains
  187. * a value greater or equal to `element`. If no such index exists (i.e. all
  188. * values in the array are strictly less than `element`), the array length is
  189. * returned. Time complexity O(log n).
  190. *
  191. * NOTE: The `array` is expected to be sorted in ascending order, and to
  192. * contain no repeated elements.
  193. *
  194. * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks
  195. * support for repeated elements in the array. The {lowerBound} function should
  196. * be used instead.
  197. */
  198. function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
  199. uint256 low = 0;
  200. uint256 high = array.length;
  201. if (high == 0) {
  202. return 0;
  203. }
  204. while (low < high) {
  205. uint256 mid = Math.average(low, high);
  206. // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
  207. // because Math.average rounds towards zero (it does integer division with truncation).
  208. if (unsafeAccess(array, mid).value > element) {
  209. high = mid;
  210. } else {
  211. low = mid + 1;
  212. }
  213. }
  214. // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
  215. if (low > 0 && unsafeAccess(array, low - 1).value == element) {
  216. return low - 1;
  217. } else {
  218. return low;
  219. }
  220. }
  221. /**
  222. * @dev Searches an `array` sorted in ascending order and returns the first
  223. * index that contains a value greater or equal than `element`. If no such index
  224. * exists (i.e. all values in the array are strictly less than `element`), the array
  225. * length is returned. Time complexity O(log n).
  226. *
  227. * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].
  228. */
  229. function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
  230. uint256 low = 0;
  231. uint256 high = array.length;
  232. if (high == 0) {
  233. return 0;
  234. }
  235. while (low < high) {
  236. uint256 mid = Math.average(low, high);
  237. // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
  238. // because Math.average rounds towards zero (it does integer division with truncation).
  239. if (unsafeAccess(array, mid).value < element) {
  240. // this cannot overflow because mid < high
  241. unchecked {
  242. low = mid + 1;
  243. }
  244. } else {
  245. high = mid;
  246. }
  247. }
  248. return low;
  249. }
  250. /**
  251. * @dev Searches an `array` sorted in ascending order and returns the first
  252. * index that contains a value strictly greater than `element`. If no such index
  253. * exists (i.e. all values in the array are strictly less than `element`), the array
  254. * length is returned. Time complexity O(log n).
  255. *
  256. * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].
  257. */
  258. function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
  259. uint256 low = 0;
  260. uint256 high = array.length;
  261. if (high == 0) {
  262. return 0;
  263. }
  264. while (low < high) {
  265. uint256 mid = Math.average(low, high);
  266. // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
  267. // because Math.average rounds towards zero (it does integer division with truncation).
  268. if (unsafeAccess(array, mid).value > element) {
  269. high = mid;
  270. } else {
  271. // this cannot overflow because mid < high
  272. unchecked {
  273. low = mid + 1;
  274. }
  275. }
  276. }
  277. return low;
  278. }
  279. /**
  280. * @dev Same as {lowerBound}, but with an array in memory.
  281. */
  282. function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
  283. uint256 low = 0;
  284. uint256 high = array.length;
  285. if (high == 0) {
  286. return 0;
  287. }
  288. while (low < high) {
  289. uint256 mid = Math.average(low, high);
  290. // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
  291. // because Math.average rounds towards zero (it does integer division with truncation).
  292. if (unsafeMemoryAccess(array, mid) < element) {
  293. // this cannot overflow because mid < high
  294. unchecked {
  295. low = mid + 1;
  296. }
  297. } else {
  298. high = mid;
  299. }
  300. }
  301. return low;
  302. }
  303. /**
  304. * @dev Same as {upperBound}, but with an array in memory.
  305. */
  306. function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
  307. uint256 low = 0;
  308. uint256 high = array.length;
  309. if (high == 0) {
  310. return 0;
  311. }
  312. while (low < high) {
  313. uint256 mid = Math.average(low, high);
  314. // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
  315. // because Math.average rounds towards zero (it does integer division with truncation).
  316. if (unsafeMemoryAccess(array, mid) > element) {
  317. high = mid;
  318. } else {
  319. // this cannot overflow because mid < high
  320. unchecked {
  321. low = mid + 1;
  322. }
  323. }
  324. }
  325. return low;
  326. }
  327. /**
  328. * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
  329. *
  330. * WARNING: Only use if you are certain `pos` is lower than the array length.
  331. */
  332. function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
  333. bytes32 slot;
  334. // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
  335. // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
  336. /// @solidity memory-safe-assembly
  337. assembly {
  338. mstore(0, arr.slot)
  339. slot := add(keccak256(0, 0x20), pos)
  340. }
  341. return slot.getAddressSlot();
  342. }
  343. /**
  344. * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
  345. *
  346. * WARNING: Only use if you are certain `pos` is lower than the array length.
  347. */
  348. function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
  349. bytes32 slot;
  350. // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
  351. // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
  352. /// @solidity memory-safe-assembly
  353. assembly {
  354. mstore(0, arr.slot)
  355. slot := add(keccak256(0, 0x20), pos)
  356. }
  357. return slot.getBytes32Slot();
  358. }
  359. /**
  360. * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
  361. *
  362. * WARNING: Only use if you are certain `pos` is lower than the array length.
  363. */
  364. function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
  365. bytes32 slot;
  366. // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
  367. // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
  368. /// @solidity memory-safe-assembly
  369. assembly {
  370. mstore(0, arr.slot)
  371. slot := add(keccak256(0, 0x20), pos)
  372. }
  373. return slot.getUint256Slot();
  374. }
  375. /**
  376. * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
  377. *
  378. * WARNING: Only use if you are certain `pos` is lower than the array length.
  379. */
  380. function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
  381. assembly {
  382. res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
  383. }
  384. }
  385. /**
  386. * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
  387. *
  388. * WARNING: Only use if you are certain `pos` is lower than the array length.
  389. */
  390. function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {
  391. assembly {
  392. res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
  393. }
  394. }
  395. /**
  396. * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
  397. *
  398. * WARNING: Only use if you are certain `pos` is lower than the array length.
  399. */
  400. function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
  401. assembly {
  402. res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
  403. }
  404. }
  405. /**
  406. * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden.
  407. *
  408. * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
  409. */
  410. function unsafeSetLength(address[] storage array, uint256 len) internal {
  411. assembly {
  412. sstore(array.slot, len)
  413. }
  414. }
  415. /**
  416. * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden.
  417. *
  418. * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
  419. */
  420. function unsafeSetLength(bytes32[] storage array, uint256 len) internal {
  421. assembly {
  422. sstore(array.slot, len)
  423. }
  424. }
  425. /**
  426. * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden.
  427. *
  428. * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
  429. */
  430. function unsafeSetLength(uint256[] storage array, uint256 len) internal {
  431. assembly {
  432. sstore(array.slot, len)
  433. }
  434. }
  435. }