20
|
1 //
|
|
2 // Copyright 2011 Kazuki Oikawa
|
|
3 //
|
|
4 // Licensed under the Apache License, Version 2.0 (the "License");
|
|
5 // you may not use this file except in compliance with the License.
|
|
6 // You may obtain a copy of the License at
|
|
7 //
|
|
8 // http://www.apache.org/licenses/LICENSE-2.0
|
|
9 //
|
|
10 // Unless required by applicable law or agreed to in writing, software
|
|
11 // distributed under the License is distributed on an "AS IS" BASIS,
|
|
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13 // See the License for the specific language governing permissions and
|
|
14 // limitations under the License.
|
|
15 //
|
|
16
|
|
17 using System;
|
|
18 using System.IO;
|
|
19 using System.Text;
|
|
20
|
|
21 namespace MsgPack
|
|
22 {
|
|
23 public class MsgPackReader
|
|
24 {
|
|
25 Stream _strm;
|
|
26 byte[] _tmp0 = new byte[8];
|
|
27 byte[] _tmp1 = new byte[8];
|
|
28
|
|
29 Encoding _encoding = Encoding.UTF8;
|
|
30 //Decoder _decoder = Encoding.UTF8.GetDecoder ();
|
|
31 byte[] _buf = new byte[64];
|
|
32
|
|
33 public MsgPackReader (Stream strm)
|
|
34 {
|
|
35 _strm = strm;
|
|
36 }
|
|
37
|
|
38 public TypePrefixes Type { get; private set; }
|
|
39
|
|
40 public bool ValueBoolean { get; private set; }
|
|
41 public uint Length { get; private set; }
|
|
42
|
|
43 public uint ValueUnsigned { get; private set; }
|
|
44 public ulong ValueUnsigned64 { get; private set; }
|
|
45
|
|
46 public int ValueSigned { get; private set; }
|
|
47 public long ValueSigned64 { get; private set; }
|
|
48
|
|
49 public float ValueFloat { get; private set; }
|
|
50 public double ValueDouble { get; private set; }
|
|
51
|
|
52 public bool IsSigned ()
|
|
53 {
|
|
54 return this.Type == TypePrefixes.NegativeFixNum ||
|
|
55 this.Type == TypePrefixes.PositiveFixNum ||
|
|
56 this.Type == TypePrefixes.Int8 ||
|
|
57 this.Type == TypePrefixes.Int16 ||
|
|
58 this.Type == TypePrefixes.Int32;
|
|
59 }
|
|
60
|
|
61 public bool IsBoolean ()
|
|
62 {
|
|
63 return this.Type == TypePrefixes.True || this.Type == TypePrefixes.False;
|
|
64 }
|
|
65
|
|
66 public bool IsSigned64 ()
|
|
67 {
|
|
68 return this.Type == TypePrefixes.Int64;
|
|
69 }
|
|
70
|
|
71 public bool IsUnsigned ()
|
|
72 {
|
|
73 return this.Type == TypePrefixes.PositiveFixNum ||
|
|
74 this.Type == TypePrefixes.UInt8 ||
|
|
75 this.Type == TypePrefixes.UInt16 ||
|
|
76 this.Type == TypePrefixes.UInt32;
|
|
77 }
|
|
78
|
|
79 public bool IsUnsigned64 ()
|
|
80 {
|
|
81 return this.Type == TypePrefixes.UInt64;
|
|
82 }
|
|
83
|
|
84 public bool IsRaw ()
|
|
85 {
|
|
86 return this.Type == TypePrefixes.FixRaw || this.Type == TypePrefixes.Raw16 || this.Type == TypePrefixes.Raw32;
|
|
87 }
|
|
88
|
|
89 public bool IsArray ()
|
|
90 {
|
|
91 return this.Type == TypePrefixes.FixArray || this.Type == TypePrefixes.Array16 || this.Type == TypePrefixes.Array32;
|
|
92 }
|
|
93
|
|
94 public bool IsMap ()
|
|
95 {
|
|
96 return this.Type == TypePrefixes.FixMap || this.Type == TypePrefixes.Map16 || this.Type == TypePrefixes.Map32;
|
|
97 }
|
|
98
|
|
99 public bool Read ()
|
|
100 {
|
|
101 byte[] tmp0 = _tmp0, tmp1 = _tmp1;
|
|
102 int x = _strm.ReadByte ();
|
|
103 if (x < 0)
|
|
104 return false; // EOS
|
|
105
|
|
106 if (x >= 0x00 && x <= 0x7f) {
|
|
107 this.Type = TypePrefixes.PositiveFixNum;
|
|
108 } else if (x >= 0xe0 && x <= 0xff) {
|
|
109 this.Type = TypePrefixes.NegativeFixNum;
|
|
110 } else if (x >= 0xa0 && x <= 0xbf) {
|
|
111 this.Type = TypePrefixes.FixRaw;
|
|
112 } else if (x >= 0x90 && x <= 0x9f) {
|
|
113 this.Type = TypePrefixes.FixArray;
|
|
114 } else if (x >= 0x80 && x <= 0x8f) {
|
|
115 this.Type = TypePrefixes.FixMap;
|
|
116 } else {
|
|
117 this.Type = (TypePrefixes)x;
|
|
118 }
|
|
119
|
|
120 switch (this.Type) {
|
|
121 case TypePrefixes.Nil:
|
|
122 break;
|
|
123 case TypePrefixes.False:
|
|
124 ValueBoolean = false;
|
|
125 break;
|
|
126 case TypePrefixes.True:
|
|
127 ValueBoolean = true;
|
|
128 break;
|
|
129 case TypePrefixes.Float:
|
|
130 _strm.Read (tmp0, 0, 4);
|
|
131 if (BitConverter.IsLittleEndian) {
|
|
132 tmp1[0] = tmp0[3];
|
|
133 tmp1[1] = tmp0[2];
|
|
134 tmp1[2] = tmp0[1];
|
|
135 tmp1[3] = tmp0[0];
|
|
136 ValueFloat = BitConverter.ToSingle (tmp1, 0);
|
|
137 } else {
|
|
138 ValueFloat = BitConverter.ToSingle (tmp0, 0);
|
|
139 }
|
|
140 break;
|
|
141 case TypePrefixes.Double:
|
|
142 _strm.Read (tmp0, 0, 8);
|
|
143 if (BitConverter.IsLittleEndian) {
|
|
144 tmp1[0] = tmp0[7];
|
|
145 tmp1[1] = tmp0[6];
|
|
146 tmp1[2] = tmp0[5];
|
|
147 tmp1[3] = tmp0[4];
|
|
148 tmp1[4] = tmp0[3];
|
|
149 tmp1[5] = tmp0[2];
|
|
150 tmp1[6] = tmp0[1];
|
|
151 tmp1[7] = tmp0[0];
|
|
152 ValueDouble = BitConverter.ToDouble (tmp1, 0);
|
|
153 } else {
|
|
154 ValueDouble = BitConverter.ToDouble (tmp0, 0);
|
|
155 }
|
|
156 break;
|
|
157 case TypePrefixes.NegativeFixNum:
|
|
158 ValueSigned = (x & 0x1f) - 0x20;
|
|
159 break;
|
|
160 case TypePrefixes.PositiveFixNum:
|
|
161 ValueSigned = x & 0x7f;
|
|
162 ValueUnsigned = (uint)ValueSigned;
|
|
163 break;
|
|
164 case TypePrefixes.UInt8:
|
|
165 x = _strm.ReadByte ();
|
|
166 if (x < 0)
|
|
167 throw new FormatException ();
|
|
168 ValueUnsigned = (uint)x;
|
|
169 break;
|
|
170 case TypePrefixes.UInt16:
|
|
171 if (_strm.Read (tmp0, 0, 2) != 2)
|
|
172 throw new FormatException ();
|
|
173 ValueUnsigned = ((uint)tmp0[0] << 8) | (uint)tmp0[1];
|
|
174 break;
|
|
175 case TypePrefixes.UInt32:
|
|
176 if (_strm.Read (tmp0, 0, 4) != 4)
|
|
177 throw new FormatException ();
|
|
178 ValueUnsigned = ((uint)tmp0[0] << 24) | ((uint)tmp0[1] << 16) | ((uint)tmp0[2] << 8) | (uint)tmp0[3];
|
|
179 break;
|
|
180 case TypePrefixes.UInt64:
|
|
181 if (_strm.Read (tmp0, 0, 8) != 8)
|
|
182 throw new FormatException ();
|
|
183 ValueUnsigned64 = ((ulong)tmp0[0] << 56) | ((ulong)tmp0[1] << 48) | ((ulong)tmp0[2] << 40) | ((ulong)tmp0[3] << 32) | ((ulong)tmp0[4] << 24) | ((ulong)tmp0[5] << 16) | ((ulong)tmp0[6] << 8) | (ulong)tmp0[7];
|
|
184 break;
|
|
185 case TypePrefixes.Int8:
|
|
186 x = _strm.ReadByte ();
|
|
187 if (x < 0)
|
|
188 throw new FormatException ();
|
|
189 ValueSigned = (sbyte)x;
|
|
190 break;
|
|
191 case TypePrefixes.Int16:
|
|
192 if (_strm.Read (tmp0, 0, 2) != 2)
|
|
193 throw new FormatException ();
|
|
194 ValueSigned = (short)((tmp0[0] << 8) | tmp0[1]);
|
|
195 break;
|
|
196 case TypePrefixes.Int32:
|
|
197 if (_strm.Read (tmp0, 0, 4) != 4)
|
|
198 throw new FormatException ();
|
|
199 ValueSigned = (tmp0[0] << 24) | (tmp0[1] << 16) | (tmp0[2] << 8) | tmp0[3];
|
|
200 break;
|
|
201 case TypePrefixes.Int64:
|
|
202 if (_strm.Read (tmp0, 0, 8) != 8)
|
|
203 throw new FormatException ();
|
|
204 ValueSigned64 = ((long)tmp0[0] << 56) | ((long)tmp0[1] << 48) | ((long)tmp0[2] << 40) | ((long)tmp0[3] << 32) | ((long)tmp0[4] << 24) | ((long)tmp0[5] << 16) | ((long)tmp0[6] << 8) | (long)tmp0[7];
|
|
205 break;
|
|
206 case TypePrefixes.FixRaw:
|
|
207 Length = (uint)(x & 0x1f);
|
|
208 break;
|
|
209 case TypePrefixes.FixArray:
|
|
210 case TypePrefixes.FixMap:
|
|
211 Length = (uint)(x & 0xf);
|
|
212 break;
|
|
213 case TypePrefixes.Raw16:
|
|
214 case TypePrefixes.Array16:
|
|
215 case TypePrefixes.Map16:
|
|
216 if (_strm.Read (tmp0, 0, 2) != 2)
|
|
217 throw new FormatException ();
|
|
218 Length = ((uint)tmp0[0] << 8) | (uint)tmp0[1];
|
|
219 break;
|
|
220 case TypePrefixes.Raw32:
|
|
221 case TypePrefixes.Array32:
|
|
222 case TypePrefixes.Map32:
|
|
223 if (_strm.Read (tmp0, 0, 4) != 4)
|
|
224 throw new FormatException ();
|
|
225 Length = ((uint)tmp0[0] << 24) | ((uint)tmp0[1] << 16) | ((uint)tmp0[2] << 8) | (uint)tmp0[3];
|
|
226 break;
|
|
227 default:
|
|
228 throw new FormatException ();
|
|
229 }
|
|
230 return true;
|
|
231 }
|
|
232
|
|
233 public int ReadValueRaw (byte[] buf, int offset, int count)
|
|
234 {
|
|
235 return _strm.Read (buf, offset, count);
|
|
236 }
|
|
237
|
|
238 public string ReadRawString ()
|
|
239 {
|
|
240 return ReadRawString (_buf);
|
|
241 }
|
|
242
|
|
243 public string ReadRawString (byte[] buf)
|
|
244 {
|
|
245 if (this.Length < buf.Length) {
|
|
246 if (ReadValueRaw (buf, 0, (int)this.Length) != this.Length)
|
|
247 throw new FormatException ();
|
|
248 return _encoding.GetString (buf, 0, (int)this.Length);
|
|
249 }
|
|
250
|
|
251 // Poor implementation
|
|
252 byte[] tmp = new byte[(int)this.Length];
|
|
253 if (ReadValueRaw (tmp, 0, tmp.Length) != tmp.Length)
|
|
254 throw new FormatException ();
|
|
255 return _encoding.GetString (tmp);
|
|
256 }
|
|
257 }
|
|
258 }
|