121 lines
3.8 KiB
C#
121 lines
3.8 KiB
C#
|
|
using System;
|
|
using System.Diagnostics;
|
|
using Unity.Assertions;
|
|
using Unity.Collections;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
using Unity.Mathematics;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace Rukhanka.Toolbox
|
|
{
|
|
// This struct intended to be used as bitfield over existing memory
|
|
public unsafe struct BitFieldN
|
|
{
|
|
uint* ptr;
|
|
int sizeInInts;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public BitFieldN(uint* ptr, int sizeInInts, NativeArrayOptions options = NativeArrayOptions.ClearMemory)
|
|
{
|
|
this.ptr = ptr;
|
|
this.sizeInInts = sizeInInts;
|
|
|
|
if (options == NativeArrayOptions.ClearMemory)
|
|
Clear();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public BitFieldN Clone(uint* ptr)
|
|
{
|
|
var rv = new BitFieldN(ptr, sizeInInts, NativeArrayOptions.UninitializedMemory);
|
|
rv.CopyFrom(this);
|
|
return rv;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public void CopyFrom(BitFieldN o)
|
|
{
|
|
UnsafeUtility.MemCpy(ptr, o.ptr, sizeInInts * sizeof(int));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public static int CalculateUIntsCountForGivenBitCount(int bitCount)
|
|
{
|
|
var rv = (bitCount >> 5);
|
|
var k = math.min(bitCount & 0x1f, 1);
|
|
return rv + k;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public bool IsSet(int pos)
|
|
{
|
|
CheckArgs(pos, 1);
|
|
var intIdx = GetIntIndexForBitPos(pos);
|
|
var rv = Bitwise.ExtractBits(ptr[intIdx], pos, 1);
|
|
return rv != 0u;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public void Set(int pos, bool value)
|
|
{
|
|
CheckArgs(pos, 1);
|
|
var intIdx = GetIntIndexForBitPos(pos);
|
|
ptr[intIdx] = Bitwise.SetBits(ptr[intIdx], pos, 1, value);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public void Clear()
|
|
{
|
|
UnsafeUtility.MemClear(ptr, sizeInInts * 4);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public bool TestAny()
|
|
{
|
|
var v = 0u;
|
|
for (var i = 0; i < sizeInInts; ++i)
|
|
{
|
|
v |= ptr[i];
|
|
}
|
|
return v != 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int GetIntIndexForBitPos(int pos) => pos >> 5;
|
|
public bool IsCreated => ptr != null;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public int SizeInInts() => sizeInInts;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public int Length
|
|
{
|
|
get => sizeInInts << 3;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")]
|
|
void CheckArgs(int pos, int numBits)
|
|
{
|
|
if (pos + numBits < 0 || pos + numBits > sizeInInts * 32)
|
|
{
|
|
throw new ArgumentException($"BitFieldN invalid arguments: pos {pos} and numBits {numBits} must be within array capacity {sizeInInts * 32}");
|
|
}
|
|
}
|
|
}
|
|
}
|