You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
8.9 KiB

4 years ago
  1. #if MYSQL_6_9
  2. // Copyright © 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  3. //
  4. // MySQL Connector/NET is licensed under the terms of the GPLv2
  5. // <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
  6. // MySQL Connectors. There are special exceptions to the terms and
  7. // conditions of the GPLv2 as it is applied to this software, see the
  8. // FLOSS License Exception
  9. // <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
  10. //
  11. // This program is free software; you can redistribute it and/or modify
  12. // it under the terms of the GNU General Public License as published
  13. // by the Free Software Foundation; version 2 of the License.
  14. //
  15. // This program is distributed in the hope that it will be useful, but
  16. // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  17. // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  18. // for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License along
  21. // with this program; if not, write to the Free Software Foundation, Inc.,
  22. // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  23. using System;
  24. using System.Diagnostics;
  25. using System.Text;
  26. using System.IO;
  27. using Externals.MySql.Data.Common;
  28. using Externals.MySql.Data.MySqlClient.Properties;
  29. namespace Externals.MySql.Data.MySqlClient
  30. {
  31. class MySqlPacket
  32. {
  33. private byte[] tempBuffer = new byte[256];
  34. private Encoding encoding;
  35. private MemoryStream buffer = new MemoryStream(5);
  36. private DBVersion version;
  37. private MySqlPacket()
  38. {
  39. Clear();
  40. }
  41. public MySqlPacket(Encoding enc)
  42. : this()
  43. {
  44. Encoding = enc;
  45. }
  46. public MySqlPacket(MemoryStream stream)
  47. : this()
  48. {
  49. buffer = stream;
  50. }
  51. #region Properties
  52. public Encoding Encoding
  53. {
  54. get { return encoding; }
  55. set
  56. {
  57. Debug.Assert(value != null);
  58. encoding = value;
  59. }
  60. }
  61. public bool HasMoreData
  62. {
  63. get { return buffer.Position < buffer.Length; }
  64. }
  65. public int Position
  66. {
  67. get { return (int)buffer.Position; }
  68. set { buffer.Position = (long)value; }
  69. }
  70. public int Length
  71. {
  72. get { return (int)buffer.Length; }
  73. set { buffer.SetLength(value); }
  74. }
  75. public bool IsLastPacket
  76. {
  77. get
  78. {
  79. byte[] bits = buffer.GetBuffer();
  80. return bits[0] == 0xfe && Length <= 5;
  81. }
  82. }
  83. public byte[] Buffer
  84. {
  85. get { return buffer.GetBuffer(); }
  86. }
  87. public DBVersion Version
  88. {
  89. get { return version; }
  90. set { version = value; }
  91. }
  92. #endregion
  93. public void Clear()
  94. {
  95. Position = 4;
  96. }
  97. #region Byte methods
  98. public byte ReadByte()
  99. {
  100. return (byte)buffer.ReadByte();
  101. }
  102. public int Read(byte[] byteBuffer, int offset, int count)
  103. {
  104. return buffer.Read(byteBuffer, offset, count);
  105. }
  106. public void WriteByte(byte b)
  107. {
  108. buffer.WriteByte(b);
  109. }
  110. public void Write(byte[] bytesToWrite)
  111. {
  112. Write(bytesToWrite, 0, bytesToWrite.Length);
  113. }
  114. public void Write(byte[] bytesToWrite, int offset, int countToWrite)
  115. {
  116. buffer.Write(bytesToWrite, offset, countToWrite);
  117. }
  118. public int ReadNBytes()
  119. {
  120. byte c = ReadByte();
  121. if (c < 1 || c > 4)
  122. throw new MySqlException(Resources.IncorrectTransmission);
  123. return ReadInteger(c);
  124. }
  125. public void SetByte(long position, byte value)
  126. {
  127. long currentPosition = buffer.Position;
  128. buffer.Position = position;
  129. buffer.WriteByte(value);
  130. buffer.Position = currentPosition;
  131. }
  132. #endregion
  133. #region Integer methods
  134. public long ReadFieldLength()
  135. {
  136. byte c = ReadByte();
  137. switch (c)
  138. {
  139. case 251: return -1;
  140. case 252: return ReadInteger(2);
  141. case 253: return ReadInteger(3);
  142. case 254: return ReadLong(8);
  143. default: return c;
  144. }
  145. }
  146. public ulong ReadBitValue(int numbytes)
  147. {
  148. ulong value = 0;
  149. int pos = (int)buffer.Position;
  150. byte[] bits = buffer.GetBuffer();
  151. int shift = 0;
  152. for (int i = 0; i < numbytes; i++)
  153. {
  154. value <<= shift;
  155. value |= bits[pos++];
  156. shift = 8;
  157. }
  158. buffer.Position += numbytes;
  159. return value;
  160. }
  161. public long ReadLong(int numbytes)
  162. {
  163. Debug.Assert((buffer.Position + numbytes) <= buffer.Length);
  164. byte[] bytes = buffer.GetBuffer();
  165. int pos = (int)buffer.Position;
  166. buffer.Position += numbytes;
  167. switch (numbytes)
  168. {
  169. case 2: return BitConverter.ToUInt16(bytes, pos);
  170. case 4: return BitConverter.ToUInt32(bytes, pos);
  171. case 8: return BitConverter.ToInt64(bytes, pos);
  172. }
  173. throw new NotSupportedException("Only byte lengths of 2, 4, or 8 are supported");
  174. }
  175. public ulong ReadULong(int numbytes)
  176. {
  177. Debug.Assert((buffer.Position + numbytes) <= buffer.Length);
  178. byte[] bytes = buffer.GetBuffer();
  179. int pos = (int)buffer.Position;
  180. buffer.Position += numbytes;
  181. switch (numbytes)
  182. {
  183. case 2: return BitConverter.ToUInt16(bytes, pos);
  184. case 4: return BitConverter.ToUInt32(bytes, pos);
  185. case 8: return BitConverter.ToUInt64(bytes, pos);
  186. }
  187. throw new NotSupportedException("Only byte lengths of 2, 4, or 8 are supported");
  188. }
  189. public int Read3ByteInt()
  190. {
  191. int value = 0;
  192. int pos = (int)buffer.Position;
  193. byte[] bits = buffer.GetBuffer();
  194. int shift = 0;
  195. for (int i = 0; i < 3; i++)
  196. {
  197. value |= (int)(bits[pos++] << shift);
  198. shift += 8;
  199. }
  200. buffer.Position += 3;
  201. return value;
  202. }
  203. public int ReadInteger(int numbytes)
  204. {
  205. if (numbytes == 3)
  206. return Read3ByteInt();
  207. Debug.Assert(numbytes <= 4);
  208. return (int)ReadLong(numbytes);
  209. }
  210. /// <summary>
  211. /// WriteInteger
  212. /// </summary>
  213. /// <param name="v"></param>
  214. /// <param name="numbytes"></param>
  215. public void WriteInteger(long v, int numbytes)
  216. {
  217. long val = v;
  218. Debug.Assert(numbytes > 0 && numbytes < 9);
  219. for (int x = 0; x < numbytes; x++)
  220. {
  221. tempBuffer[x] = (byte)(val & 0xff);
  222. val >>= 8;
  223. }
  224. Write(tempBuffer, 0, numbytes);
  225. }
  226. public int ReadPackedInteger()
  227. {
  228. byte c = ReadByte();
  229. switch (c)
  230. {
  231. case 251: return -1;
  232. case 252: return ReadInteger(2);
  233. case 253: return ReadInteger(3);
  234. case 254: return ReadInteger(4);
  235. default: return c;
  236. }
  237. }
  238. public void WriteLength(long length)
  239. {
  240. if (length < 251)
  241. WriteByte((byte)length);
  242. else if (length < 65536L)
  243. {
  244. WriteByte(252);
  245. WriteInteger(length, 2);
  246. }
  247. else if (length < 16777216L)
  248. {
  249. WriteByte(253);
  250. WriteInteger(length, 3);
  251. }
  252. else
  253. {
  254. WriteByte(254);
  255. WriteInteger(length, 4);
  256. }
  257. }
  258. #endregion
  259. #region String methods
  260. public void WriteLenString(string s)
  261. {
  262. byte[] bytes = encoding.GetBytes(s);
  263. WriteLength(bytes.Length);
  264. Write(bytes, 0, bytes.Length);
  265. }
  266. public void WriteStringNoNull(string v)
  267. {
  268. byte[] bytes = encoding.GetBytes(v);
  269. Write(bytes, 0, bytes.Length);
  270. }
  271. public void WriteString(string v)
  272. {
  273. WriteStringNoNull(v);
  274. WriteByte(0);
  275. }
  276. public string ReadLenString()
  277. {
  278. long len = ReadPackedInteger();
  279. return ReadString(len);
  280. }
  281. public string ReadAsciiString(long length)
  282. {
  283. if (length == 0)
  284. return String.Empty;
  285. // byte[] buf = new byte[length];
  286. Read(tempBuffer, 0, (int)length);
  287. return Encoding.GetEncoding("us-ascii").GetString(tempBuffer, 0, (int)length);
  288. //return encoding.GetString(tempBuffer, 0, (int)length); //buf.Length);
  289. }
  290. public string ReadString(long length)
  291. {
  292. if (length == 0)
  293. return String.Empty;
  294. if (tempBuffer == null || length > tempBuffer.Length)
  295. tempBuffer = new byte[length];
  296. Read(tempBuffer, 0, (int)length);
  297. return encoding.GetString(tempBuffer, 0, (int)length);
  298. }
  299. public string ReadString()
  300. {
  301. return ReadString(encoding);
  302. }
  303. public string ReadString(Encoding theEncoding)
  304. {
  305. byte[] bytes = ReadStringAsBytes();
  306. string s = theEncoding.GetString(bytes, 0, bytes.Length);
  307. return s;
  308. }
  309. public byte[] ReadStringAsBytes()
  310. {
  311. byte[] readBytes;
  312. byte[] tempBuffer = buffer.GetBuffer();
  313. int end = (int)buffer.Position;
  314. while (end < (int)buffer.Length &&
  315. tempBuffer[end] != 0 && (int)tempBuffer[end] != -1)
  316. end++;
  317. readBytes = new byte[end - buffer.Position];
  318. Array.Copy(tempBuffer, (int)buffer.Position, readBytes, 0, (int)(end - buffer.Position));
  319. buffer.Position = end + 1;
  320. return readBytes;
  321. }
  322. #endregion
  323. }
  324. }
  325. #endif