MemoryNode.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #region Using
  2. #endregion
  3. namespace SharpCompress.Compressors.PPMd.I1
  4. {
  5. /// <summary>
  6. /// A structure containing a single address. The address represents a location in the <see cref="_memory"/>
  7. /// array. That location in the <see cref="_memory"/> array contains information itself describing a section
  8. /// of the <see cref="_memory"/> array (ie. a block of memory).
  9. /// </summary>
  10. /// <remarks>
  11. /// <para>
  12. /// This must be a structure rather than a class because several places in the associated code assume that
  13. /// <see cref="MemoryNode"/> is a value type (meaning that assignment creates a completely new copy of
  14. /// the instance rather than just copying a reference to the same instance).
  15. /// </para>
  16. /// <para>
  17. /// MemoryNode
  18. /// 4 Stamp
  19. /// 4 Next
  20. /// 4 UnitCount
  21. /// </para>
  22. /// <para>
  23. /// Note that <see cref="_address"/> is a field rather than a property for performance reasons.
  24. /// </para>
  25. /// </remarks>
  26. internal struct MemoryNode
  27. {
  28. public uint _address;
  29. public byte[] _memory;
  30. public static readonly MemoryNode ZERO = new MemoryNode(0, null);
  31. public const int SIZE = 12;
  32. /// <summary>
  33. /// Initializes a new instance of the <see cref="MemoryNode"/> structure.
  34. /// </summary>
  35. public MemoryNode(uint address, byte[] memory)
  36. {
  37. _address = address;
  38. _memory = memory;
  39. }
  40. /// <summary>
  41. /// Gets or sets the stamp.
  42. /// </summary>
  43. public uint Stamp
  44. {
  45. get => _memory[_address] | ((uint)_memory[_address + 1]) << 8 | ((uint)_memory[_address + 2]) << 16 |
  46. ((uint)_memory[_address + 3]) << 24;
  47. set
  48. {
  49. _memory[_address] = (byte)value;
  50. _memory[_address + 1] = (byte)(value >> 8);
  51. _memory[_address + 2] = (byte)(value >> 16);
  52. _memory[_address + 3] = (byte)(value >> 24);
  53. }
  54. }
  55. /// <summary>
  56. /// Gets or sets the next memory node.
  57. /// </summary>
  58. public MemoryNode Next
  59. {
  60. get => new MemoryNode(
  61. _memory[_address + 4] | ((uint)_memory[_address + 5]) << 8 |
  62. ((uint)_memory[_address + 6]) << 16 | ((uint)_memory[_address + 7]) << 24, _memory);
  63. set
  64. {
  65. _memory[_address + 4] = (byte)value._address;
  66. _memory[_address + 5] = (byte)(value._address >> 8);
  67. _memory[_address + 6] = (byte)(value._address >> 16);
  68. _memory[_address + 7] = (byte)(value._address >> 24);
  69. }
  70. }
  71. /// <summary>
  72. /// Gets or sets the unit count.
  73. /// </summary>
  74. public uint UnitCount
  75. {
  76. get => _memory[_address + 8] | ((uint)_memory[_address + 9]) << 8 |
  77. ((uint)_memory[_address + 10]) << 16 | ((uint)_memory[_address + 11]) << 24;
  78. set
  79. {
  80. _memory[_address + 8] = (byte)value;
  81. _memory[_address + 9] = (byte)(value >> 8);
  82. _memory[_address + 10] = (byte)(value >> 16);
  83. _memory[_address + 11] = (byte)(value >> 24);
  84. }
  85. }
  86. /// <summary>
  87. /// Gets whether there is a next memory node available.
  88. /// </summary>
  89. public bool Available => Next._address != 0;
  90. /// <summary>
  91. /// Link in the provided memory node.
  92. /// </summary>
  93. /// <param name="memoryNode"></param>
  94. public void Link(MemoryNode memoryNode)
  95. {
  96. memoryNode.Next = Next;
  97. Next = memoryNode;
  98. }
  99. /// <summary>
  100. /// Unlink this memory node.
  101. /// </summary>
  102. public void Unlink()
  103. {
  104. Next = Next.Next;
  105. }
  106. /// <summary>
  107. /// Insert the memory node into the linked list.
  108. /// </summary>
  109. /// <param name="memoryNode"></param>
  110. /// <param name="unitCount"></param>
  111. public void Insert(MemoryNode memoryNode, uint unitCount)
  112. {
  113. Link(memoryNode);
  114. memoryNode.Stamp = uint.MaxValue;
  115. memoryNode.UnitCount = unitCount;
  116. Stamp++;
  117. }
  118. /// <summary>
  119. /// Remove this memory node from the linked list.
  120. /// </summary>
  121. /// <returns></returns>
  122. public MemoryNode Remove()
  123. {
  124. MemoryNode next = Next;
  125. Unlink();
  126. Stamp--;
  127. return next;
  128. }
  129. /// <summary>
  130. /// Allow a pointer to be implicitly converted to a memory node.
  131. /// </summary>
  132. /// <param name="pointer"></param>
  133. /// <returns></returns>
  134. public static implicit operator MemoryNode(Pointer pointer)
  135. {
  136. return new MemoryNode(pointer._address, pointer._memory);
  137. }
  138. /// <summary>
  139. /// Allow pointer-like addition on a memory node.
  140. /// </summary>
  141. /// <param name="memoryNode"></param>
  142. /// <param name="offset"></param>
  143. /// <returns></returns>
  144. public static MemoryNode operator +(MemoryNode memoryNode, int offset)
  145. {
  146. memoryNode._address = (uint)(memoryNode._address + offset * SIZE);
  147. return memoryNode;
  148. }
  149. /// <summary>
  150. /// Allow pointer-like addition on a memory node.
  151. /// </summary>
  152. /// <param name="memoryNode"></param>
  153. /// <param name="offset"></param>
  154. /// <returns></returns>
  155. public static MemoryNode operator +(MemoryNode memoryNode, uint offset)
  156. {
  157. memoryNode._address += offset * SIZE;
  158. return memoryNode;
  159. }
  160. /// <summary>
  161. /// Allow pointer-like subtraction on a memory node.
  162. /// </summary>
  163. /// <param name="memoryNode"></param>
  164. /// <param name="offset"></param>
  165. /// <returns></returns>
  166. public static MemoryNode operator -(MemoryNode memoryNode, int offset)
  167. {
  168. memoryNode._address = (uint)(memoryNode._address - offset * SIZE);
  169. return memoryNode;
  170. }
  171. /// <summary>
  172. /// Allow pointer-like subtraction on a memory node.
  173. /// </summary>
  174. /// <param name="memoryNode"></param>
  175. /// <param name="offset"></param>
  176. /// <returns></returns>
  177. public static MemoryNode operator -(MemoryNode memoryNode, uint offset)
  178. {
  179. memoryNode._address -= offset * SIZE;
  180. return memoryNode;
  181. }
  182. /// <summary>
  183. /// Compare two memory nodes.
  184. /// </summary>
  185. /// <param name="memoryNode1"></param>
  186. /// <param name="memoryNode2"></param>
  187. /// <returns></returns>
  188. public static bool operator ==(MemoryNode memoryNode1, MemoryNode memoryNode2)
  189. {
  190. return memoryNode1._address == memoryNode2._address;
  191. }
  192. /// <summary>
  193. /// Compare two memory nodes.
  194. /// </summary>
  195. /// <param name="memoryNode1"></param>
  196. /// <param name="memoryNode2"></param>
  197. /// <returns></returns>
  198. public static bool operator !=(MemoryNode memoryNode1, MemoryNode memoryNode2)
  199. {
  200. return memoryNode1._address != memoryNode2._address;
  201. }
  202. /// <summary>
  203. /// Indicates whether this instance and a specified object are equal.
  204. /// </summary>
  205. /// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
  206. /// <param name="obj">Another object to compare to.</param>
  207. public override bool Equals(object obj)
  208. {
  209. if (obj is MemoryNode)
  210. {
  211. MemoryNode memoryNode = (MemoryNode)obj;
  212. return memoryNode._address == _address;
  213. }
  214. return base.Equals(obj);
  215. }
  216. /// <summary>
  217. /// Returns the hash code for this instance.
  218. /// </summary>
  219. /// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
  220. public override int GetHashCode()
  221. {
  222. return _address.GetHashCode();
  223. }
  224. }
  225. }