mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-14 21:23:38 +00:00
260 lines
8.6 KiB
C#
260 lines
8.6 KiB
C#
#region Using
|
|
|
|
using System;
|
|
|
|
#endregion
|
|
|
|
namespace SharpCompress.Compressor.PPMd.I1
|
|
{
|
|
/// <summary>
|
|
/// A structure containing a single address. The address represents a location in the <see cref="Memory"/>
|
|
/// array. That location in the <see cref="Memory"/> array contains information itself describing a section
|
|
/// of the <see cref="Memory"/> array (ie. a block of memory).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This must be a structure rather than a class because several places in the associated code assume that
|
|
/// <see cref="MemoryNode"/> 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).
|
|
/// </para>
|
|
/// <para>
|
|
/// MemoryNode
|
|
/// 4 Stamp
|
|
/// 4 Next
|
|
/// 4 UnitCount
|
|
/// </para>
|
|
/// <para>
|
|
/// Note that <see cref="Address"/> is a field rather than a property for performance reasons.
|
|
/// </para>
|
|
/// </remarks>
|
|
internal struct MemoryNode
|
|
{
|
|
public uint Address;
|
|
public byte[] Memory;
|
|
public static readonly MemoryNode Zero = new MemoryNode(0, null);
|
|
public const int Size = 12;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="MemoryNode"/> structure.
|
|
/// </summary>
|
|
public MemoryNode(uint address, byte[] memory)
|
|
{
|
|
Address = address;
|
|
Memory = memory;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the stamp.
|
|
/// </summary>
|
|
public uint Stamp
|
|
{
|
|
get
|
|
{
|
|
return ((uint) 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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the next memory node.
|
|
/// </summary>
|
|
public MemoryNode Next
|
|
{
|
|
get
|
|
{
|
|
return
|
|
new MemoryNode(
|
|
((uint) 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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the unit count.
|
|
/// </summary>
|
|
public uint UnitCount
|
|
{
|
|
get
|
|
{
|
|
return ((uint) 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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether there is a next memory node available.
|
|
/// </summary>
|
|
public bool Available
|
|
{
|
|
get { return Next.Address != 0; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Link in the provided memory node.
|
|
/// </summary>
|
|
/// <param name="memoryNode"></param>
|
|
public void Link(MemoryNode memoryNode)
|
|
{
|
|
memoryNode.Next = Next;
|
|
Next = memoryNode;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unlink this memory node.
|
|
/// </summary>
|
|
public void Unlink()
|
|
{
|
|
Next = Next.Next;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Insert the memory node into the linked list.
|
|
/// </summary>
|
|
/// <param name="memoryNode"></param>
|
|
/// <param name="unitCount"></param>
|
|
public void Insert(MemoryNode memoryNode, uint unitCount)
|
|
{
|
|
Link(memoryNode);
|
|
memoryNode.Stamp = uint.MaxValue;
|
|
memoryNode.UnitCount = unitCount;
|
|
Stamp++;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove this memory node from the linked list.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public MemoryNode Remove()
|
|
{
|
|
MemoryNode next = Next;
|
|
Unlink();
|
|
Stamp--;
|
|
return next;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allow a pointer to be implicitly converted to a memory node.
|
|
/// </summary>
|
|
/// <param name="pointer"></param>
|
|
/// <returns></returns>
|
|
public static implicit operator MemoryNode(Pointer pointer)
|
|
{
|
|
return new MemoryNode(pointer.Address, pointer.Memory);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allow pointer-like addition on a memory node.
|
|
/// </summary>
|
|
/// <param name="memoryNode"></param>
|
|
/// <param name="offset"></param>
|
|
/// <returns></returns>
|
|
public static MemoryNode operator +(MemoryNode memoryNode, int offset)
|
|
{
|
|
memoryNode.Address = (uint) (memoryNode.Address + offset*Size);
|
|
return memoryNode;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allow pointer-like addition on a memory node.
|
|
/// </summary>
|
|
/// <param name="memoryNode"></param>
|
|
/// <param name="offset"></param>
|
|
/// <returns></returns>
|
|
public static MemoryNode operator +(MemoryNode memoryNode, uint offset)
|
|
{
|
|
memoryNode.Address += offset*Size;
|
|
return memoryNode;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allow pointer-like subtraction on a memory node.
|
|
/// </summary>
|
|
/// <param name="memoryNode"></param>
|
|
/// <param name="offset"></param>
|
|
/// <returns></returns>
|
|
public static MemoryNode operator -(MemoryNode memoryNode, int offset)
|
|
{
|
|
memoryNode.Address = (uint) (memoryNode.Address - offset*Size);
|
|
return memoryNode;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allow pointer-like subtraction on a memory node.
|
|
/// </summary>
|
|
/// <param name="memoryNode"></param>
|
|
/// <param name="offset"></param>
|
|
/// <returns></returns>
|
|
public static MemoryNode operator -(MemoryNode memoryNode, uint offset)
|
|
{
|
|
memoryNode.Address -= offset*Size;
|
|
return memoryNode;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compare two memory nodes.
|
|
/// </summary>
|
|
/// <param name="memoryNode1"></param>
|
|
/// <param name="memoryNode2"></param>
|
|
/// <returns></returns>
|
|
public static bool operator ==(MemoryNode memoryNode1, MemoryNode memoryNode2)
|
|
{
|
|
return memoryNode1.Address == memoryNode2.Address;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compare two memory nodes.
|
|
/// </summary>
|
|
/// <param name="memoryNode1"></param>
|
|
/// <param name="memoryNode2"></param>
|
|
/// <returns></returns>
|
|
public static bool operator !=(MemoryNode memoryNode1, MemoryNode memoryNode2)
|
|
{
|
|
return memoryNode1.Address != memoryNode2.Address;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether this instance and a specified object are equal.
|
|
/// </summary>
|
|
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
|
|
/// <param name="obj">Another object to compare to.</param>
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (obj is MemoryNode)
|
|
{
|
|
MemoryNode memoryNode = (MemoryNode) obj;
|
|
return memoryNode.Address == Address;
|
|
}
|
|
return base.Equals(obj);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the hash code for this instance.
|
|
/// </summary>
|
|
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
|
public override int GetHashCode()
|
|
{
|
|
return Address.GetHashCode();
|
|
}
|
|
}
|
|
} |