using System;
namespace Cosmos.Core
{
///
/// ManagedMemoryBlock class. Used to read and write a managed memory block.
///
public unsafe class ManagedMemoryBlock
{
private byte[] memory;
///
/// Offset.
///
public UInt32 Offset;
///
/// Size.
///
public UInt32 Size;
///
/// Create a new buffer with the given size, not aligned
///
/// Size of buffer
public ManagedMemoryBlock(UInt32 size)
: this(size, 1, false)
{ }
///
/// Create a new buffer with the given size, aligned on the byte boundary specified
///
/// Size of buffer
/// Byte Boundary alignment
public ManagedMemoryBlock(UInt32 size, byte alignment)
: this(size, alignment, true)
{ }
///
/// Create a new buffer with the given size, and aligned on the byte boundary if align is true
///
/// Size of buffer
/// Byte Boundary alignment
/// true if buffer should be aligned, false otherwise
public ManagedMemoryBlock(UInt32 size, byte alignment, bool align)
{
memory = new byte[size + alignment - 1];
fixed (byte* bodystart = memory)
{
Offset = (UInt32)bodystart;
Size = size;
}
if (align == true)
{
while (this.Offset % alignment != 0)
{
this.Offset++;
}
}
}
///
/// Get or set the byte at the given offset
///
/// Address Offset
/// Byte value at given offset
/// Thrown on invalid offset.
public byte this[uint offset]
{
get
{
if (offset > Size)
throw new ArgumentOutOfRangeException("offset");
return *(byte*)(this.Offset + offset);
}
set
{
if (offset < 0 || offset > Size)
throw new ArgumentOutOfRangeException("offset");
(*(byte*)(this.Offset + offset)) = value;
}
}
///
/// Fill memory block.
///
/// A start.
/// A count.
/// A data.
public unsafe void Fill(uint aStart, uint aCount, uint aData)
{
// TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-(
uint* xDest = (uint*)(this.Offset + aStart);
MemoryOperations.Fill(xDest, aData, (int)aCount);
}
///
/// Fill data to memory block.
///
/// A starting position in the memory block.
/// Data size.
/// A data to fill memory block with.
public unsafe void Fill(int aStart, int aCount, int aData)
{
// TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-(
fixed (byte* aArrayPtr = this.memory)
{
MemoryOperations.Fill(aArrayPtr + aStart, aData, (int)aCount);
}
}
///
/// Fill memory block.
///
/// A data to fill.
public void Fill(uint aData)
{
fixed (byte* destPtr = this.memory)
{
MemoryOperations.Fill(destPtr, (int)aData, (int)this.Size);
}
}
public unsafe void Copy(int aStart, int[] aData, int aIndex, int aCount)
{
// TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-(
int* xDest;
fixed (byte* aArrayPtr = this.memory)
{
xDest = (int*)(aArrayPtr + aStart);
}
fixed (int* aDataPtr = aData)
{
MemoryOperations.Copy(xDest, aDataPtr + aIndex, aCount);
}
}
///
/// Copy MemoryBlock into ManagedMemoryBlock
///
/// MemoryBlock to copy.
public unsafe void Copy(MemoryBlock block)
{
byte* xDest = (byte*)(this.Offset);
byte* aDataPtr = (byte*)block.Base;
MemoryOperations.Copy(xDest, aDataPtr, (int)block.Size);
}
///
/// Read 16-bit from the memory block.
///
/// Data offset.
/// UInt16 value.
/// Thrown if offset if bigger than memory block size.
public UInt16 Read16(uint offset)
{
if (offset > Size)
throw new ArgumentOutOfRangeException("offset");
return *(UInt16*)(this.Offset + offset);
}
///
/// Write 16-bit to the memory block.
///
/// Data offset.
/// Value to write.
/// Thrown if offset if bigger than memory block size or smaller than 0.
public void Write16(uint offset, UInt16 value)
{
if (offset < 0 || offset > Size)
throw new ArgumentOutOfRangeException("offset");
(*(UInt16*)(this.Offset + offset)) = value;
}
///
/// Read 32-bit from the memory block.
///
/// Data offset.
/// UInt32 value.
/// Thrown if offset if bigger than memory block size.
public UInt32 Read32(uint offset)
{
if (offset > Size)
throw new ArgumentOutOfRangeException("offset");
return *(UInt32*)(this.Offset + offset);
}
///
/// Write 32-bit to the memory block.
///
/// Data offset.
/// Value to write.
/// Thrown if offset if bigger than memory block size or smaller than 0.
public void Write32(uint offset, UInt32 value)
{
if (offset < 0 || offset > Size)
throw new ArgumentOutOfRangeException("offset");
(*(UInt32*)(this.Offset + offset)) = value;
}
}
}