view src/main/java/org/msgpack/packer/Unconverter.java @ 0:cb825acd883a

first commit
author sugi
date Sat, 18 Oct 2014 15:06:15 +0900
parents
children
line wrap: on
line source

//
// MessagePack for Java
//
// Copyright (C) 2009 - 2013 FURUHASHI Sadayuki
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//
package org.msgpack.packer;

import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;

import org.msgpack.MessagePack;
import org.msgpack.MessageTypeException;
import org.msgpack.type.Value;
import org.msgpack.type.ValueFactory;

public class Unconverter extends AbstractPacker {
    private PackerStack stack;
    private Object[] values;
    private Value result;

    // private Value topContainer;

    public Unconverter() {
        this(new MessagePack());
    }

    public Unconverter(MessagePack msgpack) {
        super(msgpack);
        this.stack = new PackerStack();
        this.values = new Object[PackerStack.MAX_STACK_SIZE];
    }

    public Value getResult() {
        return result;
    }

    public void resetResult() {
        this.result = null;
    }

    @Override
    public void writeBoolean(boolean v) throws IOException {
        put(ValueFactory.createBooleanValue(v));
    }

    @Override
    public void writeByte(byte v) throws IOException {
        put(ValueFactory.createIntegerValue(v));
    }

    @Override
    public void writeShort(short v) throws IOException {
        put(ValueFactory.createIntegerValue(v));
    }

    @Override
    public void writeInt(int v) throws IOException {
        put(ValueFactory.createIntegerValue(v));
    }

    @Override
    public void writeBigInteger(BigInteger v) throws IOException {
        put(ValueFactory.createIntegerValue(v));
    }

    @Override
    public void writeLong(long v) throws IOException {
        put(ValueFactory.createIntegerValue(v));
    }

    @Override
    public void writeFloat(float v) throws IOException {
        put(ValueFactory.createFloatValue(v));
    }

    @Override
    public void writeDouble(double v) throws IOException {
        put(ValueFactory.createFloatValue(v));
    }

    @Override
    public void writeByteArray(byte[] b, int off, int len) throws IOException {
        put(ValueFactory.createRawValue(b, off, len));
    }

    @Override
    public void writeByteBuffer(ByteBuffer bb) throws IOException {
        put(ValueFactory.createRawValue(bb));
    }

    @Override
    public void writeString(String s) throws IOException {
        put(ValueFactory.createRawValue(s));
    }

    @Override
    public Packer writeNil() throws IOException {
        put(ValueFactory.createNilValue());
        return this;
    }

    @Override
    public Packer writeArrayBegin(int size) throws IOException {
        if (size == 0) {
            // Value[] array = new Value[size];
            putContainer(ValueFactory.createArrayValue());
            stack.pushArray(0);
            values[stack.getDepth()] = null;
        } else {
            Value[] array = new Value[size];
            putContainer(ValueFactory.createArrayValue(array, true));
            stack.pushArray(size);
            values[stack.getDepth()] = array;
        }
        return this;
    }

    @Override
    public Packer writeArrayEnd(boolean check) throws IOException {
        if (!stack.topIsArray()) {
            throw new MessageTypeException(
                    "writeArrayEnd() is called but writeArrayBegin() is not called");
        }

        int remain = stack.getTopCount();
        if (remain > 0) {
            if (check) {
                throw new MessageTypeException(
                        "writeArrayEnd(check=true) is called but the array is not end");
            }
            for (int i = 0; i < remain; i++) {
                writeNil();
            }
        }
        stack.pop();
        if (stack.getDepth() <= 0) {
            this.result = (Value) values[0];
        }
        return this;
    }

    @Override
    public Packer writeMapBegin(int size) throws IOException {
        stack.checkCount();
        if (size == 0) {
            putContainer(ValueFactory.createMapValue());
            stack.pushMap(0);
            values[stack.getDepth()] = null;
        } else {
            Value[] array = new Value[size * 2];
            putContainer(ValueFactory.createMapValue(array, true));
            stack.pushMap(size);
            values[stack.getDepth()] = array;
        }
        return this;
    }

    @Override
    public Packer writeMapEnd(boolean check) throws IOException {
        if (!stack.topIsMap()) {
            throw new MessageTypeException(
                    "writeMapEnd() is called but writeMapBegin() is not called");
        }

        int remain = stack.getTopCount();
        if (remain > 0) {
            if (check) {
                throw new MessageTypeException(
                        "writeMapEnd(check=true) is called but the map is not end");
            }
            for (int i = 0; i < remain; i++) {
                writeNil();
            }
        }
        stack.pop();
        if (stack.getDepth() <= 0) {
            this.result = (Value) values[0];
        }
        return this;
    }

    @Override
    public Packer write(Value v) throws IOException {
        put(v);
        return this;
    }

    private void put(Value v) {
        if (stack.getDepth() <= 0) {
            this.result = v;
        } else {
            stack.checkCount();
            Value[] array = (Value[]) values[stack.getDepth()];
            array[array.length - stack.getTopCount()] = v;
            stack.reduceCount();
        }
    }

    private void putContainer(Value v) {
        if (stack.getDepth() <= 0) {
            values[0] = (Object) v;
        } else {
            stack.checkCount();
            Value[] array = (Value[]) values[stack.getDepth()];
            array[array.length - stack.getTopCount()] = v;
            stack.reduceCount();
        }
    }

    @Override
    public void flush() throws IOException {
    }

    @Override
    public void close() throws IOException {
    }
}