Pointer.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. #region Using
  2. using System;
  3. #endregion
  4. namespace SharpCompress.Compressors.PPMd.I1
  5. {
  6. /// <summary>
  7. /// A structure containing a single address representing a position in the <see cref="_memory"/> array. This
  8. /// is intended to mimic the behaviour of a pointer in C/C++.
  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="Pointer"/> is a value type (meaning that assignment creates a completely new copy of the
  14. /// instance rather than just copying a reference to the same instance).
  15. /// </para>
  16. /// <para>
  17. /// Note that <see cref="_address"/> is a field rather than a property for performance reasons.
  18. /// </para>
  19. /// </remarks>
  20. internal struct Pointer
  21. {
  22. public uint _address;
  23. public byte[] _memory;
  24. public static readonly Pointer ZERO = new Pointer(0, null);
  25. public const int SIZE = 1;
  26. /// <summary>
  27. /// Initializes a new instance of the <see cref="Pointer"/> structure.
  28. /// </summary>
  29. public Pointer(uint address, byte[] memory)
  30. {
  31. _address = address;
  32. _memory = memory;
  33. }
  34. /// <summary>
  35. /// Gets or sets the byte at the given <paramref name="offset"/>.
  36. /// </summary>
  37. /// <param name="offset"></param>
  38. /// <returns></returns>
  39. public byte this[int offset]
  40. {
  41. get
  42. {
  43. #if DEBUG
  44. if (_address == 0)
  45. {
  46. throw new InvalidOperationException("The pointer being indexed is a null pointer.");
  47. }
  48. #endif
  49. return _memory[_address + offset];
  50. }
  51. set
  52. {
  53. #if DEBUG
  54. if (_address == 0)
  55. {
  56. throw new InvalidOperationException("The pointer being indexed is a null pointer.");
  57. }
  58. #endif
  59. _memory[_address + offset] = value;
  60. }
  61. }
  62. /// <summary>
  63. /// Allow a <see cref="MemoryNode"/> to be implicitly converted to a <see cref="Pointer"/>.
  64. /// </summary>
  65. /// <param name="memoryNode"></param>
  66. /// <returns></returns>
  67. public static implicit operator Pointer(MemoryNode memoryNode)
  68. {
  69. return new Pointer(memoryNode._address, memoryNode._memory);
  70. }
  71. /// <summary>
  72. /// Allow a <see cref="Model.PpmContext"/> to be implicitly converted to a <see cref="Pointer"/>.
  73. /// </summary>
  74. /// <param name="context"></param>
  75. /// <returns></returns>
  76. public static implicit operator Pointer(Model.PpmContext context)
  77. {
  78. return new Pointer(context._address, context._memory);
  79. }
  80. /// <summary>
  81. /// Allow a <see cref="PpmState"/> to be implicitly converted to a <see cref="Pointer"/>.
  82. /// </summary>
  83. /// <param name="state"></param>
  84. /// <returns></returns>
  85. public static implicit operator Pointer(PpmState state)
  86. {
  87. return new Pointer(state._address, state._memory);
  88. }
  89. /// <summary>
  90. /// Increase the address of a pointer by the given number of bytes.
  91. /// </summary>
  92. /// <param name="pointer"></param>
  93. /// <param name="offset"></param>
  94. /// <returns></returns>
  95. public static Pointer operator +(Pointer pointer, int offset)
  96. {
  97. #if DEBUG
  98. if (pointer._address == 0)
  99. {
  100. throw new InvalidOperationException("The pointer is a null pointer.");
  101. }
  102. #endif
  103. pointer._address = (uint)(pointer._address + offset);
  104. return pointer;
  105. }
  106. /// <summary>
  107. /// Increase the address of a pointer by the given number of bytes.
  108. /// </summary>
  109. /// <param name="pointer"></param>
  110. /// <param name="offset"></param>
  111. /// <returns></returns>
  112. public static Pointer operator +(Pointer pointer, uint offset)
  113. {
  114. #if DEBUG
  115. if (pointer._address == 0)
  116. {
  117. throw new InvalidOperationException("The pointer is a null pointer.");
  118. }
  119. #endif
  120. pointer._address += offset;
  121. return pointer;
  122. }
  123. /// <summary>
  124. /// Increment the address of a pointer.
  125. /// </summary>
  126. /// <param name="pointer"></param>
  127. /// <returns></returns>
  128. public static Pointer operator ++(Pointer pointer)
  129. {
  130. #if DEBUG
  131. if (pointer._address == 0)
  132. {
  133. throw new InvalidOperationException("The pointer being incremented is a null pointer.");
  134. }
  135. #endif
  136. pointer._address++;
  137. return pointer;
  138. }
  139. /// <summary>
  140. /// Decrease the address of a pointer by the given number of bytes.
  141. /// </summary>
  142. /// <param name="pointer"></param>
  143. /// <param name="offset"></param>
  144. /// <returns></returns>
  145. public static Pointer operator -(Pointer pointer, int offset)
  146. {
  147. #if DEBUG
  148. if (pointer._address == 0)
  149. {
  150. throw new InvalidOperationException("The pointer is a null pointer.");
  151. }
  152. #endif
  153. pointer._address = (uint)(pointer._address - offset);
  154. return pointer;
  155. }
  156. /// <summary>
  157. /// Decrease the address of a pointer by the given number of bytes.
  158. /// </summary>
  159. /// <param name="pointer"></param>
  160. /// <param name="offset"></param>
  161. /// <returns></returns>
  162. public static Pointer operator -(Pointer pointer, uint offset)
  163. {
  164. #if DEBUG
  165. if (pointer._address == 0)
  166. {
  167. throw new InvalidOperationException("The pointer is a null pointer.");
  168. }
  169. #endif
  170. pointer._address -= offset;
  171. return pointer;
  172. }
  173. /// <summary>
  174. /// Decrement the address of a pointer.
  175. /// </summary>
  176. /// <param name="pointer"></param>
  177. /// <returns></returns>
  178. public static Pointer operator --(Pointer pointer)
  179. {
  180. #if DEBUG
  181. if (pointer._address == 0)
  182. {
  183. throw new InvalidOperationException("The pointer being decremented is a null pointer.");
  184. }
  185. #endif
  186. pointer._address--;
  187. return pointer;
  188. }
  189. /// <summary>
  190. /// Subtract two pointers.
  191. /// </summary>
  192. /// <param name="pointer1"></param>
  193. /// <param name="pointer2"></param>
  194. /// <returns>The number of bytes between the two pointers.</returns>
  195. public static uint operator -(Pointer pointer1, Pointer pointer2)
  196. {
  197. #if DEBUG
  198. if (pointer1._address == 0)
  199. {
  200. throw new InvalidOperationException(
  201. "The pointer to the left of the subtraction operator is a null pointer.");
  202. }
  203. if (pointer2._address == 0)
  204. {
  205. throw new InvalidOperationException(
  206. "The pointer to the right of the subtraction operator is a null pointer.");
  207. }
  208. #endif
  209. return pointer1._address - pointer2._address;
  210. }
  211. /// <summary>
  212. /// Compare pointers.
  213. /// </summary>
  214. /// <param name="pointer1"></param>
  215. /// <param name="pointer2"></param>
  216. /// <returns></returns>
  217. public static bool operator <(Pointer pointer1, Pointer pointer2)
  218. {
  219. #if DEBUG
  220. if (pointer1._address == 0)
  221. {
  222. throw new InvalidOperationException(
  223. "The pointer to the left of the less than operator is a null pointer.");
  224. }
  225. if (pointer2._address == 0)
  226. {
  227. throw new InvalidOperationException(
  228. "The pointer to the right of the less than operator is a null pointer.");
  229. }
  230. #endif
  231. return pointer1._address < pointer2._address;
  232. }
  233. /// <summary>
  234. /// Compare two pointers.
  235. /// </summary>
  236. /// <param name="pointer1"></param>
  237. /// <param name="pointer2"></param>
  238. /// <returns></returns>
  239. public static bool operator <=(Pointer pointer1, Pointer pointer2)
  240. {
  241. #if DEBUG
  242. if (pointer1._address == 0)
  243. {
  244. throw new InvalidOperationException(
  245. "The pointer to the left of the less than or equal to operator is a null pointer.");
  246. }
  247. if (pointer2._address == 0)
  248. {
  249. throw new InvalidOperationException(
  250. "The pointer to the right of the less than or equal to operator is a null pointer.");
  251. }
  252. #endif
  253. return pointer1._address <= pointer2._address;
  254. }
  255. /// <summary>
  256. /// Compare two pointers.
  257. /// </summary>
  258. /// <param name="pointer1"></param>
  259. /// <param name="pointer2"></param>
  260. /// <returns></returns>
  261. public static bool operator >(Pointer pointer1, Pointer pointer2)
  262. {
  263. #if DEBUG
  264. if (pointer1._address == 0)
  265. {
  266. throw new InvalidOperationException(
  267. "The pointer to the left of the greater than operator is a null pointer.");
  268. }
  269. if (pointer2._address == 0)
  270. {
  271. throw new InvalidOperationException(
  272. "The pointer to the right of the greater than operator is a null pointer.");
  273. }
  274. #endif
  275. return pointer1._address > pointer2._address;
  276. }
  277. /// <summary>
  278. /// Compare two pointers.
  279. /// </summary>
  280. /// <param name="pointer1"></param>
  281. /// <param name="pointer2"></param>
  282. /// <returns></returns>
  283. public static bool operator >=(Pointer pointer1, Pointer pointer2)
  284. {
  285. #if DEBUG
  286. if (pointer1._address == 0)
  287. {
  288. throw new InvalidOperationException(
  289. "The pointer to the left of the greater than or equal to operator is a null pointer.");
  290. }
  291. if (pointer2._address == 0)
  292. {
  293. throw new InvalidOperationException(
  294. "The pointer to the right of the greater than or equal to operator is a null pointer.");
  295. }
  296. #endif
  297. return pointer1._address >= pointer2._address;
  298. }
  299. /// <summary>
  300. /// Compare two pointers.
  301. /// </summary>
  302. /// <param name="pointer1"></param>
  303. /// <param name="pointer2"></param>
  304. /// <returns></returns>
  305. public static bool operator ==(Pointer pointer1, Pointer pointer2)
  306. {
  307. return pointer1._address == pointer2._address;
  308. }
  309. /// <summary>
  310. /// Compare two pointers.
  311. /// </summary>
  312. /// <param name="pointer1"></param>
  313. /// <param name="pointer2"></param>
  314. /// <returns></returns>
  315. public static bool operator !=(Pointer pointer1, Pointer pointer2)
  316. {
  317. return pointer1._address != pointer2._address;
  318. }
  319. /// <summary>
  320. /// Indicates whether this instance and a specified object are equal.
  321. /// </summary>
  322. /// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
  323. /// <param name="obj">Another object to compare to.</param>
  324. public override bool Equals(object obj)
  325. {
  326. if (obj is Pointer)
  327. {
  328. Pointer pointer = (Pointer)obj;
  329. return pointer._address == _address;
  330. }
  331. return base.Equals(obj);
  332. }
  333. /// <summary>
  334. /// Returns the hash code for this instance.
  335. /// </summary>
  336. /// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
  337. public override int GetHashCode()
  338. {
  339. return _address.GetHashCode();
  340. }
  341. }
  342. }