#region Using
#endregion
namespace SharpCompress.Compressors.PPMd.I1
{
///
/// A structure containing a single address. The address represents a location in the
/// array. That location in the array contains information itself describing a section
/// of the array (ie. a block of memory).
///
///
///
/// This must be a structure rather than a class because several places in the associated code assume that
/// is a value type (meaning that assignment creates a completely new copy of
/// the instance rather than just copying a reference to the same instance).
///
///
/// MemoryNode
/// 4 Stamp
/// 4 Next
/// 4 UnitCount
///
///
/// Note that is a field rather than a property for performance reasons.
///
///
internal struct MemoryNode
{
public uint _address;
public byte[] _memory;
public static readonly MemoryNode ZERO = new MemoryNode(0, null);
public const int SIZE = 12;
///
/// Initializes a new instance of the structure.
///
public MemoryNode(uint address, byte[] memory)
{
_address = address;
_memory = memory;
}
///
/// Gets or sets the stamp.
///
public uint Stamp
{
get => _memory[_address] | ((uint)_memory[_address + 1]) << 8 | ((uint)_memory[_address + 2]) << 16 |
((uint)_memory[_address + 3]) << 24;
set
{
_memory[_address] = (byte)value;
_memory[_address + 1] = (byte)(value >> 8);
_memory[_address + 2] = (byte)(value >> 16);
_memory[_address + 3] = (byte)(value >> 24);
}
}
///
/// Gets or sets the next memory node.
///
public MemoryNode Next
{
get => new MemoryNode(
_memory[_address + 4] | ((uint)_memory[_address + 5]) << 8 |
((uint)_memory[_address + 6]) << 16 | ((uint)_memory[_address + 7]) << 24, _memory);
set
{
_memory[_address + 4] = (byte)value._address;
_memory[_address + 5] = (byte)(value._address >> 8);
_memory[_address + 6] = (byte)(value._address >> 16);
_memory[_address + 7] = (byte)(value._address >> 24);
}
}
///
/// Gets or sets the unit count.
///
public uint UnitCount
{
get => _memory[_address + 8] | ((uint)_memory[_address + 9]) << 8 |
((uint)_memory[_address + 10]) << 16 | ((uint)_memory[_address + 11]) << 24;
set
{
_memory[_address + 8] = (byte)value;
_memory[_address + 9] = (byte)(value >> 8);
_memory[_address + 10] = (byte)(value >> 16);
_memory[_address + 11] = (byte)(value >> 24);
}
}
///
/// Gets whether there is a next memory node available.
///
public bool Available => Next._address != 0;
///
/// Link in the provided memory node.
///
///
public void Link(MemoryNode memoryNode)
{
memoryNode.Next = Next;
Next = memoryNode;
}
///
/// Unlink this memory node.
///
public void Unlink()
{
Next = Next.Next;
}
///
/// Insert the memory node into the linked list.
///
///
///
public void Insert(MemoryNode memoryNode, uint unitCount)
{
Link(memoryNode);
memoryNode.Stamp = uint.MaxValue;
memoryNode.UnitCount = unitCount;
Stamp++;
}
///
/// Remove this memory node from the linked list.
///
///
public MemoryNode Remove()
{
MemoryNode next = Next;
Unlink();
Stamp--;
return next;
}
///
/// Allow a pointer to be implicitly converted to a memory node.
///
///
///
public static implicit operator MemoryNode(Pointer pointer)
{
return new MemoryNode(pointer._address, pointer._memory);
}
///
/// Allow pointer-like addition on a memory node.
///
///
///
///
public static MemoryNode operator +(MemoryNode memoryNode, int offset)
{
memoryNode._address = (uint)(memoryNode._address + offset * SIZE);
return memoryNode;
}
///
/// Allow pointer-like addition on a memory node.
///
///
///
///
public static MemoryNode operator +(MemoryNode memoryNode, uint offset)
{
memoryNode._address += offset * SIZE;
return memoryNode;
}
///
/// Allow pointer-like subtraction on a memory node.
///
///
///
///
public static MemoryNode operator -(MemoryNode memoryNode, int offset)
{
memoryNode._address = (uint)(memoryNode._address - offset * SIZE);
return memoryNode;
}
///
/// Allow pointer-like subtraction on a memory node.
///
///
///
///
public static MemoryNode operator -(MemoryNode memoryNode, uint offset)
{
memoryNode._address -= offset * SIZE;
return memoryNode;
}
///
/// Compare two memory nodes.
///
///
///
///
public static bool operator ==(MemoryNode memoryNode1, MemoryNode memoryNode2)
{
return memoryNode1._address == memoryNode2._address;
}
///
/// Compare two memory nodes.
///
///
///
///
public static bool operator !=(MemoryNode memoryNode1, MemoryNode memoryNode2)
{
return memoryNode1._address != memoryNode2._address;
}
///
/// Indicates whether this instance and a specified object are equal.
///
/// true if obj and this instance are the same type and represent the same value; otherwise, false.
/// Another object to compare to.
public override bool Equals(object obj)
{
if (obj is MemoryNode)
{
MemoryNode memoryNode = (MemoryNode)obj;
return memoryNode._address == _address;
}
return base.Equals(obj);
}
///
/// Returns the hash code for this instance.
///
/// A 32-bit signed integer that is the hash code for this instance.
public override int GetHashCode()
{
return _address.GetHashCode();
}
}
}