123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- pragma solidity ^0.5.0;
- /**
- * @dev Library for managing
- * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
- * types.
- *
- * Sets have the following properties:
- *
- * - Elements are added, removed, and checked for existence in constant time
- * (O(1)).
- * - Elements are enumerated in O(n). No guarantees are made on the ordering.
- *
- * As of v2.5.0, only `address` sets are supported.
- *
- * Include with `using EnumerableSet for EnumerableSet.AddressSet;`, and use
- * {newAddressSet} to create a new `AddressSet`.
- *
- * _Available since v2.5.0._
- *
- * @author Alberto Cuesta Cañada
- */
- library EnumerableSet {
- struct AddressSet {
- // Position of the value in the `values` array, plus 1 because index 0
- // means a value is not in the set.
- mapping (address => uint256) index;
- address[] values;
- }
- /**
- * @dev Creates a new empty address set.
- */
- function newAddressSet()
- internal
- pure
- returns (AddressSet memory)
- {
- return AddressSet({values: new address[](0)});
- }
- /**
- * @dev Add a value to a set. O(1).
- * Returns false if the value was already in the set.
- */
- function add(AddressSet storage set, address value)
- internal
- returns (bool)
- {
- if (!contains(set, value)){
- set.index[value] = set.values.push(value);
- return true;
- } else {
- return false;
- }
- }
- /**
- * @dev Removes a value from a set. O(1).
- * Returns false if the value was not present in the set.
- */
- function remove(AddressSet storage set, address value)
- internal
- returns (bool)
- {
- if (contains(set, value)){
- uint256 toDeleteIndex = set.index[value] - 1;
- uint256 lastIndex = set.values.length - 1;
- // If the element we're deleting is the last one, we can just remove it without doing a swap
- if (lastIndex != toDeleteIndex) {
- address lastValue = set.values[lastIndex];
- // Move the last value to the index where the deleted value is
- set.values[toDeleteIndex] = lastValue;
- // Update the index for the moved value
- set.index[lastValue] = toDeleteIndex + 1; // All indexes are 1-based
- }
- // Delete the index entry for the deleted value
- delete set.index[value];
- // Delete the old entry for the moved value
- set.values.pop();
- return true;
- } else {
- return false;
- }
- }
- /**
- * @dev Returns true if the value is in the set. O(1).
- */
- function contains(AddressSet storage set, address value)
- internal
- view
- returns (bool)
- {
- return set.index[value] != 0;
- }
- /**
- * @dev Returns an array with all values in the set. O(N).
- * Note that there are no guarantees on the ordering of values inside the
- * array, and it may change when more values are added or removed.
- */
- function enumerate(AddressSet storage set)
- internal
- view
- returns (address[] memory)
- {
- address[] memory output = new address[](set.values.length);
- for (uint256 i; i < set.values.length; i++){
- output[i] = set.values[i];
- }
- return output;
- }
- }
|