import java.io.*; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.math.BigInteger; public class Packer { protected byte[] castBytes = new byte[9]; protected ByteBuffer castBuffer = ByteBuffer.wrap(castBytes); protected OutputStream out; public Packer(OutputStream out) { this.out = out; } public Packer packByte(byte d) throws IOException { if(d < -(1<<5)) { castBytes[0] = (byte)0xd1; castBytes[1] = d; out.write(castBytes, 0, 2); } else { out.write(d); } return this; } public Packer packShort(short d) throws IOException { if(d < -(1<<5)) { if(d < -(1<<7)) { // signed 16 castBytes[0] = (byte)0xd1; castBuffer.putShort(1, d); out.write(castBytes, 0, 3); } else { // signed 8 castBytes[0] = (byte)0xd0; castBytes[1] = (byte)d; out.write(castBytes, 0, 2); } } else if(d < (1<<7)) { // fixnum out.write((byte)d); } else { if(d < (1<<8)) { // unsigned 8 castBytes[0] = (byte)0xcc; castBytes[1] = (byte)d; out.write(castBytes, 0, 2); } else { // unsigned 16 castBytes[0] = (byte)0xcd; castBuffer.putShort(1, d); out.write(castBytes, 0, 3); } } return this; } public Packer packInt(int d) throws IOException { if(d < -(1<<5)) { if(d < -(1<<15)) { // signed 32 castBytes[0] = (byte)0xd2; castBuffer.putInt(1, d); out.write(castBytes, 0, 5); } else if(d < -(1<<7)) { // signed 16 castBytes[0] = (byte)0xd1; castBuffer.putShort(1, (short)d); out.write(castBytes, 0, 3); } else { // signed 8 castBytes[0] = (byte)0xd0; castBytes[1] = (byte)d; out.write(castBytes, 0, 2); } } else if(d < (1<<7)) { // fixnum out.write((byte)d); } else { if(d < (1<<8)) { // unsigned 8 castBytes[0] = (byte)0xcc; castBytes[1] = (byte)d; out.write(castBytes, 0, 2); } else if(d < (1<<16)) { // unsigned 16 castBytes[0] = (byte)0xcd; castBuffer.putShort(1, (short)d); out.write(castBytes, 0, 3); } else { // unsigned 32 castBytes[0] = (byte)0xce; castBuffer.putInt(1, d); out.write(castBytes, 0, 5); } } return this; } public Packer packLong(long d) throws IOException { if(d < -(1L<<5)) { if(d < -(1L<<15)) { if(d < -(1L<<31)) { // signed 64 castBytes[0] = (byte)0xd3; castBuffer.putLong(1, d); out.write(castBytes, 0, 9); } else { // signed 32 castBytes[0] = (byte)0xd2; castBuffer.putInt(1, (int)d); out.write(castBytes, 0, 5); } } else { if(d < -(1<<7)) { // signed 16 castBytes[0] = (byte)0xd1; castBuffer.putShort(1, (short)d); out.write(castBytes, 0, 3); } else { // signed 8 castBytes[0] = (byte)0xd0; castBytes[1] = (byte)d; out.write(castBytes, 0, 2); } } } else if(d < (1<<7)) { // fixnum out.write((byte)d); } else { if(d < (1L<<16)) { if(d < (1<<8)) { // unsigned 8 castBytes[0] = (byte)0xcc; castBytes[1] = (byte)d; out.write(castBytes, 0, 2); } else { // unsigned 16 castBytes[0] = (byte)0xcd; castBuffer.putShort(1, (short)d); out.write(castBytes, 0, 3); //System.out.println("pack uint 16 "+(short)d); } } else { if(d < (1L<<32)) { // unsigned 32 castBytes[0] = (byte)0xce; castBuffer.putInt(1, (int)d); out.write(castBytes, 0, 5); } else { // unsigned 64 castBytes[0] = (byte)0xcf; castBuffer.putLong(1, d); out.write(castBytes, 0, 9); } } } return this; } public Packer packFloat(float d) throws IOException { castBytes[0] = (byte)0xca; castBuffer.putFloat(1, d); out.write(castBytes, 0, 5); return this; } public Packer packDouble(double d) throws IOException { castBytes[0] = (byte)0xcb; castBuffer.putDouble(1, d); out.write(castBytes, 0, 9); return this; } public Packer packNil() throws IOException { out.write((byte)0xc0); return this; } public Packer packTrue() throws IOException { out.write((byte)0xc3); return this; } public Packer packFalse() throws IOException { out.write((byte)0xc2); return this; } public Packer packArray(int n) throws IOException { if(n < 16) { final int d = 0x90 | n; out.write((byte)d); } else if(n < 65536) { castBytes[0] = (byte)0xdc; castBuffer.putShort(1, (short)n); out.write(castBytes, 0, 3); } else { castBytes[0] = (byte)0xdd; castBuffer.putInt(1, n); out.write(castBytes, 0, 5); } return this; } public Packer packMap(int n) throws IOException { if(n < 16) { final int d = 0x80 | n; out.write((byte)d); } else if(n < 65536) { castBytes[0] = (byte)0xde; castBuffer.putShort(1, (short)n); out.write(castBytes, 0, 3); } else { castBytes[0] = (byte)0xdf; castBuffer.putInt(1, n); out.write(castBytes, 0, 5); } return this; } public Packer packRaw(int n) throws IOException { if(n < 32) { final int d = 0xa0 | n; out.write((byte)d); } else if(n < 65536) { castBytes[0] = (byte)0xda; castBuffer.putShort(1, (short)n); out.write(castBytes, 0, 3); } else { castBytes[0] = (byte)0xdb; castBuffer.putInt(1, n); out.write(castBytes, 0, 5); } return this; } public Packer packRawBody(byte[] b) throws IOException { out.write(b); return this; } public Packer packRawBody(byte[] b, int off, int length) throws IOException { out.write(b, off, length); return this; } //public Packer pack(Object o) throws IOException }