Package org.msgpack.packer

Source Code of org.msgpack.packer.MessagePackPacker

//
// MessagePack for Java
//
// Copyright (C) 2009-2011 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.io.UnsupportedEncodingException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.math.BigInteger;
import org.msgpack.io.Output;
import org.msgpack.io.StreamOutput;
import org.msgpack.MessagePack;
import org.msgpack.MessageTypeException;


public class MessagePackPacker extends AbstractPacker {
    protected final Output out;

    private PackerStack stack = new PackerStack();

    public MessagePackPacker(OutputStream stream) {
        this(new MessagePack(), stream);
    }

    public MessagePackPacker(MessagePack msgpack, OutputStream stream) {
        this(msgpack, new StreamOutput(stream));
    }

    protected MessagePackPacker(MessagePack msgpack, Output out) {
        super(msgpack);
        this.out = out;
    }

    @Override
    public void writeByte(byte d) throws IOException {
        if(d < -(1<<5)) {
            out.writeByteAndByte((byte)0xd0, d);
        } else {
            out.writeByte(d);
        }
        stack.reduceCount();
    }

    @Override
    public void writeShort(short d) throws IOException {
        if(d < -(1<<5)) {
            if(d < -(1<<7)) {
                // signed 16
                out.writeByteAndShort((byte)0xd1, d);
            } else {
                // signed 8
                out.writeByteAndByte((byte)0xd0, (byte)d);
            }
        } else if(d < (1<<7)) {
            // fixnum
            out.writeByte((byte)d);
        } else {
            if(d < (1<<8)) {
                // unsigned 8
                out.writeByteAndByte((byte)0xcc, (byte)d);
            } else {
                // unsigned 16
                out.writeByteAndShort((byte)0xcd, d);
            }
        }
        stack.reduceCount();
    }

    @Override
    public void writeInt(int d) throws IOException {
        if(d < -(1<<5)) {
            if(d < -(1<<15)) {
                // signed 32
                out.writeByteAndInt((byte)0xd2, d);
            } else if(d < -(1<<7)) {
                // signed 16
                out.writeByteAndShort((byte)0xd1, (short)d);
            } else {
                // signed 8
                out.writeByteAndByte((byte)0xd0, (byte)d);
            }
        } else if(d < (1<<7)) {
            // fixnum
            out.writeByte((byte)d);
        } else {
            if(d < (1<<8)) {
                // unsigned 8
                out.writeByteAndByte((byte)0xcc, (byte)d);
            } else if(d < (1<<16)) {
                // unsigned 16
                out.writeByteAndShort((byte)0xcd, (short)d);
            } else {
                // unsigned 32
                out.writeByteAndInt((byte)0xce, d);
            }
        }
        stack.reduceCount();
    }

    @Override
    public void writeLong(long d) throws IOException {
        if(d < -(1L<<5)) {
            if(d < -(1L<<15)) {
                if(d < -(1L<<31)) {
                    // signed 64
                    out.writeByteAndLong((byte)0xd3, d);
                } else {
                    // signed 32
                    out.writeByteAndInt((byte)0xd2, (int)d);
                }
            } else {
                if(d < -(1<<7)) {
                    // signed 16
                    out.writeByteAndShort((byte)0xd1, (short)d);
                } else {
                    // signed 8
                    out.writeByteAndByte((byte)0xd0, (byte)d);
                }
            }
        } else if(d < (1<<7)) {
            // fixnum
            out.writeByte((byte)d);
        } else {
            if(d < (1L<<16)) {
                if(d < (1<<8)) {
                    // unsigned 8
                    out.writeByteAndByte((byte)0xcc, (byte)d);
                } else {
                    // unsigned 16
                    out.writeByteAndShort((byte)0xcd, (short)d);
                }
            } else {
                if(d < (1L<<32)) {
                    // unsigned 32
                    out.writeByteAndInt((byte)0xce, (int)d);
                } else {
                    // unsigned 64
                    out.writeByteAndLong((byte)0xcf, d);
                }
            }
        }
        stack.reduceCount();
    }

