Arrays.sol 18 KB

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