diff --git a/java/src/main/java/org/msgpack/MessageConvertable.java b/java/src/main/java/org/msgpack/MessageConvertable.java index da251dc1..8acf1f28 100644 --- a/java/src/main/java/org/msgpack/MessageConvertable.java +++ b/java/src/main/java/org/msgpack/MessageConvertable.java @@ -18,6 +18,6 @@ package org.msgpack; public interface MessageConvertable { - public void messageConvert(Object obj) throws MessageTypeException; + public void messageConvert(MessagePackObject obj) throws MessageTypeException; } diff --git a/java/src/main/java/org/msgpack/Packer.java b/java/src/main/java/org/msgpack/Packer.java index 98af3d64..60e04bfe 100644 --- a/java/src/main/java/org/msgpack/Packer.java +++ b/java/src/main/java/org/msgpack/Packer.java @@ -196,19 +196,19 @@ public class Packer { } public Packer packBigInteger(BigInteger d) throws IOException { - if(d.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) <= 0) { + if(d.bitLength() <= 63) { return packLong(d.longValue()); - } else if(d.bitLength() <= 64) { + } else if(d.bitLength() <= 64 && d.signum() >= 0) { castBytes[0] = (byte)0xcf; byte[] barray = d.toByteArray(); - castBytes[1] = barray[0]; - castBytes[2] = barray[1]; - castBytes[3] = barray[2]; - castBytes[4] = barray[3]; - castBytes[5] = barray[4]; - castBytes[6] = barray[5]; - castBytes[7] = barray[6]; - castBytes[8] = barray[7]; + 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 { @@ -436,6 +436,8 @@ 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 MessageTypeException("unknown object "+o+" ("+o.getClass()+")"); } diff --git a/java/src/main/java/org/msgpack/UnpackerImpl.java b/java/src/main/java/org/msgpack/UnpackerImpl.java index d4f99e38..6a7085fb 100644 --- a/java/src/main/java/org/msgpack/UnpackerImpl.java +++ b/java/src/main/java/org/msgpack/UnpackerImpl.java @@ -18,6 +18,7 @@ package org.msgpack; import java.nio.ByteBuffer; +import java.math.BigInteger; import org.msgpack.object.*; public class UnpackerImpl { @@ -262,9 +263,7 @@ 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 = IntegerType.create(o); } diff --git a/java/src/test/java/org/msgpack/TestPackUnpack.java b/java/src/test/java/org/msgpack/TestPackUnpack.java index ca3d235c..75c5fe74 100644 --- a/java/src/test/java/org/msgpack/TestPackUnpack.java +++ b/java/src/test/java/org/msgpack/TestPackUnpack.java @@ -3,6 +3,7 @@ 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.*; @@ -36,6 +37,32 @@ public class TestPackUnpack { testInt(rand.nextInt()); } + public void testBigInteger(BigInteger val) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(val); + MessagePackObject obj = unpackOne(out); + if(!val.equals(obj.asBigInteger())) { + System.out.println("expect: "+val); + System.out.println("but : "+obj.asBigInteger()); + } + assertEquals(val, obj.asBigInteger()); + } + @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 testFloat(float val) throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); new Packer(out).pack(val);