private BitLock CreateAndIndexBitLock(IEnumerable <ushort> bitPositions) { var bitLock = new BitLock(bitPositions); foreach (var bitPosition in bitPositions) { if (!this._locksByBits.TryGetValue(bitPosition, out var indexedLocks)) { indexedLocks = new HashSet <BitLock>(ReferenceEqualityComparer <BitLock> .Default); this._locksByBits.Add(bitPosition, indexedLocks); } indexedLocks.Add(bitLock); } return(bitLock); }
private void DeindexBitLock(BitLock bitLock) { if (bitLock == null) { return; } foreach (var bitPosition in bitLock.BitPositions.Distinct()) { var bitLocks = this._locksByBits[bitPosition]; bitLocks.Remove(bitLock); if (!bitLocks.Any()) { this._locksByBits.Remove(bitPosition); } } }
public bool Unlocks(BitLock bitLock) { var totalKeySegments = this.Bits.Count; var totalLockSegments = bitLock.Bits.Count; if (totalLockSegments > totalKeySegments) { // If the lock is larger than the key, look first at all lock bytes past the key's length var farLock = bitLock.Bits.Skip(totalKeySegments); if (farLock.Any(x => x > 0)) { // If any lock byte past the key's length has any bits flipped to 1, this key cannot possibly fit return(false); } } // Only look at the bytes of the key that have corresponding lock bytes // i.e. if the key is longer than the lock, trim down the key to fit the lock for (var segmentPos = 0; segmentPos < totalLockSegments; segmentPos++) { // Example: // Key: 10010100 // Lock: 10110011 // O XO XX - passes 2 bits, fails 3 bits. Does NOT unlock. // Key: 10010100 // Lock: 10000100 // O O - passes 2 bits. Unlock successful. Don't care about extra key bits. var lockSegment = bitLock.Bits[segmentPos]; var keySegment = this.Bits[segmentPos]; if ((keySegment & lockSegment) != lockSegment) { return(false); } } // If no bytes failed, then the unlock is successful return(true); }