| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library dart2js.util.enumset; |
| 6 |
| 7 import 'dart:collection'; |
| 8 |
| 9 /// A set of enum values based on a bit mask of the shifted enum indices. |
| 10 abstract class EnumSet<E> { |
| 11 /// Creates an empty mutable set. |
| 12 factory EnumSet() = _EnumSet<E>; |
| 13 |
| 14 /// Creates a mutable set from the bit mask [value]. |
| 15 factory EnumSet.fromValue(int value) = _EnumSet<E>.fromValue; |
| 16 |
| 17 /// Creates an immutable set from the bit mask [value]. |
| 18 const factory EnumSet.fixed(int value) = _ConstEnumSet<E>; |
| 19 |
| 20 /// Create a set containing the [values]. If [fixed] is `true` the set is |
| 21 /// immutable. |
| 22 factory EnumSet.fromValues(Iterable<E> values, {bool fixed: false}) { |
| 23 if (fixed) { |
| 24 return new _ConstEnumSet<E>.fromValues(values); |
| 25 } else { |
| 26 return new _EnumSet<E>.fromValues(values); |
| 27 } |
| 28 } |
| 29 |
| 30 const EnumSet._(); |
| 31 |
| 32 /// The bit mask of the shifted indices for the enum values in this set. |
| 33 int get value; |
| 34 |
| 35 /// Adds [enumValue] to this set. |
| 36 void add(E enumValue); |
| 37 |
| 38 /// Removes [enumValue] from this set. |
| 39 void remove(E enumValue); |
| 40 |
| 41 /// Clears this set. |
| 42 void clear(); |
| 43 |
| 44 /// Returns `true` if [enumValue] is in this set. |
| 45 bool contains(E enumValue) { |
| 46 return (value & (1 << (enumValue as dynamic).index)) != 0; |
| 47 } |
| 48 |
| 49 /// Returns an [Iterable] of the values is in this set using [values] to |
| 50 /// convert the stored indices to enum values. |
| 51 /// |
| 52 /// The method is typically called with the `values` property of the enum |
| 53 /// class as argument: |
| 54 /// |
| 55 /// EnumSet<EnumClass> set = ... |
| 56 /// Iterable<EnumClass> iterable = set.iterable(EnumClass.values); |
| 57 /// |
| 58 Iterable<E> iterable(List<E> values) { |
| 59 return new _EnumSetIterable(this, values); |
| 60 } |
| 61 |
| 62 /// Returns `true` if this and [other] have any elements in common. |
| 63 bool intersects(EnumSet<E> other) { |
| 64 return (value & other.value) != 0; |
| 65 } |
| 66 |
| 67 /// Returns `true` if this set is empty. |
| 68 bool get isEmpty => value == 0; |
| 69 |
| 70 int get hashCode => value.hashCode * 19; |
| 71 |
| 72 bool operator ==(other) { |
| 73 if (identical(this, other)) return true; |
| 74 if (other is! EnumSet<E>) return false; |
| 75 return value == other.value; |
| 76 } |
| 77 |
| 78 String toString() { |
| 79 if (value == 0) return '0'; |
| 80 int index = value.bitLength - 1; |
| 81 StringBuffer sb = new StringBuffer(); |
| 82 int mask = 1 << index; |
| 83 while (index >= 0) { |
| 84 sb.write((value & mask) != 0 ? '1' : '0'); |
| 85 index--; |
| 86 mask >>= 1; |
| 87 } |
| 88 return sb.toString(); |
| 89 } |
| 90 } |
| 91 |
| 92 /// Mutable implementation of [EnumSet]. |
| 93 class _EnumSet<E> extends EnumSet<E> { |
| 94 int _value; |
| 95 |
| 96 _EnumSet() : this.fromValue(0); |
| 97 |
| 98 _EnumSet.fromValue(this._value) : super._(); |
| 99 |
| 100 _EnumSet.fromValues(Iterable<E> values) |
| 101 : this._value = 0, |
| 102 super._() { |
| 103 values.forEach(add); |
| 104 } |
| 105 |
| 106 int get value => _value; |
| 107 |
| 108 void add(E enumValue) { |
| 109 _value |= 1 << (enumValue as dynamic).index; |
| 110 } |
| 111 |
| 112 void remove(E enumValue) { |
| 113 _value &= ~(1 << (enumValue as dynamic).index); |
| 114 } |
| 115 |
| 116 void clear() { |
| 117 _value = 0; |
| 118 } |
| 119 } |
| 120 |
| 121 /// Immutable implementation of [EnumSet]. |
| 122 class _ConstEnumSet<E> extends EnumSet<E> { |
| 123 final int value; |
| 124 |
| 125 const _ConstEnumSet(this.value) : super._(); |
| 126 |
| 127 factory _ConstEnumSet.fromValues(Iterable<E> values) { |
| 128 int value = 0; |
| 129 void add(E enumValue) { |
| 130 if (enumValue != null) { |
| 131 value |= 1 << (enumValue as dynamic).index; |
| 132 } |
| 133 } |
| 134 values.forEach(add); |
| 135 return new _ConstEnumSet(value); |
| 136 } |
| 137 |
| 138 @override |
| 139 void add(E enumValue) { |
| 140 throw new UnsupportedError('EnumSet.add'); |
| 141 } |
| 142 |
| 143 @override |
| 144 void clear() { |
| 145 throw new UnsupportedError('EnumSet.clear'); |
| 146 } |
| 147 |
| 148 @override |
| 149 void remove(E enumValue) { |
| 150 throw new UnsupportedError('EnumSet.remove'); |
| 151 } |
| 152 } |
| 153 |
| 154 class _EnumSetIterable<E> extends IterableBase<E> { |
| 155 final EnumSet<E> _enumSet; |
| 156 final List<E> _values; |
| 157 |
| 158 _EnumSetIterable(this._enumSet, this._values); |
| 159 |
| 160 @override |
| 161 Iterator<E> get iterator => new _EnumSetIterator(_enumSet.value, _values); |
| 162 } |
| 163 |
| 164 class _EnumSetIterator<E> implements Iterator<E> { |
| 165 int _value; |
| 166 int _index; |
| 167 int _mask; |
| 168 final List<E> _values; |
| 169 E _current; |
| 170 |
| 171 _EnumSetIterator(this._value, this._values); |
| 172 |
| 173 @override |
| 174 E get current => _current; |
| 175 |
| 176 @override |
| 177 bool moveNext() { |
| 178 if (_value == 0) { |
| 179 return false; |
| 180 } else { |
| 181 if (_mask == null) { |
| 182 _index = _value.bitLength - 1; |
| 183 _mask = 1 << _index; |
| 184 } |
| 185 _current = null; |
| 186 while (_index >= 0) { |
| 187 if (_mask & _value != 0) { |
| 188 _current = _values[_index]; |
| 189 } |
| 190 _mask >>= 1; |
| 191 _index--; |
| 192 if (_current != null) { |
| 193 break; |
| 194 } |
| 195 } |
| 196 return _current != null; |
| 197 } |
| 198 } |
| 199 } |
| OLD | NEW |