PpmState.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #region Using
  2. #endregion
  3. namespace SharpCompress.Compressors.PPMd.I1
  4. {
  5. /// <summary>
  6. /// PPM state.
  7. /// </summary>
  8. /// <remarks>
  9. /// <para>
  10. /// This must be a structure rather than a class because several places in the associated code assume that
  11. /// <see cref="PpmState"/> is a value type (meaning that assignment creates a completely new copy of the
  12. /// instance rather than just copying a reference to the same instance).
  13. /// </para>
  14. /// <para>
  15. /// Note that <see cref="_address"/> is a field rather than a property for performance reasons.
  16. /// </para>
  17. /// </remarks>
  18. internal struct PpmState
  19. {
  20. public uint _address;
  21. public byte[] _memory;
  22. public static readonly PpmState ZERO = new PpmState(0, null);
  23. public const int SIZE = 6;
  24. /// <summary>
  25. /// Initializes a new instance of the <see cref="PpmState"/> structure.
  26. /// </summary>
  27. public PpmState(uint address, byte[] memory)
  28. {
  29. _address = address;
  30. _memory = memory;
  31. }
  32. /// <summary>
  33. /// Gets or sets the symbol.
  34. /// </summary>
  35. public byte Symbol { get => _memory[_address]; set => _memory[_address] = value; }
  36. /// <summary>
  37. /// Gets or sets the frequency.
  38. /// </summary>
  39. public byte Frequency { get => _memory[_address + 1]; set => _memory[_address + 1] = value; }
  40. /// <summary>
  41. /// Gets or sets the successor.
  42. /// </summary>
  43. public Model.PpmContext Successor
  44. {
  45. get => new Model.PpmContext(
  46. _memory[_address + 2] | ((uint)_memory[_address + 3]) << 8 |
  47. ((uint)_memory[_address + 4]) << 16 | ((uint)_memory[_address + 5]) << 24, _memory);
  48. set
  49. {
  50. _memory[_address + 2] = (byte)value._address;
  51. _memory[_address + 3] = (byte)(value._address >> 8);
  52. _memory[_address + 4] = (byte)(value._address >> 16);
  53. _memory[_address + 5] = (byte)(value._address >> 24);
  54. }
  55. }
  56. /// <summary>
  57. /// Gets the <see cref="PpmState"/> at the <paramref name="offset"/> relative to this
  58. /// <see cref="PpmState"/>.
  59. /// </summary>
  60. /// <param name="offset"></param>
  61. /// <returns></returns>
  62. public PpmState this[int offset] => new PpmState((uint)(_address + offset * SIZE), _memory);
  63. /// <summary>
  64. /// Allow a pointer to be implicitly converted to a PPM state.
  65. /// </summary>
  66. /// <param name="pointer"></param>
  67. /// <returns></returns>
  68. public static implicit operator PpmState(Pointer pointer)
  69. {
  70. return new PpmState(pointer._address, pointer._memory);
  71. }
  72. /// <summary>
  73. /// Allow pointer-like addition on a PPM state.
  74. /// </summary>
  75. /// <param name="state"></param>
  76. /// <param name="offset"></param>
  77. /// <returns></returns>
  78. public static PpmState operator +(PpmState state, int offset)
  79. {
  80. state._address = (uint)(state._address + offset * SIZE);
  81. return state;
  82. }
  83. /// <summary>
  84. /// Allow pointer-like incrementing on a PPM state.
  85. /// </summary>
  86. /// <param name="state"></param>
  87. /// <returns></returns>
  88. public static PpmState operator ++(PpmState state)
  89. {
  90. state._address += SIZE;
  91. return state;
  92. }
  93. /// <summary>
  94. /// Allow pointer-like subtraction on a PPM state.
  95. /// </summary>
  96. /// <param name="state"></param>
  97. /// <param name="offset"></param>
  98. /// <returns></returns>
  99. public static PpmState operator -(PpmState state, int offset)
  100. {
  101. state._address = (uint)(state._address - offset * SIZE);
  102. return state;
  103. }
  104. /// <summary>
  105. /// Allow pointer-like decrementing on a PPM state.
  106. /// </summary>
  107. /// <param name="state"></param>
  108. /// <returns></returns>
  109. public static PpmState operator --(PpmState state)
  110. {
  111. state._address -= SIZE;
  112. return state;
  113. }
  114. /// <summary>
  115. /// Compare two PPM states.
  116. /// </summary>
  117. /// <param name="state1"></param>
  118. /// <param name="state2"></param>
  119. /// <returns></returns>
  120. public static bool operator <=(PpmState state1, PpmState state2)
  121. {
  122. return state1._address <= state2._address;
  123. }
  124. /// <summary>
  125. /// Compare two PPM states.
  126. /// </summary>
  127. /// <param name="state1"></param>
  128. /// <param name="state2"></param>
  129. /// <returns></returns>
  130. public static bool operator >=(PpmState state1, PpmState state2)
  131. {
  132. return state1._address >= state2._address;
  133. }
  134. /// <summary>
  135. /// Compare two PPM states.
  136. /// </summary>
  137. /// <param name="state1"></param>
  138. /// <param name="state2"></param>
  139. /// <returns></returns>
  140. public static bool operator ==(PpmState state1, PpmState state2)
  141. {
  142. return state1._address == state2._address;
  143. }
  144. /// <summary>
  145. /// Compare two PPM states.
  146. /// </summary>
  147. /// <param name="state1"></param>
  148. /// <param name="state2"></param>
  149. /// <returns></returns>
  150. public static bool operator !=(PpmState state1, PpmState state2)
  151. {
  152. return state1._address != state2._address;
  153. }
  154. /// <summary>
  155. /// Indicates whether this instance and a specified object are equal.
  156. /// </summary>
  157. /// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
  158. /// <param name="obj">Another object to compare to.</param>
  159. public override bool Equals(object obj)
  160. {
  161. if (obj is PpmState)
  162. {
  163. PpmState state = (PpmState)obj;
  164. return state._address == _address;
  165. }
  166. return base.Equals(obj);
  167. }
  168. /// <summary>
  169. /// Returns the hash code for this instance.
  170. /// </summary>
  171. /// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
  172. public override int GetHashCode()
  173. {
  174. return _address.GetHashCode();
  175. }
  176. }
  177. }