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.math.BigInteger;
|
|
23
|
|
24 import org.msgpack.MessagePack;
|
|
25 import org.msgpack.MessageTypeException;
|
|
26 import org.msgpack.packer.Unconverter;
|
|
27 import org.msgpack.type.Value;
|
|
28 import org.msgpack.type.ValueType;
|
|
29 import org.msgpack.type.ArrayValue;
|
|
30 import org.msgpack.type.MapValue;
|
|
31
|
|
32 public class Converter extends AbstractUnpacker {
|
|
33 private final UnpackerStack stack;
|
|
34 private Object[] values;
|
|
35 protected Value value;
|
|
36
|
|
37 public Converter(Value value) {
|
|
38 this(new MessagePack(), value);
|
|
39 }
|
|
40
|
|
41 public Converter(MessagePack msgpack, Value value) {
|
|
42 super(msgpack);
|
|
43 this.stack = new UnpackerStack();
|
|
44 this.values = new Object[UnpackerStack.MAX_STACK_SIZE];
|
|
45 this.value = value;
|
|
46 }
|
|
47
|
|
48 protected Value nextValue() throws IOException {
|
|
49 throw new EOFException();
|
|
50 }
|
|
51
|
|
52 private void ensureValue() throws IOException {
|
|
53 if (value == null) {
|
|
54 value = nextValue();
|
|
55 }
|
|
56 }
|
|
57
|
|
58 @Override
|
|
59 public boolean tryReadNil() throws IOException {
|
|
60 stack.checkCount();
|
|
61 if (getTop().isNilValue()) {
|
|
62 stack.reduceCount();
|
|
63 if (stack.getDepth() == 0) {
|
|
64 value = null;
|
|
65 }
|
|
66 return true;
|
|
67 }
|
|
68 return false;
|
|
69 }
|
|
70
|
|
71 @Override
|
|
72 public boolean trySkipNil() throws IOException {
|
|
73 ensureValue();
|
|
74
|
|
75 if (stack.getDepth() > 0 && stack.getTopCount() <= 0) {
|
|
76 // end of array or map
|
|
77 return true;
|
|
78 }
|
|
79
|
|
80 if (getTop().isNilValue()) {
|
|
81 stack.reduceCount();
|
|
82 if (stack.getDepth() == 0) {
|
|
83 value = null;
|
|
84 }
|
|
85 return true;
|
|
86 }
|
|
87 return false;
|
|
88 }
|
|
89
|
|
90 @Override
|
|
91 public void readNil() throws IOException {
|
|
92 if (!getTop().isNilValue()) {
|
|
93 throw new MessageTypeException("Expected nil but got not nil value");
|
|
94 }
|
|
95 stack.reduceCount();
|
|
96 if (stack.getDepth() == 0) {
|
|
97 value = null;
|
|
98 }
|
|
99 }
|
|
100
|
|
101 @Override
|
|
102 public boolean readBoolean() throws IOException {
|
|
103 boolean v = getTop().asBooleanValue().getBoolean();
|
|
104 stack.reduceCount();
|
|
105 return v;
|
|
106 }
|
|
107
|
|
108 @Override
|
|
109 public byte readByte() throws IOException {
|
|
110 byte v = getTop().asIntegerValue().getByte();
|
|
111 stack.reduceCount();
|
|
112 if (stack.getDepth() == 0) {
|
|
113 value = null;
|
|
114 }
|
|
115 return v;
|
|
116 }
|
|
117
|
|
118 @Override
|
|
119 public short readShort() throws IOException {
|
|
120 short v = getTop().asIntegerValue().getShort();
|
|
121 stack.reduceCount();
|
|
122 if (stack.getDepth() == 0) {
|
|
123 value = null;
|
|
124 }
|
|
125 return v;
|
|
126 }
|
|
127
|
|
128 @Override
|
|
129 public int readInt() throws IOException {
|
|
130 int v = getTop().asIntegerValue().getInt();
|
|
131 stack.reduceCount();
|
|
132 if (stack.getDepth() == 0) {
|
|
133 value = null;
|
|
134 }
|
|
135 return v;
|
|
136 }
|
|
137
|
|
138 @Override
|
|
139 public long readLong() throws IOException {
|
|
140 long v = getTop().asIntegerValue().getLong();
|
|
141 stack.reduceCount();
|
|
142 if (stack.getDepth() == 0) {
|
|
143 value = null;
|
|
144 }
|
|
145 return v;
|
|
146 }
|
|
147
|
|
148 @Override
|
|
149 public BigInteger readBigInteger() throws IOException {
|
|
150 BigInteger v = getTop().asIntegerValue().getBigInteger();
|
|
151 stack.reduceCount();
|
|
152 if (stack.getDepth() == 0) {
|
|
153 value = null;
|
|
154 }
|
|
155 return v;
|
|
156 }
|
|
157
|
|
158 @Override
|
|
159 public float readFloat() throws IOException {
|
|
160 float v = getTop().asFloatValue().getFloat();
|
|
161 stack.reduceCount();
|
|
162 if (stack.getDepth() == 0) {
|
|
163 value = null;
|
|
164 }
|
|
165 return v;
|
|
166 }
|
|
167
|
|
168 @Override
|
|
169 public double readDouble() throws IOException {
|
|
170 double v = getTop().asFloatValue().getDouble();
|
|
171 stack.reduceCount();
|
|
172 if (stack.getDepth() == 0) {
|
|
173 value = null;
|
|
174 }
|
|
175 return v;
|
|
176 }
|
|
177
|
|
178 @Override
|
|
179 public byte[] readByteArray() throws IOException {
|
|
180 byte[] raw = getTop().asRawValue().getByteArray();
|
|
181 stack.reduceCount();
|
|
182 if (stack.getDepth() == 0) {
|
|
183 value = null;
|
|
184 }
|
|
185 return raw;
|
|
186 }
|
|
187
|
|
188 @Override
|
|
189 public String readString() throws IOException {
|
|
190 String str = getTop().asRawValue().getString();
|
|
191 stack.reduceCount();
|
|
192 if (stack.getDepth() == 0) {
|
|
193 value = null;
|
|
194 }
|
|
195 return str;
|
|
196 }
|
|
197
|
|
198 @Override
|
|
199 public int readArrayBegin() throws IOException {
|
|
200 Value v = getTop();
|
|
201 if (!v.isArrayValue()) {
|
|
202 throw new MessageTypeException(
|
|
203 "Expected array but got not array value");
|
|
204 }
|
|
205 ArrayValue a = v.asArrayValue();
|
|
206 stack.reduceCount();
|
|
207 stack.pushArray(a.size());
|
|
208 values[stack.getDepth()] = a.getElementArray();
|
|
209 return a.size();
|
|
210 }
|
|
211
|
|
212 @Override
|
|
213 public void readArrayEnd(boolean check) throws IOException {
|
|
214 if (!stack.topIsArray()) {
|
|
215 throw new MessageTypeException(
|
|
216 "readArrayEnd() is called but readArrayBegin() is not called");
|
|
217 }
|
|
218
|
|
219 int remain = stack.getTopCount();
|
|
220 if (remain > 0) {
|
|
221 if (check) {
|
|
222 throw new MessageTypeException(
|
|
223 "readArrayEnd(check=true) is called but the array is not end");
|
|
224 }
|
|
225 for (int i = 0; i < remain; i++) {
|
|
226 skip();
|
|
227 }
|
|
228 }
|
|
229 stack.pop();
|
|
230
|
|
231 if (stack.getDepth() == 0) {
|
|
232 value = null;
|
|
233 }
|
|
234 }
|
|
235
|
|
236 @Override
|
|
237 public int readMapBegin() throws IOException {
|
|
238 Value v = getTop();
|
|
239 if (!v.isMapValue()) {
|
|
240 throw new MessageTypeException("Expected map but got not map value");
|
|
241 }
|
|
242 MapValue m = v.asMapValue();
|
|
243 stack.reduceCount();
|
|
244 stack.pushMap(m.size());
|
|
245 values[stack.getDepth()] = m.getKeyValueArray();
|
|
246 return m.size();
|
|
247 }
|
|
248
|
|
249 @Override
|
|
250 public void readMapEnd(boolean check) throws IOException {
|
|
251 if (!stack.topIsMap()) {
|
|
252 throw new MessageTypeException(
|
|
253 "readMapEnd() is called but readMapBegin() is not called");
|
|
254 }
|
|
255
|
|
256 int remain = stack.getTopCount();
|
|
257 if (remain > 0) {
|
|
258 if (check) {
|
|
259 throw new MessageTypeException(
|
|
260 "readMapEnd(check=true) is called but the map is not end");
|
|
261 }
|
|
262 for (int i = 0; i < remain; i++) {
|
|
263 skip();
|
|
264 }
|
|
265 }
|
|
266 stack.pop();
|
|
267
|
|
268 if (stack.getDepth() == 0) {
|
|
269 value = null;
|
|
270 }
|
|
271 }
|
|
272
|
|
273 private Value getTop() throws IOException {
|
|
274 ensureValue();
|
|
275
|
|
276 stack.checkCount();
|
|
277 if (stack.getDepth() == 0) {
|
|
278 // if(stack.getTopCount() < 0) {
|
|
279 // //throw new EOFException(); // TODO
|
|
280 // throw new RuntimeException(new EOFException());
|
|
281 // }
|
|
282 return value;
|
|
283 }
|
|
284 Value[] array = (Value[]) values[stack.getDepth()];
|
|
285 return array[array.length - stack.getTopCount()];
|
|
286 }
|
|
287
|
|
288 @Override
|
|
289 public Value readValue() throws IOException {
|
|
290 if (stack.getDepth() == 0) {
|
|
291 if (value == null) {
|
|
292 return nextValue();
|
|
293 } else {
|
|
294 Value v = value;
|
|
295 value = null;
|
|
296 return v;
|
|
297 }
|
|
298 }
|
|
299 return super.readValue();
|
|
300 }
|
|
301
|
|
302 @Override
|
|
303 protected void readValue(Unconverter uc) throws IOException {
|
|
304 if (uc.getResult() != null) {
|
|
305 uc.resetResult();
|
|
306 }
|
|
307
|
|
308 stack.checkCount();
|
|
309 Value v = getTop();
|
|
310 if (!v.isArrayValue() && !v.isMapValue()) {
|
|
311 uc.write(v);
|
|
312 stack.reduceCount();
|
|
313 if (stack.getDepth() == 0) {
|
|
314 value = null;
|
|
315 }
|
|
316 if (uc.getResult() != null) {
|
|
317 return;
|
|
318 }
|
|
319 }
|
|
320
|
|
321 while (true) {
|
|
322 while (stack.getDepth() != 0 && stack.getTopCount() == 0) {
|
|
323 if (stack.topIsArray()) {
|
|
324 uc.writeArrayEnd(true);
|
|
325 stack.pop();
|
|
326 } else if (stack.topIsMap()) {
|
|
327 uc.writeMapEnd(true);
|
|
328 stack.pop();
|
|
329 } else {
|
|
330 throw new RuntimeException("invalid stack"); // FIXME error?
|
|
331 }
|
|
332 if (stack.getDepth() == 0) {
|
|
333 value = null;
|
|
334 }
|
|
335 if (uc.getResult() != null) {
|
|
336 return;
|
|
337 }
|
|
338 }
|
|
339
|
|
340 stack.checkCount();
|
|
341 v = getTop();
|
|
342 if (v.isArrayValue()) {
|
|
343 ArrayValue a = v.asArrayValue();
|
|
344 uc.writeArrayBegin(a.size());
|
|
345 stack.reduceCount();
|
|
346 stack.pushArray(a.size());
|
|
347 values[stack.getDepth()] = a.getElementArray();
|
|
348
|
|
349 } else if (v.isMapValue()) {
|
|
350 MapValue m = v.asMapValue();
|
|
351 uc.writeMapBegin(m.size());
|
|
352 stack.reduceCount();
|
|
353 stack.pushMap(m.size());
|
|
354 values[stack.getDepth()] = m.getKeyValueArray();
|
|
355
|
|
356 } else {
|
|
357 uc.write(v);
|
|
358 stack.reduceCount();
|
|
359 }
|
|
360 }
|
|
361 }
|
|
362
|
|
363 @Override
|
|
364 public void skip() throws IOException {
|
|
365 stack.checkCount();
|
|
366 Value v = getTop();
|
|
367 if (!v.isArrayValue() && !v.isMapValue()) {
|
|
368 stack.reduceCount();
|
|
369 if (stack.getDepth() == 0) {
|
|
370 value = null;
|
|
371 }
|
|
372 return;
|
|
373 }
|
|
374 int targetDepth = stack.getDepth();
|
|
375 while (true) {
|
|
376 while (stack.getTopCount() == 0) {
|
|
377 stack.pop();
|
|
378 if (stack.getDepth() == 0) {
|
|
379 value = null;
|
|
380 }
|
|
381 if (stack.getDepth() <= targetDepth) {
|
|
382 return;
|
|
383 }
|
|
384 }
|
|
385
|
|
386 stack.checkCount();
|
|
387 v = getTop();
|
|
388 if (v.isArrayValue()) {
|
|
389 ArrayValue a = v.asArrayValue();
|
|
390 stack.reduceCount();
|
|
391 stack.pushArray(a.size());
|
|
392 values[stack.getDepth()] = a.getElementArray();
|
|
393
|
|
394 } else if (v.isMapValue()) {
|
|
395 MapValue m = v.asMapValue();
|
|
396 stack.reduceCount();
|
|
397 stack.pushMap(m.size());
|
|
398 values[stack.getDepth()] = m.getKeyValueArray();
|
|
399
|
|
400 } else {
|
|
401 stack.reduceCount();
|
|
402 }
|
|
403 }
|
|
404 }
|
|
405
|
|
406 public ValueType getNextType() throws IOException {
|
|
407 return getTop().getType();
|
|
408 }
|
|
409
|
|
410 public void reset() {
|
|
411 stack.clear();
|
|
412 value = null;
|
|
413 }
|
|
414
|
|
415 @Override
|
|
416 public void close() throws IOException {
|
|
417 }
|
|
418
|
|
419 @Override
|
|
420 public int getReadByteCount() {
|
|
421 throw new UnsupportedOperationException("Not implemented yet");
|
|
422 }
|
|
423
|
|
424 @Override
|
|
425 public void setRawSizeLimit(int size) {
|
|
426 throw new UnsupportedOperationException("Not implemented yet");
|
|
427 }
|
|
428
|
|
429 @Override
|
|
430 public void setArraySizeLimit(int size) {
|
|
431 throw new UnsupportedOperationException("Not implemented yet");
|
|
432 }
|
|
433
|
|
434 @Override
|
|
435 public void setMapSizeLimit(int size) {
|
|
436 throw new UnsupportedOperationException("Not implemented yet");
|
|
437 }
|
7
|
438
|
|
439 @Override
|
|
440 public byte[] getSerializedByteArray(int len) {
|
|
441 throw new UnsupportedOperationException("Not implemented yet");
|
|
442 }
|
0
|
443 }
|