2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / ByteFX.Data / mysqlclient / Packet.cs
1 using System;\r
2 using System.IO;\r
3 using System.Text;\r
4 \r
5 namespace ByteFX.Data.MySqlClient\r
6 {\r
7         /// <summary>\r
8         /// Summary description for Packet.\r
9         /// </summary>\r
10         internal class Packet : MemoryStream\r
11         {\r
12                 Encoding                encoding;\r
13                 byte                    sequence;\r
14                 int                             completeLen;\r
15                 public static int   NULL_LEN=-1;\r
16                 private int             shortLen = 2;\r
17                 private int             intLen = 3;\r
18                 private int             longLen = 4;\r
19                 private bool    longInts = false;\r
20 \r
21                 public Packet(bool longInts) : base()\r
22                 {\r
23                         LongInts = longInts;\r
24                 }\r
25 \r
26                 public Packet(byte[] bytes, bool longInts) : base(bytes.Length)\r
27                 {\r
28                         this.Write( bytes, 0, bytes.Length );\r
29                         Position = 0;\r
30                         LongInts = longInts;\r
31                 }\r
32 \r
33                 public bool LongInts \r
34                 {\r
35                         get { return longInts; }\r
36                         set \r
37                         { \r
38                                 longInts = value; \r
39                                 if (longInts) \r
40                                 {\r
41                                         intLen = 4;\r
42                                         longLen = 8;\r
43                                 }\r
44                         }\r
45                 }\r
46 \r
47                 public int CompleteLength \r
48                 {\r
49                         get { return completeLen; }\r
50                         set { completeLen = value; }\r
51                 }\r
52 \r
53                 public byte Sequence \r
54                 {\r
55                         get { return sequence; }\r
56                         set { sequence = value; }\r
57                 }\r
58 \r
59                 public Encoding Encoding \r
60                 {\r
61                         set { encoding = value; }\r
62                         get { return encoding; }\r
63                 }\r
64 \r
65                 public void Clear()\r
66                 {\r
67                         Position = 0;\r
68                         this.SetLength(0);\r
69                 }\r
70 \r
71                 public byte this[int index] \r
72                 {\r
73                         get \r
74                         { \r
75                                 long pos = Position;\r
76                                 Position = index;\r
77                                 byte b = (byte)ReadByte();\r
78                                 Position = pos;\r
79                                 return b;\r
80                         }\r
81                 }\r
82 \r
83                 public new int Length \r
84                 {\r
85                         get { return (int)base.Length; }\r
86                 }\r
87 \r
88                 public bool IsLastPacket()\r
89                 {\r
90                         return (Length == 1 && this[0] == 0xfe);\r
91                 }\r
92 \r
93                 public void Append( Packet p )\r
94                 {\r
95                         long oldPos = Position;\r
96                         Position = Length;\r
97                         this.Write( p.GetBuffer(), 0, p.Length );\r
98                         Position = oldPos;\r
99                 }\r
100 \r
101                 public Packet ReadPacket()\r
102                 {\r
103                         if (! HasMoreData) return null;\r
104 \r
105                         int len = this.ReadInteger(3);\r
106                         byte seq = (byte)this.ReadByte();\r
107                         byte[] buf = new byte[ len ];\r
108                         this.Read( buf, 0, len );\r
109                         Packet p = new Packet( buf, LongInts );\r
110                         p.Sequence = seq;\r
111                         p.Encoding = this.Encoding;\r
112                         return p;\r
113                 }\r
114 \r
115                 public int ReadNBytes()\r
116                 {\r
117                         byte c = (byte)ReadByte();\r
118                         if (c < 1 || c > 4) throw new MySqlException("Unexpected byte count received");\r
119                         return ReadInteger((int)c);\r
120                 }\r
121 \r
122                 public string ReadLenString()\r
123                 {\r
124                         long len = ReadLenInteger();\r
125 \r
126                         byte[] buffer = new Byte[len];\r
127                         Read(buffer, 0, (int)len);\r
128                         return encoding.GetString( buffer, 0, (int)len);\r
129                 }\r
130 \r
131 \r
132                 /// <summary>\r
133                 /// WriteInteger\r
134                 /// </summary>\r
135                 /// <param name="v"></param>\r
136                 /// <param name="numbytes"></param>\r
137                 public void WriteInteger( int v, int numbytes )\r
138                 {\r
139                         int val = v;\r
140 \r
141                         if (numbytes < 1 || numbytes > 4) \r
142                                 throw new ArgumentOutOfRangeException("Wrong byte count for WriteInteger");\r
143 \r
144                         for (int x=0; x < numbytes; x++)\r
145                         {\r
146                                 WriteByte( (byte)(val&0xff) );\r
147                                 val >>= 8;\r
148                         }\r
149                 }\r
150 \r
151                 /// <summary>\r
152                 /// \r
153                 /// </summary>\r
154                 /// <param name="numbytes"></param>\r
155                 /// <returns></returns>\r
156                 public int ReadInteger(int numbytes)\r
157                 {\r
158                         int val = 0;\r
159                         int raise = 1;\r
160                         for (int x=0; x < numbytes; x++)\r
161                         {\r
162                                 int b = ReadByte();\r
163                                 val += (b*raise);\r
164                                 raise *= 256;\r
165                         }\r
166                         return val;\r
167                 }\r
168 \r
169                 /// <summary>\r
170                 /// \r
171                 /// </summary>\r
172                 /// <returns></returns>\r
173                 public long ReadLenInteger()\r
174                 {\r
175                         byte c  = (byte)ReadByte();\r
176 \r
177                         switch(c) \r
178                         {\r
179                                 case 251 : return NULL_LEN; \r
180                                 case 252 : return ReadInteger(shortLen);\r
181                                 case 253 : return ReadInteger(intLen);\r
182                                 case 254 : return ReadInteger(longLen);\r
183                                 default  : return c;\r
184                         }\r
185                 }\r
186 \r
187                 public bool HasMoreData\r
188                 {\r
189                         get { return Position < Length; }\r
190                 }\r
191 \r
192                 #region String Functions\r
193                 public string ReadString()\r
194                 {\r
195                         System.Text.StringBuilder sb = new System.Text.StringBuilder();\r
196 \r
197                         while ( HasMoreData )\r
198                         {\r
199                                 byte b = (byte)ReadByte();\r
200                                 if (b == 0) break;\r
201                                 sb.Append( Convert.ToChar( b ));\r
202                         }\r
203 \r
204                         return sb.ToString();\r
205                 }\r
206 \r
207                 public void WriteString(string v, Encoding encoding)\r
208                 {\r
209                         WriteStringNoNull(v, encoding);\r
210                         WriteByte(0);\r
211                 }\r
212 \r
213                 public void WriteStringNoNull(string v, Encoding encoding)\r
214                 {\r
215                         byte[] bytes = encoding.GetBytes(v);\r
216                         Write(bytes, 0, bytes.Length);\r
217                 }\r
218 \r
219                 #endregion\r
220 \r
221 \r
222         }\r
223 }\r