erlang自定义二进制协议
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

695 rader
26 KiB

  1. using System;
  2. using System.Runtime.InteropServices;
  3. namespace MiscUtil.Conversion
  4. {
  5. /// <summary>
  6. /// Equivalent of System.BitConverter, but with either endianness.
  7. /// </summary>
  8. public abstract class EndianBitConverter
  9. {
  10. #region Endianness of this converter
  11. /// <summary>
  12. /// Indicates the byte order ("endianess") in which data is converted using this class.
  13. /// </summary>
  14. /// <remarks>
  15. /// Different computer architectures store data using different byte orders. "Big-endian"
  16. /// means the most significant byte is on the left end of a word. "Little-endian" means the
  17. /// most significant byte is on the right end of a word.
  18. /// </remarks>
  19. /// <returns>true if this converter is little-endian, false otherwise.</returns>
  20. public abstract bool IsLittleEndian();
  21. /// <summary>
  22. /// Indicates the byte order ("endianess") in which data is converted using this class.
  23. /// </summary>
  24. public abstract Endianness Endianness { get; }
  25. #endregion
  26. #region Factory properties
  27. static LittleEndianBitConverter little = new LittleEndianBitConverter();
  28. /// <summary>
  29. /// Returns a little-endian bit converter instance. The same instance is
  30. /// always returned.
  31. /// </summary>
  32. public static LittleEndianBitConverter Little
  33. {
  34. get { return little; }
  35. }
  36. static BigEndianBitConverter big = new BigEndianBitConverter();
  37. /// <summary>
  38. /// Returns a big-endian bit converter instance. The same instance is
  39. /// always returned.
  40. /// </summary>
  41. public static BigEndianBitConverter Big
  42. {
  43. get { return big; }
  44. }
  45. #endregion
  46. #region Double/primitive conversions
  47. /// <summary>
  48. /// Converts the specified double-precision floating point number to a
  49. /// 64-bit signed integer. Note: the endianness of this converter does not
  50. /// affect the returned value.
  51. /// </summary>
  52. /// <param name="value">The number to convert. </param>
  53. /// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
  54. public long DoubleToInt64Bits(double value)
  55. {
  56. return BitConverter.DoubleToInt64Bits(value);
  57. }
  58. /// <summary>
  59. /// Converts the specified 64-bit signed integer to a double-precision
  60. /// floating point number. Note: the endianness of this converter does not
  61. /// affect the returned value.
  62. /// </summary>
  63. /// <param name="value">The number to convert. </param>
  64. /// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
  65. public double Int64BitsToDouble (long value)
  66. {
  67. return BitConverter.Int64BitsToDouble(value);
  68. }
  69. /// <summary>
  70. /// Converts the specified single-precision floating point number to a
  71. /// 32-bit signed integer. Note: the endianness of this converter does not
  72. /// affect the returned value.
  73. /// </summary>
  74. /// <param name="value">The number to convert. </param>
  75. /// <returns>A 32-bit signed integer whose value is equivalent to value.</returns>
  76. public int SingleToInt32Bits(float value)
  77. {
  78. return new Int32SingleUnion(value).AsInt32;
  79. }
  80. /// <summary>
  81. /// Converts the specified 32-bit signed integer to a single-precision floating point
  82. /// number. Note: the endianness of this converter does not
  83. /// affect the returned value.
  84. /// </summary>
  85. /// <param name="value">The number to convert. </param>
  86. /// <returns>A single-precision floating point number whose value is equivalent to value.</returns>
  87. public float Int32BitsToSingle (int value)
  88. {
  89. return new Int32SingleUnion(value).AsSingle;
  90. }
  91. #endregion
  92. #region To(PrimitiveType) conversions
  93. /// <summary>
  94. /// Returns a Boolean value converted from one byte at a specified position in a byte array.
  95. /// </summary>
  96. /// <param name="value">An array of bytes.</param>
  97. /// <param name="startIndex">The starting position within value.</param>
  98. /// <returns>true if the byte at startIndex in value is nonzero; otherwise, false.</returns>
  99. public bool ToBoolean (byte[] value, int startIndex)
  100. {
  101. CheckByteArgument(value, startIndex, 1);
  102. return BitConverter.ToBoolean(value, startIndex);
  103. }
  104. /// <summary>
  105. /// Returns a Unicode character converted from two bytes at a specified position in a byte array.
  106. /// </summary>
  107. /// <param name="value">An array of bytes.</param>
  108. /// <param name="startIndex">The starting position within value.</param>
  109. /// <returns>A character formed by two bytes beginning at startIndex.</returns>
  110. public char ToChar (byte[] value, int startIndex)
  111. {
  112. return unchecked((char) (CheckedFromBytes(value, startIndex, 2)));
  113. }
  114. /// <summary>
  115. /// Returns a double-precision floating point number converted from eight bytes
  116. /// at a specified position in a byte array.
  117. /// </summary>
  118. /// <param name="value">An array of bytes.</param>
  119. /// <param name="startIndex">The starting position within value.</param>
  120. /// <returns>A double precision floating point number formed by eight bytes beginning at startIndex.</returns>
  121. public double ToDouble (byte[] value, int startIndex)
  122. {
  123. return Int64BitsToDouble(ToInt64(value, startIndex));
  124. }
  125. /// <summary>
  126. /// Returns a single-precision floating point number converted from four bytes
  127. /// at a specified position in a byte array.
  128. /// </summary>
  129. /// <param name="value">An array of bytes.</param>
  130. /// <param name="startIndex">The starting position within value.</param>
  131. /// <returns>A single precision floating point number formed by four bytes beginning at startIndex.</returns>
  132. public float ToSingle (byte[] value, int startIndex)
  133. {
  134. return Int32BitsToSingle(ToInt32(value, startIndex));
  135. }
  136. /// <summary>
  137. /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.
  138. /// </summary>
  139. /// <param name="value">An array of bytes.</param>
  140. /// <param name="startIndex">The starting position within value.</param>
  141. /// <returns>A 16-bit signed integer formed by two bytes beginning at startIndex.</returns>
  142. public short ToInt16 (byte[] value, int startIndex)
  143. {
  144. return unchecked((short) (CheckedFromBytes(value, startIndex, 2)));
  145. }
  146. /// <summary>
  147. /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.
  148. /// </summary>
  149. /// <param name="value">An array of bytes.</param>
  150. /// <param name="startIndex">The starting position within value.</param>
  151. /// <returns>A 32-bit signed integer formed by four bytes beginning at startIndex.</returns>
  152. public int ToInt32 (byte[] value, int startIndex)
  153. {
  154. return unchecked((int) (CheckedFromBytes(value, startIndex, 4)));
  155. }
  156. /// <summary>
  157. /// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.
  158. /// </summary>
  159. /// <param name="value">An array of bytes.</param>
  160. /// <param name="startIndex">The starting position within value.</param>
  161. /// <returns>A 64-bit signed integer formed by eight bytes beginning at startIndex.</returns>
  162. public long ToInt64 (byte[] value, int startIndex)
  163. {
  164. return CheckedFromBytes(value, startIndex, 8);
  165. }
  166. /// <summary>
  167. /// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.
  168. /// </summary>
  169. /// <param name="value">An array of bytes.</param>
  170. /// <param name="startIndex">The starting position within value.</param>
  171. /// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
  172. public ushort ToUInt16 (byte[] value, int startIndex)
  173. {
  174. return unchecked((ushort) (CheckedFromBytes(value, startIndex, 2)));
  175. }
  176. /// <summary>
  177. /// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.
  178. /// </summary>
  179. /// <param name="value">An array of bytes.</param>
  180. /// <param name="startIndex">The starting position within value.</param>
  181. /// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
  182. public uint ToUInt32 (byte[] value, int startIndex)
  183. {
  184. return unchecked((uint) (CheckedFromBytes(value, startIndex, 4)));
  185. }
  186. /// <summary>
  187. /// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.
  188. /// </summary>
  189. /// <param name="value">An array of bytes.</param>
  190. /// <param name="startIndex">The starting position within value.</param>
  191. /// <returns>A 64-bit unsigned integer formed by eight bytes beginning at startIndex.</returns>
  192. public ulong ToUInt64 (byte[] value, int startIndex)
  193. {
  194. return unchecked((ulong) (CheckedFromBytes(value, startIndex, 8)));
  195. }
  196. /// <summary>
  197. /// Checks the given argument for validity.
  198. /// </summary>
  199. /// <param name="value">The byte array passed in</param>
  200. /// <param name="startIndex">The start index passed in</param>
  201. /// <param name="bytesRequired">The number of bytes required</param>
  202. /// <exception cref="ArgumentNullException">value is a null reference</exception>
  203. /// <exception cref="ArgumentOutOfRangeException">
  204. /// startIndex is less than zero or greater than the length of value minus bytesRequired.
  205. /// </exception>
  206. static void CheckByteArgument(byte[] value, int startIndex, int bytesRequired)
  207. {
  208. if (value==null)
  209. {
  210. throw new ArgumentNullException("value");
  211. }
  212. if (startIndex < 0 || startIndex > value.Length-bytesRequired)
  213. {
  214. throw new ArgumentOutOfRangeException("startIndex");
  215. }
  216. }
  217. /// <summary>
  218. /// Checks the arguments for validity before calling FromBytes
  219. /// (which can therefore assume the arguments are valid).
  220. /// </summary>
  221. /// <param name="value">The bytes to convert after checking</param>
  222. /// <param name="startIndex">The index of the first byte to convert</param>
  223. /// <param name="bytesToConvert">The number of bytes to convert</param>
  224. /// <returns></returns>
  225. long CheckedFromBytes(byte[] value, int startIndex, int bytesToConvert)
  226. {
  227. CheckByteArgument(value, startIndex, bytesToConvert);
  228. return FromBytes(value, startIndex, bytesToConvert);
  229. }
  230. /// <summary>
  231. /// Convert the given number of bytes from the given array, from the given start
  232. /// position, into a long, using the bytes as the least significant part of the long.
  233. /// By the time this is called, the arguments have been checked for validity.
  234. /// </summary>
  235. /// <param name="value">The bytes to convert</param>
  236. /// <param name="startIndex">The index of the first byte to convert</param>
  237. /// <param name="bytesToConvert">The number of bytes to use in the conversion</param>
  238. /// <returns>The converted number</returns>
  239. protected abstract long FromBytes(byte[] value, int startIndex, int bytesToConvert);
  240. #endregion
  241. #region ToString conversions
  242. /// <summary>
  243. /// Returns a String converted from the elements of a byte array.
  244. /// </summary>
  245. /// <param name="value">An array of bytes.</param>
  246. /// <remarks>All the elements of value are converted.</remarks>
  247. /// <returns>
  248. /// A String of hexadecimal pairs separated by hyphens, where each pair
  249. /// represents the corresponding element in value; for example, "7F-2C-4A".
  250. /// </returns>
  251. public static string ToString(byte[] value)
  252. {
  253. return BitConverter.ToString(value);
  254. }
  255. /// <summary>
  256. /// Returns a String converted from the elements of a byte array starting at a specified array position.
  257. /// </summary>
  258. /// <param name="value">An array of bytes.</param>
  259. /// <param name="startIndex">The starting position within value.</param>
  260. /// <remarks>The elements from array position startIndex to the end of the array are converted.</remarks>
  261. /// <returns>
  262. /// A String of hexadecimal pairs separated by hyphens, where each pair
  263. /// represents the corresponding element in value; for example, "7F-2C-4A".
  264. /// </returns>
  265. public static string ToString(byte[] value, int startIndex)
  266. {
  267. return BitConverter.ToString(value, startIndex);
  268. }
  269. /// <summary>
  270. /// Returns a String converted from a specified number of bytes at a specified position in a byte array.
  271. /// </summary>
  272. /// <param name="value">An array of bytes.</param>
  273. /// <param name="startIndex">The starting position within value.</param>
  274. /// <param name="length">The number of bytes to convert.</param>
  275. /// <remarks>The length elements from array position startIndex are converted.</remarks>
  276. /// <returns>
  277. /// A String of hexadecimal pairs separated by hyphens, where each pair
  278. /// represents the corresponding element in value; for example, "7F-2C-4A".
  279. /// </returns>
  280. public static string ToString(byte[] value, int startIndex, int length)
  281. {
  282. return BitConverter.ToString(value, startIndex, length);
  283. }
  284. #endregion
  285. #region Decimal conversions
  286. /// <summary>
  287. /// Returns a decimal value converted from sixteen bytes
  288. /// at a specified position in a byte array.
  289. /// </summary>
  290. /// <param name="value">An array of bytes.</param>
  291. /// <param name="startIndex">The starting position within value.</param>
  292. /// <returns>A decimal formed by sixteen bytes beginning at startIndex.</returns>
  293. public decimal ToDecimal (byte[] value, int startIndex)
  294. {
  295. // HACK: This always assumes four parts, each in their own endianness,
  296. // starting with the first part at the start of the byte array.
  297. // On the other hand, there's no real format specified...
  298. int[] parts = new int[4];
  299. for (int i=0; i < 4; i++)
  300. {
  301. parts[i] = ToInt32(value, startIndex+i*4);
  302. }
  303. return new Decimal(parts);
  304. }
  305. /// <summary>
  306. /// Returns the specified decimal value as an array of bytes.
  307. /// </summary>
  308. /// <param name="value">The number to convert.</param>
  309. /// <returns>An array of bytes with length 16.</returns>
  310. public byte[] GetBytes(decimal value)
  311. {
  312. byte[] bytes = new byte[16];
  313. int[] parts = decimal.GetBits(value);
  314. for (int i=0; i < 4; i++)
  315. {
  316. CopyBytesImpl(parts[i], 4, bytes, i*4);
  317. }
  318. return bytes;
  319. }
  320. /// <summary>
  321. /// Copies the specified decimal value into the specified byte array,
  322. /// beginning at the specified index.
  323. /// </summary>
  324. /// <param name="value">A character to convert.</param>
  325. /// <param name="buffer">The byte array to copy the bytes into</param>
  326. /// <param name="index">The first index into the array to copy the bytes into</param>
  327. public void CopyBytes(decimal value, byte[] buffer, int index)
  328. {
  329. int[] parts = decimal.GetBits(value);
  330. for (int i=0; i < 4; i++)
  331. {
  332. CopyBytesImpl(parts[i], 4, buffer, i*4+index);
  333. }
  334. }
  335. #endregion
  336. #region GetBytes conversions
  337. /// <summary>
  338. /// Returns an array with the given number of bytes formed
  339. /// from the least significant bytes of the specified value.
  340. /// This is used to implement the other GetBytes methods.
  341. /// </summary>
  342. /// <param name="value">The value to get bytes for</param>
  343. /// <param name="bytes">The number of significant bytes to return</param>
  344. byte[] GetBytes(long value, int bytes)
  345. {
  346. byte[] buffer = new byte[bytes];
  347. CopyBytes(value, bytes, buffer, 0);
  348. return buffer;
  349. }
  350. /// <summary>
  351. /// Returns the specified Boolean value as an array of bytes.
  352. /// </summary>
  353. /// <param name="value">A Boolean value.</param>
  354. /// <returns>An array of bytes with length 1.</returns>
  355. public byte[] GetBytes(bool value)
  356. {
  357. return BitConverter.GetBytes(value);
  358. }
  359. /// <summary>
  360. /// Returns the specified Unicode character value as an array of bytes.
  361. /// </summary>
  362. /// <param name="value">A character to convert.</param>
  363. /// <returns>An array of bytes with length 2.</returns>
  364. public byte[] GetBytes(char value)
  365. {
  366. return GetBytes(value, 2);
  367. }
  368. /// <summary>
  369. /// Returns the specified double-precision floating point value as an array of bytes.
  370. /// </summary>
  371. /// <param name="value">The number to convert.</param>
  372. /// <returns>An array of bytes with length 8.</returns>
  373. public byte[] GetBytes(double value)
  374. {
  375. return GetBytes(DoubleToInt64Bits(value), 8);
  376. }
  377. /// <summary>
  378. /// Returns the specified 16-bit signed integer value as an array of bytes.
  379. /// </summary>
  380. /// <param name="value">The number to convert.</param>
  381. /// <returns>An array of bytes with length 2.</returns>
  382. public byte[] GetBytes(short value)
  383. {
  384. return GetBytes(value, 2);
  385. }
  386. /// <summary>
  387. /// Returns the specified 32-bit signed integer value as an array of bytes.
  388. /// </summary>
  389. /// <param name="value">The number to convert.</param>
  390. /// <returns>An array of bytes with length 4.</returns>
  391. public byte[] GetBytes(int value)
  392. {
  393. return GetBytes(value, 4);
  394. }
  395. /// <summary>
  396. /// Returns the specified 64-bit signed integer value as an array of bytes.
  397. /// </summary>
  398. /// <param name="value">The number to convert.</param>
  399. /// <returns>An array of bytes with length 8.</returns>
  400. public byte[] GetBytes(long value)
  401. {
  402. return GetBytes(value, 8);
  403. }
  404. /// <summary>
  405. /// Returns the specified single-precision floating point value as an array of bytes.
  406. /// </summary>
  407. /// <param name="value">The number to convert.</param>
  408. /// <returns>An array of bytes with length 4.</returns>
  409. public byte[] GetBytes(float value)
  410. {
  411. return GetBytes(SingleToInt32Bits(value), 4);
  412. }
  413. /// <summary>
  414. /// Returns the specified 16-bit unsigned integer value as an array of bytes.
  415. /// </summary>
  416. /// <param name="value">The number to convert.</param>
  417. /// <returns>An array of bytes with length 2.</returns>
  418. public byte[] GetBytes(ushort value)
  419. {
  420. return GetBytes(value, 2);
  421. }
  422. /// <summary>
  423. /// Returns the specified 32-bit unsigned integer value as an array of bytes.
  424. /// </summary>
  425. /// <param name="value">The number to convert.</param>
  426. /// <returns>An array of bytes with length 4.</returns>
  427. public byte[] GetBytes(uint value)
  428. {
  429. return GetBytes(value, 4);
  430. }
  431. /// <summary>
  432. /// Returns the specified 64-bit unsigned integer value as an array of bytes.
  433. /// </summary>
  434. /// <param name="value">The number to convert.</param>
  435. /// <returns>An array of bytes with length 8.</returns>
  436. public byte[] GetBytes(ulong value)
  437. {
  438. return GetBytes(unchecked((long)value), 8);
  439. }
  440. #endregion
  441. #region CopyBytes conversions
  442. /// <summary>
  443. /// Copies the given number of bytes from the least-specific
  444. /// end of the specified value into the specified byte array, beginning
  445. /// at the specified index.
  446. /// This is used to implement the other CopyBytes methods.
  447. /// </summary>
  448. /// <param name="value">The value to copy bytes for</param>
  449. /// <param name="bytes">The number of significant bytes to copy</param>
  450. /// <param name="buffer">The byte array to copy the bytes into</param>
  451. /// <param name="index">The first index into the array to copy the bytes into</param>
  452. void CopyBytes(long value, int bytes, byte[] buffer, int index)
  453. {
  454. if (buffer==null)
  455. {
  456. throw new ArgumentNullException("buffer", "Byte array must not be null");
  457. }
  458. if (buffer.Length < index+bytes)
  459. {
  460. throw new ArgumentOutOfRangeException("Buffer not big enough for value");
  461. }
  462. CopyBytesImpl(value, bytes, buffer, index);
  463. }
  464. /// <summary>
  465. /// Copies the given number of bytes from the least-specific
  466. /// end of the specified value into the specified byte array, beginning
  467. /// at the specified index.
  468. /// This must be implemented in concrete derived classes, but the implementation
  469. /// may assume that the value will fit into the buffer.
  470. /// </summary>
  471. /// <param name="value">The value to copy bytes for</param>
  472. /// <param name="bytes">The number of significant bytes to copy</param>
  473. /// <param name="buffer">The byte array to copy the bytes into</param>
  474. /// <param name="index">The first index into the array to copy the bytes into</param>
  475. protected abstract void CopyBytesImpl(long value, int bytes, byte[] buffer, int index);
  476. /// <summary>
  477. /// Copies the specified Boolean value into the specified byte array,
  478. /// beginning at the specified index.
  479. /// </summary>
  480. /// <param name="value">A Boolean value.</param>
  481. /// <param name="buffer">The byte array to copy the bytes into</param>
  482. /// <param name="index">The first index into the array to copy the bytes into</param>
  483. public void CopyBytes(bool value, byte[] buffer, int index)
  484. {
  485. CopyBytes(value ? 1 : 0, 1, buffer, index);
  486. }
  487. /// <summary>
  488. /// Copies the specified Unicode character value into the specified byte array,
  489. /// beginning at the specified index.
  490. /// </summary>
  491. /// <param name="value">A character to convert.</param>
  492. /// <param name="buffer">The byte array to copy the bytes into</param>
  493. /// <param name="index">The first index into the array to copy the bytes into</param>
  494. public void CopyBytes(char value, byte[] buffer, int index)
  495. {
  496. CopyBytes(value, 2, buffer, index);
  497. }
  498. /// <summary>
  499. /// Copies the specified double-precision floating point value into the specified byte array,
  500. /// beginning at the specified index.
  501. /// </summary>
  502. /// <param name="value">The number to convert.</param>
  503. /// <param name="buffer">The byte array to copy the bytes into</param>
  504. /// <param name="index">The first index into the array to copy the bytes into</param>
  505. public void CopyBytes(double value, byte[] buffer, int index)
  506. {
  507. CopyBytes(DoubleToInt64Bits(value), 8, buffer, index);
  508. }
  509. /// <summary>
  510. /// Copies the specified 16-bit signed integer value into the specified byte array,
  511. /// beginning at the specified index.
  512. /// </summary>
  513. /// <param name="value">The number to convert.</param>
  514. /// <param name="buffer">The byte array to copy the bytes into</param>
  515. /// <param name="index">The first index into the array to copy the bytes into</param>
  516. public void CopyBytes(short value, byte[] buffer, int index)
  517. {
  518. CopyBytes(value, 2, buffer, index);
  519. }
  520. /// <summary>
  521. /// Copies the specified 32-bit signed integer value into the specified byte array,
  522. /// beginning at the specified index.
  523. /// </summary>
  524. /// <param name="value">The number to convert.</param>
  525. /// <param name="buffer">The byte array to copy the bytes into</param>
  526. /// <param name="index">The first index into the array to copy the bytes into</param>
  527. public void CopyBytes(int value, byte[] buffer, int index)
  528. {
  529. CopyBytes(value, 4, buffer, index);
  530. }
  531. /// <summary>
  532. /// Copies the specified 64-bit signed integer value into the specified byte array,
  533. /// beginning at the specified index.
  534. /// </summary>
  535. /// <param name="value">The number to convert.</param>
  536. /// <param name="buffer">The byte array to copy the bytes into</param>
  537. /// <param name="index">The first index into the array to copy the bytes into</param>
  538. public void CopyBytes(long value, byte[] buffer, int index)
  539. {
  540. CopyBytes(value, 8, buffer, index);
  541. }
  542. /// <summary>
  543. /// Copies the specified single-precision floating point value into the specified byte array,
  544. /// beginning at the specified index.
  545. /// </summary>
  546. /// <param name="value">The number to convert.</param>
  547. /// <param name="buffer">The byte array to copy the bytes into</param>
  548. /// <param name="index">The first index into the array to copy the bytes into</param>
  549. public void CopyBytes(float value, byte[] buffer, int index)
  550. {
  551. CopyBytes(SingleToInt32Bits(value), 4, buffer, index);
  552. }
  553. /// <summary>
  554. /// Copies the specified 16-bit unsigned integer value into the specified byte array,
  555. /// beginning at the specified index.
  556. /// </summary>
  557. /// <param name="value">The number to convert.</param>
  558. /// <param name="buffer">The byte array to copy the bytes into</param>
  559. /// <param name="index">The first index into the array to copy the bytes into</param>
  560. public void CopyBytes(ushort value, byte[] buffer, int index)
  561. {
  562. CopyBytes(value, 2, buffer, index);
  563. }
  564. /// <summary>
  565. /// Copies the specified 32-bit unsigned integer value into the specified byte array,
  566. /// beginning at the specified index.
  567. /// </summary>
  568. /// <param name="value">The number to convert.</param>
  569. /// <param name="buffer">The byte array to copy the bytes into</param>
  570. /// <param name="index">The first index into the array to copy the bytes into</param>
  571. public void CopyBytes(uint value, byte[] buffer, int index)
  572. {
  573. CopyBytes(value, 4, buffer, index);
  574. }
  575. /// <summary>
  576. /// Copies the specified 64-bit unsigned integer value into the specified byte array,
  577. /// beginning at the specified index.
  578. /// </summary>
  579. /// <param name="value">The number to convert.</param>
  580. /// <param name="buffer">The byte array to copy the bytes into</param>
  581. /// <param name="index">The first index into the array to copy the bytes into</param>
  582. public void CopyBytes(ulong value, byte[] buffer, int index)
  583. {
  584. CopyBytes(unchecked((long)value), 8, buffer, index);
  585. }
  586. #endregion
  587. #region Private struct used for Single/Int32 conversions
  588. /// <summary>
  589. /// Union used solely for the equivalent of DoubleToInt64Bits and vice versa.
  590. /// </summary>
  591. [StructLayout(LayoutKind.Explicit)]
  592. struct Int32SingleUnion
  593. {
  594. /// <summary>
  595. /// Int32 version of the value.
  596. /// </summary>
  597. [FieldOffset(0)]
  598. int i;
  599. /// <summary>
  600. /// Single version of the value.
  601. /// </summary>
  602. [FieldOffset(0)]
  603. float f;
  604. /// <summary>
  605. /// Creates an instance representing the given integer.
  606. /// </summary>
  607. /// <param name="i">The integer value of the new instance.</param>
  608. internal Int32SingleUnion(int i)
  609. {
  610. this.f = 0; // Just to keep the compiler happy
  611. this.i = i;
  612. }
  613. /// <summary>
  614. /// Creates an instance representing the given floating point number.
  615. /// </summary>
  616. /// <param name="f">The floating point value of the new instance.</param>
  617. internal Int32SingleUnion(float f)
  618. {
  619. this.i = 0; // Just to keep the compiler happy
  620. this.f = f;
  621. }
  622. /// <summary>
  623. /// Returns the value of the instance as an integer.
  624. /// </summary>
  625. internal int AsInt32
  626. {
  627. get { return i; }
  628. }
  629. /// <summary>
  630. /// Returns the value of the instance as a floating point number.
  631. /// </summary>
  632. internal float AsSingle
  633. {
  634. get { return f; }
  635. }
  636. }
  637. #endregion
  638. }
  639. }