Skip to content

Commit

Permalink
refactor: add int256 array lib
Browse files Browse the repository at this point in the history
  • Loading branch information
SeanJCasey authored Mar 26, 2024
1 parent 1f2984f commit fe18ecc
Showing 1 changed file with 176 additions and 0 deletions.
176 changes: 176 additions & 0 deletions contracts/utils/0.8.19/Int256ArrayLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// SPDX-License-Identifier: GPL-3.0

/*
This file is part of the Enzyme Protocol.
(c) Enzyme Council <council@enzyme.finance>
For the full license information, please view the LICENSE
file that was distributed with this source code.
*/

pragma solidity 0.8.19;

/// @title Int256Array Library
/// @author Enzyme Council <security@enzyme.finance>
/// @notice A library to extend the int256 array data type
library Int256ArrayLib {
/////////////
// STORAGE //
/////////////

/// @dev Helper to remove an item from a storage array
function removeStorageItem(int256[] storage _self, int256 _itemToRemove) internal returns (bool removed_) {
uint256 itemCount = _self.length;
for (uint256 i; i < itemCount; i++) {
if (_self[i] == _itemToRemove) {
if (i < itemCount - 1) {
_self[i] = _self[itemCount - 1];
}
_self.pop();
removed_ = true;
break;
}
}

return removed_;
}

/// @dev Helper to verify if a storage array contains a particular value
function storageArrayContains(int256[] storage _self, int256 _target) internal view returns (bool doesContain_) {
uint256 arrLength = _self.length;
for (uint256 i; i < arrLength; i++) {
if (_target == _self[i]) {
return true;
}
}
return false;
}

////////////
// MEMORY //
////////////

/// @dev Helper to add an item to an array. Does not assert uniqueness of the new item.
function addItem(int256[] memory _self, int256 _itemToAdd) internal pure returns (int256[] memory nextArray_) {
nextArray_ = new int256[](_self.length + 1);
for (uint256 i; i < _self.length; i++) {
nextArray_[i] = _self[i];
}
nextArray_[_self.length] = _itemToAdd;

return nextArray_;
}

/// @dev Helper to add an item to an array, only if it is not already in the array.
function addUniqueItem(int256[] memory _self, int256 _itemToAdd)
internal
pure
returns (int256[] memory nextArray_)
{
if (contains(_self, _itemToAdd)) {
return _self;
}

return addItem(_self, _itemToAdd);
}

/// @dev Helper to verify if an array contains a particular value
function contains(int256[] memory _self, int256 _target) internal pure returns (bool doesContain_) {
for (uint256 i; i < _self.length; i++) {
if (_target == _self[i]) {
return true;
}
}
return false;
}

/// @dev Helper to merge the unique items of a second array.
/// Does not consider uniqueness of either array, only relative uniqueness.
/// Preserves ordering.
function mergeArray(int256[] memory _self, int256[] memory _arrayToMerge)
internal
pure
returns (int256[] memory nextArray_)
{
uint256 newUniqueItemCount;
for (uint256 i; i < _arrayToMerge.length; i++) {
if (!contains(_self, _arrayToMerge[i])) {
newUniqueItemCount++;
}
}

if (newUniqueItemCount == 0) {
return _self;
}

nextArray_ = new int256[](_self.length + newUniqueItemCount);
for (uint256 i; i < _self.length; i++) {
nextArray_[i] = _self[i];
}
uint256 nextArrayIndex = _self.length;
for (uint256 i; i < _arrayToMerge.length; i++) {
if (!contains(_self, _arrayToMerge[i])) {
nextArray_[nextArrayIndex] = _arrayToMerge[i];
nextArrayIndex++;
}
}

return nextArray_;
}

/// @dev Helper to verify if array is a set of unique values.
/// Does not assert length > 0.
function isUniqueSet(int256[] memory _self) internal pure returns (bool isUnique_) {
if (_self.length <= 1) {
return true;
}

uint256 arrayLength = _self.length;
for (uint256 i; i < arrayLength; i++) {
for (uint256 j = i + 1; j < arrayLength; j++) {
if (_self[i] == _self[j]) {
return false;
}
}
}

return true;
}

/// @dev Helper to remove items from an array. Removes all matching occurrences of each item.
/// Does not assert uniqueness of either array.
function removeItems(int256[] memory _self, int256[] memory _itemsToRemove)
internal
pure
returns (int256[] memory nextArray_)
{
if (_itemsToRemove.length == 0) {
return _self;
}

bool[] memory indexesToRemove = new bool[](_self.length);
uint256 remainingItemsCount = _self.length;
for (uint256 i; i < _self.length; i++) {
if (contains(_itemsToRemove, _self[i])) {
indexesToRemove[i] = true;
remainingItemsCount--;
}
}

if (remainingItemsCount == _self.length) {
nextArray_ = _self;
} else if (remainingItemsCount > 0) {
nextArray_ = new int256[](remainingItemsCount);
uint256 nextArrayIndex;
for (uint256 i; i < _self.length; i++) {
if (!indexesToRemove[i]) {
nextArray_[nextArrayIndex] = _self[i];
nextArrayIndex++;
}
}
}

return nextArray_;
}
}

0 comments on commit fe18ecc

Please sign in to comment.