mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-17 19:08:53 -07:00
309 lines
8.3 KiB
C#
309 lines
8.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace BDInfo
|
|
{
|
|
using System.Diagnostics;
|
|
using System.Text;
|
|
using System;
|
|
|
|
/// <devdoc>
|
|
/// <para>Provides a simple light bit vector with easy integer or Boolean access to
|
|
/// a 32 bit storage.</para>
|
|
/// </devdoc>
|
|
public struct 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)
|
|
{
|
|
this.data = (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)
|
|
{
|
|
this.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) == (uint)bit;
|
|
}
|
|
set
|
|
{
|
|
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
|
|
{
|
|
return (int)((data & (uint)(section.Mask << section.Offset)) >> section.Offset);
|
|
}
|
|
set
|
|
{
|
|
value <<= section.Offset;
|
|
int offsetMask = (0xFFFF & (int)section.Mask) << section.Offset;
|
|
data = (data & ~(uint)offsetMask) | ((uint)value & (uint)offsetMask);
|
|
}
|
|
}
|
|
|
|
/// <devdoc>
|
|
/// returns the raw data stored in this bit vector...
|
|
/// </devdoc>
|
|
public int Data
|
|
{
|
|
get
|
|
{
|
|
return (int)data;
|
|
}
|
|
}
|
|
|
|
private static short CountBitsSet(short mask)
|
|
{
|
|
|
|
// yes, I know there are better algorithms, however, we know the
|
|
// bits are always right aligned, with no holes (i.e. always 00000111,
|
|
// never 000100011), so this is just fine...
|
|
//
|
|
short value = 0;
|
|
while ((mask & 0x1) != 0)
|
|
{
|
|
value++;
|
|
mask >>= 1;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/// <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("Bit vector full");
|
|
}
|
|
|
|
return previous << 1;
|
|
}
|
|
|
|
/// <devdoc>
|
|
/// Given a highValue, creates the mask
|
|
/// </devdoc>
|
|
private static short CreateMaskFromHighValue(short highValue)
|
|
{
|
|
short required = 16;
|
|
while ((highValue & 0x8000) == 0)
|
|
{
|
|
required--;
|
|
highValue <<= 1;
|
|
}
|
|
|
|
ushort value = 0;
|
|
while (required > 0)
|
|
{
|
|
required--;
|
|
value <<= 1;
|
|
value |= 0x1;
|
|
}
|
|
|
|
return unchecked((short)value);
|
|
}
|
|
|
|
/// <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)
|
|
{
|
|
if (maxValue < 1)
|
|
{
|
|
throw new ArgumentOutOfRangeException("maxValue");
|
|
}
|
|
#if DEBUG
|
|
int maskCheck = CreateMaskFromHighValue(maxValue);
|
|
int offsetCheck = priorOffset + CountBitsSet(priorMask);
|
|
Debug.Assert(maskCheck <= short.MaxValue && offsetCheck < 32, "Overflow on BitVector32");
|
|
#endif
|
|
short offset = (short)(priorOffset + CountBitsSet(priorMask));
|
|
if (offset >= 32)
|
|
{
|
|
throw new InvalidOperationException("Bit vector full");
|
|
}
|
|
return new Section(CreateMaskFromHighValue(maxValue), offset);
|
|
}
|
|
|
|
public override bool Equals(object o)
|
|
{
|
|
if (!(o is BitVector32))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return data == ((BitVector32)o).data;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return base.GetHashCode();
|
|
}
|
|
|
|
/// <devdoc>
|
|
/// </devdoc>
|
|
public static string ToString(BitVector32 value)
|
|
{
|
|
StringBuilder sb = new StringBuilder(/*"BitVector32{".Length*/12 + /*32 bits*/32 + /*"}".Length"*/1);
|
|
sb.Append("BitVector32{");
|
|
int locdata = (int)value.data;
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
if ((locdata & 0x80000000) != 0)
|
|
{
|
|
sb.Append("1");
|
|
}
|
|
else
|
|
{
|
|
sb.Append("0");
|
|
}
|
|
locdata <<= 1;
|
|
}
|
|
sb.Append("}");
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <devdoc>
|
|
/// </devdoc>
|
|
public override string ToString()
|
|
{
|
|
return BitVector32.ToString(this);
|
|
}
|
|
|
|
/// <devdoc>
|
|
/// <para>
|
|
/// Represents an section of the vector that can contain a integer number.</para>
|
|
/// </devdoc>
|
|
public struct Section
|
|
{
|
|
private readonly short mask;
|
|
private readonly short offset;
|
|
|
|
internal Section(short mask, short offset)
|
|
{
|
|
this.mask = mask;
|
|
this.offset = offset;
|
|
}
|
|
|
|
public short Mask
|
|
{
|
|
get
|
|
{
|
|
return mask;
|
|
}
|
|
}
|
|
|
|
public short Offset
|
|
{
|
|
get
|
|
{
|
|
return offset;
|
|
}
|
|
}
|
|
|
|
public override bool Equals(object o)
|
|
{
|
|
if (o is Section)
|
|
return Equals((Section)o);
|
|
else
|
|
return false;
|
|
}
|
|
|
|
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()
|
|
{
|
|
return base.GetHashCode();
|
|
}
|
|
|
|
/// <devdoc>
|
|
/// </devdoc>
|
|
public static string ToString(Section value)
|
|
{
|
|
return "Section{0x" + Convert.ToString(value.Mask, 16) + ", 0x" + Convert.ToString(value.Offset, 16) + "}";
|
|
}
|
|
|
|
/// <devdoc>
|
|
/// </devdoc>
|
|
public override string ToString()
|
|
{
|
|
return Section.ToString(this);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|