ByteQueue.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. namespace Org.BouncyCastle.Crypto.Tls
  4. {
  5. /// <remarks>
  6. /// A queue for bytes.
  7. /// <p>
  8. /// This file could be more optimized.
  9. /// </p>
  10. /// </remarks>
  11. public class ByteQueue
  12. {
  13. /// <returns>The smallest number which can be written as 2^x which is bigger than i.</returns>
  14. public static int NextTwoPow(
  15. int i)
  16. {
  17. /*
  18. * This code is based of a lot of code I found on the Internet
  19. * which mostly referenced a book called "Hacking delight".
  20. *
  21. */
  22. i |= (i >> 1);
  23. i |= (i >> 2);
  24. i |= (i >> 4);
  25. i |= (i >> 8);
  26. i |= (i >> 16);
  27. return i + 1;
  28. }
  29. /**
  30. * The initial size for our buffer.
  31. */
  32. private const int DefaultCapacity = 1024;
  33. /**
  34. * The buffer where we store our data.
  35. */
  36. private byte[] databuf;
  37. /**
  38. * How many bytes at the beginning of the buffer are skipped.
  39. */
  40. private int skipped = 0;
  41. /**
  42. * How many bytes in the buffer are valid data.
  43. */
  44. private int available = 0;
  45. public ByteQueue()
  46. : this(DefaultCapacity)
  47. {
  48. }
  49. public ByteQueue(int capacity)
  50. {
  51. this.databuf = new byte[capacity];
  52. }
  53. /// <summary>Read data from the buffer.</summary>
  54. /// <param name="buf">The buffer where the read data will be copied to.</param>
  55. /// <param name="offset">How many bytes to skip at the beginning of buf.</param>
  56. /// <param name="len">How many bytes to read at all.</param>
  57. /// <param name="skip">How many bytes from our data to skip.</param>
  58. public void Read(
  59. byte[] buf,
  60. int offset,
  61. int len,
  62. int skip)
  63. {
  64. if ((buf.Length - offset) < len)
  65. {
  66. throw new ArgumentException("Buffer size of " + buf.Length + " is too small for a read of " + len + " bytes");
  67. }
  68. if ((available - skip) < len)
  69. {
  70. throw new InvalidOperationException("Not enough data to read");
  71. }
  72. Array.Copy(databuf, skipped + skip, buf, offset, len);
  73. }
  74. /// <summary>Add some data to our buffer.</summary>
  75. /// <param name="data">A byte-array to read data from.</param>
  76. /// <param name="offset">How many bytes to skip at the beginning of the array.</param>
  77. /// <param name="len">How many bytes to read from the array.</param>
  78. public void AddData(
  79. byte[] data,
  80. int offset,
  81. int len)
  82. {
  83. if ((skipped + available + len) > databuf.Length)
  84. {
  85. int desiredSize = ByteQueue.NextTwoPow(available + len);
  86. if (desiredSize > databuf.Length)
  87. {
  88. byte[] tmp = new byte[desiredSize];
  89. Array.Copy(databuf, skipped, tmp, 0, available);
  90. databuf = tmp;
  91. }
  92. else
  93. {
  94. Array.Copy(databuf, skipped, databuf, 0, available);
  95. }
  96. skipped = 0;
  97. }
  98. Array.Copy(data, offset, databuf, skipped + available, len);
  99. available += len;
  100. }
  101. /// <summary>Remove some bytes from our data from the beginning.</summary>
  102. /// <param name="i">How many bytes to remove.</param>
  103. public void RemoveData(
  104. int i)
  105. {
  106. if (i > available)
  107. {
  108. throw new InvalidOperationException("Cannot remove " + i + " bytes, only got " + available);
  109. }
  110. /*
  111. * Skip the data.
  112. */
  113. available -= i;
  114. skipped += i;
  115. }
  116. public void RemoveData(byte[] buf, int off, int len, int skip)
  117. {
  118. Read(buf, off, len, skip);
  119. RemoveData(skip + len);
  120. }
  121. public byte[] RemoveData(int len, int skip)
  122. {
  123. byte[] buf = new byte[len];
  124. RemoveData(buf, 0, len, skip);
  125. return buf;
  126. }
  127. /// <summary>The number of bytes which are available in this buffer.</summary>
  128. public int Available
  129. {
  130. get { return available; }
  131. }
  132. }
  133. }
  134. #endif