diff options
Diffstat (limited to 'java/src')
51 files changed, 3049 insertions, 2811 deletions
diff --git a/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java b/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java new file mode 100644 index 0000000..5b449c7 --- /dev/null +++ b/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java @@ -0,0 +1,445 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.math.BigInteger; + +abstract class BufferedUnpackerImpl extends UnpackerImpl { + int offset = 0; + int filled = 0; + byte[] buffer = null; + private ByteBuffer castBuffer = ByteBuffer.allocate(8); + + abstract boolean fill() throws IOException; + + final boolean next(UnpackResult result) throws IOException, UnpackException { + if(filled == 0) { + if(!fill()) { + return false; + } + } + + do { + int noffset = super.execute(buffer, offset, filled); + if(noffset <= offset) { + if(!fill()) { + return false; + } + continue; + } + offset = noffset; + } while(!super.isFinished()); + + MessagePackObject obj = super.getData(); + super.reset(); + result.done(obj); + + return true; + } + + private final void more(int require) throws IOException, UnpackException { + while(filled - offset < require) { + if(!fill()) { + // FIXME + throw new UnpackException("insufficient buffer"); + } + } + } + + private final boolean tryMore(int require) throws IOException, UnpackException { + while(filled - offset < require) { + if(!fill()) { + return false; + } + } + return true; + } + + private final void advance(int length) { + offset += length; + } + + final byte unpackByte() throws IOException, MessageTypeException { + int o = unpackInt(); + if(0x7f < o || o < -0x80) { + throw new MessageTypeException(); + } + return (byte)o; + } + + final short unpackShort() throws IOException, MessageTypeException { + int o = unpackInt(); + if(0x7fff < o || o < -0x8000) { + throw new MessageTypeException(); + } + return (short)o; + } + + final int unpackInt() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset]; + if((b & 0x80) == 0 || (b & 0xe0) == 0xe0) { // Fixnum + advance(1); + return (int)b; + } + switch(b & 0xff) { + case 0xcc: // unsigned int 8 + more(2); + advance(2); + return (int)((short)(buffer[offset-1]) & 0xff); + case 0xcd: // unsigned int 16 + more(3); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 2); + advance(3); + return (int)((int)castBuffer.getShort(0) & 0xffff); + case 0xce: // unsigned int 32 + more(5); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 4); + { + int o = castBuffer.getInt(0); + if(o < 0) { + throw new MessageTypeException(); + } + advance(5); + return o; + } + case 0xcf: // unsigned int 64 + more(9); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 8); + { + long o = castBuffer.getLong(0); + if(o < 0 || o > 0x7fffffffL) { + throw new MessageTypeException(); + } + advance(9); + return (int)o; + } + case 0xd0: // signed int 8 + more(2); + advance(2); + return (int)buffer[offset-1]; + case 0xd1: // signed int 16 + more(3); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 2); + advance(3); + return (int)castBuffer.getShort(0); + case 0xd2: // signed int 32 + more(4); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 4); + advance(4); + return (int)castBuffer.getInt(0); + case 0xd3: // signed int 64 + more(9); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 8); + { + long o = castBuffer.getLong(0); + if(0x7fffffffL < o || o < -0x80000000L) { + throw new MessageTypeException(); + } + advance(9); + return (int)o; + } + default: + throw new MessageTypeException(); + } + } + + final long unpackLong() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset]; + if((b & 0x80) == 0 || (b & 0xe0) == 0xe0) { // Fixnum + advance(1); + return (long)b; + } + switch(b & 0xff) { + case 0xcc: // unsigned int 8 + more(2); + advance(2); + return (long)((short)(buffer[offset-1]) & 0xff); + case 0xcd: // unsigned int 16 + more(3); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 2); + advance(3); + return (long)((int)castBuffer.getShort(0) & 0xffff); + case 0xce: // unsigned int 32 + more(5); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 4); + advance(5); + return ((long)castBuffer.getInt(0) & 0xffffffffL); + case 0xcf: // unsigned int 64 + more(9); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 8); + { + long o = castBuffer.getLong(0); + if(o < 0) { + throw new MessageTypeException(); + } + advance(9); + return o; + } + case 0xd0: // signed int 8 + more(2); + advance(2); + return (long)buffer[offset-1]; + case 0xd1: // signed int 16 + more(3); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 2); + advance(3); + return (long)castBuffer.getShort(0); + case 0xd2: // signed int 32 + more(4); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 4); + advance(4); + return (long)castBuffer.getInt(0); + case 0xd3: // signed int 64 + more(9); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 8); + advance(9); + return (long)castBuffer.getLong(0); + default: + throw new MessageTypeException(); + } + } + + final BigInteger unpackBigInteger() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset]; + if((b & 0xff) != 0xcf) { + return BigInteger.valueOf(unpackLong()); + } + + // unsigned int 64 + more(9); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 8); + advance(9); + long o = castBuffer.getLong(0); + if(o < 0) { + return new BigInteger(1, castBuffer.array()); + } else { + return BigInteger.valueOf(o); + } + } + + final float unpackFloat() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset]; + switch(b & 0xff) { + case 0xca: // float + more(5); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 4); + advance(5); + return castBuffer.getFloat(0); + case 0xcb: // double + more(9); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 8); + advance(9); + // FIXME overflow check + return (float)castBuffer.getDouble(0); + default: + throw new MessageTypeException(); + } + } + + final double unpackDouble() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset]; + switch(b & 0xff) { + case 0xca: // float + more(5); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 4); + advance(5); + return (double)castBuffer.getFloat(0); + case 0xcb: // double + more(9); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 8); + advance(9); + return castBuffer.getDouble(0); + default: + throw new MessageTypeException(); + } + } + + final Object unpackNull() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset] & 0xff; + if(b != 0xc0) { // nil + throw new MessageTypeException(); + } + advance(1); + return null; + } + + final boolean tryUnpackNull() throws IOException { + if(!tryMore(1)) { + return false; + } + int b = buffer[offset] & 0xff; + if(b != 0xc0) { // nil + return false; + } + advance(1); + return true; + } + + final boolean unpackBoolean() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset] & 0xff; + if(b == 0xc2) { // false + advance(1); + return false; + } else if(b == 0xc3) { // true + advance(1); + return true; + } else { + throw new MessageTypeException(); + } + } + + final int unpackArray() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset]; + if((b & 0xf0) == 0x90) { // FixArray + advance(1); + return (int)(b & 0x0f); + } + switch(b & 0xff) { + case 0xdc: // array 16 + more(3); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 2); + advance(3); + return (int)castBuffer.getShort(0) & 0xffff; + case 0xdd: // array 32 + more(5); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 4); + advance(5); + // FIXME overflow check + return castBuffer.getInt(0) & 0x7fffffff; + default: + throw new MessageTypeException(); + } + } + + final int unpackMap() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset]; + if((b & 0xf0) == 0x80) { // FixMap + advance(1); + return (int)(b & 0x0f); + } + switch(b & 0xff) { + case 0xde: // map 16 + more(3); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 2); + advance(3); + return (int)castBuffer.getShort(0) & 0xffff; + case 0xdf: // map 32 + more(5); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 4); + advance(5); + // FIXME overflow check + return castBuffer.getInt(0) & 0x7fffffff; + default: + throw new MessageTypeException(); + } + } + + final int unpackRaw() throws IOException, MessageTypeException { + more(1); + int b = buffer[offset]; + if((b & 0xe0) == 0xa0) { // FixRaw + advance(1); + return (int)(b & 0x1f); + } + switch(b & 0xff) { + case 0xda: // raw 16 + more(3); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 2); + advance(3); + return (int)castBuffer.getShort(0) & 0xffff; + case 0xdb: // raw 32 + more(5); + castBuffer.rewind(); + castBuffer.put(buffer, offset+1, 4); + advance(5); + // FIXME overflow check + return castBuffer.getInt(0) & 0x7fffffff; + default: + throw new MessageTypeException(); + } + } + + final byte[] unpackRawBody(int length) throws IOException { + more(length); + byte[] bytes = new byte[length]; + System.arraycopy(buffer, offset, bytes, 0, length); + advance(length); + return bytes; + } + + final byte[] unpackByteArray() throws IOException, MessageTypeException { + int length = unpackRaw(); + return unpackRawBody(length); + } + + final String unpackString() throws IOException, MessageTypeException { + int length = unpackRaw(); + more(length); + String s; + try { + s = new String(buffer, offset, length, "UTF-8"); + } catch (Exception e) { + throw new MessageTypeException(); + } + advance(length); + return s; + } + + final MessagePackObject unpackObject() throws IOException { + UnpackResult result = new UnpackResult(); + if(!next(result)) { + super.reset(); + throw new UnpackException("insufficient buffer"); + } + return result.getData(); + } +} + diff --git a/java/src/main/java/org/msgpack/MessageMergeable.java b/java/src/main/java/org/msgpack/MessageConvertable.java index e5a5b45..8acf1f2 100644 --- a/java/src/main/java/org/msgpack/MessageMergeable.java +++ b/java/src/main/java/org/msgpack/MessageConvertable.java @@ -17,7 +17,7 @@ // package org.msgpack; -public interface MessageMergeable { - public void messageMerge(Object obj) throws MessageTypeException; +public interface MessageConvertable { + public void messageConvert(MessagePackObject obj) throws MessageTypeException; } diff --git a/java/src/main/java/org/msgpack/MessagePackObject.java b/java/src/main/java/org/msgpack/MessagePackObject.java new file mode 100644 index 0000000..2424446 --- /dev/null +++ b/java/src/main/java/org/msgpack/MessagePackObject.java @@ -0,0 +1,136 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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; + +import java.util.List; +import java.util.Set; +import java.util.Map; +import java.math.BigInteger; + +public abstract class MessagePackObject implements Cloneable, MessagePackable { + public boolean isNil() { + return false; + } + + public boolean isBooleanType() { + return false; + } + + public boolean isIntegerType() { + return false; + } + + public boolean isFloatType() { + return false; + } + + public boolean isArrayType() { + return false; + } + + public boolean isMapType() { + return false; + } + + public boolean isRawType() { + return false; + } + + public boolean asBoolean() { + throw new MessageTypeException("type error"); + } + + public byte asByte() { + throw new MessageTypeException("type error"); + } + + public short asShort() { + throw new MessageTypeException("type error"); + } + + public int asInt() { + throw new MessageTypeException("type error"); + } + + public long asLong() { + throw new MessageTypeException("type error"); + } + + public BigInteger asBigInteger() { + throw new MessageTypeException("type error"); + } + + public float asFloat() { + throw new MessageTypeException("type error"); + } + + public double asDouble() { + throw new MessageTypeException("type error"); + } + + public byte[] asByteArray() { + throw new MessageTypeException("type error"); + } + + public String asString() { + throw new MessageTypeException("type error"); + } + + public MessagePackObject[] asArray() { + throw new MessageTypeException("type error"); + } + + public List<MessagePackObject> asList() { + throw new MessageTypeException("type error"); + } + + public Map<MessagePackObject, MessagePackObject> asMap() { + throw new MessageTypeException("type error"); + } + + public byte byteValue() { + throw new MessageTypeException("type error"); + } + + public short shortValue() { + throw new MessageTypeException("type error"); + } + + public int intValue() { + throw new MessageTypeException("type error"); + } + + public long longValue() { + throw new MessageTypeException("type error"); + } + + public BigInteger bigIntegerValue() { + throw new MessageTypeException("type error"); + } + + public float floatValue() { + throw new MessageTypeException("type error"); + } + + public double doubleValue() { + throw new MessageTypeException("type error"); + } + + abstract public Object clone(); +} + diff --git a/java/src/main/java/org/msgpack/MessageTypeException.java b/java/src/main/java/org/msgpack/MessageTypeException.java index feb6c08..698ef6d 100644 --- a/java/src/main/java/org/msgpack/MessageTypeException.java +++ b/java/src/main/java/org/msgpack/MessageTypeException.java @@ -17,23 +17,11 @@ // package org.msgpack; -import java.io.IOException; - -public class MessageTypeException extends IOException { +public class MessageTypeException extends RuntimeException { public MessageTypeException() { } public MessageTypeException(String s) { super(s); } - - public static MessageTypeException invalidConvert(Object from, Schema to) { - return new MessageTypeException(from.getClass().getName()+" cannot be convert to "+to.getExpression()); - } - - /* FIXME - public static MessageTypeException schemaMismatch(Schema to) { - return new MessageTypeException("schema mismatch "+to.getExpression()); - } - */ } diff --git a/java/src/main/java/org/msgpack/schema/IArraySchema.java b/java/src/main/java/org/msgpack/MessageUnpackable.java index 67e9f55..cc206e7 100644 --- a/java/src/main/java/org/msgpack/schema/IArraySchema.java +++ b/java/src/main/java/org/msgpack/MessageUnpackable.java @@ -15,12 +15,11 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.schema; +package org.msgpack; -import org.msgpack.Schema; +import java.io.IOException; -public interface IArraySchema { - public Schema getElementSchema(int index); - public Object createFromArray(Object[] obj); +public interface MessageUnpackable { + public void messageUnpack(Unpacker pac) throws IOException, MessageTypeException; } diff --git a/java/src/main/java/org/msgpack/Packer.java b/java/src/main/java/org/msgpack/Packer.java index 935728d..139b3b1 100644 --- a/java/src/main/java/org/msgpack/Packer.java +++ b/java/src/main/java/org/msgpack/Packer.java @@ -22,7 +22,24 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.List; import java.util.Map; - +import java.math.BigInteger; + +/** + * Packer enables you to serialize objects into OutputStream. + * + * <pre> + * // create a packer with output stream + * Packer pk = new Packer(System.out); + * + * // store an object with pack() method. + * pk.pack(1); + * + * // you can store String, List, Map, byte[] and primitive types. + * pk.pack(new ArrayList()); + * </pre> + * + * You can serialize objects that implements {@link MessagePackable} interface. + */ public class Packer { protected byte[] castBytes = new byte[9]; protected ByteBuffer castBuffer = ByteBuffer.wrap(castBytes); @@ -34,7 +51,7 @@ public class Packer { public Packer packByte(byte d) throws IOException { if(d < -(1<<5)) { - castBytes[0] = (byte)0xd1; + castBytes[0] = (byte)0xd0; castBytes[1] = d; out.write(castBytes, 0, 2); } else { @@ -178,6 +195,27 @@ public class Packer { return this; } + public Packer packBigInteger(BigInteger d) throws IOException { + if(d.bitLength() <= 63) { + return packLong(d.longValue()); + } else if(d.bitLength() <= 64 && d.signum() >= 0) { + castBytes[0] = (byte)0xcf; + byte[] barray = d.toByteArray(); + castBytes[1] = barray[barray.length-8]; + castBytes[2] = barray[barray.length-7]; + castBytes[3] = barray[barray.length-6]; + castBytes[4] = barray[barray.length-5]; + castBytes[5] = barray[barray.length-4]; + castBytes[6] = barray[barray.length-3]; + castBytes[7] = barray[barray.length-2]; + castBytes[8] = barray[barray.length-1]; + out.write(castBytes); + return this; + } else { + throw new MessageTypeException("can't pack BigInteger larger than 0xffffffffffffffff"); + } + } + public Packer packFloat(float d) throws IOException { castBytes[0] = (byte)0xca; castBuffer.putFloat(1, d); @@ -207,6 +245,10 @@ public class Packer { return this; } + public Packer packBoolean(boolean d) throws IOException { + return d ? packTrue() : packFalse(); + } + public Packer packArray(int n) throws IOException { if(n < 16) { final int d = 0x90 | n; @@ -266,12 +308,6 @@ public class Packer { } - public Packer packWithSchema(Object o, Schema s) throws IOException { - s.pack(this, o); - return this; - } - - public Packer packString(String s) throws IOException { byte[] b = ((String)s).getBytes("UTF-8"); packRaw(b.length); @@ -279,39 +315,36 @@ public class Packer { } - public Packer pack(String o) throws IOException { - if(o == null) { return packNil(); } - return packString(o); + public Packer pack(boolean o) throws IOException { + if(o) { + return packTrue(); + } else { + return packFalse(); + } } - public Packer pack(MessagePackable o) throws IOException { - if(o == null) { return packNil(); } - o.messagePack(this); - return this; + public Packer pack(byte o) throws IOException { + return packByte(o); } - public Packer pack(byte[] o) throws IOException { - if(o == null) { return packNil(); } - packRaw(o.length); - return packRawBody(o); + public Packer pack(short o) throws IOException { + return packShort(o); } - public Packer pack(List o) throws IOException { - if(o == null) { return packNil(); } - packArray(o.size()); - for(Object i : o) { pack(i); } - return this; + public Packer pack(int o) throws IOException { + return packInt(o); } - @SuppressWarnings("unchecked") - public Packer pack(Map o) throws IOException { - if(o == null) { return packNil(); } - packMap(o.size()); - for(Map.Entry e : ((Map<Object,Object>)o).entrySet()) { - pack(e.getKey()); - pack(e.getValue()); - } - return this; + public Packer pack(long o) throws IOException { + return packLong(o); + } + + public Packer pack(float o) throws IOException { + return packFloat(o); + } + + public Packer pack(double o) throws IOException { + return packDouble(o); } public Packer pack(Boolean o) throws IOException { @@ -343,6 +376,11 @@ public class Packer { return packLong(o); } + public Packer pack(BigInteger o) throws IOException { + if(o == null) { return packNil(); } + return packBigInteger(o); + } + public Packer pack(Float o) throws IOException { if(o == null) { return packNil(); } return packFloat(o); @@ -353,8 +391,41 @@ public class Packer { return packDouble(o); } + public Packer pack(String o) throws IOException { + if(o == null) { return packNil(); } + return packString(o); + } + + public Packer pack(MessagePackable o) throws IOException { + if(o == null) { return packNil(); } + o.messagePack(this); + return this; + } + + public Packer pack(byte[] o) throws IOException { + if(o == null) { return packNil(); } + packRaw(o.length); + return packRawBody(o); + } + + public Packer pack(List o) throws IOException { + if(o == null) { return packNil(); } + packArray(o.size()); + for(Object i : o) { pack(i); } + return this; + } + + public Packer pack(Map o) throws IOException { + if(o == null) { return packNil(); } + packMap(o.size()); + for(Map.Entry<Object,Object> e : ((Map<Object,Object>)o).entrySet()) { + pack(e.getKey()); + pack(e.getValue()); + } + return this; + } + - @SuppressWarnings("unchecked") public Packer pack(Object o) throws IOException { if(o == null) { return packNil(); @@ -377,7 +448,7 @@ public class Packer { } else if(o instanceof Map) { Map<Object,Object> m = (Map<Object,Object>)o; packMap(m.size()); - for(Map.Entry e : m.entrySet()) { + for(Map.Entry<Object,Object> e : m.entrySet()) { pack(e.getKey()); pack(e.getValue()); } @@ -400,8 +471,10 @@ public class Packer { return packFloat((Float)o); } else if(o instanceof Double) { return packDouble((Double)o); + } else if(o instanceof BigInteger) { + return packBigInteger((BigInteger)o); } else { - throw new IOException("unknown object "+o+" ("+o.getClass()+")"); + throw new MessageTypeException("unknown object "+o+" ("+o.getClass()+")"); } } } diff --git a/java/src/main/java/org/msgpack/Schema.java b/java/src/main/java/org/msgpack/Schema.java deleted file mode 100644 index f191f7a..0000000 --- a/java/src/main/java/org/msgpack/Schema.java +++ /dev/null @@ -1,133 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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; - -import java.io.Writer; -import java.io.IOException; -import org.msgpack.schema.SSchemaParser; -import org.msgpack.schema.ClassGenerator; - -public abstract class Schema { - private String expression; - private String name; - - public Schema(String name) { - this.expression = expression; - this.name = name; - } - - public String getName() { - return name; - } - - public String getFullName() { - return name; - } - - public String getExpression() { - return name; - } - - public static Schema parse(String source) { - return SSchemaParser.parse(source); - } - - public static Schema load(String source) { - return SSchemaParser.load(source); - } - - public void write(Writer output) throws IOException { - ClassGenerator.write(this, output); - } - - public abstract void pack(Packer pk, Object obj) throws IOException; - - public abstract Object convert(Object obj) throws MessageTypeException; - - - public Object createFromNil() { - return null; - } - - public Object createFromBoolean(boolean v) { - throw new RuntimeException("type error"); - } - - public Object createFromByte(byte v) { - throw new RuntimeException("type error"); - } - - public Object createFromShort(short v) { - throw new RuntimeException("type error"); - } - - public Object createFromInt(int v) { - throw new RuntimeException("type error"); - } - - public Object createFromLong(long v) { - throw new RuntimeException("type error"); - } - - public Object createFromFloat(float v) { - throw new RuntimeException("type error"); - } - - public Object createFromDouble(double v) { - throw new RuntimeException("type error"); - } - - public Object createFromRaw(byte[] b, int offset, int length) { - throw new RuntimeException("type error"); - } - - /* FIXME - public Object createFromBoolean(boolean v) { - throw MessageTypeException.schemaMismatch(this); - } - - public Object createFromByte(byte v) { - throw MessageTypeException.schemaMismatch(this); - } - - public Object createFromShort(short v) { - throw MessageTypeException.schemaMismatch(this); - } - - public Object createFromInt(int v) { - throw MessageTypeException.schemaMismatch(this); - } - - public Object createFromLong(long v) { - throw MessageTypeException.schemaMismatch(this); - } - - public Object createFromFloat(float v) { - throw MessageTypeException.schemaMismatch(this); - } - - public Object createFromDouble(double v) { - throw MessageTypeException.schemaMismatch(this); - } - - public Object createFromRaw(byte[] b, int offset, int length) { - throw MessageTypeException.schemaMismatch(this); - } - */ -} - diff --git a/java/src/main/java/org/msgpack/UnbufferedUnpacker.java b/java/src/main/java/org/msgpack/UnbufferedUnpacker.java deleted file mode 100644 index b427973..0000000 --- a/java/src/main/java/org/msgpack/UnbufferedUnpacker.java +++ /dev/null @@ -1,82 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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; - -import java.lang.Iterable; -import java.io.InputStream; -import java.io.IOException; -import java.util.Iterator; -import org.msgpack.impl.UnpackerImpl; - -public class UnbufferedUnpacker extends UnpackerImpl { - private int offset; - private boolean finished; - private Object data; - - public UnbufferedUnpacker() { - super(); - this.offset = 0; - this.finished = false; - } - - public UnbufferedUnpacker useSchema(Schema s) { - super.setSchema(s); - return this; - } - - public Object getData() { - return data; - } - - public boolean isFinished() { - return finished; - } - - public void reset() { - super.reset(); - this.offset = 0; - } - - int getOffset() { - return offset; - } - - void setOffset(int offset) { - this.offset = offset; - } - - public int execute(byte[] buffer) throws UnpackException { - return execute(buffer, 0, buffer.length); - } - - // FIXME - public int execute(byte[] buffer, int offset, int length) throws UnpackException - { - int noffset = super.execute(buffer, offset + this.offset, length); - this.offset = noffset - offset; - if(super.isFinished()) { - this.data = super.getData(); - this.finished = true; - super.reset(); - } else { - this.finished = false; - } - return noffset; - } -} - diff --git a/java/src/main/java/org/msgpack/UnpackIterator.java b/java/src/main/java/org/msgpack/UnpackIterator.java index 0a78e83..8c778b6 100644 --- a/java/src/main/java/org/msgpack/UnpackIterator.java +++ b/java/src/main/java/org/msgpack/UnpackIterator.java @@ -21,41 +21,28 @@ import java.io.IOException; import java.util.Iterator; import java.util.NoSuchElementException; -public class UnpackIterator implements Iterator<Object> { +public class UnpackIterator extends UnpackResult implements Iterator<MessagePackObject> { private Unpacker pac; - private boolean have; - private Object data; UnpackIterator(Unpacker pac) { + super(); this.pac = pac; - this.have = false; } public boolean hasNext() { - if(have) { return true; } + if(finished) { return true; } try { - while(true) { - if(pac.execute()) { - data = pac.getData(); - pac.reset(); - have = true; - return true; - } - - if(!pac.fill()) { - return false; - } - } + return pac.next(this); } catch (IOException e) { return false; } } - public Object next() { - if(!have && !hasNext()) { + public MessagePackObject next() { + if(!finished && !hasNext()) { throw new NoSuchElementException(); } - have = false; + finished = false; return data; } diff --git a/java/src/main/java/org/msgpack/schema/FieldSchema.java b/java/src/main/java/org/msgpack/UnpackResult.java index 66c2ff2..bb981c1 100644 --- a/java/src/main/java/org/msgpack/schema/FieldSchema.java +++ b/java/src/main/java/org/msgpack/UnpackResult.java @@ -15,29 +15,28 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.schema; +package org.msgpack; -import org.msgpack.Schema; +public class UnpackResult { + protected boolean finished = false; + protected MessagePackObject data = null; -public class FieldSchema { - private String name; - private Schema schema; - - public FieldSchema(String name, Schema schema) { - this.name = name; - this.schema = schema; + public boolean isFinished() { + return finished; } - public final String getName() { - return name; + public MessagePackObject getData() { + return data; } - public final Schema getSchema() { - return schema; + public void reset() { + finished = false; + data = null; } - public String getExpression() { - return "(field "+name+" "+schema.getExpression()+")"; + void done(MessagePackObject obj) { + finished = true; + data = obj; } } diff --git a/java/src/main/java/org/msgpack/Unpacker.java b/java/src/main/java/org/msgpack/Unpacker.java index c8a8823..3cae502 100644 --- a/java/src/main/java/org/msgpack/Unpacker.java +++ b/java/src/main/java/org/msgpack/Unpacker.java @@ -22,144 +22,382 @@ import java.io.InputStream; import java.io.IOException; import java.util.Iterator; import java.nio.ByteBuffer; -import org.msgpack.impl.UnpackerImpl; - -public class Unpacker extends UnpackerImpl implements Iterable<Object> { +import java.math.BigInteger; + +/** + * Unpacker enables you to deserialize objects from stream. + * + * Unpacker provides Buffered API, Unbuffered API and + * Direct Conversion API. + * + * Buffered API uses the internal buffer of the Unpacker. + * Following code uses Buffered API with an InputStream: + * <pre> + * // create an unpacker with input stream + * Unpacker pac = new Unpacker(System.in); + * + * // take a object out using next() method, or ... + * UnpackResult result = pac.next(); + * + * // use an iterator. + * for(MessagePackObject obj : pac) { + * // use MessageConvertable interface to convert the + * // the generic object to the specific type. + * } + * </pre> + * + * Following code doesn't use the input stream and feeds buffer + * using {@link feed(byte[])} method. This is useful to use + * special stream like zlib or event-driven I/O library. + * <pre> + * // create an unpacker without input stream + * Unpacker pac = new Unpacker(); + * + * // feed buffer to the internal buffer. + * pac.feed(input_bytes); + * + * // use next() method or iterators. + * for(MessagePackObject obj : pac) { + * // ... + * } + * </pre> + * + * The combination of {@link reserveBuffer()}, {@link getBuffer()}, + * {@link getBufferOffset()}, {@link getBufferCapacity()} and + * {@link bufferConsumed()} is useful to omit copying. + * <pre> + * // create an unpacker without input stream + * Unpacker pac = new Unpacker(); + * + * // reserve internal buffer at least 1024 bytes. + * pac.reserveBuffer(1024); + * + * // feed buffer to the internal buffer upto pac.getBufferCapacity() bytes. + * System.in.read(pac.getBuffer(), pac.getBufferOffset(), pac.getBufferCapacity()); + * + * // use next() method or iterators. + * for(MessagePackObject obj : pac) { + * // ... + * } + * </pre> + * + * Unbuffered API doesn't initialize the internal buffer. + * You can manage the buffer manually. + * <pre> + * // create an unpacker with input stream + * Unpacker pac = new Unpacker(System.in); + * + * // manage the buffer manually. + * byte[] buffer = new byte[1024]; + * int filled = System.in.read(buffer); + * int offset = 0; + * + * // deserialize objects using execute() method. + * int nextOffset = pac.execute(buffer, offset, filled); + * + * // take out object if deserialized object is ready. + * if(pac.isFinished()) { + * MessagePackObject obj = pac.getData(); + * // ... + * } + * </pre> + */ +public class Unpacker implements Iterable<MessagePackObject> { + + // buffer: + // +---------------------------------------------+ + // | [object] | [obje| unparsed ... | unused ...| + // +---------------------------------------------+ + // ^ parsed + // ^ offset + // ^ filled + // ^ buffer.length + + private static final int DEFAULT_BUFFER_SIZE = 32*1024; + + protected int parsed; + protected int bufferReserveSize; + protected InputStream stream; + + final class BufferedUnpackerMixin extends BufferedUnpackerImpl { + boolean fill() throws IOException { + if(stream == null) { + return false; + } + reserveBuffer(bufferReserveSize); + int rl = stream.read(buffer, filled, buffer.length - filled); + // equals: stream.read(getBuffer(), getBufferOffset(), getBufferCapacity()); + if(rl <= 0) { + return false; + } + bufferConsumed(rl); + return true; + } + }; - public static final int DEFAULT_BUFFER_SIZE = 32*1024; + final BufferedUnpackerMixin impl = new BufferedUnpackerMixin(); - private int used; - private int offset; - private int parsed; - private byte[] buffer; - private int bufferReserveSize; - private InputStream stream; + /** + * Calls {@link Unpacker(DEFAULT_BUFFER_SIZE)} + */ public Unpacker() { this(DEFAULT_BUFFER_SIZE); } + /** + * Calls {@link Unpacker(null, bufferReserveSize)} + */ public Unpacker(int bufferReserveSize) { this(null, bufferReserveSize); } + /** + * Calls {@link Unpacker(stream, DEFAULT_BUFFER_SIZE)} + */ public Unpacker(InputStream stream) { this(stream, DEFAULT_BUFFER_SIZE); } + /** + * Constructs the unpacker. + * The stream is used to fill the buffer when more buffer is required by {@link next()} or {@link UnpackIterator#hasNext()} method. + * @param stream input stream to fill the buffer + * @param bufferReserveSize threshold size to expand the size of buffer + */ public Unpacker(InputStream stream, int bufferReserveSize) { - super(); - this.used = 0; - this.offset = 0; this.parsed = 0; - this.buffer = new byte[bufferReserveSize]; this.bufferReserveSize = bufferReserveSize/2; this.stream = stream; } - public Unpacker useSchema(Schema s) { - super.setSchema(s); - return this; + + /** + * Gets the input stream. + * @return the input stream. it may be null. + */ + public InputStream getStream() { + return this.stream; + } + + /** + * Sets the input stream. + * @param stream the input stream to set. + */ + public void setStream(InputStream stream) { + this.stream = stream; + } + + + /** + * Fills the buffer with the specified buffer. + */ + public void feed(byte[] buffer) { + feed(buffer, 0, buffer.length); + } + + /** + * Fills the buffer with the specified buffer. + */ + public void feed(byte[] buffer, int offset, int length) { + reserveBuffer(length); + System.arraycopy(buffer, offset, impl.buffer, impl.offset, length); + bufferConsumed(length); + } + + /** + * Fills the buffer with the specified buffer. + */ + public void feed(ByteBuffer buffer) { + int length = buffer.remaining(); + if (length == 0) return; + reserveBuffer(length); + buffer.get(impl.buffer, impl.offset, length); + bufferConsumed(length); + } + + /** + * Swaps the internal buffer with the specified buffer. + * This method doesn't copy the buffer and the its contents will be rewritten by {@link fill()} or {@link feed(byte[])} method. + */ + public void wrap(byte[] buffer) { + wrap(buffer, 0, buffer.length); + } + + /** + * Swaps the internal buffer with the specified buffer. + * This method doesn't copy the buffer and the its contents will be rewritten by {@link fill()} or {@link feed(byte[])} method. + */ + public void wrap(byte[] buffer, int offset, int length) { + impl.buffer = buffer; + impl.offset = offset; + impl.filled = length; } - public void reserveBuffer(int size) { - if(buffer.length - used >= size) { + /** + * Fills the internal using the input stream. + * @return false if the stream is null or stream.read returns <= 0. + */ + public boolean fill() throws IOException { + return impl.fill(); + } + + + /** + * Returns the iterator that calls {@link next()} method repeatedly. + */ + public Iterator<MessagePackObject> iterator() { + return new UnpackIterator(this); + } + + /** + * Deserializes one object and returns it. + * @return {@link UnpackResult#isFinished()} returns false if the buffer is insufficient to deserialize one object. + */ + public UnpackResult next() throws IOException, UnpackException { + UnpackResult result = new UnpackResult(); + impl.next(result); + return result; + } + + /** + * Deserializes one object and returns it. + * @return false if the buffer is insufficient to deserialize one object. + */ + public boolean next(UnpackResult result) throws IOException, UnpackException { + return impl.next(result); + } + + + /** + * Reserve free space of the internal buffer at least specified size and expands {@link getBufferCapacity()}. + */ + public void reserveBuffer(int require) { + if(impl.buffer == null) { + int nextSize = (bufferReserveSize < require) ? require : bufferReserveSize; + impl.buffer = new byte[nextSize]; return; } - /* - if(used == parsed && buffer.length >= size) { - // rewind buffer - used = 0; - offset = 0; + + if(impl.filled <= impl.offset) { + // rewind the buffer + impl.filled = 0; + impl.offset = 0; + } + + if(impl.buffer.length - impl.filled >= require) { return; } - */ - int nextSize = buffer.length * 2; - while(nextSize < size + used) { + int nextSize = impl.buffer.length * 2; + int notParsed = impl.filled - impl.offset; + while(nextSize < require + notParsed) { nextSize *= 2; } byte[] tmp = new byte[nextSize]; - System.arraycopy(buffer, offset, tmp, 0, used - offset); + System.arraycopy(impl.buffer, impl.offset, tmp, 0, impl.filled - impl.offset); - buffer = tmp; - used -= offset; - offset = 0; + impl.buffer = tmp; + impl.filled = notParsed; + impl.offset = 0; } + /** + * Returns the internal buffer. + */ public byte[] getBuffer() { - return buffer; + return impl.buffer; } - public int getBufferOffset() { - return used; + /** + * Returns the size of free space of the internal buffer. + */ + public int getBufferCapacity() { + return impl.buffer.length - impl.filled; } - public int getBufferCapacity() { - return buffer.length - used; + /** + * Returns the offset of free space in the internal buffer. + */ + public int getBufferOffset() { + return impl.filled; } + /** + * Moves front the offset of the free space in the internal buffer. + * Call this method after fill the buffer manually using {@link reserveBuffer()}, {@link getBuffer()}, {@link getBufferOffset()} and {@link getBufferCapacity()} methods. + */ public void bufferConsumed(int size) { - used += size; + impl.filled += size; } - public void feed(ByteBuffer buffer) { - int length = buffer.remaining(); - if (length == 0) return; - reserveBuffer(length); - buffer.get(this.buffer, this.offset, length); - bufferConsumed(length); + /** + * Deserializes one object upto the offset of the internal buffer. + * Call {@link reset()} method before calling this method again. + * @return true if one object is deserialized. Use {@link getData()} to get the deserialized object. + */ + public boolean execute() throws UnpackException { + int noffset = impl.execute(impl.buffer, impl.offset, impl.filled); + if(noffset <= impl.offset) { + return false; + } + parsed += noffset - impl.offset; + impl.offset = noffset; + return impl.isFinished(); } - public void feed(byte[] buffer) { - feed(buffer, 0, buffer.length); - } - public void feed(byte[] buffer, int offset, int length) { - reserveBuffer(length); - System.arraycopy(buffer, offset, this.buffer, this.offset, length); - bufferConsumed(length); + /** + * Deserializes one object over the specified buffer. + * This method doesn't use the internal buffer. + * Use {@link isFinished()} method to known a object is ready to get. + * Call {@link reset()} method before calling this method again. + * @return offset position that is parsed. + */ + public int execute(byte[] buffer) throws UnpackException { + return execute(buffer, 0, buffer.length); } - public boolean fill() throws IOException { - if(stream == null) { - return false; - } - reserveBuffer(bufferReserveSize); - int rl = stream.read(getBuffer(), getBufferOffset(), getBufferCapacity()); - if(rl <= 0) { - return false; + /** + * Deserializes one object over the specified buffer. + * This method doesn't use the internal buffer. + * Use {@link isFinished()} method to known a object is ready to get. + * Call {@link reset()} method before calling this method again. + * @return offset position that is parsed. + */ + public int execute(byte[] buffer, int offset, int length) throws UnpackException { + int noffset = impl.execute(buffer, offset + impl.offset, length); + impl.offset = noffset - offset; + if(impl.isFinished()) { + impl.resetState(); } - bufferConsumed(rl); - return true; - } - - public Iterator<Object> iterator() { - return new UnpackIterator(this); + return noffset; } - public boolean execute() throws UnpackException { - int noffset = super.execute(buffer, offset, used); - if(noffset <= offset) { - return false; - } - parsed += noffset - offset; - offset = noffset; - return super.isFinished(); + /** + * Gets the object deserialized by {@link execute(byte[])} method. + */ + public MessagePackObject getData() { + return impl.getData(); } - public Object getData() { - return super.getData(); + /** + * Returns true if an object is ready to get with {@link getData()} method. + */ + public boolean isFinished() { + return impl.isFinished(); } + /** + * Resets the internal state of the unpacker. + */ public void reset() { - super.reset(); - parsed = 0; + impl.reset(); } public int getMessageSize() { - return parsed - offset + used; + return parsed - impl.offset + impl.filled; } public int getParsedSize() { @@ -167,88 +405,168 @@ public class Unpacker extends UnpackerImpl implements Iterable<Object> { } public int getNonParsedSize() { - return used - offset; + return impl.filled - impl.offset; } public void skipNonparsedBuffer(int size) { - offset += size; + impl.offset += size; } public void removeNonparsedBuffer() { - used = offset; + impl.filled = impl.offset; } - /* - public static class Context { - private boolean finished; - private Object data; - private int offset; - private UnpackerImpl impl; - public Context() - { - this.finished = false; - this.impl = new UnpackerImpl(); - } + /** + * Gets one {@code byte} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code byte}. + */ + public byte unpackByte() throws IOException, MessageTypeException { + return impl.unpackByte(); + } - public boolean isFinished() - { - return finished; - } + /** + * Gets one {@code short} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code short}. + */ + public short unpackShort() throws IOException, MessageTypeException { + return impl.unpackShort(); + } - public Object getData() - { - return data; - } + /** + * Gets one {@code int} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code int}. + */ + public int unpackInt() throws IOException, MessageTypeException { + return impl.unpackInt(); + } - int getOffset() - { - return offset; - } + /** + * Gets one {@code long} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code long}. + */ + public long unpackLong() throws IOException, MessageTypeException { + return impl.unpackLong(); + } - void setFinished(boolean finished) - { - this.finished = finished; - } + /** + * Gets one {@code BigInteger} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code BigInteger}. + */ + public BigInteger unpackBigInteger() throws IOException, MessageTypeException { + return impl.unpackBigInteger(); + } - void setData(Object data) - { - this.data = data; - } + /** + * Gets one {@code float} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code float}. + */ + public float unpackFloat() throws IOException, MessageTypeException { + return impl.unpackFloat(); + } - void setOffset(int offset) - { - this.offset = offset; - } + /** + * Gets one {@code double} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code double}. + */ + public double unpackDouble() throws IOException, MessageTypeException { + return impl.unpackDouble(); + } - UnpackerImpl getImpl() - { - return impl; - } + /** + * Gets one {@code null} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code null}. + */ + public Object unpackNull() throws IOException, MessageTypeException { + return impl.unpackNull(); } - public static int unpack(Context ctx, byte[] buffer) throws UnpackException - { - return unpack(ctx, buffer, 0, buffer.length); + /** + * Gets one {@code boolean} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code boolean}. + */ + public boolean unpackBoolean() throws IOException, MessageTypeException { + return impl.unpackBoolean(); } - public static int unpack(Context ctx, byte[] buffer, int offset, int length) throws UnpackException - { - UnpackerImpl impl = ctx.getImpl(); - int noffset = impl.execute(buffer, offset + ctx.getOffset(), length); - ctx.setOffset(noffset - offset); - if(impl.isFinished()) { - ctx.setData(impl.getData()); - ctx.setFinished(false); - impl.reset(); - } else { - ctx.setData(null); - ctx.setFinished(true); - } - int parsed = noffset - offset; - ctx.setOffset(parsed); - return noffset; + /** + * Gets one array header from the buffer. + * This method calls {@link fill()} method if needed. + * @return the length of the map. There are {@code retval} objects to get. + * @throws MessageTypeException the first value of the buffer is not a array. + */ + public int unpackArray() throws IOException, MessageTypeException { + return impl.unpackArray(); + } + + /** + * Gets one map header from the buffer. + * This method calls {@link fill()} method if needed. + * @return the length of the map. There are {@code retval * 2} objects to get. + * @throws MessageTypeException the first value of the buffer is not a map. + */ + public int unpackMap() throws IOException, MessageTypeException { + return impl.unpackMap(); + } + + /** + * Gets one raw header from the buffer. + * This method calls {@link fill()} method if needed. + * @return the length of the raw bytes. There are {@code retval} bytes to get. + * @throws MessageTypeException the first value of the buffer is not a raw bytes. + */ + public int unpackRaw() throws IOException, MessageTypeException { + return impl.unpackRaw(); + } + + /** + * Gets one raw body from the buffer. + * This method calls {@link fill()} method if needed. + */ + public byte[] unpackRawBody(int length) throws IOException { + return impl.unpackRawBody(length); + } + + /** + * Gets one raw bytes from the buffer. + * This method calls {@link fill()} method if needed. + */ + public byte[] unpackByteArray() throws IOException { + return impl.unpackByteArray(); + } + + /** + * Gets one {@code String} value from the buffer. + * This method calls {@link fill()} method if needed. + * @throws MessageTypeException the first value of the buffer is not a {@code String}. + */ + final public String unpackString() throws IOException, MessageTypeException { + return impl.unpackString(); + } + + /** + * Gets one {@code Object} value from the buffer. + * This method calls {@link fill()} method if needed. + */ + final public MessagePackObject unpackObject() throws IOException { + return impl.unpackObject(); + } + + final public void unpack(MessageUnpackable obj) throws IOException, MessageTypeException { + obj.messageUnpack(this); + } + + final public boolean tryUnpackNull() throws IOException { + return impl.tryUnpackNull(); } - */ } diff --git a/java/src/main/java/org/msgpack/impl/UnpackerImpl.java b/java/src/main/java/org/msgpack/UnpackerImpl.java index adc62b0..6a7085f 100644 --- a/java/src/main/java/org/msgpack/impl/UnpackerImpl.java +++ b/java/src/main/java/org/msgpack/UnpackerImpl.java @@ -15,14 +15,11 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.impl; +package org.msgpack; import java.nio.ByteBuffer; -//import java.math.BigInteger; -import org.msgpack.*; -import org.msgpack.schema.GenericSchema; -import org.msgpack.schema.IMapSchema; -import org.msgpack.schema.IArraySchema; +import java.math.BigInteger; +import org.msgpack.object.*; public class UnpackerImpl { static final int CS_HEADER = 0x00; @@ -47,7 +44,7 @@ public class UnpackerImpl { static final int CT_MAP_KEY = 0x01; static final int CT_MAP_VALUE = 0x02; - static final int MAX_STACK_SIZE = 16; + static final int MAX_STACK_SIZE = 32; private int cs; private int trail; @@ -55,53 +52,45 @@ public class UnpackerImpl { private int[] stack_ct = new int[MAX_STACK_SIZE]; private int[] stack_count = new int[MAX_STACK_SIZE]; private Object[] stack_obj = new Object[MAX_STACK_SIZE]; - private Schema[] stack_schema = new Schema[MAX_STACK_SIZE]; private int top_ct; private int top_count; private Object top_obj; - private Schema top_schema; private ByteBuffer castBuffer = ByteBuffer.allocate(8); private boolean finished = false; - private Object data = null; + private MessagePackObject data = null; - private static final Schema GENERIC_SCHEMA = new GenericSchema(); - private Schema rootSchema; - - protected UnpackerImpl() - { - setSchema(GENERIC_SCHEMA); - } - - protected void setSchema(Schema schema) + public UnpackerImpl() { - this.rootSchema = schema; reset(); } - protected Object getData() + public final MessagePackObject getData() { return data; } - protected boolean isFinished() + public final boolean isFinished() { return finished; } - protected void reset() - { + public final void resetState() { cs = CS_HEADER; top = -1; - finished = false; - data = null; top_ct = 0; top_count = 0; top_obj = null; - top_schema = rootSchema; + } + + public final void reset() + { + resetState(); + finished = false; + data = null; } @SuppressWarnings("unchecked") - protected int execute(byte[] src, int off, int length) throws UnpackException + public final int execute(byte[] src, int off, int length) throws UnpackException { if(off >= length) { return off; } @@ -123,20 +112,20 @@ public class UnpackerImpl { if((b & 0x80) == 0) { // Positive Fixnum //System.out.println("positive fixnum "+b); - obj = top_schema.createFromByte((byte)b); + obj = IntegerType.create((byte)b); break _push; } if((b & 0xe0) == 0xe0) { // Negative Fixnum //System.out.println("negative fixnum "+b); - obj = top_schema.createFromByte((byte)b); + obj = IntegerType.create((byte)b); break _push; } if((b & 0xe0) == 0xa0) { // FixRaw trail = b & 0x1f; if(trail == 0) { - obj = top_schema.createFromRaw(new byte[0], 0, 0); + obj = RawType.create(new byte[0]); break _push; } cs = ACS_RAW_VALUE; @@ -147,22 +136,20 @@ public class UnpackerImpl { if(top >= MAX_STACK_SIZE) { throw new UnpackException("parse error"); } - if(!(top_schema instanceof IArraySchema)) { - throw new RuntimeException("type error"); - } count = b & 0x0f; //System.out.println("fixarray count:"+count); - obj = new Object[count]; - if(count == 0) { break _push; } // FIXME check IArraySchema + obj = new MessagePackObject[count]; + if(count == 0) { + obj = ArrayType.create((MessagePackObject[])obj); + break _push; + } ++top; stack_obj[top] = top_obj; stack_ct[top] = top_ct; stack_count[top] = top_count; - stack_schema[top] = top_schema; top_obj = obj; top_ct = CT_ARRAY_ITEM; top_count = count; - top_schema = ((IArraySchema)top_schema).getElementSchema(0); break _header_again; } @@ -170,34 +157,32 @@ public class UnpackerImpl { if(top >= MAX_STACK_SIZE) { throw new UnpackException("parse error"); } - if(!(top_schema instanceof IMapSchema)) { - throw new RuntimeException("type error"); - } count = b & 0x0f; - obj = new Object[count*2]; - if(count == 0) { break _push; } // FIXME check IMapSchema + obj = new MessagePackObject[count*2]; + if(count == 0) { + obj = MapType.create((MessagePackObject[])obj); + break _push; + } //System.out.println("fixmap count:"+count); ++top; stack_obj[top] = top_obj; stack_ct[top] = top_ct; stack_count[top] = top_count; - stack_schema[top] = top_schema; top_obj = obj; top_ct = CT_MAP_KEY; top_count = count; - top_schema = ((IMapSchema)top_schema).getKeySchema(); break _header_again; } switch(b & 0xff) { // FIXME case 0xc0: // nil - obj = top_schema.createFromNil(); + obj = NilType.create(); break _push; case 0xc2: // false - obj = top_schema.createFromBoolean(false); + obj = BooleanType.create(false); break _push; case 0xc3: // true - obj = top_schema.createFromBoolean(true); + obj = BooleanType.create(true); break _push; case 0xca: // float case 0xcb: // double @@ -241,13 +226,13 @@ public class UnpackerImpl { case CS_FLOAT: castBuffer.rewind(); castBuffer.put(src, n, 4); - obj = top_schema.createFromFloat( castBuffer.getFloat(0) ); + obj = FloatType.create( castBuffer.getFloat(0) ); //System.out.println("float "+obj); break _push; case CS_DOUBLE: castBuffer.rewind(); castBuffer.put(src, n, 8); - obj = top_schema.createFromDouble( castBuffer.getDouble(0) ); + obj = FloatType.create( castBuffer.getDouble(0) ); //System.out.println("double "+obj); break _push; case CS_UINT_8: @@ -255,7 +240,7 @@ public class UnpackerImpl { //System.out.println(src[n]); //System.out.println(src[n+1]); //System.out.println(src[n-1]); - obj = top_schema.createFromShort( (short)((src[n]) & 0xff) ); + obj = IntegerType.create( (short)((src[n]) & 0xff) ); //System.out.println("uint8 "+obj); break _push; case CS_UINT_16: @@ -263,13 +248,13 @@ public class UnpackerImpl { //System.out.println(src[n+1]); castBuffer.rewind(); castBuffer.put(src, n, 2); - obj = top_schema.createFromInt( ((int)castBuffer.getShort(0)) & 0xffff ); + obj = IntegerType.create( ((int)castBuffer.getShort(0)) & 0xffff ); //System.out.println("uint 16 "+obj); break _push; case CS_UINT_32: castBuffer.rewind(); castBuffer.put(src, n, 4); - obj = top_schema.createFromLong( ((long)castBuffer.getInt(0)) & 0xffffffffL ); + obj = IntegerType.create( ((long)castBuffer.getInt(0)) & 0xffffffffL ); //System.out.println("uint 32 "+obj); break _push; case CS_UINT_64: @@ -278,38 +263,36 @@ public class UnpackerImpl { { long o = castBuffer.getLong(0); if(o < 0) { - // FIXME - //obj = GenericBigInteger.valueOf(o & 0x7fffffffL).setBit(31); - throw new UnpackException("uint 64 bigger than 0x7fffffff is not supported"); + obj = IntegerType.create(new BigInteger(1, castBuffer.array())); } else { - obj = top_schema.createFromLong( o ); + obj = IntegerType.create(o); } } break _push; case CS_INT_8: - obj = top_schema.createFromByte( src[n] ); + obj = IntegerType.create( src[n] ); break _push; case CS_INT_16: castBuffer.rewind(); castBuffer.put(src, n, 2); - obj = top_schema.createFromShort( castBuffer.getShort(0) ); + obj = IntegerType.create( castBuffer.getShort(0) ); break _push; case CS_INT_32: castBuffer.rewind(); castBuffer.put(src, n, 4); - obj = top_schema.createFromInt( castBuffer.getInt(0) ); + obj = IntegerType.create( castBuffer.getInt(0) ); break _push; case CS_INT_64: castBuffer.rewind(); castBuffer.put(src, n, 8); - obj = top_schema.createFromLong( castBuffer.getLong(0) ); + obj = IntegerType.create( castBuffer.getLong(0) ); break _push; case CS_RAW_16: castBuffer.rewind(); castBuffer.put(src, n, 2); trail = ((int)castBuffer.getShort(0)) & 0xffff; if(trail == 0) { - obj = top_schema.createFromRaw(new byte[0], 0, 0); + obj = RawType.create(new byte[0]); break _push; } cs = ACS_RAW_VALUE; @@ -320,104 +303,100 @@ public class UnpackerImpl { // FIXME overflow check trail = castBuffer.getInt(0) & 0x7fffffff; if(trail == 0) { - obj = top_schema.createFromRaw(new byte[0], 0, 0); + obj = RawType.create(new byte[0]); break _push; } cs = ACS_RAW_VALUE; - case ACS_RAW_VALUE: - obj = top_schema.createFromRaw(src, n, trail); + break _fixed_trail_again; + case ACS_RAW_VALUE: { + byte[] raw = new byte[trail]; + System.arraycopy(src, n, raw, 0, trail); + obj = RawType.create(raw); + } break _push; case CS_ARRAY_16: if(top >= MAX_STACK_SIZE) { throw new UnpackException("parse error"); } - if(!(top_schema instanceof IArraySchema)) { - throw new RuntimeException("type error"); - } castBuffer.rewind(); castBuffer.put(src, n, 2); count = ((int)castBuffer.getShort(0)) & 0xffff; - obj = new Object[count]; - if(count == 0) { break _push; } // FIXME check IArraySchema + obj = new MessagePackObject[count]; + if(count == 0) { + obj = ArrayType.create((MessagePackObject[])obj); + break _push; + } ++top; stack_obj[top] = top_obj; stack_ct[top] = top_ct; stack_count[top] = top_count; - stack_schema[top] = top_schema; top_obj = obj; top_ct = CT_ARRAY_ITEM; top_count = count; - top_schema = ((IArraySchema)top_schema).getElementSchema(0); break _header_again; case CS_ARRAY_32: if(top >= MAX_STACK_SIZE) { throw new UnpackException("parse error"); } - if(!(top_schema instanceof IArraySchema)) { - throw new RuntimeException("type error"); - } castBuffer.rewind(); castBuffer.put(src, n, 4); // FIXME overflow check count = castBuffer.getInt(0) & 0x7fffffff; - obj = new Object[count]; - if(count == 0) { break _push; } // FIXME check IArraySchema + obj = new MessagePackObject[count]; + if(count == 0) { + obj = ArrayType.create((MessagePackObject[])obj); + break _push; + } ++top; stack_obj[top] = top_obj; stack_ct[top] = top_ct; stack_count[top] = top_count; - stack_schema[top] = top_schema; top_obj = obj; top_ct = CT_ARRAY_ITEM; top_count = count; - top_schema = ((IArraySchema)top_schema).getElementSchema(0); break _header_again; case CS_MAP_16: if(top >= MAX_STACK_SIZE) { throw new UnpackException("parse error"); } - if(!(top_schema instanceof IMapSchema)) { - throw new RuntimeException("type error"); - } castBuffer.rewind(); castBuffer.put(src, n, 2); count = ((int)castBuffer.getShort(0)) & 0xffff; - obj = new Object[count*2]; - if(count == 0) { break _push; } // FIXME check IMapSchema + obj = new MessagePackObject[count*2]; + if(count == 0) { + obj = MapType.create((MessagePackObject[])obj); + break _push; + } //System.out.println("fixmap count:"+count); ++top; stack_obj[top] = top_obj; stack_ct[top] = top_ct; stack_count[top] = top_count; - stack_schema[top] = top_schema; top_obj = obj; top_ct = CT_MAP_KEY; top_count = count; - top_schema = ((IMapSchema)top_schema).getKeySchema(); break _header_again; case CS_MAP_32: if(top >= MAX_STACK_SIZE) { throw new UnpackException("parse error"); } - if(!(top_schema instanceof IMapSchema)) { - throw new RuntimeException("type error"); - } castBuffer.rewind(); castBuffer.put(src, n, 4); // FIXME overflow check count = castBuffer.getInt(0) & 0x7fffffff; - obj = new Object[count*2]; - if(count == 0) { break _push; } // FIXME check IMapSchema + obj = new MessagePackObject[count*2]; + if(count == 0) { + obj = MapType.create((MessagePackObject[])obj); + break _push; + } //System.out.println("fixmap count:"+count); ++top; stack_obj[top] = top_obj; stack_ct[top] = top_ct; stack_count[top] = top_count; - stack_schema[top] = top_schema; top_obj = obj; top_ct = CT_MAP_KEY; top_count = count; - top_schema = ((IMapSchema)top_schema).getKeySchema(); break _header_again; default: throw new UnpackException("parse error"); @@ -432,7 +411,7 @@ public class UnpackerImpl { //System.out.println("push top:"+top); if(top == -1) { ++i; - data = obj; + data = (MessagePackObject)obj; finished = true; break _out; } @@ -446,14 +425,10 @@ public class UnpackerImpl { top_obj = stack_obj[top]; top_ct = stack_ct[top]; top_count = stack_count[top]; - top_schema = stack_schema[top]; - obj = ((IArraySchema)top_schema).createFromArray(ar); + obj = ArrayType.create((MessagePackObject[])ar); stack_obj[top] = null; - stack_schema[top] = null; --top; break _push; - } else { - top_schema = ((IArraySchema)stack_schema[top]).getElementSchema(ar.length - top_count); } break _header_again; } @@ -462,7 +437,6 @@ public class UnpackerImpl { Object[] mp = (Object[])top_obj; mp[mp.length - top_count*2] = obj; top_ct = CT_MAP_VALUE; - top_schema = ((IMapSchema)stack_schema[top]).getValueSchema(); break _header_again; } case CT_MAP_VALUE: { @@ -473,10 +447,8 @@ public class UnpackerImpl { top_obj = stack_obj[top]; top_ct = stack_ct[top]; top_count = stack_count[top]; - top_schema = stack_schema[top]; - obj = ((IMapSchema)top_schema).createFromMap(mp); + obj = MapType.create((MessagePackObject[])mp); stack_obj[top] = null; - stack_schema[top] = null; --top; break _push; } diff --git a/java/src/main/java/org/msgpack/object/ArrayType.java b/java/src/main/java/org/msgpack/object/ArrayType.java new file mode 100644 index 0000000..36134dc --- /dev/null +++ b/java/src/main/java/org/msgpack/object/ArrayType.java @@ -0,0 +1,81 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.util.List; +import java.util.Arrays; +import java.io.IOException; +import org.msgpack.*; + +public class ArrayType extends MessagePackObject { + private MessagePackObject[] array; + + ArrayType(MessagePackObject[] array) { + this.array = array; + } + + public static ArrayType create(MessagePackObject[] array) { + return new ArrayType(array); + } + + @Override + public boolean isArrayType() { + return true; + } + + @Override + public MessagePackObject[] asArray() { + return array; + } + + @Override + public List<MessagePackObject> asList() { + return Arrays.asList(array); + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packArray(array.length); + for(int i=0; i < array.length; i++) { + array[i].messagePack(pk); + } + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + return false; + } + return Arrays.equals(((ArrayType)obj).array, array); + } + + @Override + public int hashCode() { + return array.hashCode(); + } + + @Override + public Object clone() { + MessagePackObject[] copy = new MessagePackObject[array.length]; + for(int i=0; i < array.length; i++) { + copy[i] = (MessagePackObject)array[i].clone(); + } + return copy; + } +} + diff --git a/java/src/main/java/org/msgpack/object/BigIntegerTypeIMPL.java b/java/src/main/java/org/msgpack/object/BigIntegerTypeIMPL.java new file mode 100644 index 0000000..b29879f --- /dev/null +++ b/java/src/main/java/org/msgpack/object/BigIntegerTypeIMPL.java @@ -0,0 +1,131 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.math.BigInteger; +import java.io.IOException; +import org.msgpack.*; + +class BigIntegerTypeIMPL extends IntegerType { + private BigInteger value; + + BigIntegerTypeIMPL(BigInteger value) { + this.value = value; + } + + @Override + public byte asByte() { + if(value.compareTo(BigInteger.valueOf((long)Byte.MAX_VALUE)) > 0) { + throw new MessageTypeException("type error"); + } + return value.byteValue(); + } + + @Override + public short asShort() { + if(value.compareTo(BigInteger.valueOf((long)Short.MAX_VALUE)) > 0) { + throw new MessageTypeException("type error"); + } + return value.shortValue(); + } + + @Override + public int asInt() { + if(value.compareTo(BigInteger.valueOf((long)Integer.MAX_VALUE)) > 0) { + throw new MessageTypeException("type error"); + } + return value.intValue(); + } + + @Override + public long asLong() { + if(value.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { + throw new MessageTypeException("type error"); + } + return value.longValue(); + } + + @Override + public BigInteger asBigInteger() { + return value; + } + + @Override + public byte byteValue() { + return value.byteValue(); + } + + @Override + public short shortValue() { + return value.shortValue(); + } + + @Override + public int intValue() { + return value.intValue(); + } + + @Override + public long longValue() { + return value.longValue(); + } + + @Override + public BigInteger bigIntegerValue() { + return value; + } + + @Override + public float floatValue() { + return value.floatValue(); + } + + @Override + public double doubleValue() { + return value.doubleValue(); + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packBigInteger(value); + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + if(obj.getClass() == ShortIntegerTypeIMPL.class) { + return BigInteger.valueOf(((ShortIntegerTypeIMPL)obj).longValue()).equals(value); + } else if(obj.getClass() == LongIntegerTypeIMPL.class) { + return BigInteger.valueOf(((LongIntegerTypeIMPL)obj).longValue()).equals(value); + } + return false; + } + return ((BigIntegerTypeIMPL)obj).value.equals(value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public Object clone() { + return new BigIntegerTypeIMPL(value); + } +} + diff --git a/java/src/main/java/org/msgpack/object/BooleanType.java b/java/src/main/java/org/msgpack/object/BooleanType.java new file mode 100644 index 0000000..65bd42b --- /dev/null +++ b/java/src/main/java/org/msgpack/object/BooleanType.java @@ -0,0 +1,71 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.io.IOException; +import org.msgpack.*; + +public class BooleanType extends MessagePackObject { + private boolean value; + + BooleanType(boolean value) { + this.value = value; + } + + public static BooleanType create(boolean value) { + return new BooleanType(value); + } + + @Override + public boolean isBooleanType() { + return true; + } + + @Override + public boolean asBoolean() { + return value; + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packBoolean(value); + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + return false; + } + return ((BooleanType)obj).value == value; + } + + @Override + public int hashCode() { + if(value) { + return 1231; + } else { + return 1237; + } + } + + @Override + public Object clone() { + return new BooleanType(value); + } +} + diff --git a/java/src/main/java/org/msgpack/object/DoubleTypeIMPL.java b/java/src/main/java/org/msgpack/object/DoubleTypeIMPL.java new file mode 100644 index 0000000..fd38089 --- /dev/null +++ b/java/src/main/java/org/msgpack/object/DoubleTypeIMPL.java @@ -0,0 +1,101 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.math.BigInteger; +import java.io.IOException; +import org.msgpack.*; + +class DoubleTypeIMPL extends FloatType { + private double value; + + public DoubleTypeIMPL(double value) { + this.value = value; + } + + @Override + public float asFloat() { + // FIXME check overflow, underflow? + return (float)value; + } + + @Override + public double asDouble() { + return value; + } + + @Override + public byte byteValue() { + return (byte)value; + } + + @Override + public short shortValue() { + return (short)value; + } + + @Override + public int intValue() { + return (int)value; + } + + @Override + public long longValue() { + return (long)value; + } + + @Override + public BigInteger bigIntegerValue() { + return BigInteger.valueOf((long)value); + } + + @Override + public float floatValue() { + return (float)value; + } + + @Override + public double doubleValue() { + return (double)value; + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packDouble(value); + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + return false; + } + return ((DoubleTypeIMPL)obj).value == value; + } + + @Override + public int hashCode() { + long v = Double.doubleToLongBits(value); + return (int)(v^(v>>>32)); + } + + @Override + public Object clone() { + return new DoubleTypeIMPL(value); + } +} + diff --git a/java/src/main/java/org/msgpack/schema/IMapSchema.java b/java/src/main/java/org/msgpack/object/FloatType.java index 3a2f556..514efd5 100644 --- a/java/src/main/java/org/msgpack/schema/IMapSchema.java +++ b/java/src/main/java/org/msgpack/object/FloatType.java @@ -15,13 +15,22 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.schema; +package org.msgpack.object; -import org.msgpack.Schema; +import org.msgpack.*; -public interface IMapSchema { - public Schema getKeySchema(); - public Schema getValueSchema(); - public Object createFromMap(Object[] obj); +public abstract class FloatType extends MessagePackObject { + @Override + public boolean isFloatType() { + return true; + } + + public static FloatType create(float value) { + return new FloatTypeIMPL(value); + } + + public static FloatType create(double value) { + return new DoubleTypeIMPL(value); + } } diff --git a/java/src/main/java/org/msgpack/object/FloatTypeIMPL.java b/java/src/main/java/org/msgpack/object/FloatTypeIMPL.java new file mode 100644 index 0000000..1d79961 --- /dev/null +++ b/java/src/main/java/org/msgpack/object/FloatTypeIMPL.java @@ -0,0 +1,94 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.math.BigInteger; +import java.io.IOException; +import org.msgpack.*; + +class FloatTypeIMPL extends FloatType { + private float value; + + public FloatTypeIMPL(float value) { + this.value = value; + } + + @Override + public float asFloat() { + return value; + } + + @Override + public double asDouble() { + return (double)value; + } + + @Override + public byte byteValue() { + return (byte)value; + } + + @Override + public short shortValue() { + return (short)value; + } + + @Override + public int intValue() { + return (int)value; + } + + @Override + public long longValue() { + return (long)value; + } + + @Override + public float floatValue() { + return (float)value; + } + + @Override + public double doubleValue() { + return (double)value; + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packFloat(value); + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + return false; + } + return ((FloatTypeIMPL)obj).value == value; + } + + @Override + public int hashCode() { + return Float.floatToIntBits(value); + } + + @Override + public Object clone() { + return new FloatTypeIMPL(value); + } +} + diff --git a/java/src/main/java/org/msgpack/object/IntegerType.java b/java/src/main/java/org/msgpack/object/IntegerType.java new file mode 100644 index 0000000..43357e8 --- /dev/null +++ b/java/src/main/java/org/msgpack/object/IntegerType.java @@ -0,0 +1,49 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.math.BigInteger; +import org.msgpack.*; + +public abstract class IntegerType extends MessagePackObject { + @Override + public boolean isIntegerType() { + return true; + } + + public static IntegerType create(byte value) { + return new ShortIntegerTypeIMPL((int)value); + } + + public static IntegerType create(short value) { + return new ShortIntegerTypeIMPL((int)value); + } + + public static IntegerType create(int value) { + return new ShortIntegerTypeIMPL(value); + } + + public static IntegerType create(long value) { + return new LongIntegerTypeIMPL(value); + } + + public static IntegerType create(BigInteger value) { + return new BigIntegerTypeIMPL(value); + } +} + diff --git a/java/src/main/java/org/msgpack/object/LongIntegerTypeIMPL.java b/java/src/main/java/org/msgpack/object/LongIntegerTypeIMPL.java new file mode 100644 index 0000000..d052e77 --- /dev/null +++ b/java/src/main/java/org/msgpack/object/LongIntegerTypeIMPL.java @@ -0,0 +1,128 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.math.BigInteger; +import java.io.IOException; +import org.msgpack.*; + +class LongIntegerTypeIMPL extends IntegerType { + private long value; + + LongIntegerTypeIMPL(long value) { + this.value = value; + } + + @Override + public byte asByte() { + if(value > (long)Byte.MAX_VALUE) { + throw new MessageTypeException("type error"); + } + return (byte)value; + } + + @Override + public short asShort() { + if(value > (long)Short.MAX_VALUE) { + throw new MessageTypeException("type error"); + } + return (short)value; + } + + @Override + public int asInt() { + if(value > (long)Integer.MAX_VALUE) { + throw new MessageTypeException("type error"); + } + return (int)value; + } + + @Override + public long asLong() { + return value; + } + + @Override + public BigInteger asBigInteger() { + return BigInteger.valueOf(value); + } + + @Override + public byte byteValue() { + return (byte)value; + } + + @Override + public short shortValue() { + return (short)value; + } + + @Override + public int intValue() { + return (int)value; + } + + @Override + public long longValue() { + return (long)value; + } + + @Override + public BigInteger bigIntegerValue() { + return BigInteger.valueOf(value); + } + + @Override + public float floatValue() { + return (float)value; + } + + @Override + public double doubleValue() { + return (double)value; + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packLong(value); + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + if(obj.getClass() == ShortIntegerTypeIMPL.class) { + return value == ((ShortIntegerTypeIMPL)obj).longValue(); + } else if(obj.getClass() == BigIntegerTypeIMPL.class) { + return BigInteger.valueOf(value).equals(((BigIntegerTypeIMPL)obj).bigIntegerValue()); + } + return false; + } + return ((LongIntegerTypeIMPL)obj).value == value; + } + + @Override + public int hashCode() { + return (int)(value^(value>>>32)); + } + + @Override + public Object clone() { + return new LongIntegerTypeIMPL(value); + } +} + diff --git a/java/src/main/java/org/msgpack/object/MapType.java b/java/src/main/java/org/msgpack/object/MapType.java new file mode 100644 index 0000000..148c0bf --- /dev/null +++ b/java/src/main/java/org/msgpack/object/MapType.java @@ -0,0 +1,84 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.util.HashMap; +import java.util.Map; +import java.util.Arrays; +import java.io.IOException; +import org.msgpack.*; + +public class MapType extends MessagePackObject { + private MessagePackObject[] map; + + MapType(MessagePackObject[] map) { + this.map = map; + } + + public static MapType create(MessagePackObject[] map) { + return new MapType(map); + } + + @Override + public boolean isMapType() { + return true; + } + + @Override + public Map<MessagePackObject, MessagePackObject> asMap() { + HashMap<MessagePackObject, MessagePackObject> m = new HashMap(map.length / 2); + int i = 0; + while(i < map.length) { + MessagePackObject k = map[i++]; + MessagePackObject v = map[i++]; + m.put(k, v); + } + return m; + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packMap(map.length / 2); + for(int i=0; i < map.length; i++) { + map[i].messagePack(pk); + } + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + return false; + } + return Arrays.equals(((MapType)obj).map, map); + } + + @Override + public int hashCode() { + return map.hashCode(); + } + + @Override + public Object clone() { + MessagePackObject[] copy = new MessagePackObject[map.length]; + for(int i=0; i < map.length; i++) { + copy[i] = (MessagePackObject)map[i].clone(); + } + return copy; + } +} + diff --git a/java/src/main/java/org/msgpack/object/NilType.java b/java/src/main/java/org/msgpack/object/NilType.java new file mode 100644 index 0000000..c443db1 --- /dev/null +++ b/java/src/main/java/org/msgpack/object/NilType.java @@ -0,0 +1,60 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.io.IOException; +import org.msgpack.*; + +public class NilType extends MessagePackObject { + private final static NilType INSTANCE = new NilType(); + + public static NilType create() { + return INSTANCE; + } + + private NilType() { } + + @Override + public boolean isNil() { + return true; + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packNil(); + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public Object clone() { + return INSTANCE; + } +} + diff --git a/java/src/main/java/org/msgpack/object/RawType.java b/java/src/main/java/org/msgpack/object/RawType.java new file mode 100644 index 0000000..26f6e0d --- /dev/null +++ b/java/src/main/java/org/msgpack/object/RawType.java @@ -0,0 +1,90 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.util.Arrays; +import java.io.IOException; +import org.msgpack.*; + +public class RawType extends MessagePackObject { + private byte[] bytes; + + RawType(byte[] bytes) { + this.bytes = bytes; + } + + RawType(String str) { + try { + this.bytes = str.getBytes("UTF-8"); + } catch (Exception e) { + throw new MessageTypeException("type error"); + } + } + + public static RawType create(byte[] bytes) { + return new RawType(bytes); + } + + public static RawType create(String str) { + return new RawType(str); + } + + @Override + public boolean isRawType() { + return true; + } + + @Override + public byte[] asByteArray() { + return bytes; + } + + @Override + public String asString() { + try { + return new String(bytes, "UTF-8"); + } catch (Exception e) { + throw new MessageTypeException("type error"); + } + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packRaw(bytes.length); + pk.packRawBody(bytes); + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + return false; + } + return Arrays.equals(((RawType)obj).bytes, bytes); + } + + @Override + public int hashCode() { + return bytes.hashCode(); + } + + @Override + public Object clone() { + return new RawType((byte[])bytes.clone()); + } +} + diff --git a/java/src/main/java/org/msgpack/object/ShortIntegerTypeIMPL.java b/java/src/main/java/org/msgpack/object/ShortIntegerTypeIMPL.java new file mode 100644 index 0000000..dbed426 --- /dev/null +++ b/java/src/main/java/org/msgpack/object/ShortIntegerTypeIMPL.java @@ -0,0 +1,125 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2010 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.object; + +import java.math.BigInteger; +import java.io.IOException; +import org.msgpack.*; + +class ShortIntegerTypeIMPL extends IntegerType { + private int value; + + ShortIntegerTypeIMPL(int value) { + this.value = value; + } + + @Override + public byte asByte() { + if(value > (int)Byte.MAX_VALUE) { + throw new MessageTypeException("type error"); + } + return (byte)value; + } + + @Override + public short asShort() { + if(value > (int)Short.MAX_VALUE) { + throw new MessageTypeException("type error"); + } + return (short)value; + } + + @Override + public int asInt() { + return value; + } + + @Override + public long asLong() { + return value; + } + + @Override + public BigInteger asBigInteger() { + return BigInteger.valueOf((long)value); + } + + @Override + public byte byteValue() { + return (byte)value; + } + + @Override + public short shortValue() { + return (short)value; + } + + @Override + public int intValue() { + return (int)value; + } + + @Override + public long longValue() { + return (long)value; + } + + @Override + public BigInteger bigIntegerValue() { + return BigInteger.valueOf((long)value); + } + + @Override + public float floatValue() { + return (float)value; + } + + @Override + public double doubleValue() { + return (double)value; + } + + @Override + public void messagePack(Packer pk) throws IOException { + pk.packInt(value); + } + + @Override + public boolean equals(Object obj) { + if(obj.getClass() != getClass()) { + if(obj.getClass() == LongIntegerTypeIMPL.class) { + return (long)value == ((LongIntegerTypeIMPL)obj).longValue(); + } else if(obj.getClass() == BigIntegerTypeIMPL.class) { + return ((BigIntegerTypeIMPL)obj).bigIntegerValue().equals(BigInteger.valueOf((long)value)); + } + return false; + } + return ((ShortIntegerTypeIMPL)obj).value == value; + } + + @Override + public int hashCode() { + return value; + } + + @Override + public Object clone() { + return new ShortIntegerTypeIMPL(value); + } +} + diff --git a/java/src/main/java/org/msgpack/package-info.java b/java/src/main/java/org/msgpack/package-info.java new file mode 100644 index 0000000..7e9b8a2 --- /dev/null +++ b/java/src/main/java/org/msgpack/package-info.java @@ -0,0 +1,8 @@ +/** + * MessagePack is a binary-based efficient object serialization library. + * It enables to exchange structured objects between many languages like JSON. + * But unlike JSON, it is very fast and small. + * + * Use {@link Packer} to serialize and {@link Unpacker} to deserialize. + */ +package org.msgpack; diff --git a/java/src/main/java/org/msgpack/schema/ArraySchema.java b/java/src/main/java/org/msgpack/schema/ArraySchema.java deleted file mode 100644 index fd47143..0000000 --- a/java/src/main/java/org/msgpack/schema/ArraySchema.java +++ /dev/null @@ -1,125 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Set; -import java.util.List; -import java.util.ArrayList; -import java.util.RandomAccess; -import java.io.IOException; -import org.msgpack.*; - -public class ArraySchema extends Schema implements IArraySchema { - private Schema elementSchema; - - public ArraySchema(Schema elementSchema) - { - super("array"); - this.elementSchema = elementSchema; - } - - @Override - public String getFullName() - { - return "List<"+elementSchema.getFullName()+">"; - } - - @Override - public String getExpression() - { - return "(array "+elementSchema.getExpression()+")"; - } - - @Override - @SuppressWarnings("unchecked") - public void pack(Packer pk, Object obj) throws IOException - { - if(obj instanceof List) { - ArrayList<Object> d = (ArrayList<Object>)obj; - pk.packArray(d.size()); - if(obj instanceof RandomAccess) { - for(int i=0; i < d.size(); ++i) { - elementSchema.pack(pk, d.get(i)); - } - } else { - for(Object e : d) { - elementSchema.pack(pk, e); - } - } - - } else if(obj instanceof Set) { - Set<Object> d = (Set<Object>)obj; - pk.packArray(d.size()); - for(Object e : d) { - elementSchema.pack(pk, e); - } - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - @SuppressWarnings("unchecked") - public Object convert(Object obj) throws MessageTypeException - { - if(obj instanceof List) { - List d = (List)obj; - ArrayList ar = new ArrayList(d.size()); - if(obj instanceof RandomAccess) { - for(int i=0; i < d.size(); ++i) { - ar.add( elementSchema.convert(d.get(i)) ); - } - } else { - for(Object e : d) { - ar.add( elementSchema.convert(e) ); - } - } - return ar; - - } else if(obj instanceof Collection) { - Collection d = (Collection)obj; - ArrayList ar = new ArrayList(d.size()); - for(Object e : (Collection)obj) { - ar.add( elementSchema.convert(e) ); - } - return ar; - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Schema getElementSchema(int index) - { - return elementSchema; - } - - @Override - public Object createFromArray(Object[] obj) - { - return Arrays.asList(obj); - } -} - diff --git a/java/src/main/java/org/msgpack/schema/ByteSchema.java b/java/src/main/java/org/msgpack/schema/ByteSchema.java deleted file mode 100644 index 9ee6a82..0000000 --- a/java/src/main/java/org/msgpack/schema/ByteSchema.java +++ /dev/null @@ -1,89 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.io.IOException; -import org.msgpack.*; - -public class ByteSchema extends Schema { - public ByteSchema() { - super("Byte"); - } - - @Override - public String getExpression() { - return "byte"; - } - - @Override - public void pack(Packer pk, Object obj) throws IOException { - if(obj instanceof Number) { - pk.packByte( ((Number)obj).byteValue() ); - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - if(obj instanceof Byte) { - return obj; - - } else if(obj instanceof Number) { - return ((Number)obj).byteValue(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object createFromByte(byte v) { - return (byte)v; - } - - @Override - public Object createFromShort(short v) { - return (byte)v; - } - - @Override - public Object createFromInt(int v) { - return (byte)v; - } - - @Override - public Object createFromLong(long v) { - return (byte)v; - } - - @Override - public Object createFromFloat(float v) { - return (byte)v; - } - - @Override - public Object createFromDouble(double v) { - return (byte)v; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/ClassGenerator.java b/java/src/main/java/org/msgpack/schema/ClassGenerator.java deleted file mode 100644 index 061dcbb..0000000 --- a/java/src/main/java/org/msgpack/schema/ClassGenerator.java +++ /dev/null @@ -1,241 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.util.ArrayList; -import java.util.List; -import java.io.IOException; -import java.io.File; -import java.io.Writer; -import org.msgpack.*; - -public class ClassGenerator { - private ClassSchema schema; - private Writer writer; - private int indent; - - private ClassGenerator(Writer writer) { - this.writer = writer; - this.indent = 0; - } - - public static void write(Schema schema, Writer dest) throws IOException { - if(!(schema instanceof ClassSchema)) { - throw new RuntimeException("schema is not class schema"); - } - ClassSchema cs = (ClassSchema)schema; - new ClassGenerator(dest).run(cs); - } - - private void run(ClassSchema cs) throws IOException { - List<ClassSchema> subclasses = new ArrayList<ClassSchema>(); - for(FieldSchema f : cs.getFields()) { - findSubclassSchema(subclasses, f.getSchema()); - } - - for(ClassSchema sub : subclasses) { - sub.setNamespace(cs.getNamespace()); - sub.setImports(cs.getImports()); - } - - this.schema = cs; - - writeHeader(); - - writeClass(); - - for(ClassSchema sub : subclasses) { - this.schema = sub; - writeSubclass(); - } - - writeFooter(); - - this.schema = null; - writer.flush(); - } - - private void findSubclassSchema(List<ClassSchema> dst, Schema s) { - if(s instanceof ClassSchema) { - ClassSchema cs = (ClassSchema)s; - if(!dst.contains(cs)) { dst.add(cs); } - for(FieldSchema f : cs.getFields()) { - findSubclassSchema(dst, f.getSchema()); - } - } else if(s instanceof ArraySchema) { - ArraySchema as = (ArraySchema)s; - findSubclassSchema(dst, as.getElementSchema(0)); - } else if(s instanceof MapSchema) { - MapSchema as = (MapSchema)s; - findSubclassSchema(dst, as.getKeySchema()); - findSubclassSchema(dst, as.getValueSchema()); - } - } - - private void writeHeader() throws IOException { - if(schema.getNamespace() != null) { - line("package "+schema.getNamespace()+";"); - line(); - } - line("import java.util.*;"); - line("import java.io.*;"); - line("import org.msgpack.*;"); - line("import org.msgpack.schema.ClassSchema;"); - line("import org.msgpack.schema.FieldSchema;"); - } - - private void writeFooter() throws IOException { - line(); - } - - private void writeClass() throws IOException { - line(); - line("public final class "+schema.getName()+" implements MessagePackable, MessageMergeable"); - line("{"); - pushIndent(); - writeSchema(); - writeMemberVariables(); - writeMemberFunctions(); - popIndent(); - line("}"); - } - - private void writeSubclass() throws IOException { - line(); - line("final class "+schema.getName()+" implements MessagePackable, MessageMergeable"); - line("{"); - pushIndent(); - writeSchema(); - writeMemberVariables(); - writeMemberFunctions(); - popIndent(); - line("}"); - } - - private void writeSchema() throws IOException { - line("private static final ClassSchema _SCHEMA = (ClassSchema)Schema.load(\""+schema.getExpression()+"\");"); - line("public static ClassSchema getSchema() { return _SCHEMA; }"); - } - - private void writeMemberVariables() throws IOException { - line(); - for(FieldSchema f : schema.getFields()) { - line("public "+f.getSchema().getFullName()+" "+f.getName()+";"); - } - } - - private void writeMemberFunctions() throws IOException { - // void messagePack(Packer pk) - // boolean equals(Object obj) - // int hashCode() - // void set(int _index, Object _value) - // Object get(int _index); - // getXxx() - // setXxx(Xxx xxx) - writeConstructors(); - writeAccessors(); - writePackFunction(); - writeMergeFunction(); - writeFactoryFunction(); - } - - private void writeConstructors() throws IOException { - line(); - line("public "+schema.getName()+"() { }"); - } - - private void writeAccessors() throws IOException { - // FIXME - //line(); - //for(FieldSchema f : schema.getFields()) { - // line(""); - //} - } - - private void writePackFunction() throws IOException { - line(); - line("@Override"); - line("public void messagePack(Packer _pk) throws IOException"); - line("{"); - pushIndent(); - line("_pk.packArray("+schema.getFields().length+");"); - line("FieldSchema[] _fields = _SCHEMA.getFields();"); - int i = 0; - for(FieldSchema f : schema.getFields()) { - line("_fields["+i+"].getSchema().pack(_pk, "+f.getName()+");"); - ++i; - } - popIndent(); - line("}"); - } - - private void writeMergeFunction() throws IOException { - line(); - line("@Override"); - line("@SuppressWarnings(\"unchecked\")"); - line("public void messageMerge(Object obj) throws MessageTypeException"); - line("{"); - pushIndent(); - line("Object[] _source = ((List)obj).toArray();"); - line("FieldSchema[] _fields = _SCHEMA.getFields();"); - int i = 0; - for(FieldSchema f : schema.getFields()) { - line("if(_source.length <= "+i+") { return; } this."+f.getName()+" = ("+f.getSchema().getFullName()+")_fields["+i+"].getSchema().convert(_source["+i+"]);"); - ++i; - } - popIndent(); - line("}"); - } - - private void writeFactoryFunction() throws IOException { - line(); - line("@SuppressWarnings(\"unchecked\")"); - line("public static "+schema.getName()+" createFromMessage(Object[] _message)"); - line("{"); - pushIndent(); - line(schema.getName()+" _self = new "+schema.getName()+"();"); - int i = 0; - for(FieldSchema f : schema.getFields()) { - line("if(_message.length <= "+i+") { return _self; } _self."+f.getName()+" = ("+f.getSchema().getFullName()+")_message["+i+"];"); - ++i; - } - line("return _self;"); - popIndent(); - line("}"); - } - - private void line(String str) throws IOException { - for(int i=0; i < indent; ++i) { - writer.write("\t"); - } - writer.write(str+"\n"); - } - - private void line() throws IOException { - writer.write("\n"); - } - - private void pushIndent() { - indent += 1; - } - - private void popIndent() { - indent -= 1; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/ClassSchema.java b/java/src/main/java/org/msgpack/schema/ClassSchema.java deleted file mode 100644 index cd5c008..0000000 --- a/java/src/main/java/org/msgpack/schema/ClassSchema.java +++ /dev/null @@ -1,95 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.util.Arrays; -import java.util.List; -import org.msgpack.*; - -public abstract class ClassSchema extends Schema implements IArraySchema { - protected FieldSchema[] fields; - protected List<String> imports; - protected String namespace; - protected String fqdn; - - public ClassSchema( - String name, String namespace, - List<String> imports, List<FieldSchema> fields) { - super(name); - this.namespace = namespace; - this.imports = imports; // FIXME clone? - this.fields = new FieldSchema[fields.size()]; - System.arraycopy(fields.toArray(), 0, this.fields, 0, fields.size()); - if(namespace == null) { - this.fqdn = name; - } else { - this.fqdn = namespace+"."+name; - } - } - - public final FieldSchema[] getFields() { - return fields; - } - - String getNamespace() { - return namespace; - } - - List<String> getImports() { - return imports; - } - - void setNamespace(String namespace) { - this.namespace = namespace; - } - - void setImports(List<String> imports) { - this.imports = imports; // FIXME clone? - } - - //@Override - //public String getFullName() - //{ - // if(namespace == null) { - // return getName(); - // } else { - // return namespace+"."+getName(); - // } - //} - - @Override - public String getExpression() { - StringBuffer b = new StringBuffer(); - b.append("(class "); - b.append(getName()); - if(namespace != null) { - b.append(" (package "+namespace+")"); - } - for(FieldSchema f : fields) { - b.append(" "+f.getExpression()); - } - b.append(")"); - return b.toString(); - } - - public boolean equals(SpecificClassSchema o) { - return (namespace != null ? namespace.equals(o.getNamespace()) : o.getNamespace() == null) && - getName().equals(o.getName()); - } -} - diff --git a/java/src/main/java/org/msgpack/schema/DoubleSchema.java b/java/src/main/java/org/msgpack/schema/DoubleSchema.java deleted file mode 100644 index d53e47d..0000000 --- a/java/src/main/java/org/msgpack/schema/DoubleSchema.java +++ /dev/null @@ -1,84 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.io.IOException; -import org.msgpack.*; - -public class DoubleSchema extends Schema { - public DoubleSchema() { - super("Double"); - } - - @Override - public String getExpression() { - return "double"; - } - - @Override - public void pack(Packer pk, Object obj) throws IOException { - if(obj instanceof Number) { - pk.packDouble( ((Number)obj).doubleValue() ); - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - if(obj instanceof Double) { - return obj; - - } else if(obj instanceof Number) { - return ((Number)obj).doubleValue(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object createFromByte(byte v) { - return (double)v; - } - - @Override - public Object createFromShort(short v) { - return (double)v; - } - - @Override - public Object createFromInt(int v) { - return (double)v; - } - - @Override - public Object createFromFloat(float v) { - return (double)v; - } - - @Override - public Object createFromDouble(double v) { - return (double)v; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/FloatSchema.java b/java/src/main/java/org/msgpack/schema/FloatSchema.java deleted file mode 100644 index 2777521..0000000 --- a/java/src/main/java/org/msgpack/schema/FloatSchema.java +++ /dev/null @@ -1,84 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.io.IOException; -import org.msgpack.*; - -public class FloatSchema extends Schema { - public FloatSchema() { - super("Float"); - } - - @Override - public String getExpression() { - return "float"; - } - - @Override - public void pack(Packer pk, Object obj) throws IOException { - if(obj instanceof Number) { - pk.packFloat( ((Number)obj).floatValue() ); - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - if(obj instanceof Float) { - return obj; - - } else if(obj instanceof Number) { - return ((Number)obj).floatValue(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object createFromByte(byte v) { - return (float)v; - } - - @Override - public Object createFromShort(short v) { - return (float)v; - } - - @Override - public Object createFromInt(int v) { - return (float)v; - } - - @Override - public Object createFromFloat(float v) { - return (float)v; - } - - @Override - public Object createFromDouble(double v) { - return (float)v; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/GenericClassSchema.java b/java/src/main/java/org/msgpack/schema/GenericClassSchema.java deleted file mode 100644 index ffdd4ab..0000000 --- a/java/src/main/java/org/msgpack/schema/GenericClassSchema.java +++ /dev/null @@ -1,91 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.io.IOException; -import org.msgpack.*; - -public class GenericClassSchema extends ClassSchema { - public GenericClassSchema( - String name, String namespace, - List<String> imports, List<FieldSchema> fields) { - super(name, namespace, imports, fields); - } - - @Override - @SuppressWarnings("unchecked") - public void pack(Packer pk, Object obj) throws IOException { - if(obj instanceof Map) { - Map d = (Map)obj; - pk.packArray(fields.length); - for(int i=0; i < fields.length; ++i) { - FieldSchema f = fields[i]; - f.getSchema().pack(pk, d.get(f.getName())); - } - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - if(obj instanceof Collection) { - // FIXME optimize - return createFromArray( ((Collection)obj).toArray() ); - - } else if(obj instanceof Map) { - HashMap<String,Object> m = new HashMap<String,Object>(fields.length); - Map d = (Map)obj; - for(int i=0; i < fields.length; ++i) { - FieldSchema f = fields[i]; - String fieldName = f.getName(); - m.put(fieldName, f.getSchema().convert(d.get(fieldName))); - } - return m; - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - public Schema getElementSchema(int index) { - // FIXME check index < fields.length - return fields[index].getSchema(); - } - - public Object createFromArray(Object[] obj) { - HashMap<String,Object> m = new HashMap<String,Object>(fields.length); - int i=0; - for(; i < obj.length; ++i) { - m.put(fields[i].getName(), obj[i]); - } - for(; i < fields.length; ++i) { - m.put(fields[i].getName(), null); - } - return m; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/GenericSchema.java b/java/src/main/java/org/msgpack/schema/GenericSchema.java deleted file mode 100644 index 0adf898..0000000 --- a/java/src/main/java/org/msgpack/schema/GenericSchema.java +++ /dev/null @@ -1,192 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.util.Arrays; -import java.util.List; -import java.util.HashMap; -import java.io.IOException; -import org.msgpack.*; -//import org.msgpack.generic.*; - -public class GenericSchema extends Schema implements IArraySchema, IMapSchema { - public GenericSchema() { - super("Object"); - } - - @Override - public String getExpression() { - return "object"; - } - - @Override - public void pack(Packer pk, Object obj) throws IOException { - pk.pack(obj); - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - return obj; - } - - @Override - public Schema getElementSchema(int index) { - return this; - } - - @Override - public Schema getKeySchema() { - return this; - } - - @Override - public Schema getValueSchema() { - return this; - } - - @Override - public Object createFromNil() { - return null; - } - - @Override - public Object createFromBoolean(boolean v) { - return v; - } - - @Override - public Object createFromByte(byte v) { - return v; - } - - @Override - public Object createFromShort(short v) { - return v; - } - - @Override - public Object createFromInt(int v) { - return v; - } - - @Override - public Object createFromLong(long v) { - return v; - } - - @Override - public Object createFromFloat(float v) { - return v; - } - - @Override - public Object createFromDouble(double v) { - return v; - } - - @Override - public Object createFromRaw(byte[] b, int offset, int length) { - byte[] bytes = new byte[length]; - System.arraycopy(b, offset, bytes, 0, length); - return bytes; - } - - @Override - public Object createFromArray(Object[] obj) { - return Arrays.asList(obj); - } - - @Override - @SuppressWarnings("unchecked") - public Object createFromMap(Object[] obj) { - HashMap m = new HashMap(obj.length / 2); - int i = 0; - while(i < obj.length) { - Object k = obj[i++]; - Object v = obj[i++]; - m.put(k, v); - } - return m; - } - - /* - @Override - public Object createFromNil() { - return null; - } - - @Override - public Object createFromBoolean(boolean v) { - return new GenericBoolean(v); - } - - @Override - public Object createFromFromByte(byte v) { - return new GenericByte(v); - } - - @Override - public Object createFromShort(short v) { - return new GenericShort(v); - } - - @Override - public Object createFromInt(int v) { - return new GenericInt(v); - } - - @Override - public Object createFromLong(long v) { - return new GenericLong(v); - } - - @Override - public Object createFromFloat(float v) { - return new GenericFloat(v); - } - - @Override - public Object createFromDouble(double v) { - return new GenericDouble(v); - } - - @Override - public Object createFromRaw(byte[] b, int offset, int length) { - return new GenericRaw(b, offset, length); - } - - @Override - public Object createFromArray(Object[] obj) { - // FIXME GenericArray - return Arrays.asList(obj); - } - - @Override - public Object createFromMap(Object[] obj) { - GenericMap m = new GenericMap(obj.length / 2); - int i = 0; - while(i < obj.length) { - Object k = obj[i++]; - Object v = obj[i++]; - m.put(k, v); - } - return m; - } - */ -} - diff --git a/java/src/main/java/org/msgpack/schema/IntSchema.java b/java/src/main/java/org/msgpack/schema/IntSchema.java deleted file mode 100644 index 5a7e281..0000000 --- a/java/src/main/java/org/msgpack/schema/IntSchema.java +++ /dev/null @@ -1,89 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.io.IOException; -import org.msgpack.*; - -public class IntSchema extends Schema { - public IntSchema() { - super("Integer"); - } - - @Override - public String getExpression() { - return "int"; - } - - @Override - public void pack(Packer pk, Object obj) throws IOException { - if(obj instanceof Number) { - pk.packInt( ((Number)obj).intValue() ); - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - if(obj instanceof Integer) { - return obj; - - } else if(obj instanceof Number) { - return ((Number)obj).intValue(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object createFromByte(byte v) { - return (int)v; - } - - @Override - public Object createFromShort(short v) { - return (int)v; - } - - @Override - public Object createFromInt(int v) { - return (int)v; - } - - @Override - public Object createFromLong(long v) { - return (int)v; - } - - @Override - public Object createFromFloat(float v) { - return (int)v; - } - - @Override - public Object createFromDouble(double v) { - return (int)v; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/LongSchema.java b/java/src/main/java/org/msgpack/schema/LongSchema.java deleted file mode 100644 index 83a30e3..0000000 --- a/java/src/main/java/org/msgpack/schema/LongSchema.java +++ /dev/null @@ -1,89 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.io.IOException; -import org.msgpack.*; - -public class LongSchema extends Schema { - public LongSchema() { - super("Long"); - } - - @Override - public String getExpression() { - return "long"; - } - - @Override - public void pack(Packer pk, Object obj) throws IOException { - if(obj instanceof Number) { - pk.packLong( ((Number)obj).longValue() ); - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - if(obj instanceof Long) { - return obj; - - } else if(obj instanceof Number) { - return ((Number)obj).longValue(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object createFromByte(byte v) { - return (long)v; - } - - @Override - public Object createFromShort(short v) { - return (long)v; - } - - @Override - public Object createFromInt(int v) { - return (long)v; - } - - @Override - public Object createFromLong(long v) { - return (long)v; - } - - @Override - public Object createFromFloat(float v) { - return (long)v; - } - - @Override - public Object createFromDouble(double v) { - return (long)v; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/MapSchema.java b/java/src/main/java/org/msgpack/schema/MapSchema.java deleted file mode 100644 index ba75993..0000000 --- a/java/src/main/java/org/msgpack/schema/MapSchema.java +++ /dev/null @@ -1,103 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.util.Map; -import java.util.HashMap; -import java.io.IOException; -import org.msgpack.*; - -public class MapSchema extends Schema implements IMapSchema { - private Schema keySchema; - private Schema valueSchema; - - public MapSchema(Schema keySchema, Schema valueSchema) { - super("map"); - this.keySchema = keySchema; - this.valueSchema = valueSchema; - } - - @Override - public String getFullName() { - return "HashList<"+keySchema.getFullName()+", "+valueSchema.getFullName()+">"; - } - - @Override - public String getExpression() { - return "(map "+keySchema.getExpression()+" "+valueSchema.getExpression()+")"; - } - - @Override - @SuppressWarnings("unchecked") - public void pack(Packer pk, Object obj) throws IOException { - if(obj instanceof Map) { - Map<Object,Object> d = (Map<Object,Object>)obj; - pk.packMap(d.size()); - for(Map.Entry<Object,Object> e : d.entrySet()) { - keySchema.pack(pk, e.getKey()); - valueSchema.pack(pk, e.getValue()); - } - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - @SuppressWarnings("unchecked") - public Object convert(Object obj) throws MessageTypeException { - if(obj instanceof Map) { - Map<Object,Object> d = (Map<Object,Object>)obj; - Map<Object,Object> m = new HashMap<Object,Object>(); - for(Map.Entry<Object,Object> e : d.entrySet()) { - m.put(keySchema.convert(e.getKey()), valueSchema.convert(e.getValue())); - } - return m; - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Schema getKeySchema() { - return keySchema; - } - - @Override - public Schema getValueSchema() { - return valueSchema; - } - - @Override - @SuppressWarnings("unchecked") - public Object createFromMap(Object[] obj) { - HashMap m = new HashMap(obj.length / 2); - int i = 0; - while(i < obj.length) { - Object k = obj[i++]; - Object v = obj[i++]; - m.put(k, v); - } - return m; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/RawSchema.java b/java/src/main/java/org/msgpack/schema/RawSchema.java deleted file mode 100644 index f621e4c..0000000 --- a/java/src/main/java/org/msgpack/schema/RawSchema.java +++ /dev/null @@ -1,105 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.nio.ByteBuffer; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import org.msgpack.*; - -public class RawSchema extends Schema { - public RawSchema() { - super("raw"); - } - - public String getFullName() { - return "byte[]"; - } - - @Override - public void pack(Packer pk, Object obj) throws IOException { - // FIXME instanceof GenericObject - if(obj instanceof byte[]) { - byte[] d = (byte[])obj; - pk.packRaw(d.length); - pk.packRawBody(d); - - } else if(obj instanceof ByteBuffer) { - ByteBuffer d = (ByteBuffer)obj; - if(!d.hasArray()) { - throw MessageTypeException.invalidConvert(obj, this); - } - pk.packRaw(d.capacity()); - pk.packRawBody(d.array(), d.position(), d.capacity()); - - } else if(obj instanceof String) { - try { - byte[] d = ((String)obj).getBytes("UTF-8"); - pk.packRaw(d.length); - pk.packRawBody(d); - } catch (UnsupportedEncodingException e) { - throw MessageTypeException.invalidConvert(obj, this); - } - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - // FIXME instanceof GenericObject - if(obj instanceof byte[]) { - // FIXME copy? - //byte[] d = (byte[])obj; - //byte[] v = new byte[d.length]; - //System.arraycopy(d, 0, v, 0, d.length); - //return v; - return obj; - - } else if(obj instanceof ByteBuffer) { - ByteBuffer d = (ByteBuffer)obj; - byte[] v = new byte[d.capacity()]; - int pos = d.position(); - d.get(v); - d.position(pos); - return v; - - } else if(obj instanceof String) { - try { - return ((String)obj).getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw MessageTypeException.invalidConvert(obj, this); - } - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object createFromRaw(byte[] b, int offset, int length) { - byte[] d = new byte[length]; - System.arraycopy(b, offset, d, 0, length); - return d; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/ReflectionClassSchema.java b/java/src/main/java/org/msgpack/schema/ReflectionClassSchema.java deleted file mode 100644 index fb94adf..0000000 --- a/java/src/main/java/org/msgpack/schema/ReflectionClassSchema.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.msgpack.schema; - -import java.util.Arrays; -import java.util.List; -import java.lang.reflect.*; -import org.msgpack.*; - -// FIXME -public abstract class ReflectionClassSchema extends ClassSchema { - private Constructor constructorCache; - - public ReflectionClassSchema(String name, List<FieldSchema> fields, String namespace, List<String> imports) { - super(name, namespace, imports, fields); - } - - /* - Schema getElementSchema(int index) - { - // FIXME check index < fields.length - fields[index].getSchema(); - } - - Object createFromArray(Object[] obj) - { - Object o = newInstance(); - ((MessageConvertable)o).messageConvert(obj); - return o; - } - - Object newInstance() - { - if(constructorCache == null) { - cacheConstructor(); - } - try { - return constructorCache.newInstance((Object[])null); - } catch (InvocationTargetException e) { - throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage()); - } catch (InstantiationException e) { - throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage()); - } catch (IllegalAccessException e) { - throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage()); - } - } - - private void cacheConstructor() - { - try { - Class c = Class.forName(fqdn); - int index = 0; - for(SpecificFieldSchema f : fields) { - f.cacheField(c, index++); - } - constructorCache = c.getDeclaredConstructor((Class[])null); - constructorCache.setAccessible(true); - } catch(ClassNotFoundException e) { - throw new RuntimeException("class not found: "+fqdn); - } catch (NoSuchMethodException e) { - throw new RuntimeException("class not found: "+fqdn+": "+e.getMessage()); - } - } - */ -} - diff --git a/java/src/main/java/org/msgpack/schema/SSchemaParser.java b/java/src/main/java/org/msgpack/schema/SSchemaParser.java deleted file mode 100644 index 4ae8a4b..0000000 --- a/java/src/main/java/org/msgpack/schema/SSchemaParser.java +++ /dev/null @@ -1,254 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Stack; -import java.util.regex.Pattern; -import java.util.regex.Matcher; -import org.msgpack.*; - -// FIXME exception class - -public class SSchemaParser { - public static Schema parse(String source) { - return new SSchemaParser(false).run(source); - } - - public static Schema load(String source) { - return new SSchemaParser(true).run(source); - } - - private static abstract class SExp { - boolean isAtom() { return false; } - public String getAtom() { return null; } - - boolean isTuple() { return false; } - public SExp getTuple(int i) { return null; } - public int size() { return 0; } - public boolean empty() { return size() == 0; } - Iterator<SExp> iterator(int offset) { return null; } - } - - private static class SAtom extends SExp { - private String atom; - - SAtom(String atom) { this.atom = atom; } - - boolean isAtom() { return true; } - public String getAtom() { return atom; } - - public String toString() { return atom; } - } - - private static class STuple extends SExp { - private List<SExp> tuple; - - STuple() { this.tuple = new ArrayList<SExp>(); } - - public void add(SExp e) { tuple.add(e); } - - boolean isTuple() { return true; } - public SExp getTuple(int i) { return tuple.get(i); } - public int size() { return tuple.size(); } - - Iterator<SExp> iterator(int skip) { - Iterator<SExp> i = tuple.iterator(); - for(int s=0; s < skip; ++s) { i.next(); } - return i; - } - - public String toString() { - if(tuple.isEmpty()) { return "()"; } - Iterator<SExp> i = tuple.iterator(); - StringBuffer o = new StringBuffer(); - o.append("(").append(i.next()); - while(i.hasNext()) { o.append(" ").append(i.next()); } - o.append(")"); - return o.toString(); - } - } - - boolean specificClass; - - private SSchemaParser(boolean specificClass) { - this.specificClass = specificClass; - } - - private static Pattern pattern = Pattern.compile( - "(?:\\s+)|([\\(\\)]|[\\d\\w\\.]+)"); - - private Schema run(String source) { - Matcher m = pattern.matcher(source); - - Stack<STuple> stack = new Stack<STuple>(); - String token; - - while(true) { - while(true) { - if(!m.find()) { throw new RuntimeException("unexpected end of file"); } - token = m.group(1); - if(token != null) { break; } - } - - if(token.equals("(")) { - stack.push(new STuple()); - } else if(token.equals(")")) { - STuple top = stack.pop(); - if(stack.empty()) { - stack.push(top); - break; - } - stack.peek().add(top); - } else { - if(stack.empty()) { - throw new RuntimeException("unexpected token '"+token+"'"); - } - stack.peek().add(new SAtom(token)); - } - } - - while(true) { - if(!m.find()) { break; } - token = m.group(1); - if(token != null) { throw new RuntimeException("unexpected token '"+token+"'"); } - } - - return readType( stack.pop() ); - } - - private Schema readType(SExp exp) { - if(exp.isAtom()) { - String type = exp.getAtom(); - if(type.equals("string")) { - return new StringSchema(); - } else if(type.equals("raw")) { - return new RawSchema(); - } else if(type.equals("byte")) { - return new ByteSchema(); - } else if(type.equals("short")) { - return new ShortSchema(); - } else if(type.equals("int")) { - return new IntSchema(); - } else if(type.equals("long")) { - return new LongSchema(); - } else if(type.equals("float")) { - return new FloatSchema(); - } else if(type.equals("double")) { - return new DoubleSchema(); - } else if(type.equals("object")) { - return new GenericSchema(); - } else { - throw new RuntimeException("byte, short, int, long, float, double, raw, string or object is expected but got '"+type+"': "+exp); - } - } else { - String type = exp.getTuple(0).getAtom(); - if(type.equals("class")) { - return parseClass(exp); - } else if(type.equals("array")) { - return parseArray(exp); - } else if(type.equals("map")) { - return parseMap(exp); - } else { - throw new RuntimeException("class, array or map is expected but got '"+type+"': "+exp); - } - } - } - - private ClassSchema parseClass(SExp exp) { - if(exp.size() < 3 || !exp.getTuple(1).isAtom()) { - throw new RuntimeException("class is (class NAME CLASS_BODY): "+exp); - } - - String namespace = null; - List<String> imports = new ArrayList<String>(); - String name = exp.getTuple(1).getAtom(); - List<FieldSchema> fields = new ArrayList<FieldSchema>(); - - for(Iterator<SExp> i=exp.iterator(2); i.hasNext();) { - SExp subexp = i.next(); - if(!subexp.isTuple() || subexp.empty() || !subexp.getTuple(0).isAtom()) { - throw new RuntimeException("field, package or import is expected: "+subexp); - } - String type = subexp.getTuple(0).getAtom(); - if(type.equals("field")) { - fields.add( parseField(subexp) ); - } else if(type.equals("package")) { - if(namespace != null) { - throw new RuntimeException("duplicated package definition: "+subexp); - } - namespace = parseNamespace(subexp); - } else if(type.equals("import")) { - imports.add( parseImport(subexp) ); - } else { - throw new RuntimeException("field, package or import is expected but got '"+type+"': "+subexp); - } - } - - if(specificClass) { - return new SpecificClassSchema(name, namespace, imports, fields); - } else { - return new GenericClassSchema(name, namespace, imports, fields); - } - } - - private ArraySchema parseArray(SExp exp) { - if(exp.size() != 2) { - throw new RuntimeException("array is (array ELEMENT_TYPE): "+exp); - } - Schema elementType = readType(exp.getTuple(1)); - return new ArraySchema(elementType); - } - - private MapSchema parseMap(SExp exp) { - if(exp.size() != 3 || !exp.getTuple(1).isAtom()) { - throw new RuntimeException("map is (map KEY_TYPE VALUE_TYPE): "+exp); - } - Schema keyType = readType(exp.getTuple(1)); - Schema valueType = readType(exp.getTuple(2)); - return new MapSchema(keyType, valueType); - } - - private String parseNamespace(SExp exp) { - if(exp.size() != 2 || !exp.getTuple(1).isAtom()) { - throw new RuntimeException("package is (package NAME): "+exp); - } - String name = exp.getTuple(1).getAtom(); - return name; - } - - private String parseImport(SExp exp) { - if(exp.size() != 2 || !exp.getTuple(1).isAtom()) { - throw new RuntimeException("import is (import NAME): "+exp); - } - String name = exp.getTuple(1).getAtom(); - return name; - } - - private FieldSchema parseField(SExp exp) { - if(exp.size() != 3 || !exp.getTuple(1).isAtom()) { - throw new RuntimeException("field is (field NAME TYPE): "+exp); - } - String name = exp.getTuple(1).getAtom(); - Schema type = readType(exp.getTuple(2)); - return new FieldSchema(name, type); - } -} - diff --git a/java/src/main/java/org/msgpack/schema/ShortSchema.java b/java/src/main/java/org/msgpack/schema/ShortSchema.java deleted file mode 100644 index f32ab41..0000000 --- a/java/src/main/java/org/msgpack/schema/ShortSchema.java +++ /dev/null @@ -1,89 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.io.IOException; -import org.msgpack.*; - -public class ShortSchema extends Schema { - public ShortSchema() { - super("Short"); - } - - @Override - public String getExpression() { - return "short"; - } - - @Override - public void pack(Packer pk, Object obj) throws IOException { - if(obj instanceof Number) { - pk.packShort( ((Number)obj).shortValue() ); - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - if(obj instanceof Short) { - return obj; - - } else if(obj instanceof Number) { - return ((Number)obj).shortValue(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object createFromByte(byte v) { - return (short)v; - } - - @Override - public Object createFromShort(short v) { - return (short)v; - } - - @Override - public Object createFromInt(int v) { - return (short)v; - } - - @Override - public Object createFromLong(long v) { - return (short)v; - } - - @Override - public Object createFromFloat(float v) { - return (short)v; - } - - @Override - public Object createFromDouble(double v) { - return (short)v; - } -} - diff --git a/java/src/main/java/org/msgpack/schema/SpecificClassSchema.java b/java/src/main/java/org/msgpack/schema/SpecificClassSchema.java deleted file mode 100644 index 30bd9e1..0000000 --- a/java/src/main/java/org/msgpack/schema/SpecificClassSchema.java +++ /dev/null @@ -1,122 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.util.Collection; -import java.util.List; -import java.lang.reflect.*; -import java.io.IOException; -import org.msgpack.*; - -public class SpecificClassSchema extends ClassSchema { - private Class classCache; - private Method factoryCache; - private Constructor constructorCache; - - public SpecificClassSchema( - String name, String namespace, - List<String> imports, List<FieldSchema> fields) { - super(name, namespace, imports, fields); - } - - @Override - @SuppressWarnings("unchecked") - public void pack(Packer pk, Object obj) throws IOException { - if(obj == null) { - pk.packNil(); - return; - } - if(classCache == null) { - cacheFactory(); - } - if(classCache.isInstance(obj)) { - ((MessagePackable)obj).messagePack(pk); - } else { - // FIXME Map<String,Object> - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - if(obj instanceof Collection) { - if(constructorCache == null) { - cacheConstructor(); - } - try { - MessageMergeable o = (MessageMergeable)constructorCache.newInstance((Object[])null); - o.messageMerge(obj); - return o; - } catch (InvocationTargetException e) { - throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage()); - } catch (InstantiationException e) { - throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage()); - } catch (IllegalAccessException e) { - throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage()); - } - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - public Schema getElementSchema(int index) { - // FIXME check index < fields.length - return fields[index].getSchema(); - } - - public Object createFromArray(Object[] obj) { - if(factoryCache == null) { - cacheFactory(); - } - try { - return factoryCache.invoke(null, new Object[]{obj}); - } catch (InvocationTargetException e) { - throw new RuntimeException("can't instantiate "+fqdn+": "+e.getCause()); - } catch (IllegalAccessException e) { - throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage()); - } - } - - @SuppressWarnings("unchecked") - private void cacheFactory() { - try { - classCache = Class.forName(fqdn); - factoryCache = classCache.getDeclaredMethod("createFromMessage", new Class[]{Object[].class}); - factoryCache.setAccessible(true); - } catch(ClassNotFoundException e) { - throw new RuntimeException("class not found: "+fqdn); - } catch (NoSuchMethodException e) { - throw new RuntimeException("class not found: "+fqdn+": "+e.getMessage()); - } - } - - @SuppressWarnings("unchecked") - private void cacheConstructor() { - try { - classCache = Class.forName(fqdn); - constructorCache = classCache.getDeclaredConstructor((Class[])null); - constructorCache.setAccessible(true); - } catch(ClassNotFoundException e) { - throw new RuntimeException("class not found: "+fqdn); - } catch (NoSuchMethodException e) { - throw new RuntimeException("class not found: "+fqdn+": "+e.getMessage()); - } - } -} - diff --git a/java/src/main/java/org/msgpack/schema/StringSchema.java b/java/src/main/java/org/msgpack/schema/StringSchema.java deleted file mode 100644 index 46d515b..0000000 --- a/java/src/main/java/org/msgpack/schema/StringSchema.java +++ /dev/null @@ -1,111 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2010 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.schema; - -import java.nio.ByteBuffer; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import org.msgpack.*; - -public class StringSchema extends Schema { - public StringSchema() { - super("string"); - } - - @Override - public String getFullName() { - return "String"; - } - - @Override - public void pack(Packer pk, Object obj) throws IOException { - // FIXME instanceof GenericObject - if(obj instanceof String) { - try { - byte[] d = ((String)obj).getBytes("UTF-8"); - pk.packRaw(d.length); - pk.packRawBody(d); - } catch (UnsupportedEncodingException e) { - throw MessageTypeException.invalidConvert(obj, this); - } - - } else if(obj instanceof byte[]) { - byte[] d = (byte[])obj; - pk.packRaw(d.length); - pk.packRawBody(d); - - } else if(obj instanceof ByteBuffer) { - ByteBuffer d = (ByteBuffer)obj; - if(!d.hasArray()) { - throw MessageTypeException.invalidConvert(obj, this); - } - pk.packRaw(d.capacity()); - pk.packRawBody(d.array(), d.position(), d.capacity()); - - } else if(obj == null) { - pk.packNil(); - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object convert(Object obj) throws MessageTypeException { - // FIXME instanceof GenericObject - if(obj instanceof String) { - return obj; - - } else if(obj instanceof byte[]) { - try { - return new String((byte[])obj, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw MessageTypeException.invalidConvert(obj, this); - } - - } else if(obj instanceof ByteBuffer) { - ByteBuffer d = (ByteBuffer)obj; - try { - if(d.hasArray()) { - return new String(d.array(), d.position(), d.capacity(), "UTF-8"); - } else { - byte[] v = new byte[d.capacity()]; - int pos = d.position(); - d.get(v); - d.position(pos); - return new String(v, "UTF-8"); - } - } catch (UnsupportedEncodingException e) { - throw MessageTypeException.invalidConvert(obj, this); - } - - } else { - throw MessageTypeException.invalidConvert(obj, this); - } - } - - @Override - public Object createFromRaw(byte[] b, int offset, int length) { - try { - return new String(b, offset, length, "UTF-8"); - } catch (Exception e) { - throw new RuntimeException(e.getMessage()); - } - } -} - diff --git a/java/src/test/java/org/msgpack/Image.java b/java/src/test/java/org/msgpack/Image.java new file mode 100644 index 0000000..3fcfe38 --- /dev/null +++ b/java/src/test/java/org/msgpack/Image.java @@ -0,0 +1,50 @@ +package org.msgpack; + +import org.msgpack.*; +import java.io.*; +import java.util.*; + +public class Image implements MessagePackable, MessageUnpackable { + public String uri = ""; + public String title = ""; + public int width = 0; + public int height = 0; + public int size = 0; + + public void messagePack(Packer pk) throws IOException { + pk.packArray(5); + pk.pack(uri); + pk.pack(title); + pk.pack(width); + pk.pack(height); + pk.pack(size); + } + + public void messageUnpack(Unpacker pac) throws IOException, MessageTypeException { + int length = pac.unpackArray(); + if(length != 5) { + throw new MessageTypeException(); + } + uri = pac.unpackString(); + title = pac.unpackString(); + width = pac.unpackInt(); + height = pac.unpackInt(); + size = pac.unpackInt(); + } + + public boolean equals(Image obj) { + return uri.equals(obj.uri) && + title.equals(obj.title) && + width == obj.width && + height == obj.height && + size == obj.size; + } + + public boolean equals(Object obj) { + if(obj.getClass() != Image.class) { + return false; + } + return equals((Image)obj); + } +} + diff --git a/java/src/test/java/org/msgpack/TestCases.java b/java/src/test/java/org/msgpack/TestCases.java new file mode 100644 index 0000000..c368972 --- /dev/null +++ b/java/src/test/java/org/msgpack/TestCases.java @@ -0,0 +1,40 @@ +package org.msgpack; + +import java.io.*; +import java.util.*; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class TestCases { + public void feedFile(Unpacker pac, String path) throws Exception { + FileInputStream input = new FileInputStream(path); + byte[] buffer = new byte[32*1024]; + while(true) { + int count = input.read(buffer); + if(count < 0) { + break; + } + pac.feed(buffer, 0, count); + } + } + + @Test + public void testCases() throws Exception { + Unpacker pac = new Unpacker(); + Unpacker pac_compact = new Unpacker(); + + feedFile(pac, "src/test/resources/cases.mpac"); + feedFile(pac_compact, "src/test/resources/cases_compact.mpac"); + + UnpackResult result = new UnpackResult(); + while(pac.next(result)) { + UnpackResult result_compact = new UnpackResult(); + assertTrue( pac_compact.next(result_compact) ); + assertTrue( result.getData().equals(result_compact.getData()) ); + } + + assertFalse( pac_compact.next(result) ); + } +}; + diff --git a/java/src/test/java/org/msgpack/TestDirectConversion.java b/java/src/test/java/org/msgpack/TestDirectConversion.java new file mode 100644 index 0000000..1822ecb --- /dev/null +++ b/java/src/test/java/org/msgpack/TestDirectConversion.java @@ -0,0 +1,279 @@ +package org.msgpack; + +import org.msgpack.*; +import java.io.*; +import java.util.*; +import java.math.BigInteger; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class TestDirectConversion { + @Test + public void testInt() throws Exception { + testInt(0); + testInt(-1); + testInt(1); + testInt(Integer.MIN_VALUE); + testInt(Integer.MAX_VALUE); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testInt(rand.nextInt()); + } + public void testInt(int val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + assertEquals(val, pac.unpackInt()); + } + + @Test + public void testLong() throws Exception { + testLong(0); + testLong(-1); + testLong(1); + testLong(Integer.MIN_VALUE); + testLong(Integer.MAX_VALUE); + testLong(Long.MIN_VALUE); + testLong(Long.MAX_VALUE); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testLong(rand.nextLong()); + } + public void testLong(long val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + assertEquals(val, pac.unpackLong()); + } + + @Test + public void testBigInteger() throws Exception { + testBigInteger(BigInteger.valueOf(0)); + testBigInteger(BigInteger.valueOf(-1)); + testBigInteger(BigInteger.valueOf(1)); + testBigInteger(BigInteger.valueOf(Integer.MIN_VALUE)); + testBigInteger(BigInteger.valueOf(Integer.MAX_VALUE)); + testBigInteger(BigInteger.valueOf(Long.MIN_VALUE)); + testBigInteger(BigInteger.valueOf(Long.MAX_VALUE)); + BigInteger max = BigInteger.valueOf(Long.MAX_VALUE).setBit(63); + testBigInteger(max); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testBigInteger( max.subtract(BigInteger.valueOf( Math.abs(rand.nextLong()) )) ); + } + public void testBigInteger(BigInteger val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + assertEquals(val, pac.unpackBigInteger()); + } + + @Test + public void testFloat() throws Exception { + testFloat((float)0.0); + testFloat((float)-0.0); + testFloat((float)1.0); + testFloat((float)-1.0); + testFloat((float)Float.MAX_VALUE); + testFloat((float)Float.MIN_VALUE); + testFloat((float)Float.NaN); + testFloat((float)Float.NEGATIVE_INFINITY); + testFloat((float)Float.POSITIVE_INFINITY); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testFloat(rand.nextFloat()); + } + public void testFloat(float val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + assertEquals(val, pac.unpackFloat(), 10e-10); + } + + @Test + public void testDouble() throws Exception { + testDouble((double)0.0); + testDouble((double)-0.0); + testDouble((double)1.0); + testDouble((double)-1.0); + testDouble((double)Double.MAX_VALUE); + testDouble((double)Double.MIN_VALUE); + testDouble((double)Double.NaN); + testDouble((double)Double.NEGATIVE_INFINITY); + testDouble((double)Double.POSITIVE_INFINITY); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testDouble(rand.nextDouble()); + } + public void testDouble(double val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + assertEquals(val, pac.unpackDouble(), 10e-10); + } + + @Test + public void testNil() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).packNil(); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + assertEquals(null, pac.unpackNull()); + } + + @Test + public void testBoolean() throws Exception { + testBoolean(false); + testBoolean(true); + } + public void testBoolean(boolean val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + assertEquals(val, pac.unpackBoolean()); + } + + @Test + public void testString() throws Exception { + testString(""); + testString("a"); + testString("ab"); + testString("abc"); + + // small size string + for (int i = 0; i < 100; i++) { + StringBuilder sb = new StringBuilder(); + int len = (int)Math.random() % 31 + 1; + for (int j = 0; j < len; j++) + sb.append('a' + ((int)Math.random()) & 26); + testString(sb.toString()); + } + + // medium size string + for (int i = 0; i < 100; i++) { + StringBuilder sb = new StringBuilder(); + int len = (int)Math.random() % 100 + (1 << 15); + for (int j = 0; j < len; j++) + sb.append('a' + ((int)Math.random()) & 26); + testString(sb.toString()); + } + + // large size string + for (int i = 0; i < 10; i++) { + StringBuilder sb = new StringBuilder(); + int len = (int)Math.random() % 100 + (1 << 31); + for (int j = 0; j < len; j++) + sb.append('a' + ((int)Math.random()) & 26); + testString(sb.toString()); + } + } + public void testString(String val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + assertEquals(val, pac.unpackString()); + } + + @Test + public void testArray() throws Exception { + List<Integer> emptyList = new ArrayList<Integer>(); + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(emptyList); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + int ulen = pac.unpackArray(); + assertEquals(0, ulen); + } + + for (int i = 0; i < 1000; i++) { + List<Integer> l = new ArrayList<Integer>(); + int len = (int)Math.random() % 1000 + 1; + for (int j = 0; j < len; j++) + l.add(j); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(l); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + int ulen = pac.unpackArray(); + assertEquals(len, ulen); + for (int j = 0; j < len; j++) { + assertEquals(l.get(j).intValue(), pac.unpackInt()); + } + } + + for (int i = 0; i < 1000; i++) { + List<String> l = new ArrayList<String>(); + int len = (int)Math.random() % 1000 + 1; + for (int j = 0; j < len; j++) + l.add(Integer.toString(j)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(l); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + int ulen = pac.unpackArray(); + assertEquals(len, ulen); + for (int j = 0; j < len; j++) { + assertEquals(l.get(j), pac.unpackString()); + } + } + } + + @Test + public void testMap() throws Exception { + Map<Integer, Integer> emptyMap = new HashMap<Integer, Integer>(); + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(emptyMap); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + int ulen = pac.unpackMap(); + assertEquals(0, ulen); + } + + for (int i = 0; i < 1000; i++) { + Map<Integer, Integer> m = new HashMap<Integer, Integer>(); + int len = (int)Math.random() % 1000 + 1; + for (int j = 0; j < len; j++) + m.put(j, j); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(m); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + int ulen = pac.unpackMap(); + assertEquals(len, ulen); + for (int j = 0; j < len; j++) { + Integer val = m.get(pac.unpackInt()); + assertNotNull(val); + assertEquals(val.intValue(), pac.unpackInt()); + } + } + + for (int i = 0; i < 1000; i++) { + Map<String, Integer> m = new HashMap<String, Integer>(); + int len = (int)Math.random() % 1000 + 1; + for (int j = 0; j < len; j++) + m.put(Integer.toString(j), j); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(m); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + int ulen = pac.unpackMap(); + assertEquals(len, ulen); + for (int j = 0; j < len; j++) { + Integer val = m.get(pac.unpackString()); + assertNotNull(val); + assertEquals(val.intValue(), pac.unpackInt()); + } + } + } +}; + diff --git a/java/src/test/java/org/msgpack/TestMessageUnpackable.java b/java/src/test/java/org/msgpack/TestMessageUnpackable.java new file mode 100644 index 0000000..32917c7 --- /dev/null +++ b/java/src/test/java/org/msgpack/TestMessageUnpackable.java @@ -0,0 +1,32 @@ +package org.msgpack; + +import org.msgpack.*; +import java.io.*; +import java.util.*; +import java.math.BigInteger; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class TestMessageUnpackable { + @Test + public void testImage() throws Exception { + Image src = new Image(); + src.title = "msgpack"; + src.uri = "http://msgpack.org/"; + src.width = 2560; + src.height = 1600; + src.size = 4096000; + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + src.messagePack(new Packer(out)); + + Image dst = new Image(); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + dst.messageUnpack(new Unpacker(in)); + + assertEquals(src, dst); + } +} + diff --git a/java/src/test/java/org/msgpack/TestObjectEquals.java b/java/src/test/java/org/msgpack/TestObjectEquals.java new file mode 100644 index 0000000..25fe927 --- /dev/null +++ b/java/src/test/java/org/msgpack/TestObjectEquals.java @@ -0,0 +1,96 @@ +package org.msgpack; + +import org.msgpack.*; +import org.msgpack.object.*; +import java.math.BigInteger; +import java.util.*; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class TestObjectEquals { + @Test + public void testInt() throws Exception { + testInt(0); + testInt(-1); + testInt(1); + testInt(Integer.MIN_VALUE); + testInt(Integer.MAX_VALUE); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testInt(rand.nextInt()); + } + public void testInt(int val) throws Exception { + MessagePackObject objInt = IntegerType.create(val); + MessagePackObject objLong = IntegerType.create((long)val); + MessagePackObject objBigInt = IntegerType.create(BigInteger.valueOf((long)val)); + assertTrue(objInt.equals(objInt)); + assertTrue(objInt.equals(objLong)); + assertTrue(objInt.equals(objBigInt)); + assertTrue(objLong.equals(objInt)); + assertTrue(objLong.equals(objLong)); + assertTrue(objLong.equals(objBigInt)); + assertTrue(objBigInt.equals(objInt)); + assertTrue(objBigInt.equals(objLong)); + assertTrue(objBigInt.equals(objBigInt)); + } + + @Test + public void testLong() throws Exception { + testLong(0); + testLong(-1); + testLong(1); + testLong(Integer.MIN_VALUE); + testLong(Integer.MAX_VALUE); + testLong(Long.MIN_VALUE); + testLong(Long.MAX_VALUE); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testLong(rand.nextLong()); + } + public void testLong(long val) throws Exception { + MessagePackObject objInt = IntegerType.create((int)val); + MessagePackObject objLong = IntegerType.create(val); + MessagePackObject objBigInt = IntegerType.create(BigInteger.valueOf(val)); + if(val > (long)Integer.MAX_VALUE || val < (long)Integer.MIN_VALUE) { + assertTrue(objInt.equals(objInt)); + assertFalse(objInt.equals(objLong)); + assertFalse(objInt.equals(objBigInt)); + assertFalse(objLong.equals(objInt)); + assertTrue(objLong.equals(objLong)); + assertTrue(objLong.equals(objBigInt)); + assertFalse(objBigInt.equals(objInt)); + assertTrue(objBigInt.equals(objLong)); + assertTrue(objBigInt.equals(objBigInt)); + } else { + assertTrue(objInt.equals(objInt)); + assertTrue(objInt.equals(objLong)); + assertTrue(objInt.equals(objBigInt)); + assertTrue(objLong.equals(objInt)); + assertTrue(objLong.equals(objLong)); + assertTrue(objLong.equals(objBigInt)); + assertTrue(objBigInt.equals(objInt)); + assertTrue(objBigInt.equals(objLong)); + assertTrue(objBigInt.equals(objBigInt)); + } + } + + @Test + public void testNil() throws Exception { + assertTrue(NilType.create().equals(NilType.create())); + assertFalse(NilType.create().equals(IntegerType.create(0))); + assertFalse(NilType.create().equals(BooleanType.create(false))); + } + + @Test + public void testString() throws Exception { + testString(""); + testString("a"); + testString("ab"); + testString("abc"); + } + public void testString(String str) throws Exception { + assertTrue(RawType.create(str).equals(RawType.create(str))); + } +} + diff --git a/java/src/test/java/org/msgpack/TestPackUnpack.java b/java/src/test/java/org/msgpack/TestPackUnpack.java index 6877853..494c8a8 100644 --- a/java/src/test/java/org/msgpack/TestPackUnpack.java +++ b/java/src/test/java/org/msgpack/TestPackUnpack.java @@ -3,239 +3,273 @@ package org.msgpack; import org.msgpack.*; import java.io.*; import java.util.*; +import java.math.BigInteger; import org.junit.Test; import static org.junit.Assert.*; public class TestPackUnpack { - protected Object unpackOne(ByteArrayOutputStream out) { - return unpackOne(out, null); - } - protected Object unpackOne(ByteArrayOutputStream out, Schema schema) { - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - Unpacker upk = new Unpacker(in); - if (schema != null) - upk = upk.useSchema(schema); - Iterator<Object> it = upk.iterator(); - assertEquals(true, it.hasNext()); - Object obj = it.next(); - assertEquals(false, it.hasNext()); - return obj; - } - - @Test - public void testInt() throws Exception { - testInt(0); - testInt(-1); - testInt(1); - testInt(Integer.MIN_VALUE); - testInt(Integer.MAX_VALUE); - Random rand = new Random(); - for (int i = 0; i < 1000; i++) - testInt(rand.nextInt()); - } - public void testInt(int val) throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new Packer(out).pack(val); - Object obj = unpackOne(out); - if (obj instanceof Byte) - assertEquals(val, ((Byte)obj).intValue()); - else if (obj instanceof Integer) - assertEquals(val, ((Integer)obj).intValue()); - else if (obj instanceof Short) - assertEquals(val, ((Short)obj).intValue()); - else if (obj instanceof Long) - assertEquals(val, ((Long)obj).intValue()); - else { - System.out.println("Got unexpected class: " + obj.getClass()); - assertTrue(false); - } - } - - @Test - public void testFloat() throws Exception { - testFloat((float)0.0); - testFloat((float)-0.0); - testFloat((float)1.0); - testFloat((float)-1.0); - testFloat((float)Float.MAX_VALUE); - testFloat((float)Float.MIN_VALUE); - testFloat((float)Float.NaN); - testFloat((float)Float.NEGATIVE_INFINITY); - testFloat((float)Float.POSITIVE_INFINITY); - Random rand = new Random(); - for (int i = 0; i < 1000; i++) - testFloat(rand.nextFloat()); - } - public void testFloat(float val) throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new Packer(out).pack(val); - Object obj = unpackOne(out); - if (obj instanceof Float) - assertEquals(val, ((Float)obj).floatValue(), 10e-10); - else { - System.out.println("Got unexpected class: " + obj.getClass()); - assertTrue(false); - } - } - - @Test - public void testDouble() throws Exception { - testDouble((double)0.0); - testDouble((double)-0.0); - testDouble((double)1.0); - testDouble((double)-1.0); - testDouble((double)Double.MAX_VALUE); - testDouble((double)Double.MIN_VALUE); - testDouble((double)Double.NaN); - testDouble((double)Double.NEGATIVE_INFINITY); - testDouble((double)Double.POSITIVE_INFINITY); - Random rand = new Random(); - for (int i = 0; i < 1000; i++) - testDouble(rand.nextDouble()); - } - public void testDouble(double val) throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new Packer(out).pack(val); - Object obj = unpackOne(out); - if (obj instanceof Double) - assertEquals(val, ((Double)obj).doubleValue(), 10e-10); - else { - System.out.println("Got unexpected class: " + obj.getClass()); - assertTrue(false); - } - } - - @Test - public void testNil() throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new Packer(out).packNil(); - Object obj = unpackOne(out); - assertEquals(null, obj); - } - - @Test - public void testBoolean() throws Exception { - testBoolean(false); - testBoolean(true); - } - public void testBoolean(boolean val) throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new Packer(out).pack(val); - Object obj = unpackOne(out); - if (obj instanceof Boolean) - assertEquals(val, ((Boolean)obj).booleanValue()); - else { - System.out.println("Got unexpected class: " + obj.getClass()); - assertTrue(false); - } - } - - @Test - public void testString() throws Exception { - testString(""); - testString("a"); - testString("ab"); - testString("abc"); - // small size string - for (int i = 0; i < 100; i++) { - StringBuilder sb = new StringBuilder(); - int len = (int)Math.random() % 31 + 1; - for (int j = 0; j < len; j++) - sb.append('a' + ((int)Math.random()) & 26); - testString(sb.toString()); - } - // medium size string - for (int i = 0; i < 100; i++) { - StringBuilder sb = new StringBuilder(); - int len = (int)Math.random() % 100 + (1 << 15); - for (int j = 0; j < len; j++) - sb.append('a' + ((int)Math.random()) & 26); - testString(sb.toString()); - } - // large size string - for (int i = 0; i < 10; i++) { - StringBuilder sb = new StringBuilder(); - int len = (int)Math.random() % 100 + (1 << 31); - for (int j = 0; j < len; j++) - sb.append('a' + ((int)Math.random()) & 26); - testString(sb.toString()); - } - } - public void testString(String val) throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new Packer(out).pack(val); - Object obj = unpackOne(out); - if (obj instanceof byte[]) - assertEquals(val, new String((byte[])obj)); - else { - System.out.println("obj=" + obj); - System.out.println("Got unexpected class: " + obj.getClass()); - assertTrue(false); - } - } - - @Test - public void testArray() throws Exception { - for (int i = 0; i < 1000; i++) { - Schema schema = Schema.parse("(array int)"); - List<Integer> l = new ArrayList<Integer>(); - int len = (int)Math.random() % 1000 + 1; - for (int j = 0; j < len; j++) - l.add(j); - testArray(l, schema); - } - for (int i = 0; i < 1000; i++) { - Schema schema = Schema.parse("(array string)"); - List<String> l = new ArrayList<String>(); - int len = (int)Math.random() % 1000 + 1; - for (int j = 0; j < len; j++) - l.add(Integer.toString(j)); - testArray(l, schema); - } - } - public void testArray(List val, Schema schema) throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new Packer(out).pack(val); - Object obj = unpackOne(out, schema); - if (obj instanceof List) - assertTrue(val.equals(obj)); - else { - System.out.println("obj=" + obj); - System.out.println("Got unexpected class: " + obj.getClass()); - assertTrue(false); - } - } - - @Test - public void testMap() throws Exception { - for (int i = 0; i < 1000; i++) { - Schema schema = Schema.parse("(map int int)"); - Map<Integer, Integer> m = new HashMap<Integer, Integer>(); - int len = (int)Math.random() % 1000 + 1; - for (int j = 0; j < len; j++) - m.put(j, j); - testMap(m, schema); - } - for (int i = 0; i < 1000; i++) { - Schema schema = Schema.parse("(map string int)"); - Map<String, Integer> m = new HashMap<String, Integer>(); - int len = (int)Math.random() % 1000 + 1; - for (int j = 0; j < len; j++) - m.put(Integer.toString(j), j); - testMap(m, schema); - } - } - public void testMap(Map val, Schema schema) throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new Packer(out).pack(val); - Object obj = unpackOne(out, schema); - if (obj instanceof Map) - assertTrue(val.equals(obj)); - else { - System.out.println("obj=" + obj); - System.out.println("Got unexpected class: " + obj.getClass()); - assertTrue(false); - } - } + public MessagePackObject unpackOne(ByteArrayOutputStream out) { + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + Iterator<MessagePackObject> it = pac.iterator(); + assertEquals(true, it.hasNext()); + MessagePackObject obj = it.next(); + assertEquals(false, it.hasNext()); + return obj; + } + + @Test + public void testInt() throws Exception { + testInt(0); + testInt(-1); + testInt(1); + testInt(Integer.MIN_VALUE); + testInt(Integer.MAX_VALUE); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testInt(rand.nextInt()); + } + public void testInt(int val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + MessagePackObject obj = unpackOne(out); + assertEquals(val, obj.asInt()); + } + + @Test + public void testLong() throws Exception { + testLong(0); + testLong(-1); + testLong(1); + testLong(Integer.MIN_VALUE); + testLong(Integer.MAX_VALUE); + testLong(Long.MIN_VALUE); + testLong(Long.MAX_VALUE); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testLong(rand.nextLong()); + } + public void testLong(long val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + MessagePackObject obj = unpackOne(out); + assertEquals(val, obj.asLong()); + } + + @Test + public void testBigInteger() throws Exception { + testBigInteger(BigInteger.valueOf(0)); + testBigInteger(BigInteger.valueOf(-1)); + testBigInteger(BigInteger.valueOf(1)); + testBigInteger(BigInteger.valueOf(Integer.MIN_VALUE)); + testBigInteger(BigInteger.valueOf(Integer.MAX_VALUE)); + testBigInteger(BigInteger.valueOf(Long.MIN_VALUE)); + testBigInteger(BigInteger.valueOf(Long.MAX_VALUE)); + BigInteger max = BigInteger.valueOf(Long.MAX_VALUE).setBit(63); + testBigInteger(max); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testBigInteger( max.subtract(BigInteger.valueOf( Math.abs(rand.nextLong()) )) ); + } + public void testBigInteger(BigInteger val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + MessagePackObject obj = unpackOne(out); + assertEquals(val, obj.asBigInteger()); + } + + @Test + public void testFloat() throws Exception { + testFloat((float)0.0); + testFloat((float)-0.0); + testFloat((float)1.0); + testFloat((float)-1.0); + testFloat((float)Float.MAX_VALUE); + testFloat((float)Float.MIN_VALUE); + testFloat((float)Float.NaN); + testFloat((float)Float.NEGATIVE_INFINITY); + testFloat((float)Float.POSITIVE_INFINITY); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testFloat(rand.nextFloat()); + } + public void testFloat(float val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + MessagePackObject obj = unpackOne(out); + float f = obj.asFloat(); + assertEquals(val, f, 10e-10); + } + + @Test + public void testDouble() throws Exception { + testDouble((double)0.0); + testDouble((double)-0.0); + testDouble((double)1.0); + testDouble((double)-1.0); + testDouble((double)Double.MAX_VALUE); + testDouble((double)Double.MIN_VALUE); + testDouble((double)Double.NaN); + testDouble((double)Double.NEGATIVE_INFINITY); + testDouble((double)Double.POSITIVE_INFINITY); + Random rand = new Random(); + for (int i = 0; i < 1000; i++) + testDouble(rand.nextDouble()); + } + public void testDouble(double val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + MessagePackObject obj = unpackOne(out); + double f = obj.asDouble(); + assertEquals(val, f, 10e-10); + } + + @Test + public void testNil() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).packNil(); + MessagePackObject obj = unpackOne(out); + assertTrue(obj.isNil()); + } + + @Test + public void testBoolean() throws Exception { + testBoolean(false); + testBoolean(true); + } + public void testBoolean(boolean val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + MessagePackObject obj = unpackOne(out); + assertEquals(val, obj.asBoolean()); + } + + @Test + public void testString() throws Exception { + testString(""); + testString("a"); + testString("ab"); + testString("abc"); + + // small size string + for (int i = 0; i < 100; i++) { + StringBuilder sb = new StringBuilder(); + int len = (int)Math.random() % 31 + 1; + for (int j = 0; j < len; j++) + sb.append('a' + ((int)Math.random()) & 26); + testString(sb.toString()); + } + + // medium size string + for (int i = 0; i < 100; i++) { + StringBuilder sb = new StringBuilder(); + int len = (int)Math.random() % 100 + (1 << 15); + for (int j = 0; j < len; j++) + sb.append('a' + ((int)Math.random()) & 26); + testString(sb.toString()); + } + + // large size string + for (int i = 0; i < 10; i++) { + StringBuilder sb = new StringBuilder(); + int len = (int)Math.random() % 100 + (1 << 31); + for (int j = 0; j < len; j++) + sb.append('a' + ((int)Math.random()) & 26); + testString(sb.toString()); + } + } + public void testString(String val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + MessagePackObject obj = unpackOne(out); + assertEquals(val, obj.asString()); + } + + @Test + public void testArray() throws Exception { + List<Integer> emptyList = new ArrayList<Integer>(); + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(emptyList); + MessagePackObject obj = unpackOne(out); + assertEquals(emptyList, obj.asList()); + } + + for (int i = 0; i < 1000; i++) { + List<Integer> l = new ArrayList<Integer>(); + int len = (int)Math.random() % 1000 + 1; + for (int j = 0; j < len; j++) + l.add(j); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(l); + MessagePackObject obj = unpackOne(out); + List<MessagePackObject> list = obj.asList(); + assertEquals(l.size(), list.size()); + for (int j = 0; j < len; j++) { + assertEquals(l.get(j).intValue(), list.get(j).asInt()); + } + } + + for (int i = 0; i < 1000; i++) { + List<String> l = new ArrayList<String>(); + int len = (int)Math.random() % 1000 + 1; + for (int j = 0; j < len; j++) + l.add(Integer.toString(j)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(l); + MessagePackObject obj = unpackOne(out); + List<MessagePackObject> list = obj.asList(); + assertEquals(l.size(), list.size()); + for (int j = 0; j < len; j++) { + assertEquals(l.get(j), list.get(j).asString()); + } + } + } + + @Test + public void testMap() throws Exception { + Map<Integer, Integer> emptyMap = new HashMap<Integer, Integer>(); + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(emptyMap); + MessagePackObject obj = unpackOne(out); + assertEquals(emptyMap, obj.asMap()); + } + + for (int i = 0; i < 1000; i++) { + Map<Integer, Integer> m = new HashMap<Integer, Integer>(); + int len = (int)Math.random() % 1000 + 1; + for (int j = 0; j < len; j++) + m.put(j, j); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(m); + MessagePackObject obj = unpackOne(out); + Map<MessagePackObject, MessagePackObject> map = obj.asMap(); + assertEquals(m.size(), map.size()); + for (Map.Entry<MessagePackObject, MessagePackObject> pair : map.entrySet()) { + Integer val = m.get(pair.getKey().asInt()); + assertNotNull(val); + assertEquals(val.intValue(), pair.getValue().asInt()); + } + } + + for (int i = 0; i < 1000; i++) { + Map<String, Integer> m = new HashMap<String, Integer>(); + int len = (int)Math.random() % 1000 + 1; + for (int j = 0; j < len; j++) + m.put(Integer.toString(j), j); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(m); + MessagePackObject obj = unpackOne(out); + Map<MessagePackObject, MessagePackObject> map = obj.asMap(); + assertEquals(m.size(), map.size()); + for (Map.Entry<MessagePackObject, MessagePackObject> pair : map.entrySet()) { + Integer val = m.get(pair.getKey().asString()); + assertNotNull(val); + assertEquals(val.intValue(), pair.getValue().asInt()); + } + } + } }; + diff --git a/java/src/test/resources/cases.json b/java/src/test/resources/cases.json new file mode 100644 index 0000000..fd390d4 --- /dev/null +++ b/java/src/test/resources/cases.json @@ -0,0 +1 @@ +[false,true,null,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,127,127,255,65535,4294967295,-32,-32,-128,-32768,-2147483648,0.0,-0.0,1.0,-1.0,"a","a","a","","","",[0],[0],[0],[],[],[],{},{},{},{"a":97},{"a":97},{"a":97},[[]],[["a"]]]
\ No newline at end of file diff --git a/java/src/test/resources/cases.mpac b/java/src/test/resources/cases.mpac Binary files differnew file mode 100644 index 0000000..5ec08c6 --- /dev/null +++ b/java/src/test/resources/cases.mpac diff --git a/java/src/test/resources/cases_compact.mpac b/java/src/test/resources/cases_compact.mpac Binary files differnew file mode 100644 index 0000000..8812442 --- /dev/null +++ b/java/src/test/resources/cases_compact.mpac |
