/Library/lidgren-network/Lidgren.Network/NetBuffer.cs

https://bitbucket.org/kenzoix/tanka · C# · 213 lines · 135 code · 20 blank · 58 comment · 11 complexity · 8840d95343971eaa14fda12963d8266d MD5 · raw file

  1. /* Copyright (c) 2008 Michael Lidgren
  2. Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  3. and associated documentation files (the "Software"), to deal in the Software without
  4. restriction, including without limitation the rights to use, copy, modify, merge, publish,
  5. distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom
  6. the Software is furnished to do so, subject to the following conditions:
  7. The above copyright notice and this permission notice shall be included in all copies or
  8. substantial portions of the Software.
  9. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  10. INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  11. PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  12. LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  13. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  14. USE OR OTHER DEALINGS IN THE SOFTWARE.
  15. */
  16. using System;
  17. using System.Collections.Generic;
  18. using System.Diagnostics.CodeAnalysis;
  19. using System.Text;
  20. namespace Lidgren.Network
  21. {
  22. /// <summary>
  23. /// Wrapper around a byte array with methods for reading/writing at bit level
  24. /// </summary>
  25. public sealed partial class NetBuffer
  26. {
  27. // how many NetMessages are using this buffer?
  28. internal int m_refCount;
  29. internal int m_bitLength;
  30. internal int m_readPosition;
  31. [SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]
  32. public byte[] Data;
  33. /// <summary>
  34. /// User application data
  35. /// </summary>
  36. public object Tag;
  37. /// <summary>
  38. /// Creates a new NetBuffer
  39. /// </summary>
  40. public NetBuffer()
  41. {
  42. Data = new byte[8];
  43. }
  44. /// <summary>
  45. /// Creates a new NetBuffer initially capable of holding 'capacity' bytes
  46. /// </summary>
  47. public NetBuffer(int capacityBytes)
  48. {
  49. if (capacityBytes < 0)
  50. capacityBytes = 4;
  51. Data = new byte[capacityBytes];
  52. }
  53. /// <summary>
  54. /// Creates a new NetBuffer and copies the data supplied
  55. /// </summary>
  56. public NetBuffer(byte[] copyData)
  57. {
  58. if (copyData != null)
  59. {
  60. Data = new byte[copyData.Length];
  61. Buffer.BlockCopy(copyData, 0, Data, 0, copyData.Length);
  62. m_bitLength = copyData.Length * 8;
  63. }
  64. else
  65. {
  66. Data = new byte[4];
  67. }
  68. }
  69. public NetBuffer(string str)
  70. {
  71. if (string.IsNullOrEmpty(str))
  72. {
  73. Data = new byte[1];
  74. WriteVariableUInt32(0);
  75. return;
  76. }
  77. byte[] strData = Encoding.UTF8.GetBytes(str);
  78. Data = new byte[1 + strData.Length];
  79. WriteVariableUInt32((uint)strData.Length);
  80. Write(strData);
  81. }
  82. /// <summary>
  83. /// Data is NOT copied; but now owned by the NetBuffer
  84. /// </summary>
  85. public static NetBuffer FromData(byte[] data)
  86. {
  87. NetBuffer retval = new NetBuffer(false);
  88. retval.Data = data;
  89. retval.LengthBytes = data.Length;
  90. return retval;
  91. }
  92. internal NetBuffer(bool createDataStorage)
  93. {
  94. if (createDataStorage)
  95. Data = new byte[8];
  96. }
  97. /// <summary>
  98. /// Gets or sets the length of the buffer in bytes
  99. /// </summary>
  100. public int LengthBytes {
  101. get { return (m_bitLength >> 3) + ((m_bitLength & 7) > 0 ? 1 : 0); }
  102. set
  103. {
  104. m_bitLength = value * 8;
  105. InternalEnsureBufferSize(m_bitLength);
  106. }
  107. }
  108. /// <summary>
  109. /// Gets or sets the length of the buffer in bits
  110. /// </summary>
  111. public int LengthBits
  112. {
  113. get { return m_bitLength; }
  114. set
  115. {
  116. m_bitLength = value;
  117. InternalEnsureBufferSize(m_bitLength);
  118. }
  119. }
  120. /// <summary>
  121. /// Gets or sets the read position in the buffer, in bits (not bytes)
  122. /// </summary>
  123. public int Position
  124. {
  125. get { return m_readPosition; }
  126. set { m_readPosition = value; }
  127. }
  128. /// <summary>
  129. /// Resets read and write pointers
  130. /// </summary>
  131. public void Reset()
  132. {
  133. m_readPosition = 0;
  134. m_bitLength = 0;
  135. m_refCount = 0;
  136. Tag = null;
  137. }
  138. /// <summary>
  139. /// Resets read and write pointers
  140. /// </summary>
  141. internal void Reset(int readPos, int writePos)
  142. {
  143. m_readPosition = readPos;
  144. m_bitLength = writePos;
  145. m_refCount = 0;
  146. Tag = null;
  147. }
  148. /// <summary>
  149. /// Ensures this buffer can hold the specified number of bits prior to a write operation
  150. /// </summary>
  151. public void EnsureBufferSize(int numberOfBits)
  152. {
  153. int byteLen = (numberOfBits >> 3) + ((numberOfBits & 7) > 0 ? 1 : 0);
  154. if (Data == null)
  155. {
  156. Data = new byte[byteLen + 4]; // overallocate 4 bytes
  157. return;
  158. }
  159. if (Data.Length < byteLen)
  160. Array.Resize<byte>(ref Data, byteLen + 4); // overallocate 4 bytes
  161. return;
  162. }
  163. internal void InternalEnsureBufferSize(int numberOfBits)
  164. {
  165. int byteLen = (numberOfBits >> 3) + ((numberOfBits & 7) > 0 ? 1 : 0);
  166. if (Data == null)
  167. {
  168. Data = new byte[byteLen];
  169. return;
  170. }
  171. if (Data.Length < byteLen)
  172. Array.Resize<byte>(ref Data, byteLen);
  173. return;
  174. }
  175. /// <summary>
  176. /// Copies the content of the buffer to a new byte array
  177. /// </summary>
  178. public byte[] ToArray()
  179. {
  180. int len = LengthBytes;
  181. byte[] copy = new byte[len];
  182. Array.Copy(Data, copy, copy.Length);
  183. return copy;
  184. }
  185. public override string ToString()
  186. {
  187. return "[NetBuffer " + m_bitLength + " bits, " + m_readPosition + " read]";
  188. }
  189. }
  190. }