    @Override
    public void writeBigInteger(BigInteger d) throws IOException {
        if(d.bitLength() <= 63) {
            writeLong(d.longValue());
            stack.reduceCount();
        } else if(d.bitLength() == 64 && d.signum() == 1) {
            // unsigned 64
            out.writeByteAndLong((byte)0xcf, d.longValue());
            stack.reduceCount();
        } else {
            throw new MessageTypeException("MessagePack can't serialize BigInteger larger than (2^64)-1");
        }
    }

    @Override
    public void writeFloat(float d) throws IOException {
        out.writeByteAndFloat((byte)0xca, d);
        stack.reduceCount();
    }

    @Override
    public void writeDouble(double d) throws IOException {
        out.writeByteAndDouble((byte)0xcb, d);
        stack.reduceCount();
    }

    @Override
    public void writeNil() throws IOException {
        out.writeByte((byte)0xc0);
        stack.reduceCount();
    }

    @Override
    public void writeBoolean(boolean d) throws IOException {
        if(d) {
            // true
            out.writeByte((byte)0xc3);
        } else {
            // false
            out.writeByte((byte)0xc2);
        }
        stack.reduceCount();
    }

    @Override
    public void writeByteArray(byte[] b, int off, int len) throws IOException {
        if(len < 32) {
            out.writeByte((byte)(0xa0 | len));
        } else if(len < 65536) {
            out.writeByteAndShort((byte)0xda, (short)len);
        } else {
            out.writeByteAndInt((byte)0xdb, len);
        }
        out.write(b, off, len);
        stack.reduceCount();
    }

    @Override
    public void writeByteBuffer(ByteBuffer bb) throws IOException {
        int len = bb.remaining();
        if(len < 32) {
            out.writeByte((byte)(0xa0 | len));
        } else if(len < 65536) {
            out.writeByteAndShort((byte)0xda, (short)len);
        } else {
            out.writeByteAndInt((byte)0xdb, len);
        }
        int pos = bb.position();
        try {
            out.write(bb);
        } finally {
            bb.position(pos);
        }
        stack.reduceCount();
    }

    @Override
    public void writeString(String s) throws IOException {
        // TODO encoding error
        byte[] b;
        try {
            b = s.getBytes("UTF-8");
        } catch (UnsupportedEncodingException ex) {
            throw new MessageTypeException();
        }
        writeByteArray(b, 0, b.length);
        stack.reduceCount();
    }

    @Override
    public void writeArrayBegin(int size) throws IOException {
        // TODO check size < 0?
        if(size < 16) {
            // FixArray
            out.writeByte((byte)(0x90 | size));
        } else if(size < 65536) {
            out.writeByteAndShort((byte)0xdc, (short)size);
        } else {
            out.writeByteAndInt((byte)0xdd, size);
        }
        stack.reduceCount();
        stack.pushArray(size);
    }

    @Override
    public void 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: "+remain);
            }
            for(int i=0; i < remain; i++) {
                writeNil();
            }
        }
        stack.pop();
    }

    @Override
    public void writeMapBegin(int size) throws IOException {
        // TODO check size < 0?
        if(size < 16) {
            // FixMap
            out.writeByte((byte)(0x80 | size));
        } else if(size < 65536) {
            out.writeByteAndShort((byte)0xde, (short)size);
        } else {
            out.writeByteAndInt((byte)0xdf, size);
        }
        stack.reduceCount();
        stack.pushMap(size);
    }

    @Override
    public void 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: "+remain);
            }
            for(int i=0; i < remain; i++) {
                writeNil();
            }
        }
        stack.pop();
    }

    public void close() throws IOException {
        out.close();
    }
}
TOP

Related Classes of org.msgpack.packer.MessagePackPacker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.