fork(1) download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using MiscUtil.Conversion;
  6.  
  7. public class Test
  8. {
  9. public static void Main()
  10. {
  11. var message = Encoding.ASCII.GetBytes("message \"Render\"");
  12.  
  13. var lenc = new LittleEndianBitConverter();
  14.  
  15. var bytes = new List<byte[]>(new[]
  16. {
  17. lenc.GetBytes(message.LongLength),
  18. message
  19. });
  20.  
  21. Console.WriteLine("Got {0} Arrays, total {1} bytes",
  22. bytes.Count, bytes.Sum(barray => barray.LongLength));
  23.  
  24. var msg = new byte[bytes.Sum(barray => barray.LongLength)];
  25. int offset = 0;
  26. foreach (var bArray in bytes)
  27. {
  28. Buffer.BlockCopy(bArray, 0, msg, offset, bArray.Length);
  29. offset = bArray.Length;
  30. }
  31.  
  32. Console.WriteLine(BitConverter.ToString(msg).Replace("-", ":"));
  33. }
  34. }
  35.  
  36. namespace MiscUtil.Conversion
  37. {
  38. /// <summary>
  39. /// Implementation of EndianBitConverter which converts to/from big-endian
  40. /// byte arrays.
  41. /// </summary>
  42. public sealed class BigEndianBitConverter : EndianBitConverter
  43. {
  44. /// <summary>
  45. /// Indicates the byte order ("endianess") in which data is converted using this class.
  46. /// </summary>
  47. /// <remarks>
  48. /// Different computer architectures store data using different byte orders. "Big-endian"
  49. /// means the most significant byte is on the left end of a word. "Little-endian" means the
  50. /// most significant byte is on the right end of a word.
  51. /// </remarks>
  52. /// <returns>true if this converter is little-endian, false otherwise.</returns>
  53. public sealed override bool IsLittleEndian()
  54. {
  55. return false;
  56. }
  57.  
  58. /// <summary>
  59. /// Indicates the byte order ("endianess") in which data is converted using this class.
  60. /// </summary>
  61. public sealed override Endianness Endianness
  62. {
  63. get { return Endianness.BigEndian; }
  64. }
  65.  
  66. /// <summary>
  67. /// Copies the specified number of bytes from value to buffer, starting at index.
  68. /// </summary>
  69. /// <param name="value">The value to copy</param>
  70. /// <param name="bytes">The number of bytes to copy</param>
  71. /// <param name="buffer">The buffer to copy the bytes into</param>
  72. /// <param name="index">The index to start at</param>
  73. protected override void CopyBytesImpl(long value, int bytes, byte[] buffer, int index)
  74. {
  75. int endOffset = index + bytes - 1;
  76. for (int i = 0; i < bytes; i++)
  77. {
  78. buffer[endOffset - i] = unchecked((byte)(value & 0xff));
  79. value = value >> 8;
  80. }
  81. }
  82.  
  83. /// <summary>
  84. /// Returns a value built from the specified number of bytes from the given buffer,
  85. /// starting at index.
  86. /// </summary>
  87. /// <param name="buffer">The data in byte array format</param>
  88. /// <param name="startIndex">The first index to use</param>
  89. /// <param name="bytesToConvert">The number of bytes to use</param>
  90. /// <returns>The value built from the given bytes</returns>
  91. protected override long FromBytes(byte[] buffer, int startIndex, int bytesToConvert)
  92. {
  93. long ret = 0;
  94. for (int i = 0; i < bytesToConvert; i++)
  95. {
  96. ret = unchecked((ret << 8) | buffer[startIndex + i]);
  97. }
  98. return ret;
  99. }
  100. }
  101. }
  102.  
  103.  
  104. namespace MiscUtil.Conversion
  105. {
  106. /// <summary>
  107. /// Implementation of EndianBitConverter which converts to/from little-endian
  108. /// byte arrays.
  109. /// </summary>
  110. public sealed class LittleEndianBitConverter : EndianBitConverter
  111. {
  112. /// <summary>
  113. /// Indicates the byte order ("endianess") in which data is converted using this class.
  114. /// </summary>
  115. /// <remarks>
  116. /// Different computer architectures store data using different byte orders. "Big-endian"
  117. /// means the most significant byte is on the left end of a word. "Little-endian" means the
  118. /// most significant byte is on the right end of a word.
  119. /// </remarks>
  120. /// <returns>true if this converter is little-endian, false otherwise.</returns>
  121. public sealed override bool IsLittleEndian()
  122. {
  123. return true;
  124. }
  125.  
  126. /// <summary>
  127. /// Indicates the byte order ("endianess") in which data is converted using this class.
  128. /// </summary>
  129. public sealed override Endianness Endianness
  130. {
  131. get { return Endianness.LittleEndian; }
  132. }
  133.  
  134. /// <summary>
  135. /// Copies the specified number of bytes from value to buffer, starting at index.
  136. /// </summary>
  137. /// <param name="value">The value to copy</param>
  138. /// <param name="bytes">The number of bytes to copy</param>
  139. /// <param name="buffer">The buffer to copy the bytes into</param>
  140. /// <param name="index">The index to start at</param>
  141. protected override void CopyBytesImpl(long value, int bytes, byte[] buffer, int index)
  142. {
  143. for (int i=0; i < bytes; i++)
  144. {
  145. buffer[i+index] = unchecked((byte)(value&0xff));
  146. value = value >> 8;
  147. }
  148. }
  149.  
  150. /// <summary>
  151. /// Returns a value built from the specified number of bytes from the given buffer,
  152. /// starting at index.
  153. /// </summary>
  154. /// <param name="buffer">The data in byte array format</param>
  155. /// <param name="startIndex">The first index to use</param>
  156. /// <param name="bytesToConvert">The number of bytes to use</param>
  157. /// <returns>The value built from the given bytes</returns>
  158. protected override long FromBytes(byte[] buffer, int startIndex, int bytesToConvert)
  159. {
  160. long ret = 0;
  161. for (int i=0; i < bytesToConvert; i++)
  162. {
  163. ret = unchecked((ret << 8) | buffer[startIndex+bytesToConvert-1-i]);
  164. }
  165. return ret;
  166. }
  167. }
  168. }
  169.  
  170. namespace MiscUtil.Conversion
  171. {
  172. using System;
  173. using System.Runtime.InteropServices;
  174.  
  175. /// <summary>
  176. /// Equivalent of System.BitConverter, but with either endianness.
  177. /// </summary>
  178. public abstract class EndianBitConverter
  179. {
  180. #region Endianness of this converter
  181. /// <summary>
  182. /// Indicates the byte order ("endianess") in which data is converted using this class.
  183. /// </summary>
  184. /// <remarks>
  185. /// Different computer architectures store data using different byte orders. "Big-endian"
  186. /// means the most significant byte is on the left end of a word. "Little-endian" means the
  187. /// most significant byte is on the right end of a word.
  188. /// </remarks>
  189. /// <returns>true if this converter is little-endian, false otherwise.</returns>
  190. public abstract bool IsLittleEndian();
  191.  
  192. /// <summary>
  193. /// Indicates the byte order ("endianess") in which data is converted using this class.
  194. /// </summary>
  195. public abstract Endianness Endianness { get; }
  196. #endregion
  197.  
  198. #region Factory properties
  199. static LittleEndianBitConverter little = new LittleEndianBitConverter();
  200. /// <summary>
  201. /// Returns a little-endian bit converter instance. The same instance is
  202. /// always returned.
  203. /// </summary>
  204. public static LittleEndianBitConverter Little
  205. {
  206. get { return little; }
  207. }
  208.  
  209. static BigEndianBitConverter big = new BigEndianBitConverter();
  210. /// <summary>
  211. /// Returns a big-endian bit converter instance. The same instance is
  212. /// always returned.
  213. /// </summary>
  214. public static BigEndianBitConverter Big
  215. {
  216. get { return big; }
  217. }
  218. #endregion
  219.  
  220. #region Double/primitive conversions
  221. /// <summary>
  222. /// Converts the specified double-precision floating point number to a
  223. /// 64-bit signed integer. Note: the endianness of this converter does not
  224. /// affect the returned value.
  225. /// </summary>
  226. /// <param name="value">The number to convert. </param>
  227. /// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
  228. public long DoubleToInt64Bits(double value)
  229. {
  230. return BitConverter.DoubleToInt64Bits(value);
  231. }
  232.  
  233. /// <summary>
  234. /// Converts the specified 64-bit signed integer to a double-precision
  235. /// floating point number. Note: the endianness of this converter does not
  236. /// affect the returned value.
  237. /// </summary>
  238. /// <param name="value">The number to convert. </param>
  239. /// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
  240. public double Int64BitsToDouble(long value)
  241. {
  242. return BitConverter.Int64BitsToDouble(value);
  243. }
  244.  
  245. /// <summary>
  246. /// Converts the specified single-precision floating point number to a
  247. /// 32-bit signed integer. Note: the endianness of this converter does not
  248. /// affect the returned value.
  249. /// </summary>
  250. /// <param name="value">The number to convert. </param>
  251. /// <returns>A 32-bit signed integer whose value is equivalent to value.</returns>
  252. public int SingleToInt32Bits(float value)
  253. {
  254. return new Int32SingleUnion(value).AsInt32;
  255. }
  256.  
  257. /// <summary>
  258. /// Converts the specified 32-bit signed integer to a single-precision floating point
  259. /// number. Note: the endianness of this converter does not
  260. /// affect the returned value.
  261. /// </summary>
  262. /// <param name="value">The number to convert. </param>
  263. /// <returns>A single-precision floating point number whose value is equivalent to value.</returns>
  264. public float Int32BitsToSingle(int value)
  265. {
  266. return new Int32SingleUnion(value).AsSingle;
  267. }
  268. #endregion
  269.  
  270. #region To(PrimitiveType) conversions
  271. /// <summary>
  272. /// Returns a Boolean value converted from one byte at a specified position in a byte array.
  273. /// </summary>
  274. /// <param name="value">An array of bytes.</param>
  275. /// <param name="startIndex">The starting position within value.</param>
  276. /// <returns>true if the byte at startIndex in value is nonzero; otherwise, false.</returns>
  277. public bool ToBoolean(byte[] value, int startIndex)
  278. {
  279. CheckByteArgument(value, startIndex, 1);
  280. return BitConverter.ToBoolean(value, startIndex);
  281. }
  282.  
  283. /// <summary>
  284. /// Returns a Unicode character converted from two bytes at a specified position in a byte array.
  285. /// </summary>
  286. /// <param name="value">An array of bytes.</param>
  287. /// <param name="startIndex">The starting position within value.</param>
  288. /// <returns>A character formed by two bytes beginning at startIndex.</returns>
  289. public char ToChar(byte[] value, int startIndex)
  290. {
  291. return unchecked((char)(CheckedFromBytes(value, startIndex, 2)));
  292. }
  293.  
  294. /// <summary>
  295. /// Returns a double-precision floating point number converted from eight bytes
  296. /// at a specified position in a byte array.
  297. /// </summary>
  298. /// <param name="value">An array of bytes.</param>
  299. /// <param name="startIndex">The starting position within value.</param>
  300. /// <returns>A double precision floating point number formed by eight bytes beginning at startIndex.</returns>
  301. public double ToDouble(byte[] value, int startIndex)
  302. {
  303. return Int64BitsToDouble(ToInt64(value, startIndex));
  304. }
  305.  
  306. /// <summary>
  307. /// Returns a single-precision floating point number converted from four bytes
  308. /// at a specified position in a byte array.
  309. /// </summary>
  310. /// <param name="value">An array of bytes.</param>
  311. /// <param name="startIndex">The starting position within value.</param>
  312. /// <returns>A single precision floating point number formed by four bytes beginning at startIndex.</returns>
  313. public float ToSingle(byte[] value, int startIndex)
  314. {
  315. return Int32BitsToSingle(ToInt32(value, startIndex));
  316. }
  317.  
  318. /// <summary>
  319. /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.
  320. /// </summary>
  321. /// <param name="value">An array of bytes.</param>
  322. /// <param name="startIndex">The starting position within value.</param>
  323. /// <returns>A 16-bit signed integer formed by two bytes beginning at startIndex.</returns>
  324. public short ToInt16(byte[] value, int startIndex)
  325. {
  326. return unchecked((short)(CheckedFromBytes(value, startIndex, 2)));
  327. }
  328.  
  329. /// <summary>
  330. /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.
  331. /// </summary>
  332. /// <param name="value">An array of bytes.</param>
  333. /// <param name="startIndex">The starting position within value.</param>
  334. /// <returns>A 32-bit signed integer formed by four bytes beginning at startIndex.</returns>
  335. public int ToInt32(byte[] value, int startIndex)
  336. {
  337. return unchecked((int)(CheckedFromBytes(value, startIndex, 4)));
  338. }
  339.  
  340. /// <summary>
  341. /// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.
  342. /// </summary>
  343. /// <param name="value">An array of bytes.</param>
  344. /// <param name="startIndex">The starting position within value.</param>
  345. /// <returns>A 64-bit signed integer formed by eight bytes beginning at startIndex.</returns>
  346. public long ToInt64(byte[] value, int startIndex)
  347. {
  348. return CheckedFromBytes(value, startIndex, 8);
  349. }
  350.  
  351. /// <summary>
  352. /// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.
  353. /// </summary>
  354. /// <param name="value">An array of bytes.</param>
  355. /// <param name="startIndex">The starting position within value.</param>
  356. /// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
  357. public ushort ToUInt16(byte[] value, int startIndex)
  358. {
  359. return unchecked((ushort)(CheckedFromBytes(value, startIndex, 2)));
  360. }
  361.  
  362. /// <summary>
  363. /// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.
  364. /// </summary>
  365. /// <param name="value">An array of bytes.</param>
  366. /// <param name="startIndex">The starting position within value.</param>
  367. /// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
  368. public uint ToUInt32(byte[] value, int startIndex)
  369. {
  370. return unchecked((uint)(CheckedFromBytes(value, startIndex, 4)));
  371. }
  372.  
  373. /// <summary>
  374. /// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.
  375. /// </summary>
  376. /// <param name="value">An array of bytes.</param>
  377. /// <param name="startIndex">The starting position within value.</param>
  378. /// <returns>A 64-bit unsigned integer formed by eight bytes beginning at startIndex.</returns>
  379. public ulong ToUInt64(byte[] value, int startIndex)
  380. {
  381. return unchecked((ulong)(CheckedFromBytes(value, startIndex, 8)));
  382. }
  383.  
  384. /// <summary>
  385. /// Checks the given argument for validity.
  386. /// </summary>
  387. /// <param name="value">The byte array passed in</param>
  388. /// <param name="startIndex">The start index passed in</param>
  389. /// <param name="bytesRequired">The number of bytes required</param>
  390. /// <exception cref="ArgumentNullException">value is a null reference</exception>
  391. /// <exception cref="ArgumentOutOfRangeException">
  392. /// startIndex is less than zero or greater than the length of value minus bytesRequired.
  393. /// </exception>
  394. static void CheckByteArgument(byte[] value, int startIndex, int bytesRequired)
  395. {
  396. if (value == null)
  397. {
  398. throw new ArgumentNullException("value");
  399. }
  400. if (startIndex < 0 || startIndex > value.Length - bytesRequired)
  401. {
  402. throw new ArgumentOutOfRangeException("startIndex");
  403. }
  404. }
  405.  
  406. /// <summary>
  407. /// Checks the arguments for validity before calling FromBytes
  408. /// (which can therefore assume the arguments are valid).
  409. /// </summary>
  410. /// <param name="value">The bytes to convert after checking</param>
  411. /// <param name="startIndex">The index of the first byte to convert</param>
  412. /// <param name="bytesToConvert">The number of bytes to convert</param>
  413. /// <returns></returns>
  414. long CheckedFromBytes(byte[] value, int startIndex, int bytesToConvert)
  415. {
  416. CheckByteArgument(value, startIndex, bytesToConvert);
  417. return FromBytes(value, startIndex, bytesToConvert);
  418. }
  419.  
  420. /// <summary>
  421. /// Convert the given number of bytes from the given array, from the given start
  422. /// position, into a long, using the bytes as the least significant part of the long.
  423. /// By the time this is called, the arguments have been checked for validity.
  424. /// </summary>
  425. /// <param name="value">The bytes to convert</param>
  426. /// <param name="startIndex">The index of the first byte to convert</param>
  427. /// <param name="bytesToConvert">The number of bytes to use in the conversion</param>
  428. /// <returns>The converted number</returns>
  429. protected abstract long FromBytes(byte[] value, int startIndex, int bytesToConvert);
  430. #endregion
  431.  
  432. #region ToString conversions
  433. /// <summary>
  434. /// Returns a String converted from the elements of a byte array.
  435. /// </summary>
  436. /// <param name="value">An array of bytes.</param>
  437. /// <remarks>All the elements of value are converted.</remarks>
  438. /// <returns>
  439. /// A String of hexadecimal pairs separated by hyphens, where each pair
  440. /// represents the corresponding element in value; for example, "7F-2C-4A".
  441. /// </returns>
  442. public static string ToString(byte[] value)
  443. {
  444. return BitConverter.ToString(value);
  445. }
  446.  
  447. /// <summary>
  448. /// Returns a String converted from the elements of a byte array starting at a specified array position.
  449. /// </summary>
  450. /// <param name="value">An array of bytes.</param>
  451. /// <param name="startIndex">The starting position within value.</param>
  452. /// <remarks>The elements from array position startIndex to the end of the array are converted.</remarks>
  453. /// <returns>
  454. /// A String of hexadecimal pairs separated by hyphens, where each pair
  455. /// represents the corresponding element in value; for example, "7F-2C-4A".
  456. /// </returns>
  457. public static string ToString(byte[] value, int startIndex)
  458. {
  459. return BitConverter.ToString(value, startIndex);
  460. }
  461.  
  462. /// <summary>
  463. /// Returns a String converted from a specified number of bytes at a specified position in a byte array.
  464. /// </summary>
  465. /// <param name="value">An array of bytes.</param>
  466. /// <param name="startIndex">The starting position within value.</param>
  467. /// <param name="length">The number of bytes to convert.</param>
  468. /// <remarks>The length elements from array position startIndex are converted.</remarks>
  469. /// <returns>
  470. /// A String of hexadecimal pairs separated by hyphens, where each pair
  471. /// represents the corresponding element in value; for example, "7F-2C-4A".
  472. /// </returns>
  473. public static string ToString(byte[] value, int startIndex, int length)
  474. {
  475. return BitConverter.ToString(value, startIndex, length);
  476. }
  477. #endregion
  478.  
  479. #region Decimal conversions
  480. /// <summary>
  481. /// Returns a decimal value converted from sixteen bytes
  482. /// at a specified position in a byte array.
  483. /// </summary>
  484. /// <param name="value">An array of bytes.</param>
  485. /// <param name="startIndex">The starting position within value.</param>
  486. /// <returns>A decimal formed by sixteen bytes beginning at startIndex.</returns>
  487. public decimal ToDecimal(byte[] value, int startIndex)
  488. {
  489. // HACK: This always assumes four parts, each in their own endianness,
  490. // starting with the first part at the start of the byte array.
  491. // On the other hand, there's no real format specified...
  492. int[] parts = new int[4];
  493. for (int i = 0; i < 4; i++)
  494. {
  495. parts[i] = ToInt32(value, startIndex + i * 4);
  496. }
  497. return new Decimal(parts);
  498. }
  499.  
  500. /// <summary>
  501. /// Returns the specified decimal value as an array of bytes.
  502. /// </summary>
  503. /// <param name="value">The number to convert.</param>
  504. /// <returns>An array of bytes with length 16.</returns>
  505. public byte[] GetBytes(decimal value)
  506. {
  507. byte[] bytes = new byte[16];
  508. int[] parts = decimal.GetBits(value);
  509. for (int i = 0; i < 4; i++)
  510. {
  511. CopyBytesImpl(parts[i], 4, bytes, i * 4);
  512. }
  513. return bytes;
  514. }
  515.  
  516. /// <summary>
  517. /// Copies the specified decimal value into the specified byte array,
  518. /// beginning at the specified index.
  519. /// </summary>
  520. /// <param name="value">A character to convert.</param>
  521. /// <param name="buffer">The byte array to copy the bytes into</param>
  522. /// <param name="index">The first index into the array to copy the bytes into</param>
  523. public void CopyBytes(decimal value, byte[] buffer, int index)
  524. {
  525. int[] parts = decimal.GetBits(value);
  526. for (int i = 0; i < 4; i++)
  527. {
  528. CopyBytesImpl(parts[i], 4, buffer, i * 4 + index);
  529. }
  530. }
  531. #endregion
  532.  
  533. #region GetBytes conversions
  534. /// <summary>
  535. /// Returns an array with the given number of bytes formed
  536. /// from the least significant bytes of the specified value.
  537. /// This is used to implement the other GetBytes methods.
  538. /// </summary>
  539. /// <param name="value">The value to get bytes for</param>
  540. /// <param name="bytes">The number of significant bytes to return</param>
  541. byte[] GetBytes(long value, int bytes)
  542. {
  543. byte[] buffer = new byte[bytes];
  544. CopyBytes(value, bytes, buffer, 0);
  545. return buffer;
  546. }
  547.  
  548. /// <summary>
  549. /// Returns the specified Boolean value as an array of bytes.
  550. /// </summary>
  551. /// <param name="value">A Boolean value.</param>
  552. /// <returns>An array of bytes with length 1.</returns>
  553. public byte[] GetBytes(bool value)
  554. {
  555. return BitConverter.GetBytes(value);
  556. }
  557.  
  558. /// <summary>
  559. /// Returns the specified Unicode character value as an array of bytes.
  560. /// </summary>
  561. /// <param name="value">A character to convert.</param>
  562. /// <returns>An array of bytes with length 2.</returns>
  563. public byte[] GetBytes(char value)
  564. {
  565. return GetBytes(value, 2);
  566. }
  567.  
  568. /// <summary>
  569. /// Returns the specified double-precision floating point value as an array of bytes.
  570. /// </summary>
  571. /// <param name="value">The number to convert.</param>
  572. /// <returns>An array of bytes with length 8.</returns>
  573. public byte[] GetBytes(double value)
  574. {
  575. return GetBytes(DoubleToInt64Bits(value), 8);
  576. }
  577.  
  578. /// <summary>
  579. /// Returns the specified 16-bit signed integer value as an array of bytes.
  580. /// </summary>
  581. /// <param name="value">The number to convert.</param>
  582. /// <returns>An array of bytes with length 2.</returns>
  583. public byte[] GetBytes(short value)
  584. {
  585. return GetBytes(value, 2);
  586. }
  587.  
  588. /// <summary>
  589. /// Returns the specified 32-bit signed integer value as an array of bytes.
  590. /// </summary>
  591. /// <param name="value">The number to convert.</param>
  592. /// <returns>An array of bytes with length 4.</returns>
  593. public byte[] GetBytes(int value)
  594. {
  595. return GetBytes(value, 4);
  596. }
  597.  
  598. /// <summary>
  599. /// Returns the specified 64-bit signed integer value as an array of bytes.
  600. /// </summary>
  601. /// <param name="value">The number to convert.</param>
  602. /// <returns>An array of bytes with length 8.</returns>
  603. public byte[] GetBytes(long value)
  604. {
  605. return GetBytes(value, 8);
  606. }
  607.  
  608. /// <summary>
  609. /// Returns the specified single-precision floating point value as an array of bytes.
  610. /// </summary>
  611. /// <param name="value">The number to convert.</param>
  612. /// <returns>An array of bytes with length 4.</returns>
  613. public byte[] GetBytes(float value)
  614. {
  615. return GetBytes(SingleToInt32Bits(value), 4);
  616. }
  617.  
  618. /// <summary>
  619. /// Returns the specified 16-bit unsigned integer value as an array of bytes.
  620. /// </summary>
  621. /// <param name="value">The number to convert.</param>
  622. /// <returns>An array of bytes with length 2.</returns>
  623. public byte[] GetBytes(ushort value)
  624. {
  625. return GetBytes(value, 2);
  626. }
  627.  
  628. /// <summary>
  629. /// Returns the specified 32-bit unsigned integer value as an array of bytes.
  630. /// </summary>
  631. /// <param name="value">The number to convert.</param>
  632. /// <returns>An array of bytes with length 4.</returns>
  633. public byte[] GetBytes(uint value)
  634. {
  635. return GetBytes(value, 4);
  636. }
  637.  
  638. /// <summary>
  639. /// Returns the specified 64-bit unsigned integer value as an array of bytes.
  640. /// </summary>
  641. /// <param name="value">The number to convert.</param>
  642. /// <returns>An array of bytes with length 8.</returns>
  643. public byte[] GetBytes(ulong value)
  644. {
  645. return GetBytes(unchecked((long)value), 8);
  646. }
  647.  
  648. #endregion
  649.  
  650. #region CopyBytes conversions
  651. /// <summary>
  652. /// Copies the given number of bytes from the least-specific
  653. /// end of the specified value into the specified byte array, beginning
  654. /// at the specified index.
  655. /// This is used to implement the other CopyBytes methods.
  656. /// </summary>
  657. /// <param name="value">The value to copy bytes for</param>
  658. /// <param name="bytes">The number of significant bytes to copy</param>
  659. /// <param name="buffer">The byte array to copy the bytes into</param>
  660. /// <param name="index">The first index into the array to copy the bytes into</param>
  661. void CopyBytes(long value, int bytes, byte[] buffer, int index)
  662. {
  663. if (buffer == null)
  664. {
  665. throw new ArgumentNullException("buffer", "Byte array must not be null");
  666. }
  667. if (buffer.Length < index + bytes)
  668. {
  669. throw new ArgumentOutOfRangeException("Buffer not big enough for value");
  670. }
  671. CopyBytesImpl(value, bytes, buffer, index);
  672. }
  673.  
  674. /// <summary>
  675. /// Copies the given number of bytes from the least-specific
  676. /// end of the specified value into the specified byte array, beginning
  677. /// at the specified index.
  678. /// This must be implemented in concrete derived classes, but the implementation
  679. /// may assume that the value will fit into the buffer.
  680. /// </summary>
  681. /// <param name="value">The value to copy bytes for</param>
  682. /// <param name="bytes">The number of significant bytes to copy</param>
  683. /// <param name="buffer">The byte array to copy the bytes into</param>
  684. /// <param name="index">The first index into the array to copy the bytes into</param>
  685. protected abstract void CopyBytesImpl(long value, int bytes, byte[] buffer, int index);
  686.  
  687. /// <summary>
  688. /// Copies the specified Boolean value into the specified byte array,
  689. /// beginning at the specified index.
  690. /// </summary>
  691. /// <param name="value">A Boolean value.</param>
  692. /// <param name="buffer">The byte array to copy the bytes into</param>
  693. /// <param name="index">The first index into the array to copy the bytes into</param>
  694. public void CopyBytes(bool value, byte[] buffer, int index)
  695. {
  696. CopyBytes(value ? 1 : 0, 1, buffer, index);
  697. }
  698.  
  699. /// <summary>
  700. /// Copies the specified Unicode character value into the specified byte array,
  701. /// beginning at the specified index.
  702. /// </summary>
  703. /// <param name="value">A character to convert.</param>
  704. /// <param name="buffer">The byte array to copy the bytes into</param>
  705. /// <param name="index">The first index into the array to copy the bytes into</param>
  706. public void CopyBytes(char value, byte[] buffer, int index)
  707. {
  708. CopyBytes(value, 2, buffer, index);
  709. }
  710.  
  711. /// <summary>
  712. /// Copies the specified double-precision floating point value into the specified byte array,
  713. /// beginning at the specified index.
  714. /// </summary>
  715. /// <param name="value">The number to convert.</param>
  716. /// <param name="buffer">The byte array to copy the bytes into</param>
  717. /// <param name="index">The first index into the array to copy the bytes into</param>
  718. public void CopyBytes(double value, byte[] buffer, int index)
  719. {
  720. CopyBytes(DoubleToInt64Bits(value), 8, buffer, index);
  721. }
  722.  
  723. /// <summary>
  724. /// Copies the specified 16-bit signed integer value into the specified byte array,
  725. /// beginning at the specified index.
  726. /// </summary>
  727. /// <param name="value">The number to convert.</param>
  728. /// <param name="buffer">The byte array to copy the bytes into</param>
  729. /// <param name="index">The first index into the array to copy the bytes into</param>
  730. public void CopyBytes(short value, byte[] buffer, int index)
  731. {
  732. CopyBytes(value, 2, buffer, index);
  733. }
  734.  
  735. /// <summary>
  736. /// Copies the specified 32-bit signed integer value into the specified byte array,
  737. /// beginning at the specified index.
  738. /// </summary>
  739. /// <param name="value">The number to convert.</param>
  740. /// <param name="buffer">The byte array to copy the bytes into</param>
  741. /// <param name="index">The first index into the array to copy the bytes into</param>
  742. public void CopyBytes(int value, byte[] buffer, int index)
  743. {
  744. CopyBytes(value, 4, buffer, index);
  745. }
  746.  
  747. /// <summary>
  748. /// Copies the specified 64-bit signed integer value into the specified byte array,
  749. /// beginning at the specified index.
  750. /// </summary>
  751. /// <param name="value">The number to convert.</param>
  752. /// <param name="buffer">The byte array to copy the bytes into</param>
  753. /// <param name="index">The first index into the array to copy the bytes into</param>
  754. public void CopyBytes(long value, byte[] buffer, int index)
  755. {
  756. CopyBytes(value, 8, buffer, index);
  757. }
  758.  
  759. /// <summary>
  760. /// Copies the specified single-precision floating point value into the specified byte array,
  761. /// beginning at the specified index.
  762. /// </summary>
  763. /// <param name="value">The number to convert.</param>
  764. /// <param name="buffer">The byte array to copy the bytes into</param>
  765. /// <param name="index">The first index into the array to copy the bytes into</param>
  766. public void CopyBytes(float value, byte[] buffer, int index)
  767. {
  768. CopyBytes(SingleToInt32Bits(value), 4, buffer, index);
  769. }
  770.  
  771. /// <summary>
  772. /// Copies the specified 16-bit unsigned integer value into the specified byte array,
  773. /// beginning at the specified index.
  774. /// </summary>
  775. /// <param name="value">The number to convert.</param>
  776. /// <param name="buffer">The byte array to copy the bytes into</param>
  777. /// <param name="index">The first index into the array to copy the bytes into</param>
  778. public void CopyBytes(ushort value, byte[] buffer, int index)
  779. {
  780. CopyBytes(value, 2, buffer, index);
  781. }
  782.  
  783. /// <summary>
  784. /// Copies the specified 32-bit unsigned integer value into the specified byte array,
  785. /// beginning at the specified index.
  786. /// </summary>
  787. /// <param name="value">The number to convert.</param>
  788. /// <param name="buffer">The byte array to copy the bytes into</param>
  789. /// <param name="index">The first index into the array to copy the bytes into</param>
  790. public void CopyBytes(uint value, byte[] buffer, int index)
  791. {
  792. CopyBytes(value, 4, buffer, index);
  793. }
  794.  
  795. /// <summary>
  796. /// Copies the specified 64-bit unsigned integer value into the specified byte array,
  797. /// beginning at the specified index.
  798. /// </summary>
  799. /// <param name="value">The number to convert.</param>
  800. /// <param name="buffer">The byte array to copy the bytes into</param>
  801. /// <param name="index">The first index into the array to copy the bytes into</param>
  802. public void CopyBytes(ulong value, byte[] buffer, int index)
  803. {
  804. CopyBytes(unchecked((long)value), 8, buffer, index);
  805. }
  806.  
  807. #endregion
  808.  
  809. #region Private struct used for Single/Int32 conversions
  810. /// <summary>
  811. /// Union used solely for the equivalent of DoubleToInt64Bits and vice versa.
  812. /// </summary>
  813. [StructLayout(LayoutKind.Explicit)]
  814. struct Int32SingleUnion
  815. {
  816. /// <summary>
  817. /// Int32 version of the value.
  818. /// </summary>
  819. [FieldOffset(0)]
  820. int i;
  821. /// <summary>
  822. /// Single version of the value.
  823. /// </summary>
  824. [FieldOffset(0)]
  825. float f;
  826.  
  827. /// <summary>
  828. /// Creates an instance representing the given integer.
  829. /// </summary>
  830. /// <param name="i">The integer value of the new instance.</param>
  831. internal Int32SingleUnion(int i)
  832. {
  833. this.f = 0; // Just to keep the compiler happy
  834. this.i = i;
  835. }
  836.  
  837. /// <summary>
  838. /// Creates an instance representing the given floating point number.
  839. /// </summary>
  840. /// <param name="f">The floating point value of the new instance.</param>
  841. internal Int32SingleUnion(float f)
  842. {
  843. this.i = 0; // Just to keep the compiler happy
  844. this.f = f;
  845. }
  846.  
  847. /// <summary>
  848. /// Returns the value of the instance as an integer.
  849. /// </summary>
  850. internal int AsInt32
  851. {
  852. get { return i; }
  853. }
  854.  
  855. /// <summary>
  856. /// Returns the value of the instance as a floating point number.
  857. /// </summary>
  858. internal float AsSingle
  859. {
  860. get { return f; }
  861. }
  862. }
  863. #endregion
  864. }
  865. }
  866.  
  867.  
  868. namespace MiscUtil.Conversion
  869. {
  870. /// <summary>
  871. /// Endianness of a converter
  872. /// </summary>
  873. public enum Endianness
  874. {
  875. /// <summary>
  876. /// Little endian - least significant byte first
  877. /// </summary>
  878. LittleEndian,
  879. /// <summary>
  880. /// Big endian - most significant byte first
  881. /// </summary>
  882. BigEndian
  883. }
  884. }
Success #stdin #stdout 0.04s 33960KB
stdin
Standard input is empty
stdout
Got 2 Arrays, total 24 bytes
10:00:00:00:00:00:00:00:6D:65:73:73:61:67:65:20:22:52:65:6E:64:65:72:22