0
|
1 //
|
|
2 // MessagePack for Java
|
|
3 //
|
|
4 // Copyright (C) 2009 - 2013 FURUHASHI Sadayuki
|
|
5 //
|
|
6 // Licensed under the Apache License, Version 2.0 (the "License");
|
|
7 // you may not use this file except in compliance with the License.
|
|
8 // You may obtain a copy of the License at
|
|
9 //
|
|
10 // http://www.apache.org/licenses/LICENSE-2.0
|
|
11 //
|
|
12 // Unless required by applicable law or agreed to in writing, software
|
|
13 // distributed under the License is distributed on an "AS IS" BASIS,
|
|
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15 // See the License for the specific language governing permissions and
|
|
16 // limitations under the License.
|
|
17 //
|
|
18 package org.msgpack.unpacker;
|
|
19
|
|
20 import java.io.IOException;
|
|
21 import java.io.EOFException;
|
|
22 import java.io.InputStream;
|
|
23 import java.math.BigInteger;
|
|
24 import org.msgpack.io.Input;
|
|
25 import org.msgpack.io.StreamInput;
|
|
26 import org.msgpack.io.BufferReferer;
|
|
27 import org.msgpack.MessagePack;
|
|
28 import org.msgpack.MessageTypeException;
|
|
29 import org.msgpack.packer.Unconverter;
|
|
30 import org.msgpack.type.ValueType;
|
|
31
|
|
32 public class MessagePackUnpacker extends AbstractUnpacker {
|
|
33 private static final byte REQUIRE_TO_READ_HEAD = (byte) 0xc1;
|
|
34
|
|
35 protected final Input in;
|
|
36 private final UnpackerStack stack = new UnpackerStack();
|
|
37
|
|
38 private byte headByte = REQUIRE_TO_READ_HEAD;
|
|
39
|
|
40 private byte[] raw;
|
|
41 private int rawFilled;
|
|
42
|
|
43 private final IntAccept intAccept = new IntAccept();
|
|
44 private final LongAccept longAccept = new LongAccept();
|
|
45 private final BigIntegerAccept bigIntegerAccept = new BigIntegerAccept();
|
|
46 private final DoubleAccept doubleAccept = new DoubleAccept();
|
|
47 private final ByteArrayAccept byteArrayAccept = new ByteArrayAccept();
|
|
48 private final StringAccept stringAccept = new StringAccept();
|
|
49 private final ArrayAccept arrayAccept = new ArrayAccept();
|
|
50 private final MapAccept mapAccept = new MapAccept();
|
|
51 private final ValueAccept valueAccept = new ValueAccept();
|
|
52 private final SkipAccept skipAccept = new SkipAccept();
|
|
53
|
|
54 public MessagePackUnpacker(MessagePack msgpack, InputStream stream) {
|
|
55 this(msgpack, new StreamInput(stream));
|
|
56 }
|
|
57
|
|
58 protected MessagePackUnpacker(MessagePack msgpack, Input in) {
|
|
59 super(msgpack);
|
|
60 this.in = in;
|
|
61 }
|
|
62
|
|
63 private byte getHeadByte() throws IOException {
|
|
64 byte b = headByte;
|
|
65 if (b == REQUIRE_TO_READ_HEAD) {
|
|
66 b = headByte = in.readByte();
|
|
67 }
|
|
68 return b;
|
|
69 }
|
|
70
|
|
71 final void readOne(Accept a) throws IOException {
|
|
72 stack.checkCount();
|
|
73 if (readOneWithoutStack(a)) {
|
|
74 stack.reduceCount();
|
|
75 }
|
|
76 }
|
|
77
|
|
78 final boolean readOneWithoutStack(Accept a) throws IOException {
|
|
79 if (raw != null) {
|
|
80 readRawBodyCont();
|
|
81 a.acceptRaw(raw);
|
|
82 raw = null;
|
|
83 headByte = REQUIRE_TO_READ_HEAD;
|
|
84 return true;
|
|
85 }
|
|
86
|
|
87 final int b = (int) getHeadByte();
|
|
88
|
|
89 if ((b & 0x80) == 0) { // Positive Fixnum
|
|
90 // System.out.println("positive fixnum "+b);
|
|
91 a.acceptInteger(b);
|
|
92 headByte = REQUIRE_TO_READ_HEAD;
|
|
93 return true;
|
|
94 }
|
|
95
|
|
96 if ((b & 0xe0) == 0xe0) { // Negative Fixnum
|
|
97 // System.out.println("negative fixnum "+b);
|
|
98 a.acceptInteger(b);
|
|
99 headByte = REQUIRE_TO_READ_HEAD;
|
|
100 return true;
|
|
101 }
|
|
102
|
|
103 if ((b & 0xe0) == 0xa0) { // FixRaw
|
|
104 int count = b & 0x1f;
|
|
105 if (count == 0) {
|
|
106 a.acceptEmptyRaw();
|
|
107 headByte = REQUIRE_TO_READ_HEAD;
|
|
108 return true;
|
|
109 }
|
|
110 if (!tryReferRawBody(a, count)) {
|
|
111 readRawBody(count);
|
|
112 a.acceptRaw(raw);
|
|
113 raw = null;
|
|
114 }
|
|
115 headByte = REQUIRE_TO_READ_HEAD;
|
|
116 return true;
|
|
117 }
|
|
118
|
|
119 if ((b & 0xf0) == 0x90) { // FixArray
|
|
120 int count = b & 0x0f;
|
|
121 // System.out.println("fixarray count:"+count);
|
|
122 a.acceptArray(count);
|
|
123 stack.reduceCount();
|
|
124 stack.pushArray(count);
|
|
125 headByte = REQUIRE_TO_READ_HEAD;
|
|
126 return false;
|
|
127 }
|
|
128
|
|
129 if ((b & 0xf0) == 0x80) { // FixMap
|
|
130 int count = b & 0x0f;
|
|
131 // System.out.println("fixmap count:"+count/2);
|
|
132 a.acceptMap(count);
|
|
133 stack.reduceCount();
|
|
134 stack.pushMap(count);
|
|
135 headByte = REQUIRE_TO_READ_HEAD;
|
|
136 return false;
|
|
137 }
|
|
138
|
|
139 return readOneWithoutStackLarge(a, b);
|
|
140 }
|
|
141
|
|
142 private boolean readOneWithoutStackLarge(Accept a, final int b)
|
|
143 throws IOException {
|
|
144 switch (b & 0xff) {
|
|
145 case 0xc0: // nil
|
|
146 a.acceptNil();
|
|
147 headByte = REQUIRE_TO_READ_HEAD;
|
|
148 return true;
|
|
149 case 0xc2: // false
|
|
150 a.acceptBoolean(false);
|
|
151 headByte = REQUIRE_TO_READ_HEAD;
|
|
152 return true;
|
|
153 case 0xc3: // true
|
|
154 a.acceptBoolean(true);
|
|
155 headByte = REQUIRE_TO_READ_HEAD;
|
|
156 return true;
|
|
157 //case 0xc4: // bin 8 -> see 0xd9
|
|
158 //case 0xc5: // bin 16 -> see 0xda
|
|
159 //case 0xc6: // bin 32 -> see 0xdb
|
|
160 case 0xca: // float
|
|
161 a.acceptFloat(in.getFloat());
|
|
162 in.advance();
|
|
163 headByte = REQUIRE_TO_READ_HEAD;
|
|
164 return true;
|
|
165 case 0xcb: // double
|
|
166 a.acceptDouble(in.getDouble());
|
|
167 in.advance();
|
|
168 headByte = REQUIRE_TO_READ_HEAD;
|
|
169 return true;
|
|
170 case 0xcc: // unsigned int 8
|
|
171 a.acceptUnsignedInteger(in.getByte());
|
|
172 in.advance();
|
|
173 headByte = REQUIRE_TO_READ_HEAD;
|
|
174 return true;
|
|
175 case 0xcd: // unsigned int 16
|
|
176 a.acceptUnsignedInteger(in.getShort());
|
|
177 in.advance();
|
|
178 headByte = REQUIRE_TO_READ_HEAD;
|
|
179 return true;
|
|
180 case 0xce: // unsigned int 32
|
|
181 a.acceptUnsignedInteger(in.getInt());
|
|
182 in.advance();
|
|
183 headByte = REQUIRE_TO_READ_HEAD;
|
|
184 return true;
|
|
185 case 0xcf: // unsigned int 64
|
|
186 a.acceptUnsignedInteger(in.getLong());
|
|
187 in.advance();
|
|
188 headByte = REQUIRE_TO_READ_HEAD;
|
|
189 return true;
|
|
190 case 0xd0: // signed int 8
|
|
191 a.acceptInteger(in.getByte());
|
|
192 in.advance();
|
|
193 headByte = REQUIRE_TO_READ_HEAD;
|
|
194 return true;
|
|
195 case 0xd1: // signed int 16
|
|
196 a.acceptInteger(in.getShort());
|
|
197 in.advance();
|
|
198 headByte = REQUIRE_TO_READ_HEAD;
|
|
199 return true;
|
|
200 case 0xd2: // signed int 32
|
|
201 a.acceptInteger(in.getInt());
|
|
202 in.advance();
|
|
203 headByte = REQUIRE_TO_READ_HEAD;
|
|
204 return true;
|
|
205 case 0xd3: // signed int 64
|
|
206 a.acceptInteger(in.getLong());
|
|
207 in.advance();
|
|
208 headByte = REQUIRE_TO_READ_HEAD;
|
|
209 return true;
|
|
210 case 0xc4: // bin 8
|
|
211 case 0xd9: // str 8
|
|
212 {
|
|
213 int count = in.getByte() & 0xff;
|
|
214 if (count == 0) {
|
|
215 a.acceptEmptyRaw();
|
|
216 in.advance();
|
|
217 headByte = REQUIRE_TO_READ_HEAD;
|
|
218 return true;
|
|
219 }
|
|
220 if (count >= rawSizeLimit) {
|
|
221 String reason = String.format(
|
|
222 "Size of raw (%d) over limit at %d",
|
|
223 new Object[] { count, rawSizeLimit });
|
|
224 throw new SizeLimitException(reason);
|
|
225 }
|
|
226 in.advance();
|
|
227 if (!tryReferRawBody(a, count)) {
|
|
228 readRawBody(count);
|
|
229 a.acceptRaw(raw);
|
|
230 raw = null;
|
|
231 }
|
|
232 headByte = REQUIRE_TO_READ_HEAD;
|
|
233 return true;
|
|
234 }
|
|
235 case 0xc5: // bin 16
|
|
236 case 0xda: // raw 16
|
|
237 {
|
|
238 int count = in.getShort() & 0xffff;
|
|
239 if (count == 0) {
|
|
240 a.acceptEmptyRaw();
|
|
241 in.advance();
|
|
242 headByte = REQUIRE_TO_READ_HEAD;
|
|
243 return true;
|
|
244 }
|
|
245 if (count >= rawSizeLimit) {
|
|
246 String reason = String.format(
|
|
247 "Size of raw (%d) over limit at %d",
|
|
248 new Object[] { count, rawSizeLimit });
|
|
249 throw new SizeLimitException(reason);
|
|
250 }
|
|
251 in.advance();
|
|
252 if (!tryReferRawBody(a, count)) {
|
|
253 readRawBody(count);
|
|
254 a.acceptRaw(raw);
|
|
255 raw = null;
|
|
256 }
|
|
257 headByte = REQUIRE_TO_READ_HEAD;
|
|
258 return true;
|
|
259 }
|
|
260 case 0xc6: // bin 32
|
|
261 case 0xdb: // raw 32
|
|
262 {
|
|
263 int count = in.getInt();
|
|
264 if (count == 0) {
|
|
265 a.acceptEmptyRaw();
|
|
266 in.advance();
|
|
267 headByte = REQUIRE_TO_READ_HEAD;
|
|
268 return true;
|
|
269 }
|
|
270 if (count < 0 || count >= rawSizeLimit) {
|
|
271 String reason = String.format(
|
|
272 "Size of raw (%d) over limit at %d",
|
|
273 new Object[] { count, rawSizeLimit });
|
|
274 throw new SizeLimitException(reason);
|
|
275 }
|
|
276 in.advance();
|
|
277 if (!tryReferRawBody(a, count)) {
|
|
278 readRawBody(count);
|
|
279 a.acceptRaw(raw);
|
|
280 raw = null;
|
|
281 }
|
|
282 headByte = REQUIRE_TO_READ_HEAD;
|
|
283 return true;
|
|
284 }
|
|
285 case 0xdc: // array 16
|
|
286 {
|
|
287 int count = in.getShort() & 0xffff;
|
|
288 if (count >= arraySizeLimit) {
|
|
289 String reason = String.format(
|
|
290 "Size of array (%d) over limit at %d",
|
|
291 new Object[] { count, arraySizeLimit });
|
|
292 throw new SizeLimitException(reason);
|
|
293 }
|
|
294 a.acceptArray(count);
|
|
295 stack.reduceCount();
|
|
296 stack.pushArray(count);
|
|
297 in.advance();
|
|
298 headByte = REQUIRE_TO_READ_HEAD;
|
|
299 return false;
|
|
300 }
|
|
301 case 0xdd: // array 32
|
|
302 {
|
|
303 int count = in.getInt();
|
|
304 if (count < 0 || count >= arraySizeLimit) {
|
|
305 String reason = String.format(
|
|
306 "Size of array (%d) over limit at %d",
|
|
307 new Object[] { count, arraySizeLimit });
|
|
308 throw new SizeLimitException(reason);
|
|
309 }
|
|
310 a.acceptArray(count);
|
|
311 stack.reduceCount();
|
|
312 stack.pushArray(count);
|
|
313 in.advance();
|
|
314 headByte = REQUIRE_TO_READ_HEAD;
|
|
315 return false;
|
|
316 }
|
|
317 case 0xde: // map 16
|
|
318 {
|
|
319 int count = in.getShort() & 0xffff;
|
|
320 if (count >= mapSizeLimit) {
|
|
321 String reason = String.format(
|
|
322 "Size of map (%d) over limit at %d",
|
|
323 new Object[] { count, mapSizeLimit });
|
|
324 throw new SizeLimitException(reason);
|
|
325 }
|
|
326 a.acceptMap(count);
|
|
327 stack.reduceCount();
|
|
328 stack.pushMap(count);
|
|
329 in.advance();
|
|
330 headByte = REQUIRE_TO_READ_HEAD;
|
|
331 return false;
|
|
332 }
|
|
333 case 0xdf: // map 32
|
|
334 {
|
|
335 int count = in.getInt();
|
|
336 if (count < 0 || count >= mapSizeLimit) {
|
|
337 String reason = String.format(
|
|
338 "Size of map (%d) over limit at %d",
|
|
339 new Object[] { count, mapSizeLimit });
|
|
340 throw new SizeLimitException(reason);
|
|
341 }
|
|
342 a.acceptMap(count);
|
|
343 stack.reduceCount();
|
|
344 stack.pushMap(count);
|
|
345 in.advance();
|
|
346 headByte = REQUIRE_TO_READ_HEAD;
|
|
347 return false;
|
|
348 }
|
|
349 default:
|
|
350 // System.out.println("unknown b "+(b&0xff));
|
|
351 // headByte = CS_INVALID
|
|
352 headByte = REQUIRE_TO_READ_HEAD;
|
|
353 throw new IOException("Invalid byte: " + b); // TODO error FormatException
|
|
354 }
|
|
355 }
|
|
356
|
|
357 private boolean tryReferRawBody(BufferReferer referer, int size) throws IOException {
|
|
358 return in.tryRefer(referer, size);
|
|
359 }
|
|
360
|
|
361 private void readRawBody(int size) throws IOException {
|
|
362 raw = new byte[size];
|
|
363 rawFilled = 0;
|
|
364 readRawBodyCont();
|
|
365 }
|
|
366
|
|
367 private void readRawBodyCont() throws IOException {
|
|
368 int len = in.read(raw, rawFilled, raw.length - rawFilled);
|
|
369 rawFilled += len;
|
|
370 if (rawFilled < raw.length) {
|
|
371 throw new EOFException();
|
|
372 }
|
|
373 }
|
|
374
|
|
375 @Override
|
|
376 protected boolean tryReadNil() throws IOException {
|
|
377 stack.checkCount();
|
|
378 int b = getHeadByte() & 0xff;
|
|
379 if (b == 0xc0) {
|
|
380 // nil is read
|
|
381 stack.reduceCount();
|
|
382 headByte = REQUIRE_TO_READ_HEAD;
|
|
383 return true;
|
|
384 }
|
|
385 // not nil
|
|
386 return false;
|
|
387 }
|
|
388
|
|
389 @Override
|
|
390 public boolean trySkipNil() throws IOException {
|
|
391 if (stack.getDepth() > 0 && stack.getTopCount() <= 0) {
|
|
392 // end of array or map
|
|
393 return true;
|
|
394 }
|
|
395
|
|
396 int b = getHeadByte() & 0xff;
|
|
397 if (b == 0xc0) {
|
|
398 // nil is skipped
|
|
399 stack.reduceCount();
|
|
400 headByte = REQUIRE_TO_READ_HEAD;
|
|
401 return true;
|
|
402 }
|
|
403 // not nil
|
|
404 return false;
|
|
405 }
|
|
406
|
|
407 @Override
|
|
408 public void readNil() throws IOException {
|
|
409 // optimized not to allocate nilAccept
|
|
410 stack.checkCount();
|
|
411 int b = getHeadByte() & 0xff;
|
|
412 if (b == 0xc0) {
|
|
413 stack.reduceCount();
|
|
414 headByte = REQUIRE_TO_READ_HEAD;
|
|
415 return;
|
|
416 }
|
|
417 throw new MessageTypeException("Expected nil but got not nil value");
|
|
418 }
|
|
419
|
|
420 @Override
|
|
421 public boolean readBoolean() throws IOException {
|
|
422 // optimized not to allocate booleanAccept
|
|
423 stack.checkCount();
|
|
424 int b = getHeadByte() & 0xff;
|
|
425 if (b == 0xc2) {
|
|
426 stack.reduceCount();
|
|
427 headByte = REQUIRE_TO_READ_HEAD;
|
|
428 return false;
|
|
429 } else if (b == 0xc3) {
|
|
430 stack.reduceCount();
|
|
431 headByte = REQUIRE_TO_READ_HEAD;
|
|
432 return true;
|
|
433 }
|
|
434 throw new MessageTypeException(
|
|
435 "Expected Boolean but got not boolean value");
|
|
436 }
|
|
437
|
|
438 @Override
|
|
439 public byte readByte() throws IOException {
|
|
440 // optimized not to allocate byteAccept
|
|
441 stack.checkCount();
|
|
442 readOneWithoutStack(intAccept);
|
|
443 int value = intAccept.value;
|
|
444 if (value < (int) Byte.MIN_VALUE || value > (int) Byte.MAX_VALUE) {
|
|
445 throw new MessageTypeException(); // TODO message
|
|
446 }
|
|
447 stack.reduceCount();
|
|
448 return (byte) value;
|
|
449 }
|
|
450
|
|
451 @Override
|
|
452 public short readShort() throws IOException {
|
|
453 // optimized not to allocate shortAccept
|
|
454 stack.checkCount();
|
|
455 readOneWithoutStack(intAccept);
|
|
456 int value = intAccept.value;
|
|
457 if (value < (int) Short.MIN_VALUE || value > (int) Short.MAX_VALUE) {
|
|
458 throw new MessageTypeException(); // TODO message
|
|
459 }
|
|
460 stack.reduceCount();
|
|
461 return (short) value;
|
|
462 }
|
|
463
|
|
464 @Override
|
|
465 public int readInt() throws IOException {
|
|
466 readOne(intAccept);
|
|
467 return intAccept.value;
|
|
468 }
|
|
469
|
|
470 @Override
|
|
471 public long readLong() throws IOException {
|
|
472 readOne(longAccept);
|
|
473 return longAccept.value;
|
|
474 }
|
|
475
|
|
476 @Override
|
|
477 public BigInteger readBigInteger() throws IOException {
|
|
478 readOne(bigIntegerAccept);
|
|
479 return bigIntegerAccept.value;
|
|
480 }
|
|
481
|
|
482 @Override
|
|
483 public float readFloat() throws IOException {
|
|
484 readOne(doubleAccept);
|
|
485 return (float) doubleAccept.value;
|
|
486 }
|
|
487
|
|
488 @Override
|
|
489 public double readDouble() throws IOException {
|
|
490 readOne(doubleAccept);
|
|
491 return doubleAccept.value;
|
|
492 }
|
|
493
|
|
494 @Override
|
|
495 public byte[] readByteArray() throws IOException {
|
|
496 readOne(byteArrayAccept);
|
|
497 return byteArrayAccept.value;
|
|
498 }
|
|
499
|
|
500 @Override
|
|
501 public String readString() throws IOException {
|
|
502 readOne(stringAccept);
|
|
503 return stringAccept.value;
|
|
504 }
|
|
505
|
|
506 @Override
|
|
507 public int readArrayBegin() throws IOException {
|
|
508 readOne(arrayAccept);
|
|
509 return arrayAccept.size;
|
|
510 }
|
|
511
|
|
512 @Override
|
|
513 public void readArrayEnd(boolean check) throws IOException {
|
|
514 if (!stack.topIsArray()) {
|
|
515 throw new MessageTypeException(
|
|
516 "readArrayEnd() is called but readArrayBegin() is not called");
|
|
517 }
|
|
518
|
|
519 int remain = stack.getTopCount();
|
|
520 if (remain > 0) {
|
|
521 if (check) {
|
|
522 throw new MessageTypeException(
|
|
523 "readArrayEnd(check=true) is called but the array is not end");
|
|
524 }
|
|
525 for (int i = 0; i < remain; i++) {
|
|
526 skip();
|
|
527 }
|
|
528 }
|
|
529 stack.pop();
|
|
530 }
|
|
531
|
|
532 @Override
|
|
533 public int readMapBegin() throws IOException {
|
|
534 readOne(mapAccept);
|
|
535 return mapAccept.size;
|
|
536 }
|
|
537
|
|
538 @Override
|
|
539 public void readMapEnd(boolean check) throws IOException {
|
|
540 if (!stack.topIsMap()) {
|
|
541 throw new MessageTypeException(
|
|
542 "readMapEnd() is called but readMapBegin() is not called");
|
|
543 }
|
|
544
|
|
545 int remain = stack.getTopCount();
|
|
546 if (remain > 0) {
|
|
547 if (check) {
|
|
548 throw new MessageTypeException(
|
|
549 "readMapEnd(check=true) is called but the map is not end");
|
|
550 }
|
|
551 for (int i = 0; i < remain; i++) {
|
|
552 skip();
|
|
553 }
|
|
554 }
|
|
555 stack.pop();
|
|
556 }
|
|
557
|
|
558 @Override
|
|
559 protected void readValue(Unconverter uc) throws IOException {
|
|
560 if (uc.getResult() != null) {
|
|
561 uc.resetResult();
|
|
562 }
|
|
563 valueAccept.setUnconverter(uc);
|
|
564
|
|
565 stack.checkCount();
|
|
566 if (readOneWithoutStack(valueAccept)) {
|
|
567 stack.reduceCount();
|
|
568 if (uc.getResult() != null) {
|
|
569 return;
|
|
570 }
|
|
571 }
|
|
572 while (true) {
|
|
573 while (stack.getTopCount() == 0) {
|
|
574 if (stack.topIsArray()) {
|
|
575 uc.writeArrayEnd(true);
|
|
576 stack.pop();
|
|
577 // stack.reduceCount();
|
|
578 } else if (stack.topIsMap()) {
|
|
579 uc.writeMapEnd(true);
|
|
580 stack.pop();
|
|
581 // stack.reduceCount();
|
|
582 } else {
|
|
583 throw new RuntimeException("invalid stack"); // FIXME error?
|
|
584 }
|
|
585 if (uc.getResult() != null) {
|
|
586 return;
|
|
587 }
|
|
588 }
|
|
589 readOne(valueAccept);
|
|
590 }
|
|
591 }
|
|
592
|
|
593 @Override
|
|
594 public void skip() throws IOException {
|
|
595 stack.checkCount();
|
|
596 if (readOneWithoutStack(skipAccept)) {
|
|
597 stack.reduceCount();
|
|
598 return;
|
|
599 }
|
|
600 int targetDepth = stack.getDepth() - 1;
|
|
601 while (true) {
|
|
602 while (stack.getTopCount() == 0) {
|
|
603 stack.pop();
|
|
604 if (stack.getDepth() <= targetDepth) {
|
|
605 return;
|
|
606 }
|
|
607 }
|
|
608 readOne(skipAccept);
|
|
609 }
|
|
610 }
|
|
611
|
|
612 public ValueType getNextType() throws IOException {
|
|
613 final int b = (int) getHeadByte();
|
|
614 if ((b & 0x80) == 0) { // Positive Fixnum
|
|
615 return ValueType.INTEGER;
|
|
616 }
|
|
617 if ((b & 0xe0) == 0xe0) { // Negative Fixnum
|
|
618 return ValueType.INTEGER;
|
|
619 }
|
|
620 if ((b & 0xe0) == 0xa0) { // FixRaw
|
|
621 return ValueType.RAW;
|
|
622 }
|
|
623 if ((b & 0xf0) == 0x90) { // FixArray
|
|
624 return ValueType.ARRAY;
|
|
625 }
|
|
626 if ((b & 0xf0) == 0x80) { // FixMap
|
|
627 return ValueType.MAP;
|
|
628 }
|
|
629 switch (b & 0xff) {
|
|
630 case 0xc0: // nil
|
|
631 return ValueType.NIL;
|
|
632 case 0xc2: // false
|
|
633 case 0xc3: // true
|
|
634 return ValueType.BOOLEAN;
|
|
635 case 0xca: // float
|
|
636 case 0xcb: // double
|
|
637 return ValueType.FLOAT;
|
|
638 case 0xcc: // unsigned int 8
|
|
639 case 0xcd: // unsigned int 16
|
|
640 case 0xce: // unsigned int 32
|
|
641 case 0xcf: // unsigned int 64
|
|
642 case 0xd0: // signed int 8
|
|
643 case 0xd1: // signed int 16
|
|
644 case 0xd2: // signed int 32
|
|
645 case 0xd3: // signed int 64
|
|
646 return ValueType.INTEGER;
|
|
647 // The definition based on a minor upgrade guide.
|
|
648 // https://github.com/msgpack/msgpack/blob/master/spec.md#impl-upgrade
|
|
649 case 0xc4: // bin 8
|
|
650 case 0xc5: // bin 16
|
|
651 case 0xc6: // bin 32
|
|
652 case 0xd9: // str8
|
|
653 case 0xda: // raw 16
|
|
654 case 0xdb: // raw 32
|
|
655 return ValueType.RAW;
|
|
656 case 0xdc: // array 16
|
|
657 case 0xdd: // array 32
|
|
658 return ValueType.ARRAY;
|
|
659 case 0xde: // map 16
|
|
660 case 0xdf: // map 32
|
|
661 return ValueType.MAP;
|
|
662 default:
|
|
663 throw new IOException("Invalid byte: " + b); // TODO error FormatException
|
|
664 }
|
|
665 }
|
|
666
|
|
667 public void reset() {
|
|
668 raw = null;
|
|
669 stack.clear();
|
|
670 }
|
|
671
|
|
672 public void close() throws IOException {
|
|
673 in.close();
|
|
674 }
|
|
675
|
|
676 @Override
|
|
677 public int getReadByteCount() {
|
|
678 return in.getReadByteCount();
|
|
679 }
|
|
680
|
|
681 @Override
|
|
682 public void resetReadByteCount() {
|
|
683 in.resetReadByteCount();
|
|
684 }
|
4
|
685
|
7
|
686 public byte[] getSerializedByteArray(int len) {
|
6
|
687 byte[] b = new byte[len];
|
7
|
688 try {
|
|
689 in.read(b, 0, b.length);
|
|
690 } catch (IOException e) {
|
|
691 e.printStackTrace();
|
|
692 }
|
6
|
693 return b;
|
1
|
694 }
|
0
|
695 }
|