| File: System\Collections\Specialized\BitVector32.cs | Web Access |
| Project: src\runtime\src\libraries\System.Collections.Specialized\src\System.Collections.Specialized.csproj (System.Collections.Specialized) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using System.Numerics; namespace System.Collections.Specialized { /// <devdoc> /// <para>Provides a simple light bit vector with easy integer or Boolean access to /// a 32 bit storage.</para> /// </devdoc> public struct BitVector32 : IEquatable<BitVector32> { private uint _data; /// <devdoc> /// <para>Initializes a new instance of the BitVector32 structure with the specified internal data.</para> /// </devdoc> public BitVector32(int data) { _data = unchecked((uint)data); } /// <devdoc> /// <para>Initializes a new instance of the BitVector32 structure with the information in the specified /// value.</para> /// </devdoc> public BitVector32(BitVector32 value) { _data = value._data; } /// <devdoc> /// <para>Gets or sets a value indicating whether all the specified bits are set.</para> /// </devdoc> public bool this[int bit] { get { return (_data & bit) == unchecked((uint)bit); } set { unchecked { if (value) { _data |= (uint)bit; } else { _data &= ~(uint)bit; } } } } /// <devdoc> /// <para>Gets or sets the value for the specified section.</para> /// </devdoc> public int this[Section section] { get { unchecked { return (int)((_data & (uint)(section.Mask << section.Offset)) >> section.Offset); } } set { // The code should really have originally validated "(value & section.Mask) == value" with // an exception (it instead validated it with a Debug.Assert, which does little good in a // public method when in a Release build). We don't include such a check now as it would // likely break things and for little benefit. value <<= section.Offset; int offsetMask = (0xFFFF & (int)section.Mask) << section.Offset; _data = unchecked((_data & ~(uint)offsetMask) | ((uint)value & (uint)offsetMask)); } } /// <devdoc> /// returns the raw data stored in this bit vector... /// </devdoc> public int Data { get { return unchecked((int)_data); } } /// <devdoc> /// <para> Creates the first mask in a series.</para> /// </devdoc> public static int CreateMask() { return CreateMask(0); } /// <devdoc> /// Creates the next mask in a series. /// </devdoc> public static int CreateMask(int previous) { if (previous == 0) { return 1; } if (previous == unchecked((int)0x80000000)) { throw new InvalidOperationException(SR.BitVectorFull); } return previous << 1; } /// <devdoc> /// <para>Creates the first section in a series, with the specified maximum value.</para> /// </devdoc> public static Section CreateSection(short maxValue) { return CreateSectionHelper(maxValue, 0, 0); } /// <devdoc> /// <para>Creates the next section in a series, with the specified maximum value.</para> /// </devdoc> public static Section CreateSection(short maxValue, Section previous) { return CreateSectionHelper(maxValue, previous.Mask, previous.Offset); } private static Section CreateSectionHelper(short maxValue, short priorMask, short priorOffset) { ArgumentOutOfRangeException.ThrowIfNegativeOrZero(maxValue); short offset = (short)(priorOffset + BitOperations.PopCount((uint)(ushort)priorMask)); if (offset >= 32) { throw new InvalidOperationException(SR.BitVectorFull); } short mask = (short)(BitOperations.RoundUpToPowerOf2((uint)(ushort)maxValue + 1) - 1); return new Section(mask, offset); } public override bool Equals([NotNullWhen(true)] object? o) => o is BitVector32 other && Equals(other); /// <summary>Indicates whether the current instance is equal to another instance of the same type.</summary> /// <param name="other">An instance to compare with this instance.</param> /// <returns>true if the current instance is equal to the other instance; otherwise, false.</returns> public bool Equals(BitVector32 other) => _data == other._data; public override int GetHashCode() => _data.GetHashCode(); public static string ToString(BitVector32 value) { return string.Create(/*"BitVector32{".Length*/12 + /*32 bits*/32 + /*"}".Length"*/1, value, (dst, v) => { ReadOnlySpan<char> prefix = "BitVector32{"; prefix.CopyTo(dst); dst[dst.Length - 1] = '}'; int locdata = unchecked((int)v._data); dst = dst.Slice(prefix.Length, 32); for (int i = 0; i < dst.Length; i++) { dst[i] = (locdata & 0x80000000) != 0 ? '1' : '0'; locdata <<= 1; } }); } public override string ToString() { return ToString(this); } /// <devdoc> /// <para> /// Represents an section of the vector that can contain a integer number.</para> /// </devdoc> public readonly struct Section : IEquatable<Section> { private readonly short _mask; private readonly short _offset; internal Section(short mask, short offset) { _mask = mask; _offset = offset; } public short Mask => _mask; public short Offset => _offset; public override bool Equals([NotNullWhen(true)] object? o) => o is Section other && Equals(other); public bool Equals(Section obj) { return obj._mask == _mask && obj._offset == _offset; } public static bool operator ==(Section a, Section b) { return a.Equals(b); } public static bool operator !=(Section a, Section b) { return !(a == b); } public override int GetHashCode() => HashCode.Combine(_mask, _offset); public static string ToString(Section value) { return $"Section{{0x{value.Mask:x}, 0x{value.Offset:x}}}"; } public override string ToString() { return ToString(this); } } } }