EnumerableSet.sol 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. pragma solidity ^0.5.0;
  2. /**
  3. * @dev Library for managing
  4. * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
  5. * types.
  6. *
  7. * Sets have the following properties:
  8. *
  9. * - Elements are added, removed, and checked for existence in constant time
  10. * (O(1)).
  11. * - Elements are enumerated in O(n). No guarantees are made on the ordering.
  12. *
  13. * As of v2.5.0, only `address` sets are supported.
  14. *
  15. * Include with `using EnumerableSet for EnumerableSet.AddressSet;`.
  16. *
  17. * _Available since v2.5.0._
  18. *
  19. * @author Alberto Cuesta Cañada
  20. */
  21. library EnumerableSet {
  22. struct AddressSet {
  23. // Position of the value in the `values` array, plus 1 because index 0
  24. // means a value is not in the set.
  25. mapping (address => uint256) index;
  26. address[] values;
  27. }
  28. /**
  29. * @dev Add a value to a set. O(1).
  30. * Returns false if the value was already in the set.
  31. */
  32. function add(AddressSet storage set, address value)
  33. internal
  34. returns (bool)
  35. {
  36. if (!contains(set, value)){
  37. set.index[value] = set.values.push(value);
  38. return true;
  39. } else {
  40. return false;
  41. }
  42. }
  43. /**
  44. * @dev Removes a value from a set. O(1).
  45. * Returns false if the value was not present in the set.
  46. */
  47. function remove(AddressSet storage set, address value)
  48. internal
  49. returns (bool)
  50. {
  51. if (contains(set, value)){
  52. uint256 toDeleteIndex = set.index[value] - 1;
  53. uint256 lastIndex = set.values.length - 1;
  54. // If the element we're deleting is the last one, we can just remove it without doing a swap
  55. if (lastIndex != toDeleteIndex) {
  56. address lastValue = set.values[lastIndex];
  57. // Move the last value to the index where the deleted value is
  58. set.values[toDeleteIndex] = lastValue;
  59. // Update the index for the moved value
  60. set.index[lastValue] = toDeleteIndex + 1; // All indexes are 1-based
  61. }
  62. // Delete the index entry for the deleted value
  63. delete set.index[value];
  64. // Delete the old entry for the moved value
  65. set.values.pop();
  66. return true;
  67. } else {
  68. return false;
  69. }
  70. }
  71. /**
  72. * @dev Returns true if the value is in the set. O(1).
  73. */
  74. function contains(AddressSet storage set, address value)
  75. internal
  76. view
  77. returns (bool)
  78. {
  79. return set.index[value] != 0;
  80. }
  81. /**
  82. * @dev Returns an array with all values in the set. O(N).
  83. * Note that there are no guarantees on the ordering of values inside the
  84. * array, and it may change when more values are added or removed.
  85. * WARNING: This function may run out of gas on large sets: use {length} and
  86. * {get} instead in these cases.
  87. */
  88. function enumerate(AddressSet storage set)
  89. internal
  90. view
  91. returns (address[] memory)
  92. {
  93. address[] memory output = new address[](set.values.length);
  94. for (uint256 i; i < set.values.length; i++){
  95. output[i] = set.values[i];
  96. }
  97. return output;
  98. }
  99. /**
  100. * @dev Returns the number of elements on the set. O(1).
  101. */
  102. function length(AddressSet storage set)
  103. internal
  104. view
  105. returns (uint256)
  106. {
  107. return set.values.length;
  108. }
  109. /** @dev Returns the element stored at position `index` in the set. O(1).
  110. * Note that there are no guarantees on the ordering of values inside the
  111. * array, and it may change when more values are added or removed.
  112. *
  113. * Requirements:
  114. *
  115. * - `index` must be strictly less than {length}.
  116. */
  117. function get(AddressSet storage set, uint256 index)
  118. internal
  119. view
  120. returns (address)
  121. {
  122. return set.values[index];
  123. }
  124. }