Chromium Code Reviews| 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) return false; | |
|
sigurdm
2016/01/11 08:48:55
Ideally this should be
```
if (other is! EnumSet<E
Johnni Winther
2016/01/22 11:54:13
Updated. Should be OK as the VM canonicalizes the
| |
| 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 |