mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-19 21:18:23 +01:00
Merge branch 'master' of git@github.com:msgpack/msgpack
This commit is contained in:
commit
53b0ee6536
@ -18,6 +18,7 @@
|
|||||||
package org.msgpack;
|
package org.msgpack;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import org.msgpack.template.TemplateRegistry;
|
||||||
|
|
||||||
public class CustomMessage {
|
public class CustomMessage {
|
||||||
public static void registerPacker(Class<?> target, MessagePacker packer) {
|
public static void registerPacker(Class<?> target, MessagePacker packer) {
|
||||||
@ -33,6 +34,7 @@ public class CustomMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void register(Class<?> target, Template tmpl) {
|
public static void register(Class<?> target, Template tmpl) {
|
||||||
|
TemplateRegistry.register(target, tmpl);
|
||||||
CustomPacker.register(target, tmpl);
|
CustomPacker.register(target, tmpl);
|
||||||
CustomConverter.register(target, tmpl);
|
CustomConverter.register(target, tmpl);
|
||||||
CustomUnpacker.register(target, tmpl);
|
CustomUnpacker.register(target, tmpl);
|
||||||
|
@ -27,6 +27,8 @@ import java.lang.reflect.Method;
|
|||||||
import org.msgpack.util.codegen.DynamicTemplate;
|
import org.msgpack.util.codegen.DynamicTemplate;
|
||||||
import org.msgpack.util.codegen.DynamicOrdinalEnumTemplate;
|
import org.msgpack.util.codegen.DynamicOrdinalEnumTemplate;
|
||||||
import org.msgpack.util.codegen.FieldList;
|
import org.msgpack.util.codegen.FieldList;
|
||||||
|
import org.msgpack.template.TemplateRegistry;
|
||||||
|
import org.msgpack.template.TemplateBuilder;
|
||||||
|
|
||||||
public class MessagePack {
|
public class MessagePack {
|
||||||
public static byte[] pack(Object obj) {
|
public static byte[] pack(Object obj) {
|
||||||
@ -150,6 +152,8 @@ public class MessagePack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void register(Class<?> target) { // auto-detect
|
public static void register(Class<?> target) { // auto-detect
|
||||||
|
TemplateRegistry.register(target);
|
||||||
|
|
||||||
Template tmpl;
|
Template tmpl;
|
||||||
if(target.isEnum()) {
|
if(target.isEnum()) {
|
||||||
tmpl = DynamicOrdinalEnumTemplate.create(target);
|
tmpl = DynamicOrdinalEnumTemplate.create(target);
|
||||||
@ -194,6 +198,7 @@ public class MessagePack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void register(Class<?> target, FieldList opts) {
|
public static void register(Class<?> target, FieldList opts) {
|
||||||
|
TemplateRegistry.register(target); // FIXME FieldList
|
||||||
Template tmpl = DynamicTemplate.create(target, opts);
|
Template tmpl = DynamicTemplate.create(target, opts);
|
||||||
CustomPacker.register(target, tmpl);
|
CustomPacker.register(target, tmpl);
|
||||||
CustomConverter.register(target, tmpl);
|
CustomConverter.register(target, tmpl);
|
||||||
@ -201,6 +206,7 @@ public class MessagePack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void register(Class<?> target, Template tmpl) {
|
public static void register(Class<?> target, Template tmpl) {
|
||||||
|
TemplateRegistry.register(target, tmpl);
|
||||||
CustomPacker.register(target, tmpl);
|
CustomPacker.register(target, tmpl);
|
||||||
CustomConverter.register(target, tmpl);
|
CustomConverter.register(target, tmpl);
|
||||||
CustomUnpacker.register(target, tmpl);
|
CustomUnpacker.register(target, tmpl);
|
||||||
|
@ -21,14 +21,9 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.msgpack.template.ClassTemplate;
|
import org.msgpack.template.TemplateRegistry;
|
||||||
import org.msgpack.template.NullableTemplate;
|
|
||||||
|
|
||||||
public abstract class MessagePackObject implements Cloneable, MessagePackable {
|
public abstract class MessagePackObject implements Cloneable, MessagePackable {
|
||||||
static {
|
|
||||||
Templates.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNil() {
|
public boolean isNil() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -155,9 +150,11 @@ public abstract class MessagePackObject implements Cloneable, MessagePackable {
|
|||||||
return convert((Class<T>)to.getClass(), to);
|
return convert((Class<T>)to.getClass(), to);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T convert(Class<T> klass, T to) throws MessageTypeException {
|
public <T> T convert(Class<T> klass, T to) throws MessageTypeException {
|
||||||
// FIXME nullable?
|
if(isNil()) {
|
||||||
return (T)convert(new NullableTemplate(new ClassTemplate(klass)), to);
|
return null;
|
||||||
|
}
|
||||||
|
return (T)convert(TemplateRegistry.lookup(klass), to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,5 +27,9 @@ public class MessageTypeException extends RuntimeException {
|
|||||||
public MessageTypeException(String s, Throwable t) {
|
public MessageTypeException(String s, Throwable t) {
|
||||||
super(s, t);
|
super(s, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MessageTypeException(Throwable t) {
|
||||||
|
super(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,7 @@ import java.util.Set;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import org.msgpack.template.TemplateRegistry;
|
||||||
import org.msgpack.annotation.MessagePackDelegate;
|
|
||||||
import org.msgpack.annotation.MessagePackMessage;
|
|
||||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
|
||||||
import org.msgpack.util.codegen.DynamicTemplate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packer enables you to serialize objects into OutputStream.
|
* Packer enables you to serialize objects into OutputStream.
|
||||||
@ -48,14 +44,10 @@ import org.msgpack.util.codegen.DynamicTemplate;
|
|||||||
* You can serialize objects that implements {@link MessagePackable} interface.
|
* You can serialize objects that implements {@link MessagePackable} interface.
|
||||||
*/
|
*/
|
||||||
public class Packer {
|
public class Packer {
|
||||||
static {
|
|
||||||
Templates.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void load() { }
|
public static void load() { }
|
||||||
|
|
||||||
protected byte[] castBytes = new byte[9];
|
protected byte[] castBytes = new byte[9];
|
||||||
protected ByteBuffer castBuffer = ByteBuffer.wrap(castBytes);
|
//protected ByteBuffer castBuffer = ByteBuffer.wrap(castBytes);
|
||||||
protected OutputStream out;
|
protected OutputStream out;
|
||||||
|
|
||||||
public Packer(OutputStream out) {
|
public Packer(OutputStream out) {
|
||||||
@ -78,7 +70,9 @@ public class Packer {
|
|||||||
if(d < -(1<<7)) {
|
if(d < -(1<<7)) {
|
||||||
// signed 16
|
// signed 16
|
||||||
castBytes[0] = (byte)0xd1;
|
castBytes[0] = (byte)0xd1;
|
||||||
castBuffer.putShort(1, d);
|
// castBuffer.putShort(1, d);
|
||||||
|
castBytes[1] = (byte)(d >> 8);
|
||||||
|
castBytes[2] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 3);
|
out.write(castBytes, 0, 3);
|
||||||
} else {
|
} else {
|
||||||
// signed 8
|
// signed 8
|
||||||
@ -98,7 +92,9 @@ public class Packer {
|
|||||||
} else {
|
} else {
|
||||||
// unsigned 16
|
// unsigned 16
|
||||||
castBytes[0] = (byte)0xcd;
|
castBytes[0] = (byte)0xcd;
|
||||||
castBuffer.putShort(1, d);
|
// castBuffer.putShort(1, d);
|
||||||
|
castBytes[1] = (byte)(d >> 8);
|
||||||
|
castBytes[2] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 3);
|
out.write(castBytes, 0, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,12 +106,18 @@ public class Packer {
|
|||||||
if(d < -(1<<15)) {
|
if(d < -(1<<15)) {
|
||||||
// signed 32
|
// signed 32
|
||||||
castBytes[0] = (byte)0xd2;
|
castBytes[0] = (byte)0xd2;
|
||||||
castBuffer.putInt(1, d);
|
// castBuffer.putInt(1, d);
|
||||||
|
castBytes[1] = (byte)(d >> 24);
|
||||||
|
castBytes[2] = (byte)(d >> 16);
|
||||||
|
castBytes[3] = (byte)(d >> 8);
|
||||||
|
castBytes[4] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 5);
|
out.write(castBytes, 0, 5);
|
||||||
} else if(d < -(1<<7)) {
|
} else if(d < -(1<<7)) {
|
||||||
// signed 16
|
// signed 16
|
||||||
castBytes[0] = (byte)0xd1;
|
castBytes[0] = (byte)0xd1;
|
||||||
castBuffer.putShort(1, (short)d);
|
// castBuffer.putShort(1, (short)d);
|
||||||
|
castBytes[1] = (byte)(d >> 8);
|
||||||
|
castBytes[2] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 3);
|
out.write(castBytes, 0, 3);
|
||||||
} else {
|
} else {
|
||||||
// signed 8
|
// signed 8
|
||||||
@ -135,12 +137,18 @@ public class Packer {
|
|||||||
} else if(d < (1<<16)) {
|
} else if(d < (1<<16)) {
|
||||||
// unsigned 16
|
// unsigned 16
|
||||||
castBytes[0] = (byte)0xcd;
|
castBytes[0] = (byte)0xcd;
|
||||||
castBuffer.putShort(1, (short)d);
|
// castBuffer.putShort(1, (short)d);
|
||||||
|
castBytes[1] = (byte)(d >> 8);
|
||||||
|
castBytes[2] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 3);
|
out.write(castBytes, 0, 3);
|
||||||
} else {
|
} else {
|
||||||
// unsigned 32
|
// unsigned 32
|
||||||
castBytes[0] = (byte)0xce;
|
castBytes[0] = (byte)0xce;
|
||||||
castBuffer.putInt(1, d);
|
// castBuffer.putInt(1, d);
|
||||||
|
castBytes[1] = (byte)(d >> 24);
|
||||||
|
castBytes[2] = (byte)(d >> 16);
|
||||||
|
castBytes[3] = (byte)(d >> 8);
|
||||||
|
castBytes[4] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 5);
|
out.write(castBytes, 0, 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,19 +161,33 @@ public class Packer {
|
|||||||
if(d < -(1L<<31)) {
|
if(d < -(1L<<31)) {
|
||||||
// signed 64
|
// signed 64
|
||||||
castBytes[0] = (byte)0xd3;
|
castBytes[0] = (byte)0xd3;
|
||||||
castBuffer.putLong(1, d);
|
// castBuffer.putLong(1, d);
|
||||||
|
castBytes[1] = (byte)(d >> 56);
|
||||||
|
castBytes[2] = (byte)(d >> 48);
|
||||||
|
castBytes[3] = (byte)(d >> 40);
|
||||||
|
castBytes[4] = (byte)(d >> 32);
|
||||||
|
castBytes[5] = (byte)(d >> 24);
|
||||||
|
castBytes[6] = (byte)(d >> 16);
|
||||||
|
castBytes[7] = (byte)(d >> 8);
|
||||||
|
castBytes[8] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 9);
|
out.write(castBytes, 0, 9);
|
||||||
} else {
|
} else {
|
||||||
// signed 32
|
// signed 32
|
||||||
castBytes[0] = (byte)0xd2;
|
castBytes[0] = (byte)0xd2;
|
||||||
castBuffer.putInt(1, (int)d);
|
// castBuffer.putInt(1, (int)d);
|
||||||
|
castBytes[1] = (byte)(d >> 24);
|
||||||
|
castBytes[2] = (byte)(d >> 16);
|
||||||
|
castBytes[3] = (byte)(d >> 8);
|
||||||
|
castBytes[4] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 5);
|
out.write(castBytes, 0, 5);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(d < -(1<<7)) {
|
if(d < -(1<<7)) {
|
||||||
// signed 16
|
// signed 16
|
||||||
castBytes[0] = (byte)0xd1;
|
castBytes[0] = (byte)0xd1;
|
||||||
castBuffer.putShort(1, (short)d);
|
// castBuffer.putShort(1, (short)d);
|
||||||
|
castBytes[1] = (byte)(d >> 8);
|
||||||
|
castBytes[2] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 3);
|
out.write(castBytes, 0, 3);
|
||||||
} else {
|
} else {
|
||||||
// signed 8
|
// signed 8
|
||||||
@ -187,7 +209,9 @@ public class Packer {
|
|||||||
} else {
|
} else {
|
||||||
// unsigned 16
|
// unsigned 16
|
||||||
castBytes[0] = (byte)0xcd;
|
castBytes[0] = (byte)0xcd;
|
||||||
castBuffer.putShort(1, (short)d);
|
// castBuffer.putShort(1, (short)d);
|
||||||
|
castBytes[1] = (byte)((d & 0x0000ff00) >> 8);
|
||||||
|
castBytes[2] = (byte)((d & 0x000000ff) >> 0);
|
||||||
out.write(castBytes, 0, 3);
|
out.write(castBytes, 0, 3);
|
||||||
//System.out.println("pack uint 16 "+(short)d);
|
//System.out.println("pack uint 16 "+(short)d);
|
||||||
}
|
}
|
||||||
@ -195,12 +219,24 @@ public class Packer {
|
|||||||
if(d < (1L<<32)) {
|
if(d < (1L<<32)) {
|
||||||
// unsigned 32
|
// unsigned 32
|
||||||
castBytes[0] = (byte)0xce;
|
castBytes[0] = (byte)0xce;
|
||||||
castBuffer.putInt(1, (int)d);
|
// castBuffer.putInt(1, (int)d);
|
||||||
|
castBytes[1] = (byte)((d & 0xff000000) >> 24);
|
||||||
|
castBytes[2] = (byte)((d & 0x00ff0000) >> 16);
|
||||||
|
castBytes[3] = (byte)((d & 0x0000ff00) >> 8);
|
||||||
|
castBytes[4] = (byte)((d & 0x000000ff) >> 0);
|
||||||
out.write(castBytes, 0, 5);
|
out.write(castBytes, 0, 5);
|
||||||
} else {
|
} else {
|
||||||
// unsigned 64
|
// unsigned 64
|
||||||
castBytes[0] = (byte)0xcf;
|
castBytes[0] = (byte)0xcf;
|
||||||
castBuffer.putLong(1, d);
|
// castBuffer.putLong(1, d);
|
||||||
|
castBytes[1] = (byte)(d >> 56);
|
||||||
|
castBytes[2] = (byte)(d >> 48);
|
||||||
|
castBytes[3] = (byte)(d >> 40);
|
||||||
|
castBytes[4] = (byte)(d >> 32);
|
||||||
|
castBytes[5] = (byte)(d >> 24);
|
||||||
|
castBytes[6] = (byte)(d >> 16);
|
||||||
|
castBytes[7] = (byte)(d >> 8);
|
||||||
|
castBytes[8] = (byte)(d >> 0);
|
||||||
out.write(castBytes, 0, 9);
|
out.write(castBytes, 0, 9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,7 +258,7 @@ public class Packer {
|
|||||||
castBytes[6] = barray[barray.length-3];
|
castBytes[6] = barray[barray.length-3];
|
||||||
castBytes[7] = barray[barray.length-2];
|
castBytes[7] = barray[barray.length-2];
|
||||||
castBytes[8] = barray[barray.length-1];
|
castBytes[8] = barray[barray.length-1];
|
||||||
out.write(castBytes);
|
out.write(castBytes, 0, 9);
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
throw new MessageTypeException("can't pack BigInteger larger than 0xffffffffffffffff");
|
throw new MessageTypeException("can't pack BigInteger larger than 0xffffffffffffffff");
|
||||||
@ -231,14 +267,28 @@ public class Packer {
|
|||||||
|
|
||||||
public Packer packFloat(float d) throws IOException {
|
public Packer packFloat(float d) throws IOException {
|
||||||
castBytes[0] = (byte)0xca;
|
castBytes[0] = (byte)0xca;
|
||||||
castBuffer.putFloat(1, d);
|
// castBuffer.putFloat(1, d);
|
||||||
|
int f = Float.floatToRawIntBits(d);
|
||||||
|
castBytes[1] = (byte)(f >> 24);
|
||||||
|
castBytes[2] = (byte)(f >> 16);
|
||||||
|
castBytes[3] = (byte)(f >> 8);
|
||||||
|
castBytes[4] = (byte)(f >> 0);
|
||||||
out.write(castBytes, 0, 5);
|
out.write(castBytes, 0, 5);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Packer packDouble(double d) throws IOException {
|
public Packer packDouble(double d) throws IOException {
|
||||||
castBytes[0] = (byte)0xcb;
|
castBytes[0] = (byte)0xcb;
|
||||||
castBuffer.putDouble(1, d);
|
// castBuffer.putDouble(1, d);
|
||||||
|
long f = Double.doubleToRawLongBits(d);
|
||||||
|
castBytes[1] = (byte)(f >> 56);
|
||||||
|
castBytes[2] = (byte)(f >> 48);
|
||||||
|
castBytes[3] = (byte)(f >> 40);
|
||||||
|
castBytes[4] = (byte)(f >> 32);
|
||||||
|
castBytes[5] = (byte)(f >> 24);
|
||||||
|
castBytes[6] = (byte)(f >> 16);
|
||||||
|
castBytes[7] = (byte)(f >> 8);
|
||||||
|
castBytes[8] = (byte)(f >> 0);
|
||||||
out.write(castBytes, 0, 9);
|
out.write(castBytes, 0, 9);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -268,11 +318,17 @@ public class Packer {
|
|||||||
out.write((byte)d);
|
out.write((byte)d);
|
||||||
} else if(n < 65536) {
|
} else if(n < 65536) {
|
||||||
castBytes[0] = (byte)0xdc;
|
castBytes[0] = (byte)0xdc;
|
||||||
castBuffer.putShort(1, (short)n);
|
// castBuffer.putShort(1, (short)n);
|
||||||
|
castBytes[1] = (byte)(n >> 8);
|
||||||
|
castBytes[2] = (byte)(n >> 0);
|
||||||
out.write(castBytes, 0, 3);
|
out.write(castBytes, 0, 3);
|
||||||
} else {
|
} else {
|
||||||
castBytes[0] = (byte)0xdd;
|
castBytes[0] = (byte)0xdd;
|
||||||
castBuffer.putInt(1, n);
|
// castBuffer.putInt(1, n);
|
||||||
|
castBytes[1] = (byte)(n >> 24);
|
||||||
|
castBytes[2] = (byte)(n >> 16);
|
||||||
|
castBytes[3] = (byte)(n >> 8);
|
||||||
|
castBytes[4] = (byte)(n >> 0);
|
||||||
out.write(castBytes, 0, 5);
|
out.write(castBytes, 0, 5);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
@ -284,11 +340,17 @@ public class Packer {
|
|||||||
out.write((byte)d);
|
out.write((byte)d);
|
||||||
} else if(n < 65536) {
|
} else if(n < 65536) {
|
||||||
castBytes[0] = (byte)0xde;
|
castBytes[0] = (byte)0xde;
|
||||||
castBuffer.putShort(1, (short)n);
|
// castBuffer.putShort(1, (short)n);
|
||||||
|
castBytes[1] = (byte)(n >> 8);
|
||||||
|
castBytes[2] = (byte)(n >> 0);
|
||||||
out.write(castBytes, 0, 3);
|
out.write(castBytes, 0, 3);
|
||||||
} else {
|
} else {
|
||||||
castBytes[0] = (byte)0xdf;
|
castBytes[0] = (byte)0xdf;
|
||||||
castBuffer.putInt(1, n);
|
// castBuffer.putInt(1, n);
|
||||||
|
castBytes[1] = (byte)(n >> 24);
|
||||||
|
castBytes[2] = (byte)(n >> 16);
|
||||||
|
castBytes[3] = (byte)(n >> 8);
|
||||||
|
castBytes[4] = (byte)(n >> 0);
|
||||||
out.write(castBytes, 0, 5);
|
out.write(castBytes, 0, 5);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
@ -300,11 +362,17 @@ public class Packer {
|
|||||||
out.write((byte)d);
|
out.write((byte)d);
|
||||||
} else if(n < 65536) {
|
} else if(n < 65536) {
|
||||||
castBytes[0] = (byte)0xda;
|
castBytes[0] = (byte)0xda;
|
||||||
castBuffer.putShort(1, (short)n);
|
// castBuffer.putShort(1, (short)n);
|
||||||
|
castBytes[1] = (byte)(n >> 8);
|
||||||
|
castBytes[2] = (byte)(n >> 0);
|
||||||
out.write(castBytes, 0, 3);
|
out.write(castBytes, 0, 3);
|
||||||
} else {
|
} else {
|
||||||
castBytes[0] = (byte)0xdb;
|
castBytes[0] = (byte)0xdb;
|
||||||
castBuffer.putInt(1, n);
|
// castBuffer.putInt(1, n);
|
||||||
|
castBytes[1] = (byte)(n >> 24);
|
||||||
|
castBytes[2] = (byte)(n >> 16);
|
||||||
|
castBytes[3] = (byte)(n >> 8);
|
||||||
|
castBytes[4] = (byte)(n >> 0);
|
||||||
out.write(castBytes, 0, 5);
|
out.write(castBytes, 0, 5);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
@ -449,7 +517,8 @@ public class Packer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Packer pack(Object o) throws IOException {
|
public Packer pack(Object o) throws IOException {
|
||||||
Templates.TAny.pack(this, o);
|
if(o == null) { return packNil(); }
|
||||||
|
TemplateRegistry.lookup(o.getClass()).pack(this, o);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,8 +20,6 @@ package org.msgpack;
|
|||||||
import org.msgpack.template.*;
|
import org.msgpack.template.*;
|
||||||
|
|
||||||
public class Templates {
|
public class Templates {
|
||||||
public static void load() { }
|
|
||||||
|
|
||||||
public static Template tNullable(Template elementTemplate) {
|
public static Template tNullable(Template elementTemplate) {
|
||||||
return new NullableTemplate(elementTemplate);
|
return new NullableTemplate(elementTemplate);
|
||||||
}
|
}
|
||||||
@ -46,7 +44,11 @@ public class Templates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Template tClass(Class target) {
|
public static Template tClass(Class target) {
|
||||||
return new ClassTemplate(target);
|
Template tmpl = TemplateRegistry.lookup(target);
|
||||||
|
if(tmpl == null) {
|
||||||
|
// FIXME
|
||||||
|
}
|
||||||
|
return tmpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Template TByte = ByteTemplate.getInstance();
|
public static final Template TByte = ByteTemplate.getInstance();
|
||||||
|
@ -23,8 +23,7 @@ import java.io.IOException;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.msgpack.template.ClassTemplate;
|
import org.msgpack.template.TemplateRegistry;
|
||||||
import org.msgpack.template.NullableTemplate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unpacker enables you to deserialize objects from stream.
|
* Unpacker enables you to deserialize objects from stream.
|
||||||
@ -105,10 +104,6 @@ import org.msgpack.template.NullableTemplate;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class Unpacker implements Iterable<MessagePackObject> {
|
public class Unpacker implements Iterable<MessagePackObject> {
|
||||||
static {
|
|
||||||
Templates.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
// buffer:
|
// buffer:
|
||||||
// +---------------------------------------------+
|
// +---------------------------------------------+
|
||||||
// | [object] | [obje| unparsed ... | unused ...|
|
// | [object] | [obje| unparsed ... | unused ...|
|
||||||
@ -578,6 +573,19 @@ public class Unpacker implements Iterable<MessagePackObject> {
|
|||||||
// return unpackObject();
|
// return unpackObject();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
final public <T> T unpack(T to) throws IOException, MessageTypeException {
|
||||||
|
return unpack((Class<T>)to.getClass(), to);
|
||||||
|
}
|
||||||
|
|
||||||
|
final public <T> T unpack(Class<T> klass) throws IOException, MessageTypeException {
|
||||||
|
return unpack(klass, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final public <T> T unpack(Class<T> klass, T to) throws IOException, MessageTypeException {
|
||||||
|
if(tryUnpackNull()) { return null; }
|
||||||
|
return (T)TemplateRegistry.lookup(klass).unpack(this, to);
|
||||||
|
}
|
||||||
|
|
||||||
final public Object unpack(Template tmpl) throws IOException, MessageTypeException {
|
final public Object unpack(Template tmpl) throws IOException, MessageTypeException {
|
||||||
return unpack(tmpl, null);
|
return unpack(tmpl, null);
|
||||||
}
|
}
|
||||||
@ -585,18 +593,5 @@ public class Unpacker implements Iterable<MessagePackObject> {
|
|||||||
final public <T> T unpack(Template tmpl, T to) throws IOException, MessageTypeException {
|
final public <T> T unpack(Template tmpl, T to) throws IOException, MessageTypeException {
|
||||||
return (T)tmpl.unpack(this, to);
|
return (T)tmpl.unpack(this, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
final public <T> T unpack(Class<T> klass) throws IOException, MessageTypeException {
|
|
||||||
return unpack(klass, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
final public <T> T unpack(T to) throws IOException, MessageTypeException {
|
|
||||||
return unpack((Class<T>)to.getClass(), to);
|
|
||||||
}
|
|
||||||
|
|
||||||
final public <T> T unpack(Class<T> klass, T to) throws IOException, MessageTypeException {
|
|
||||||
// FIXME nullable?
|
|
||||||
return (T)unpack(new NullableTemplate(new ClassTemplate(klass)), to);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
java/src/main/java/org/msgpack/annotation/Ignore.java
Normal file
28
java/src/main/java/org/msgpack/annotation/Ignore.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// 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.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Ignore {
|
||||||
|
}
|
29
java/src/main/java/org/msgpack/annotation/Index.java
Normal file
29
java/src/main/java/org/msgpack/annotation/Index.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// 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.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Index {
|
||||||
|
int value();
|
||||||
|
}
|
@ -25,4 +25,5 @@ import java.lang.annotation.Target;
|
|||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface MessagePackDelegate {
|
public @interface MessagePackDelegate {
|
||||||
|
String value();
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,10 @@ import java.lang.annotation.ElementType;
|
|||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
import org.msgpack.template.FieldOption;
|
||||||
|
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface MessagePackMessage {
|
public @interface MessagePackMessage {
|
||||||
|
FieldOption value() default FieldOption.DEFAULT;
|
||||||
}
|
}
|
||||||
|
28
java/src/main/java/org/msgpack/annotation/Required.java
Normal file
28
java/src/main/java/org/msgpack/annotation/Required.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// 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.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Required {
|
||||||
|
}
|
462
java/src/main/java/org/msgpack/buffer/VectoredByteBuffer.java
Normal file
462
java/src/main/java/org/msgpack/buffer/VectoredByteBuffer.java
Normal file
@ -0,0 +1,462 @@
|
|||||||
|
//
|
||||||
|
// MessagePack for Java
|
||||||
|
//
|
||||||
|
// Copyright (C) 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.buffer;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.GatheringByteChannel;
|
||||||
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
|
|
||||||
|
public class VectoredByteBuffer implements GatheringByteChannel, ScatteringByteChannel {
|
||||||
|
private List<ByteBuffer> vec = new ArrayList<ByteBuffer>();
|
||||||
|
private ByteBuffer internalBuffer;
|
||||||
|
private ByteBuffer lastInternalBuffer;
|
||||||
|
private int chunkSize;
|
||||||
|
private int referenceThreshold;
|
||||||
|
|
||||||
|
public VectoredByteBuffer() {
|
||||||
|
this(32*1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VectoredByteBuffer(int chunkSize) {
|
||||||
|
this(chunkSize, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VectoredByteBuffer(int chunkSize, int referenceThreshold) {
|
||||||
|
this.chunkSize = chunkSize;
|
||||||
|
this.referenceThreshold = referenceThreshold;
|
||||||
|
internalBuffer = ByteBuffer.allocateDirect(chunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setChunkSize(int chunkSize) {
|
||||||
|
this.chunkSize = chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChunkSize(int chunkSize) {
|
||||||
|
return this.chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReferenceThreshold(int referenceThreshold) {
|
||||||
|
this.referenceThreshold = referenceThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getReferenceThreshold(int referenceThreshold) {
|
||||||
|
return this.referenceThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOpen() {
|
||||||
|
return true; // FIXME?
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized void reset() {
|
||||||
|
vec.clear();
|
||||||
|
lastInternalBuffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void write(byte[] b) {
|
||||||
|
write(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] b, int off, int len) {
|
||||||
|
if(off < 0 || len < 0 || b.length < off+len) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
if(referenceThreshold >= 0 && len > referenceThreshold) {
|
||||||
|
writeReference(b, off, len);
|
||||||
|
} else {
|
||||||
|
writeCopy(b, off, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int b) {
|
||||||
|
byte[] ba = new byte[1];
|
||||||
|
ba[0] = (byte)b;
|
||||||
|
write(ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int write(ByteBuffer src) {
|
||||||
|
int slen = src.remaining();
|
||||||
|
if(referenceThreshold >= 0 && slen > referenceThreshold) {
|
||||||
|
writeCopy(src);
|
||||||
|
} else {
|
||||||
|
writeReference(src);
|
||||||
|
}
|
||||||
|
return slen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized long write(ByteBuffer[] srcs) {
|
||||||
|
return write(srcs, 0, srcs.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized long write(ByteBuffer[] srcs, int offset, int length) {
|
||||||
|
if(offset < 0 || length < 0 || srcs.length < offset+length) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
long total = 0;
|
||||||
|
for(int i=offset; offset < length; offset++) {
|
||||||
|
ByteBuffer src = srcs[i];
|
||||||
|
total += write(src);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void writeCopy(byte[] b, int off, int len) {
|
||||||
|
int ipos = internalBuffer.position();
|
||||||
|
if(internalBuffer.capacity() - ipos < len) {
|
||||||
|
// allocate new buffer
|
||||||
|
int nsize = chunkSize > len ? chunkSize : len;
|
||||||
|
internalBuffer = ByteBuffer.allocateDirect(nsize);
|
||||||
|
ipos = 0;
|
||||||
|
} else if(internalBuffer == lastInternalBuffer) {
|
||||||
|
// optimization: concatenates to the last buffer instead
|
||||||
|
// of adding new reference
|
||||||
|
ByteBuffer dup = vec.get(vec.size()-1);
|
||||||
|
internalBuffer.put(b, off, len);
|
||||||
|
dup.limit(ipos + len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
internalBuffer.put(b, off, len);
|
||||||
|
ByteBuffer dup = internalBuffer.duplicate();
|
||||||
|
dup.position(ipos);
|
||||||
|
dup.mark();
|
||||||
|
dup.limit(ipos + len);
|
||||||
|
vec.add(dup);
|
||||||
|
lastInternalBuffer = internalBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void writeCopy(ByteBuffer src) {
|
||||||
|
int slen = src.remaining();
|
||||||
|
int ipos = internalBuffer.position();
|
||||||
|
if(internalBuffer.capacity() - ipos < slen) {
|
||||||
|
// allocate new buffer
|
||||||
|
int nsize = chunkSize > slen ? chunkSize : slen;
|
||||||
|
internalBuffer = ByteBuffer.allocateDirect(nsize);
|
||||||
|
ipos = 0;
|
||||||
|
} else if(internalBuffer == lastInternalBuffer) {
|
||||||
|
// optimization: concatenates to the last buffer instead
|
||||||
|
// of adding new reference
|
||||||
|
ByteBuffer dup = vec.get(vec.size()-1);
|
||||||
|
int dpos = dup.position();
|
||||||
|
internalBuffer.put(src);
|
||||||
|
ByteBuffer dup2 = internalBuffer.duplicate();
|
||||||
|
dup2.position(dpos);
|
||||||
|
dup2.limit(ipos + slen);
|
||||||
|
vec.set(vec.size()-1, dup2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
internalBuffer.put(src);
|
||||||
|
ByteBuffer dup = internalBuffer.duplicate();
|
||||||
|
dup.position(ipos);
|
||||||
|
dup.mark();
|
||||||
|
dup.limit(ipos + slen);
|
||||||
|
vec.add(dup);
|
||||||
|
lastInternalBuffer = internalBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void writeReference(byte[] b, int off, int len) {
|
||||||
|
ByteBuffer buf = ByteBuffer.wrap(b, off, len);
|
||||||
|
vec.add(buf);
|
||||||
|
lastInternalBuffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void writeReference(ByteBuffer src) {
|
||||||
|
ByteBuffer buf = src.duplicate();
|
||||||
|
vec.add(buf);
|
||||||
|
lastInternalBuffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized void writeTo(java.io.OutputStream out) throws IOException {
|
||||||
|
byte[] tmpbuf = null;
|
||||||
|
for(int i=0; i < vec.size(); i++) {
|
||||||
|
ByteBuffer r = vec.get(i);
|
||||||
|
int rpos = r.position();
|
||||||
|
int rlen = r.limit() - rpos;
|
||||||
|
if(r.hasArray()) {
|
||||||
|
byte[] array = r.array();
|
||||||
|
out.write(array, rpos, rlen);
|
||||||
|
} else {
|
||||||
|
if(tmpbuf == null) {
|
||||||
|
int max = rlen;
|
||||||
|
for(int j=i+1; j < vec.size(); j++) {
|
||||||
|
ByteBuffer c = vec.get(j);
|
||||||
|
int clen = c.remaining();
|
||||||
|
if(max < clen) {
|
||||||
|
max = clen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmpbuf = new byte[max];
|
||||||
|
}
|
||||||
|
r.get(tmpbuf, 0, rlen);
|
||||||
|
r.position(rpos);
|
||||||
|
out.write(tmpbuf, 0, rlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized byte[] toByteArray() {
|
||||||
|
byte[] out = new byte[available()];
|
||||||
|
int off = 0;
|
||||||
|
for(ByteBuffer r: vec) {
|
||||||
|
int rpos = r.position();
|
||||||
|
int rlen = r.limit() - rpos;
|
||||||
|
r.get(out, off, rlen);
|
||||||
|
r.position(rpos);
|
||||||
|
off += rlen;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized int available() {
|
||||||
|
int total = 0;
|
||||||
|
for(ByteBuffer r : vec) {
|
||||||
|
total += r.remaining();
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int read(byte[] b) {
|
||||||
|
return read(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int read(byte[] b, int off, int len) {
|
||||||
|
if(off < 0 || len < 0 || b.length < off+len) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
int start = len;
|
||||||
|
while(!vec.isEmpty()) {
|
||||||
|
ByteBuffer r = vec.get(0);
|
||||||
|
int rlen = r.remaining();
|
||||||
|
if(rlen <= len) {
|
||||||
|
r.get(b, off, rlen);
|
||||||
|
vec.remove(0);
|
||||||
|
off += rlen;
|
||||||
|
len -= rlen;
|
||||||
|
} else {
|
||||||
|
r.get(b, off, len);
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return start - len;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int read() {
|
||||||
|
byte[] ba = new byte[1];
|
||||||
|
if(read(ba) >= 1) {
|
||||||
|
return ba[0];
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized int read(ByteBuffer dst) {
|
||||||
|
int len = dst.remaining();
|
||||||
|
int start = len;
|
||||||
|
while(!vec.isEmpty()) {
|
||||||
|
ByteBuffer r = vec.get(0);
|
||||||
|
int rlen = r.remaining();
|
||||||
|
if(rlen <= len) {
|
||||||
|
dst.put(r);
|
||||||
|
vec.remove(0);
|
||||||
|
len -= rlen;
|
||||||
|
} else {
|
||||||
|
int blim = r.limit();
|
||||||
|
r.limit(len);
|
||||||
|
try {
|
||||||
|
dst.put(r);
|
||||||
|
} finally {
|
||||||
|
r.limit(blim);
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return start - len;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized long read(ByteBuffer[] dsts) {
|
||||||
|
return read(dsts, 0, dsts.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized long read(ByteBuffer[] dsts, int offset, int length) {
|
||||||
|
if(offset < 0 || length < 0 || dsts.length < offset+length) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
long total = 0;
|
||||||
|
for(int i=offset; i < length; i++) {
|
||||||
|
ByteBuffer dst = dsts[i];
|
||||||
|
int dlen = dst.remaining();
|
||||||
|
int rlen = read(dsts[i]);
|
||||||
|
total += rlen;
|
||||||
|
if(rlen < dlen) {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized long read(GatheringByteChannel to) throws IOException {
|
||||||
|
long total = to.write((ByteBuffer[])vec.toArray());
|
||||||
|
while(!vec.isEmpty()) {
|
||||||
|
ByteBuffer r = vec.get(0);
|
||||||
|
if(r.remaining() == 0) {
|
||||||
|
vec.remove(0);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized long skip(long len) {
|
||||||
|
if(len <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
long start = len;
|
||||||
|
while(!vec.isEmpty()) {
|
||||||
|
ByteBuffer r = vec.get(0);
|
||||||
|
int rlen = r.remaining();
|
||||||
|
if(rlen <= len) {
|
||||||
|
r.position(r.position()+rlen);
|
||||||
|
vec.remove(0);
|
||||||
|
len -= rlen;
|
||||||
|
} else {
|
||||||
|
r.position((int)(r.position()+len));
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return start - len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final static class OutputStream extends java.io.OutputStream {
|
||||||
|
private VectoredByteBuffer vbb;
|
||||||
|
|
||||||
|
OutputStream(VectoredByteBuffer vbb) {
|
||||||
|
this.vbb = vbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b) {
|
||||||
|
vbb.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b, int off, int len) {
|
||||||
|
vbb.write(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int b) {
|
||||||
|
vbb.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int write(ByteBuffer src) {
|
||||||
|
return vbb.write(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long write(ByteBuffer[] srcs) {
|
||||||
|
return vbb.write(srcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long write(ByteBuffer[] srcs, int offset, int length) {
|
||||||
|
return vbb.write(srcs, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
vbb.writeTo(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] toByteArray() {
|
||||||
|
return vbb.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static class InputStream extends java.io.InputStream {
|
||||||
|
private VectoredByteBuffer vbb;
|
||||||
|
|
||||||
|
InputStream(VectoredByteBuffer vbb) {
|
||||||
|
this.vbb = vbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() {
|
||||||
|
return vbb.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b) {
|
||||||
|
return vbb.read(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b, int off, int len) {
|
||||||
|
return vbb.read(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() {
|
||||||
|
return vbb.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(ByteBuffer dst) {
|
||||||
|
return vbb.read(dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long read(ByteBuffer[] dsts, int offset, int length) {
|
||||||
|
return vbb.read(dsts, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long read(GatheringByteChannel to) throws IOException {
|
||||||
|
return vbb.read(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long skip(long len) {
|
||||||
|
return vbb.skip(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputStream outputStream() {
|
||||||
|
return new OutputStream(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream inputStream() {
|
||||||
|
return new InputStream(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,10 +24,13 @@ public class AnyTemplate implements Template {
|
|||||||
private AnyTemplate() { }
|
private AnyTemplate() { }
|
||||||
|
|
||||||
public void pack(Packer pk, Object target) throws IOException {
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
if(target == null) {
|
if(target instanceof MessagePackObject) {
|
||||||
|
pk.pack((MessagePackObject)target);
|
||||||
|
} else if(target == null) {
|
||||||
pk.packNil();
|
pk.packNil();
|
||||||
} else {
|
} else {
|
||||||
new ClassTemplate(target.getClass()).pack(pk, target);
|
TemplateRegistry.lookup(target.getClass()).pack(pk, target);
|
||||||
|
//new ClassTemplate(target.getClass()).pack(pk, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +50,7 @@ public class AnyTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(MessagePackObject.class, instance);
|
CustomMessage.register(MessagePackObject.class, instance);
|
||||||
|
TemplateRegistry.register(MessagePackObject.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ public class BigIntegerTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(BigInteger.class, instance);
|
CustomMessage.register(BigInteger.class, instance);
|
||||||
|
TemplateRegistry.register(BigInteger.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public class BooleanArrayTemplate implements Template {
|
||||||
|
private BooleanArrayTemplate() { }
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
if(!(target instanceof boolean[])) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
boolean[] array = (boolean[])target;
|
||||||
|
pk.packArray(array.length);
|
||||||
|
for(boolean a : array) {
|
||||||
|
pk.pack(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
int length = pac.unpackArray();
|
||||||
|
boolean[] array;
|
||||||
|
if(to != null && to instanceof boolean[] && ((boolean[])to).length == length) {
|
||||||
|
array = (boolean[])to;
|
||||||
|
} else {
|
||||||
|
array = new boolean[length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < length; i++) {
|
||||||
|
array[i] = pac.unpackBoolean();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
MessagePackObject[] src = from.asArray();
|
||||||
|
boolean[] array;
|
||||||
|
if(to != null && to instanceof boolean[] && ((boolean[])to).length == src.length) {
|
||||||
|
array = (boolean[])to;
|
||||||
|
} else {
|
||||||
|
array = new boolean[src.length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < src.length; i++) {
|
||||||
|
MessagePackObject s = src[i];
|
||||||
|
array[i] = s.asBoolean();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public BooleanArrayTemplate getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final BooleanArrayTemplate instance = new BooleanArrayTemplate();
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.register(boolean[].class, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,8 @@ public class BooleanTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(Boolean.class, instance);
|
CustomMessage.register(Boolean.class, instance);
|
||||||
|
TemplateRegistry.register(Boolean.class, instance);
|
||||||
|
TemplateRegistry.register(boolean.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
public class BuiltInTemplateLoader {
|
||||||
|
public static void load() {
|
||||||
|
AnyTemplate.getInstance();
|
||||||
|
BigIntegerTemplate.getInstance();
|
||||||
|
BooleanArrayTemplate.getInstance();
|
||||||
|
BooleanTemplate.getInstance();
|
||||||
|
ByteArrayTemplate.getInstance();
|
||||||
|
ByteTemplate.getInstance();
|
||||||
|
DoubleArrayTemplate.getInstance();
|
||||||
|
DoubleTemplate.getInstance();
|
||||||
|
FloatArrayTemplate.getInstance();
|
||||||
|
FloatTemplate.getInstance();
|
||||||
|
IntArrayTemplate.getInstance();
|
||||||
|
IntegerTemplate.getInstance();
|
||||||
|
LongArrayTemplate.getInstance();
|
||||||
|
LongTemplate.getInstance();
|
||||||
|
ShortArrayTemplate.getInstance();
|
||||||
|
ShortTemplate.getInstance();
|
||||||
|
StringTemplate.getInstance();
|
||||||
|
|
||||||
|
CollectionTemplate.load();
|
||||||
|
ListTemplate.load();
|
||||||
|
MapTemplate.load();
|
||||||
|
NullableTemplate.load();
|
||||||
|
ObjectArrayTemplate.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,7 @@ public class ByteArrayTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(byte[].class, instance);
|
CustomMessage.register(byte[].class, instance);
|
||||||
|
TemplateRegistry.register(byte[].class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,5 +56,9 @@ public class ByteBufferTemplate implements Template {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static final ByteBufferTemplate instance = new ByteBufferTemplate();
|
static final ByteBufferTemplate instance = new ByteBufferTemplate();
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.register(ByteBuffer.class, instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ public class ByteTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(Byte.class, instance);
|
CustomMessage.register(Byte.class, instance);
|
||||||
|
TemplateRegistry.register(Byte.class, instance);
|
||||||
|
TemplateRegistry.register(byte.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
package org.msgpack.template;
|
package org.msgpack.template;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.AccessibleObject;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import org.msgpack.*;
|
import org.msgpack.*;
|
||||||
import org.msgpack.annotation.MessagePackDelegate;
|
import org.msgpack.annotation.MessagePackDelegate;
|
||||||
import org.msgpack.annotation.MessagePackMessage;
|
import org.msgpack.annotation.MessagePackMessage;
|
||||||
@ -30,10 +32,6 @@ import java.math.BigInteger;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
public class ClassTemplate implements Template {
|
public class ClassTemplate implements Template {
|
||||||
static {
|
|
||||||
Templates.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class<?> klass;
|
private Class<?> klass;
|
||||||
|
|
||||||
public ClassTemplate(Class<?> klass) {
|
public ClassTemplate(Class<?> klass) {
|
||||||
@ -119,14 +117,14 @@ public class ClassTemplate implements Template {
|
|||||||
// pk.packDouble((Double)o);
|
// pk.packDouble((Double)o);
|
||||||
// return;
|
// return;
|
||||||
//}
|
//}
|
||||||
if(o instanceof BigInteger) {
|
//if(o instanceof BigInteger) {
|
||||||
pk.packBigInteger((BigInteger)o);
|
// pk.packBigInteger((BigInteger)o);
|
||||||
return;
|
// return;
|
||||||
}
|
//}
|
||||||
if (o instanceof ByteBuffer) { // FIXME
|
//if (o instanceof ByteBuffer) {
|
||||||
Templates.tByteBuffer().pack(pk, o);
|
// Templates.tByteBuffer().pack(pk, o);
|
||||||
return;
|
// return;
|
||||||
}
|
//}
|
||||||
|
|
||||||
MessagePacker packer = CustomPacker.get(klass);
|
MessagePacker packer = CustomPacker.get(klass);
|
||||||
if(packer != null) {
|
if(packer != null) {
|
||||||
@ -134,15 +132,15 @@ public class ClassTemplate implements Template {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
if (isAnnotated(klass, MessagePackMessage.class)) {
|
||||||
Template tmpl = DynamicTemplate.create(klass);
|
Template tmpl = DynamicTemplate.create(klass);
|
||||||
CustomMessage.register(klass, tmpl);
|
CustomMessage.register(klass, tmpl);
|
||||||
tmpl.pack(pk, o);
|
tmpl.pack(pk, o);
|
||||||
return;
|
return;
|
||||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
} else if (isAnnotated(klass, MessagePackDelegate.class)) {
|
||||||
// FIXME DelegatePacker
|
// FIXME DelegatePacker
|
||||||
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
||||||
} else if (CustomMessage.isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
} else if (isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
||||||
Template tmpl = DynamicOrdinalEnumTemplate.create(klass);
|
Template tmpl = DynamicOrdinalEnumTemplate.create(klass);
|
||||||
CustomMessage.register(klass, tmpl);
|
CustomMessage.register(klass, tmpl);
|
||||||
tmpl.pack(pk, o);
|
tmpl.pack(pk, o);
|
||||||
@ -171,14 +169,14 @@ public class ClassTemplate implements Template {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
if (isAnnotated(klass, MessagePackMessage.class)) {
|
||||||
Template tmpl = DynamicTemplate.create(klass);
|
Template tmpl = DynamicTemplate.create(klass);
|
||||||
CustomMessage.register(klass, tmpl);
|
CustomMessage.register(klass, tmpl);
|
||||||
return tmpl.unpack(pac, to);
|
return tmpl.unpack(pac, to);
|
||||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
} else if (isAnnotated(klass, MessagePackDelegate.class)) {
|
||||||
// TODO DelegateUnpacker
|
// TODO DelegateUnpacker
|
||||||
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
||||||
} else if (CustomMessage.isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
} else if (isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
||||||
Template tmpl = DynamicOrdinalEnumTemplate.create(klass);
|
Template tmpl = DynamicOrdinalEnumTemplate.create(klass);
|
||||||
CustomMessage.register(klass, tmpl);
|
CustomMessage.register(klass, tmpl);
|
||||||
return tmpl.unpack(pac, to);
|
return tmpl.unpack(pac, to);
|
||||||
@ -187,20 +185,20 @@ public class ClassTemplate implements Template {
|
|||||||
// fallback
|
// fallback
|
||||||
MessageConverter converter = null;
|
MessageConverter converter = null;
|
||||||
|
|
||||||
if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
if (isAnnotated(klass, MessagePackMessage.class)) {
|
||||||
Template tmpl = DynamicTemplate.create(klass);
|
Template tmpl = DynamicTemplate.create(klass);
|
||||||
CustomMessage.register(klass, tmpl);
|
CustomMessage.register(klass, tmpl);
|
||||||
return tmpl.convert(pac.unpackObject(), to);
|
return tmpl.convert(pac.unpackObject(), to);
|
||||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
} else if (isAnnotated(klass, MessagePackDelegate.class)) {
|
||||||
// TODO DelegateConverter
|
// TODO DelegateConverter
|
||||||
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
||||||
} else if (CustomMessage.isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
} else if (isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
||||||
Template tmpl = DynamicOrdinalEnumTemplate.create(klass);
|
Template tmpl = DynamicOrdinalEnumTemplate.create(klass);
|
||||||
CustomMessage.register(klass, tmpl);
|
CustomMessage.register(klass, tmpl);
|
||||||
return tmpl.convert(pac.unpackObject(), to);
|
return tmpl.convert(pac.unpackObject(), to);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new MessageTypeException();
|
throw new MessageTypeException("unknown type: "+klass);
|
||||||
|
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new MessageTypeException(e.getMessage()); // FIXME
|
throw new MessageTypeException(e.getMessage()); // FIXME
|
||||||
@ -228,14 +226,14 @@ public class ClassTemplate implements Template {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
if (isAnnotated(klass, MessagePackMessage.class)) {
|
||||||
Template tmpl = DynamicTemplate.create(klass);
|
Template tmpl = DynamicTemplate.create(klass);
|
||||||
CustomMessage.register(klass, tmpl);
|
CustomMessage.register(klass, tmpl);
|
||||||
return tmpl.convert(from, to);
|
return tmpl.convert(from, to);
|
||||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
} else if (isAnnotated(klass, MessagePackDelegate.class)) {
|
||||||
// TODO DelegateConverter
|
// TODO DelegateConverter
|
||||||
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
||||||
} else if (CustomMessage.isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
} else if (isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
||||||
Template tmpl = DynamicOrdinalEnumTemplate.create(klass);
|
Template tmpl = DynamicOrdinalEnumTemplate.create(klass);
|
||||||
CustomMessage.register(klass, tmpl);
|
CustomMessage.register(klass, tmpl);
|
||||||
return tmpl.convert(from, to);
|
return tmpl.convert(from, to);
|
||||||
@ -249,5 +247,9 @@ public class ClassTemplate implements Template {
|
|||||||
throw new MessageTypeException(e.getMessage()); // FIXME
|
throw new MessageTypeException(e.getMessage()); // FIXME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) {
|
||||||
|
return ao.getAnnotation(with) != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ import java.io.IOException;
|
|||||||
import org.msgpack.*;
|
import org.msgpack.*;
|
||||||
|
|
||||||
public class CollectionTemplate implements Template {
|
public class CollectionTemplate implements Template {
|
||||||
|
public static void load() { }
|
||||||
|
|
||||||
private Template elementTemplate;
|
private Template elementTemplate;
|
||||||
|
|
||||||
public CollectionTemplate(Template elementTemplate) {
|
public CollectionTemplate(Template elementTemplate) {
|
||||||
@ -72,5 +74,10 @@ public class CollectionTemplate implements Template {
|
|||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.registerGeneric(Collection.class, new GenericTemplate1(CollectionTemplate.class));
|
||||||
|
TemplateRegistry.register(Collection.class, new CollectionTemplate(AnyTemplate.getInstance()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
93
java/src/main/java/org/msgpack/template/DefaultTemplate.java
Normal file
93
java/src/main/java/org/msgpack/template/DefaultTemplate.java
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public class DefaultTemplate implements Template {
|
||||||
|
private Class<?> targetClass;
|
||||||
|
private Type lookupType;
|
||||||
|
private boolean messagePackable;
|
||||||
|
private boolean messageUnpackable;
|
||||||
|
private boolean messageConvertable;
|
||||||
|
|
||||||
|
public DefaultTemplate(Class<?> targetClass) {
|
||||||
|
this(targetClass, (Type)targetClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultTemplate(Class<?> targetClass, Type lookupType) {
|
||||||
|
this.targetClass = targetClass;
|
||||||
|
this.lookupType = lookupType;
|
||||||
|
this.messagePackable = MessagePackable.class.isAssignableFrom(targetClass);
|
||||||
|
this.messageUnpackable = MessageUnpackable.class.isAssignableFrom(targetClass);
|
||||||
|
this.messageConvertable = MessageConvertable.class.isAssignableFrom(targetClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
if(messagePackable) {
|
||||||
|
((MessagePackable)target).messagePack(pk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
||||||
|
if(tmpl == this || tmpl == null) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
tmpl.pack(pk, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
if(messageUnpackable) {
|
||||||
|
if(to == null) {
|
||||||
|
try {
|
||||||
|
to = targetClass.newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MessageTypeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
((MessageUnpackable)to).messageUnpack(pac);
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
||||||
|
if(tmpl == this || tmpl == null) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
return tmpl.unpack(pac, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
if(messageConvertable) {
|
||||||
|
if(to == null) {
|
||||||
|
try {
|
||||||
|
to = targetClass.newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MessageTypeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
((MessageConvertable)to).messageConvert(from);
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
||||||
|
if(tmpl == this || tmpl == null) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
return tmpl.convert(from, to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public class DoubleArrayTemplate implements Template {
|
||||||
|
private DoubleArrayTemplate() { }
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
if(!(target instanceof double[])) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
double[] array = (double[])target;
|
||||||
|
pk.packArray(array.length);
|
||||||
|
for(double a : array) {
|
||||||
|
pk.pack(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
int length = pac.unpackArray();
|
||||||
|
double[] array;
|
||||||
|
if(to != null && to instanceof double[] && ((double[])to).length == length) {
|
||||||
|
array = (double[])to;
|
||||||
|
} else {
|
||||||
|
array = new double[length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < length; i++) {
|
||||||
|
array[i] = pac.unpackDouble();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
MessagePackObject[] src = from.asArray();
|
||||||
|
double[] array;
|
||||||
|
if(to != null && to instanceof double[] && ((double[])to).length == src.length) {
|
||||||
|
array = (double[])to;
|
||||||
|
} else {
|
||||||
|
array = new double[src.length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < src.length; i++) {
|
||||||
|
MessagePackObject s = src[i];
|
||||||
|
array[i] = s.asDouble();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public DoubleArrayTemplate getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final DoubleArrayTemplate instance = new DoubleArrayTemplate();
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.register(double[].class, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,8 @@ public class DoubleTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(Double.class, instance);
|
CustomMessage.register(Double.class, instance);
|
||||||
|
TemplateRegistry.register(Double.class, instance);
|
||||||
|
TemplateRegistry.register(double.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
96
java/src/main/java/org/msgpack/template/FieldList.java
Normal file
96
java/src/main/java/org/msgpack/template/FieldList.java
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class FieldList {
|
||||||
|
public static class Entry {
|
||||||
|
public Entry() {
|
||||||
|
this.name = null;
|
||||||
|
this.option = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entry(String name, FieldOption option) {
|
||||||
|
this.name = name;
|
||||||
|
this.option = option;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private FieldOption option;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FieldOption getOption() {
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isAvailable() {
|
||||||
|
return this.name != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isRequired() {
|
||||||
|
return this.option == FieldOption.REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isOptional() {
|
||||||
|
return this.option == FieldOption.OPTIONAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isNullable() {
|
||||||
|
return this.option == FieldOption.NULLABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<Entry> list;
|
||||||
|
|
||||||
|
public FieldList() {
|
||||||
|
list = new ArrayList<Entry>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(final String name) {
|
||||||
|
add(name, FieldOption.REQUIRED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(final String name, final FieldOption option) {
|
||||||
|
list.add(new Entry(name, option));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(int index, final String name) {
|
||||||
|
put(index, name, FieldOption.REQUIRED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(int index, final String name, final FieldOption option) {
|
||||||
|
if(list.size() < index) {
|
||||||
|
do {
|
||||||
|
list.add(new Entry());
|
||||||
|
} while(list.size() < index);
|
||||||
|
list.add(new Entry(name, option));
|
||||||
|
} else {
|
||||||
|
list.set(index, new Entry(name, option));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Entry> getList() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
27
java/src/main/java/org/msgpack/template/FieldOption.java
Normal file
27
java/src/main/java/org/msgpack/template/FieldOption.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
public enum FieldOption {
|
||||||
|
IGNORE,
|
||||||
|
REQUIRED,
|
||||||
|
OPTIONAL,
|
||||||
|
NULLABLE,
|
||||||
|
DEFAULT;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public class FloatArrayTemplate implements Template {
|
||||||
|
private FloatArrayTemplate() { }
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
if(!(target instanceof float[])) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
float[] array = (float[])target;
|
||||||
|
pk.packArray(array.length);
|
||||||
|
for(float a : array) {
|
||||||
|
pk.pack(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
int length = pac.unpackArray();
|
||||||
|
float[] array;
|
||||||
|
if(to != null && to instanceof float[] && ((float[])to).length == length) {
|
||||||
|
array = (float[])to;
|
||||||
|
} else {
|
||||||
|
array = new float[length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < length; i++) {
|
||||||
|
array[i] = pac.unpackFloat();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
MessagePackObject[] src = from.asArray();
|
||||||
|
float[] array;
|
||||||
|
if(to != null && to instanceof float[] && ((float[])to).length == src.length) {
|
||||||
|
array = (float[])to;
|
||||||
|
} else {
|
||||||
|
array = new float[src.length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < src.length; i++) {
|
||||||
|
MessagePackObject s = src[i];
|
||||||
|
array[i] = s.asFloat();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public FloatArrayTemplate getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final FloatArrayTemplate instance = new FloatArrayTemplate();
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.register(float[].class, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,8 @@ public class FloatTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(Float.class, instance);
|
CustomMessage.register(Float.class, instance);
|
||||||
|
TemplateRegistry.register(Float.class, instance);
|
||||||
|
TemplateRegistry.register(float.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
java/src/main/java/org/msgpack/template/GenericTemplate.java
Normal file
25
java/src/main/java/org/msgpack/template/GenericTemplate.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import org.msgpack.Template;
|
||||||
|
|
||||||
|
public interface GenericTemplate {
|
||||||
|
public Template build(Template[] params);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import org.msgpack.Template;
|
||||||
|
|
||||||
|
public class GenericTemplate1 implements GenericTemplate {
|
||||||
|
Constructor<? extends Template> constructor;
|
||||||
|
|
||||||
|
public GenericTemplate1(Class<? extends Template> tmpl) {
|
||||||
|
try {
|
||||||
|
this.constructor = tmpl.getConstructor(new Class<?>[]{Template.class});
|
||||||
|
constructor.newInstance(new Object[]{AnyTemplate.getInstance()});
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template build(Template[] params) {
|
||||||
|
try {
|
||||||
|
return constructor.newInstance(params);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import org.msgpack.Template;
|
||||||
|
|
||||||
|
public class GenericTemplate2 implements GenericTemplate {
|
||||||
|
Constructor<? extends Template> constructor;
|
||||||
|
|
||||||
|
public GenericTemplate2(Class<? extends Template> tmpl) {
|
||||||
|
try {
|
||||||
|
this.constructor = tmpl.getConstructor(new Class<?>[]{Template.class, Template.class});
|
||||||
|
constructor.newInstance(new Object[]{AnyTemplate.getInstance(), AnyTemplate.getInstance()});
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template build(Template[] params) {
|
||||||
|
try {
|
||||||
|
return constructor.newInstance(params);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public class IntArrayTemplate implements Template {
|
||||||
|
private IntArrayTemplate() { }
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
if(!(target instanceof int[])) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
int[] array = (int[])target;
|
||||||
|
pk.packArray(array.length);
|
||||||
|
for(int a : array) {
|
||||||
|
pk.pack(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
int length = pac.unpackArray();
|
||||||
|
int[] array;
|
||||||
|
if(to != null && to instanceof int[] && ((int[])to).length == length) {
|
||||||
|
array = (int[])to;
|
||||||
|
} else {
|
||||||
|
array = new int[length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < length; i++) {
|
||||||
|
array[i] = pac.unpackInt();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
MessagePackObject[] src = from.asArray();
|
||||||
|
int[] array;
|
||||||
|
if(to != null && to instanceof int[] && ((int[])to).length == src.length) {
|
||||||
|
array = (int[])to;
|
||||||
|
} else {
|
||||||
|
array = new int[src.length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < src.length; i++) {
|
||||||
|
MessagePackObject s = src[i];
|
||||||
|
array[i] = s.asInt();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public IntArrayTemplate getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final IntArrayTemplate instance = new IntArrayTemplate();
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.register(int[].class, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,8 @@ public class IntegerTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(Integer.class, instance);
|
CustomMessage.register(Integer.class, instance);
|
||||||
|
TemplateRegistry.register(Integer.class, instance);
|
||||||
|
TemplateRegistry.register(int.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,523 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
import javassist.CannotCompileException;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtConstructor;
|
||||||
|
import javassist.CtField;
|
||||||
|
import javassist.CtMethod;
|
||||||
|
import javassist.CtNewConstructor;
|
||||||
|
import javassist.CtNewMethod;
|
||||||
|
import javassist.LoaderClassPath;
|
||||||
|
import javassist.NotFoundException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||||
|
private static JavassistTemplateBuilder instance;
|
||||||
|
public synchronized static JavassistTemplateBuilder getInstance() {
|
||||||
|
if(instance == null) {
|
||||||
|
instance = new JavassistTemplateBuilder();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavassistTemplateBuilder() {
|
||||||
|
this.pool = ClassPool.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Logger LOG = LoggerFactory
|
||||||
|
.getLogger(JavassistTemplateBuilder.class);
|
||||||
|
|
||||||
|
protected ClassPool pool;
|
||||||
|
private int seqId = 0;
|
||||||
|
|
||||||
|
CtClass makeCtClass(String className) {
|
||||||
|
return pool.makeClass(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
CtClass getCtClass(String className) throws NotFoundException {
|
||||||
|
return pool.get(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextSeqId() {
|
||||||
|
return seqId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class JavassistTemplate extends AbstractTemplate {
|
||||||
|
public Class targetClass;
|
||||||
|
public Template[] templates;
|
||||||
|
|
||||||
|
public JavassistTemplate(Class targetClass, Template[] templates) {
|
||||||
|
this.targetClass = targetClass;
|
||||||
|
this.templates = templates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static abstract class BuildContextBase {
|
||||||
|
protected JavassistTemplateBuilder director;
|
||||||
|
protected Class<?> origClass;
|
||||||
|
protected String origName;
|
||||||
|
protected String tmplName;
|
||||||
|
protected CtClass tmplCtClass;
|
||||||
|
|
||||||
|
protected abstract void setSuperClass() throws CannotCompileException, NotFoundException;
|
||||||
|
protected abstract void buildConstructor() throws CannotCompileException, NotFoundException;
|
||||||
|
protected void buildMethodInit() { }
|
||||||
|
protected abstract String buildPackMethodBody();
|
||||||
|
protected abstract String buildUnpackMethodBody();
|
||||||
|
protected abstract String buildConvertMethodBody();
|
||||||
|
protected abstract Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException;
|
||||||
|
|
||||||
|
public BuildContextBase(JavassistTemplateBuilder director) {
|
||||||
|
this.director = director;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Template build(Class<?> targetClass) {
|
||||||
|
try {
|
||||||
|
reset(targetClass);
|
||||||
|
buildClass();
|
||||||
|
buildConstructor();
|
||||||
|
buildMethodInit();
|
||||||
|
buildPackMethod();
|
||||||
|
buildUnpackMethod();
|
||||||
|
buildConvertMethod();
|
||||||
|
return buildInstance(createClass());
|
||||||
|
} catch (Exception e) {
|
||||||
|
if(this.stringBuilder != null) {
|
||||||
|
LOG.error("builder: "+this.stringBuilder.toString());
|
||||||
|
}
|
||||||
|
throw new MessageTypeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reset(Class<?> targetClass) {
|
||||||
|
this.origClass = targetClass;
|
||||||
|
this.origName = this.origClass.getName();
|
||||||
|
this.tmplName = this.origName + "_$$_Template" + director.nextSeqId();
|
||||||
|
this.tmplCtClass = director.makeCtClass(this.tmplName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildClass() throws CannotCompileException, NotFoundException {
|
||||||
|
setSuperClass();
|
||||||
|
this.tmplCtClass.addInterface(
|
||||||
|
director.getCtClass(Template.class.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildPackMethod() throws CannotCompileException, NotFoundException {
|
||||||
|
String mbody = buildPackMethodBody();
|
||||||
|
int mod = javassist.Modifier.PUBLIC;
|
||||||
|
CtClass returnType = CtClass.voidType;
|
||||||
|
String mname = "pack";
|
||||||
|
CtClass[] paramTypes = new CtClass[] {
|
||||||
|
director.getCtClass(Packer.class.getName()),
|
||||||
|
director.getCtClass(Object.class.getName())
|
||||||
|
};
|
||||||
|
CtClass[] exceptTypes = new CtClass[] {
|
||||||
|
director.getCtClass(IOException.class.getName())
|
||||||
|
};
|
||||||
|
CtMethod newCtMethod = CtNewMethod.make(
|
||||||
|
mod, returnType, mname,
|
||||||
|
paramTypes, exceptTypes, mbody,
|
||||||
|
this.tmplCtClass);
|
||||||
|
this.tmplCtClass.addMethod(newCtMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildUnpackMethod() throws CannotCompileException, NotFoundException {
|
||||||
|
String mbody = buildUnpackMethodBody();
|
||||||
|
int mod = javassist.Modifier.PUBLIC;
|
||||||
|
CtClass returnType = director.getCtClass(Object.class.getName());
|
||||||
|
String mname = "unpack";
|
||||||
|
CtClass[] paramTypes = new CtClass[] {
|
||||||
|
director.getCtClass(Unpacker.class.getName()),
|
||||||
|
director.getCtClass(Object.class.getName())
|
||||||
|
};
|
||||||
|
CtClass[] exceptTypes = new CtClass[] {
|
||||||
|
director.getCtClass(MessageTypeException.class.getName())
|
||||||
|
};
|
||||||
|
CtMethod newCtMethod = CtNewMethod.make(
|
||||||
|
mod, returnType, mname,
|
||||||
|
paramTypes, exceptTypes, mbody,
|
||||||
|
this.tmplCtClass);
|
||||||
|
this.tmplCtClass.addMethod(newCtMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildConvertMethod() throws CannotCompileException, NotFoundException {
|
||||||
|
String mbody = buildConvertMethodBody();
|
||||||
|
int mod = javassist.Modifier.PUBLIC;
|
||||||
|
CtClass returnType = director.getCtClass(Object.class.getName());
|
||||||
|
String mname = "convert";
|
||||||
|
CtClass[] paramTypes = new CtClass[] {
|
||||||
|
director.getCtClass(MessagePackObject.class.getName()),
|
||||||
|
director.getCtClass(Object.class.getName())
|
||||||
|
};
|
||||||
|
CtClass[] exceptTypes = new CtClass[] {
|
||||||
|
director.getCtClass(MessageTypeException.class.getName())
|
||||||
|
};
|
||||||
|
CtMethod newCtMethod = CtNewMethod.make(
|
||||||
|
mod, returnType, mname,
|
||||||
|
paramTypes, exceptTypes, mbody,
|
||||||
|
this.tmplCtClass);
|
||||||
|
this.tmplCtClass.addMethod(newCtMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?> createClass() throws CannotCompileException {
|
||||||
|
return (Class<?>)this.tmplCtClass.toClass(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StringBuilder stringBuilder = null;
|
||||||
|
|
||||||
|
protected void resetStringBuilder() {
|
||||||
|
this.stringBuilder = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildString(String str) {
|
||||||
|
this.stringBuilder.append(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildString(String format, Object... args) {
|
||||||
|
this.stringBuilder.append(String.format(format, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getBuiltString() {
|
||||||
|
return this.stringBuilder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BuildContext extends BuildContextBase {
|
||||||
|
protected FieldEntry[] entries;
|
||||||
|
protected Template[] templates;
|
||||||
|
protected int minimumArrayLength;
|
||||||
|
|
||||||
|
public BuildContext(JavassistTemplateBuilder director) {
|
||||||
|
super(director);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries, Template[] templates) {
|
||||||
|
this.entries = entries;
|
||||||
|
this.templates = templates;
|
||||||
|
return build(targetClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setSuperClass() throws CannotCompileException, NotFoundException {
|
||||||
|
this.tmplCtClass.setSuperclass(
|
||||||
|
director.getCtClass(JavassistTemplate.class.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildConstructor() throws CannotCompileException, NotFoundException {
|
||||||
|
// Constructor(Class targetClass, Template[] templates)
|
||||||
|
CtConstructor newCtCons = CtNewConstructor.make(
|
||||||
|
new CtClass[] {
|
||||||
|
director.getCtClass(Class.class.getName()),
|
||||||
|
director.getCtClass(Template.class.getName()+"[]")
|
||||||
|
},
|
||||||
|
new CtClass[0],
|
||||||
|
this.tmplCtClass);
|
||||||
|
this.tmplCtClass.addConstructor(newCtCons);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||||
|
Constructor<?> cons = c.getConstructor(new Class[] {
|
||||||
|
Class.class,
|
||||||
|
Template[].class
|
||||||
|
});
|
||||||
|
Object tmpl = cons.newInstance(new Object[] {
|
||||||
|
this.origClass,
|
||||||
|
this.templates
|
||||||
|
});
|
||||||
|
return (Template)tmpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildMethodInit() {
|
||||||
|
this.minimumArrayLength = 0;
|
||||||
|
for(int i=0; i < entries.length; i++) {
|
||||||
|
FieldEntry e = entries[i];
|
||||||
|
if(e.isRequired() || e.isNullable()) {
|
||||||
|
this.minimumArrayLength = i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String buildPackMethodBody() {
|
||||||
|
resetStringBuilder();
|
||||||
|
buildString("{");
|
||||||
|
|
||||||
|
buildString("%s _$$_t = (%s)$2;", this.origName, this.origName);
|
||||||
|
buildString("$1.packArray(%d);", entries.length);
|
||||||
|
for(int i=0; i < entries.length; i++) {
|
||||||
|
FieldEntry e = entries[i];
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
buildString("$1.packNil();");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Class<?> type = e.getType();
|
||||||
|
if(type.isPrimitive()) {
|
||||||
|
buildString("$1.%s(_$$_t.%s);", primitivePackName(type), e.getName());
|
||||||
|
} else {
|
||||||
|
buildString("if(_$$_t.%s == null) {", e.getName());
|
||||||
|
if(!e.isNullable() && !e.isOptional()) {
|
||||||
|
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||||
|
} else {
|
||||||
|
buildString("$1.packNil();");
|
||||||
|
}
|
||||||
|
buildString("} else {");
|
||||||
|
buildString(" this.templates[%d].pack($1, _$$_t.%s);", i, e.getName());
|
||||||
|
buildString("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildString("}");
|
||||||
|
return getBuiltString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String buildUnpackMethodBody() {
|
||||||
|
resetStringBuilder();
|
||||||
|
buildString("{ ");
|
||||||
|
|
||||||
|
buildString("%s _$$_t;", this.origName);
|
||||||
|
buildString("if($2 == null) {");
|
||||||
|
buildString(" _$$_t = (%s)this.targetClass.newInstance();", this.origName);
|
||||||
|
buildString("} else {");
|
||||||
|
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||||
|
buildString("}");
|
||||||
|
|
||||||
|
buildString("int length = $1.unpackArray();");
|
||||||
|
buildString("if(length < %d) {", this.minimumArrayLength);
|
||||||
|
buildString(" throw new %s();", MessageTypeException.class.getName());
|
||||||
|
buildString("}");
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i=0; i < this.minimumArrayLength; i++) {
|
||||||
|
FieldEntry e = entries[i];
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
buildString("$1.unpackObject();");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildString("if($1.tryUnpackNull()) {");
|
||||||
|
if(e.isRequired()) {
|
||||||
|
// Requred + nil => exception
|
||||||
|
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||||
|
} else if(e.isOptional()) {
|
||||||
|
// Optional + nil => keep default value
|
||||||
|
} else { // Nullable
|
||||||
|
// Nullable + nil => set null
|
||||||
|
buildString("_$$_t.%s = null;", e.getName());
|
||||||
|
}
|
||||||
|
buildString("} else {");
|
||||||
|
Class<?> type = e.getType();
|
||||||
|
if(type.isPrimitive()) {
|
||||||
|
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
|
||||||
|
} else {
|
||||||
|
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||||
|
}
|
||||||
|
buildString("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; i < entries.length; i++) {
|
||||||
|
buildString("if(length <= %d) { return _$$_t; }", i);
|
||||||
|
|
||||||
|
FieldEntry e = entries[i];
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
buildString("$1.unpackObject();");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildString("if($1.tryUnpackNull()) {");
|
||||||
|
buildString("} else {");
|
||||||
|
Class<?> type = e.getType();
|
||||||
|
if(type.isPrimitive()) {
|
||||||
|
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
|
||||||
|
} else {
|
||||||
|
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||||
|
}
|
||||||
|
buildString("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
buildString("for(int i=%d; i < length; i++) {", i);
|
||||||
|
buildString(" $1.unpackObject();");
|
||||||
|
buildString("}");
|
||||||
|
|
||||||
|
buildString("return _$$_t;");
|
||||||
|
|
||||||
|
buildString("}");
|
||||||
|
return getBuiltString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String buildConvertMethodBody() {
|
||||||
|
resetStringBuilder();
|
||||||
|
buildString("{ ");
|
||||||
|
|
||||||
|
buildString("%s _$$_t;", this.origName);
|
||||||
|
buildString("if($2 == null) {");
|
||||||
|
buildString(" _$$_t = (%s)this.targetClass.newInstance();", this.origName);
|
||||||
|
buildString("} else {");
|
||||||
|
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||||
|
buildString("}");
|
||||||
|
|
||||||
|
buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName());
|
||||||
|
buildString("int length = array.length;");
|
||||||
|
buildString("if(length < %d) {", this.minimumArrayLength);
|
||||||
|
buildString(" throw new %s();", MessageTypeException.class.getName());
|
||||||
|
buildString("}");
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i=0; i < this.minimumArrayLength; i++) {
|
||||||
|
FieldEntry e = entries[i];
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildString("%s obj = array[%d];", MessagePackObject.class.getName(), i);
|
||||||
|
buildString("if(obj.isNil()) {");
|
||||||
|
if(e.isRequired()) {
|
||||||
|
// Requred + nil => exception
|
||||||
|
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||||
|
} else if(e.isOptional()) {
|
||||||
|
// Optional + nil => keep default value
|
||||||
|
} else { // Nullable
|
||||||
|
// Nullable + nil => set null
|
||||||
|
buildString("_$$_t.%s = null;", e.getName());
|
||||||
|
}
|
||||||
|
buildString("} else {");
|
||||||
|
Class<?> type = e.getType();
|
||||||
|
if(type.isPrimitive()) {
|
||||||
|
buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type));
|
||||||
|
} else {
|
||||||
|
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||||
|
}
|
||||||
|
buildString("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; i < entries.length; i++) {
|
||||||
|
buildString("if(length <= %d) { return _$$_t; }", i);
|
||||||
|
|
||||||
|
FieldEntry e = entries[i];
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildString("%s obj = array[%d];", MessagePackObject.class.getName(), i);
|
||||||
|
buildString("if(obj.isNil()) {");
|
||||||
|
buildString("} else {");
|
||||||
|
Class<?> type = e.getType();
|
||||||
|
if(type.isPrimitive()) {
|
||||||
|
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveConvertName(type));
|
||||||
|
} else {
|
||||||
|
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||||
|
}
|
||||||
|
buildString("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
buildString("return _$$_t;");
|
||||||
|
|
||||||
|
buildString("}");
|
||||||
|
return getBuiltString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected String primitivePackName(Class<?> type) {
|
||||||
|
if(type == boolean.class) {
|
||||||
|
return "packBoolean";
|
||||||
|
} else if(type == byte.class) {
|
||||||
|
return "packByte";
|
||||||
|
} else if(type == short.class) {
|
||||||
|
return "packShort";
|
||||||
|
} else if(type == int.class) {
|
||||||
|
return "packInt";
|
||||||
|
} else if(type == long.class) {
|
||||||
|
return "packLong";
|
||||||
|
} else if(type == float.class) {
|
||||||
|
return "packFloat";
|
||||||
|
} else if(type == double.class) {
|
||||||
|
return "packDouble";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String primitiveUnpackName(Class<?> type) {
|
||||||
|
if(type == boolean.class) {
|
||||||
|
return "unpackBoolean";
|
||||||
|
} else if(type == byte.class) {
|
||||||
|
return "unpackByte";
|
||||||
|
} else if(type == short.class) {
|
||||||
|
return "unpackShort";
|
||||||
|
} else if(type == int.class) {
|
||||||
|
return "unpackInt";
|
||||||
|
} else if(type == long.class) {
|
||||||
|
return "unpackLong";
|
||||||
|
} else if(type == float.class) {
|
||||||
|
return "unpackFloat";
|
||||||
|
} else if(type == double.class) {
|
||||||
|
return "unpackDouble";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String primitiveConvertName(Class<?> type) {
|
||||||
|
if(type == boolean.class) {
|
||||||
|
return "asBoolean";
|
||||||
|
} else if(type == byte.class) {
|
||||||
|
return "asByte";
|
||||||
|
} else if(type == short.class) {
|
||||||
|
return "asShort";
|
||||||
|
} else if(type == int.class) {
|
||||||
|
return "asInt";
|
||||||
|
} else if(type == long.class) {
|
||||||
|
return "asLong";
|
||||||
|
} else if(type == float.class) {
|
||||||
|
return "asFloat";
|
||||||
|
} else if(type == double.class) {
|
||||||
|
return "asDouble";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries) {
|
||||||
|
Template[] tmpls = new Template[entries.length];
|
||||||
|
for(int i=0; i < entries.length; i++) {
|
||||||
|
FieldEntry e = entries[i];
|
||||||
|
Template tmpl = TemplateRegistry.lookup(e.getGenericType(), true);
|
||||||
|
tmpls[i] = tmpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildContext bc = new BuildContext(this);
|
||||||
|
return bc.buildTemplate(targetClass, entries, tmpls);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class JavassistOrdinalEnumTemplate extends ReflectionTemplateBuilder.ReflectionOrdinalEnumTemplate {
|
||||||
|
JavassistOrdinalEnumTemplate(Enum<?>[] entries) {
|
||||||
|
super(entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template buildOrdinalEnumTemplate(Class<?> targetClass, Enum<?>[] entries) {
|
||||||
|
return new JavassistOrdinalEnumTemplate(entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,8 @@ import java.io.IOException;
|
|||||||
import org.msgpack.*;
|
import org.msgpack.*;
|
||||||
|
|
||||||
public class ListTemplate implements Template {
|
public class ListTemplate implements Template {
|
||||||
|
static void load() { }
|
||||||
|
|
||||||
private Template elementTemplate;
|
private Template elementTemplate;
|
||||||
|
|
||||||
public ListTemplate(Template elementTemplate) {
|
public ListTemplate(Template elementTemplate) {
|
||||||
@ -75,5 +77,10 @@ public class ListTemplate implements Template {
|
|||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.registerGeneric(List.class, new GenericTemplate1(ListTemplate.class));
|
||||||
|
TemplateRegistry.register(List.class, new ListTemplate(AnyTemplate.getInstance()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public class LongArrayTemplate implements Template {
|
||||||
|
private LongArrayTemplate() { }
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
if(!(target instanceof long[])) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
long[] array = (long[])target;
|
||||||
|
pk.packArray(array.length);
|
||||||
|
for(long a : array) {
|
||||||
|
pk.pack(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
int length = pac.unpackArray();
|
||||||
|
long[] array;
|
||||||
|
if(to != null && to instanceof long[] && ((long[])to).length == length) {
|
||||||
|
array = (long[])to;
|
||||||
|
} else {
|
||||||
|
array = new long[length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < length; i++) {
|
||||||
|
array[i] = pac.unpackLong();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
MessagePackObject[] src = from.asArray();
|
||||||
|
long[] array;
|
||||||
|
if(to != null && to instanceof long[] && ((long[])to).length == src.length) {
|
||||||
|
array = (long[])to;
|
||||||
|
} else {
|
||||||
|
array = new long[src.length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < src.length; i++) {
|
||||||
|
MessagePackObject s = src[i];
|
||||||
|
array[i] = s.asLong();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public LongArrayTemplate getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final LongArrayTemplate instance = new LongArrayTemplate();
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.register(long[].class, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,8 @@ public class LongTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(Long.class, instance);
|
CustomMessage.register(Long.class, instance);
|
||||||
|
TemplateRegistry.register(Long.class, instance);
|
||||||
|
TemplateRegistry.register(long.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ import java.io.IOException;
|
|||||||
import org.msgpack.*;
|
import org.msgpack.*;
|
||||||
|
|
||||||
public class MapTemplate implements Template {
|
public class MapTemplate implements Template {
|
||||||
|
static void load() { }
|
||||||
|
|
||||||
private Template keyTemplate;
|
private Template keyTemplate;
|
||||||
private Template valueTemplate;
|
private Template valueTemplate;
|
||||||
|
|
||||||
@ -86,5 +88,10 @@ public class MapTemplate implements Template {
|
|||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.registerGeneric(Map.class, new GenericTemplate2(MapTemplate.class));
|
||||||
|
TemplateRegistry.register(Map.class, new MapTemplate(AnyTemplate.getInstance(), AnyTemplate.getInstance()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ import java.io.IOException;
|
|||||||
import org.msgpack.*;
|
import org.msgpack.*;
|
||||||
|
|
||||||
public class NullableTemplate implements Template {
|
public class NullableTemplate implements Template {
|
||||||
|
static void load() { }
|
||||||
|
|
||||||
private Template elementTemplate;
|
private Template elementTemplate;
|
||||||
|
|
||||||
public NullableTemplate(Template elementTemplate) {
|
public NullableTemplate(Template elementTemplate) {
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public class ObjectArrayTemplate implements Template {
|
||||||
|
static void load() { }
|
||||||
|
|
||||||
|
private Template componentTemplate;
|
||||||
|
|
||||||
|
public ObjectArrayTemplate(Template componentTemplate) {
|
||||||
|
this.componentTemplate = componentTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template getcomponentTemplate() {
|
||||||
|
return componentTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
if(!(target instanceof Object[])) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
Object[] array = (Object[])target;
|
||||||
|
pk.packArray(array.length);
|
||||||
|
for(Object a : array) {
|
||||||
|
componentTemplate.pack(pk, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
int length = pac.unpackArray();
|
||||||
|
Object[] array;
|
||||||
|
if(to != null && to instanceof Object[] && ((Object[])to).length == length) {
|
||||||
|
array = (Object[])to;
|
||||||
|
} else {
|
||||||
|
array = new Object[length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < length; i++) {
|
||||||
|
array[i] = componentTemplate.unpack(pac, null);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
MessagePackObject[] src = from.asArray();
|
||||||
|
Object[] array;
|
||||||
|
if(to != null && to instanceof Object[] && ((Object[])to).length == src.length) {
|
||||||
|
array = (Object[])to;
|
||||||
|
} else {
|
||||||
|
array = new Object[src.length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < src.length; i++) {
|
||||||
|
MessagePackObject s = src[i];
|
||||||
|
array[i] = componentTemplate.convert(s, array[i]);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,444 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||||
|
private static ReflectionTemplateBuilder instance;
|
||||||
|
public synchronized static ReflectionTemplateBuilder getInstance() {
|
||||||
|
if(instance == null) {
|
||||||
|
instance = new ReflectionTemplateBuilder();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReflectionTemplateBuilder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static abstract class ReflectionFieldEntry extends FieldEntry {
|
||||||
|
public ReflectionFieldEntry(FieldEntry e) {
|
||||||
|
super(e.getField(), e.getOption());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void pack(Object target, Packer pac) throws IOException;
|
||||||
|
|
||||||
|
public abstract void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException;
|
||||||
|
|
||||||
|
public abstract void unpack(Object target, Unpacker pac) throws IOException, MessageTypeException, IllegalAccessException;
|
||||||
|
|
||||||
|
public void setNull(Object target) throws IllegalAccessException {
|
||||||
|
getField().set(target, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ObjectFieldEntry extends ReflectionFieldEntry {
|
||||||
|
private Template template;
|
||||||
|
|
||||||
|
ObjectFieldEntry(FieldEntry e, Template template) {
|
||||||
|
super(e);
|
||||||
|
this.template = template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pack(Object target, Packer pac) throws IOException {
|
||||||
|
template.pack(pac, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||||
|
Field f = getField();
|
||||||
|
Class<Object> type = (Class<Object>)f.getType();
|
||||||
|
Object fieldReference = f.get(target);
|
||||||
|
Object valueReference = template.convert(obj, fieldReference);
|
||||||
|
if(valueReference != fieldReference) {
|
||||||
|
f.set(target, valueReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unpack(Object target, Unpacker pac) throws IOException, MessageTypeException, IllegalAccessException {
|
||||||
|
Field f = getField();
|
||||||
|
Class<Object> type = (Class<Object>)f.getType();
|
||||||
|
Object fieldReference = f.get(target);
|
||||||
|
Object valueReference = template.unpack(pac, fieldReference);
|
||||||
|
if(valueReference != fieldReference) {
|
||||||
|
f.set(target, valueReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class BooleanFieldEntry extends ReflectionFieldEntry {
|
||||||
|
BooleanFieldEntry(FieldEntry e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
public void pack(Object target, Packer pac) throws IOException {
|
||||||
|
pac.pack((boolean)(Boolean)target);
|
||||||
|
}
|
||||||
|
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setBoolean(target, obj.asBoolean());
|
||||||
|
}
|
||||||
|
public void unpack(Object target, Unpacker pac) throws IOException, MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setBoolean(target, pac.unpackBoolean());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ByteFieldEntry extends ReflectionFieldEntry {
|
||||||
|
ByteFieldEntry(FieldEntry e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
public void pack(Object target, Packer pac) throws IOException {
|
||||||
|
pac.pack((byte)(Byte)target);
|
||||||
|
}
|
||||||
|
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setByte(target, obj.asByte());
|
||||||
|
}
|
||||||
|
public void unpack(Object target, Unpacker pac) throws IOException, MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setByte(target, pac.unpackByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ShortFieldEntry extends ReflectionFieldEntry {
|
||||||
|
ShortFieldEntry(FieldEntry e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
public void pack(Object target, Packer pac) throws IOException {
|
||||||
|
pac.pack((short)(Short)target);
|
||||||
|
}
|
||||||
|
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setShort(target, obj.asShort());
|
||||||
|
}
|
||||||
|
public void unpack(Object target, Unpacker pac) throws IOException, MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setShort(target, pac.unpackShort());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class IntFieldEntry extends ReflectionFieldEntry {
|
||||||
|
IntFieldEntry(FieldEntry e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
public void pack(Object target, Packer pac) throws IOException {
|
||||||
|
pac.pack((int)(Integer)target);
|
||||||
|
}
|
||||||
|
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setInt(target, obj.asInt());
|
||||||
|
}
|
||||||
|
public void unpack(Object target, Unpacker pac) throws IOException, MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setInt(target, pac.unpackInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class LongFieldEntry extends ReflectionFieldEntry {
|
||||||
|
LongFieldEntry(FieldEntry e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
public void pack(Object target, Packer pac) throws IOException {
|
||||||
|
pac.pack((long)(Long)target);
|
||||||
|
}
|
||||||
|
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setLong(target, obj.asLong());
|
||||||
|
}
|
||||||
|
public void unpack(Object target, Unpacker pac) throws IOException, MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setLong(target, pac.unpackLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FloatFieldEntry extends ReflectionFieldEntry {
|
||||||
|
FloatFieldEntry(FieldEntry e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
public void pack(Object target, Packer pac) throws IOException {
|
||||||
|
pac.pack((float)(Float)target);
|
||||||
|
}
|
||||||
|
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setFloat(target, obj.asFloat());
|
||||||
|
}
|
||||||
|
public void unpack(Object target, Unpacker pac) throws IOException, MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setFloat(target, pac.unpackFloat());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DoubleFieldEntry extends ReflectionFieldEntry {
|
||||||
|
DoubleFieldEntry(FieldEntry e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
public void pack(Object target, Packer pac) throws IOException {
|
||||||
|
pac.pack((double)(Double)target);
|
||||||
|
}
|
||||||
|
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setDouble(target, obj.asDouble());
|
||||||
|
}
|
||||||
|
public void unpack(Object target, Unpacker pac) throws IOException, MessageTypeException, IllegalAccessException {
|
||||||
|
getField().setDouble(target, pac.unpackDouble());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ReflectionTemplate extends AbstractTemplate {
|
||||||
|
protected Class<?> targetClass;
|
||||||
|
protected ReflectionFieldEntry[] entries;
|
||||||
|
protected int minimumArrayLength;
|
||||||
|
|
||||||
|
ReflectionTemplate(Class<?> targetClass, ReflectionFieldEntry[] entries) {
|
||||||
|
this.targetClass = targetClass;
|
||||||
|
this.entries = entries;
|
||||||
|
this.minimumArrayLength = 0;
|
||||||
|
for(int i=0; i < entries.length; i++) {
|
||||||
|
ReflectionFieldEntry e = entries[i];
|
||||||
|
if(e.isRequired() || e.isNullable()) {
|
||||||
|
this.minimumArrayLength = i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
try {
|
||||||
|
pk.packArray(entries.length);
|
||||||
|
for(ReflectionFieldEntry e : entries) {
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
pk.packNil();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Object obj = e.getField().get(target);
|
||||||
|
if(obj == null) {
|
||||||
|
if(!e.isNullable() && !e.isOptional()) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
pk.packNil();
|
||||||
|
} else {
|
||||||
|
e.pack(obj, pk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (MessageTypeException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MessageTypeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
try {
|
||||||
|
if(to == null) {
|
||||||
|
to = targetClass.newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
int length = pac.unpackArray();
|
||||||
|
if(length < minimumArrayLength) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i=0; i < minimumArrayLength; i++) {
|
||||||
|
ReflectionFieldEntry e = entries[i];
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
pac.unpackObject();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pac.tryUnpackNull()) {
|
||||||
|
if(e.isRequired()) {
|
||||||
|
// Requred + nil => exception
|
||||||
|
throw new MessageTypeException();
|
||||||
|
} else if(e.isOptional()) {
|
||||||
|
// Optional + nil => keep default value
|
||||||
|
} else { // Nullable
|
||||||
|
// Nullable + nil => set null
|
||||||
|
e.setNull(to);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
e.unpack(to, pac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int max = length < entries.length ? length : entries.length;
|
||||||
|
for(; i < max; i++) {
|
||||||
|
ReflectionFieldEntry e = entries[i];
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
pac.unpackObject();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pac.tryUnpackNull()) {
|
||||||
|
// this is Optional field becaue i >= minimumArrayLength
|
||||||
|
// Optional + nil => keep default value
|
||||||
|
} else {
|
||||||
|
e.unpack(to, pac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// latter entries are all Optional + nil => keep default value
|
||||||
|
|
||||||
|
for(; i < length; i++) {
|
||||||
|
pac.unpackObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
return to;
|
||||||
|
|
||||||
|
} catch (MessageTypeException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MessageTypeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
try {
|
||||||
|
if(to == null) {
|
||||||
|
to = targetClass.newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagePackObject[] array = from.asArray();
|
||||||
|
int length = array.length;
|
||||||
|
if(length < minimumArrayLength) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i=0; i < minimumArrayLength; i++) {
|
||||||
|
ReflectionFieldEntry e = entries[i];
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagePackObject obj = array[i];
|
||||||
|
if(obj.isNil()) {
|
||||||
|
if(e.isRequired()) {
|
||||||
|
// Requred + nil => exception
|
||||||
|
throw new MessageTypeException();
|
||||||
|
} else if(e.isOptional()) {
|
||||||
|
// Optional + nil => keep default value
|
||||||
|
} else { // Nullable
|
||||||
|
// Nullable + nil => set null
|
||||||
|
e.setNull(to);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
e.convert(to, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int max = length < entries.length ? length : entries.length;
|
||||||
|
for(; i < max; i++) {
|
||||||
|
ReflectionFieldEntry e = entries[i];
|
||||||
|
if(!e.isAvailable()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagePackObject obj = array[i];
|
||||||
|
if(obj.isNil()) {
|
||||||
|
// this is Optional field becaue i >= minimumArrayLength
|
||||||
|
// Optional + nil => keep default value
|
||||||
|
} else {
|
||||||
|
e.convert(to, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// latter entries are all Optional + nil => keep default value
|
||||||
|
|
||||||
|
return to;
|
||||||
|
|
||||||
|
} catch (MessageTypeException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MessageTypeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries) {
|
||||||
|
for(FieldEntry e : entries) {
|
||||||
|
Field f = e.getField();
|
||||||
|
int mod = f.getModifiers();
|
||||||
|
if(!Modifier.isPublic(mod)) {
|
||||||
|
f.setAccessible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReflectionFieldEntry[] res = new ReflectionFieldEntry[entries.length];
|
||||||
|
for(int i=0; i < entries.length; i++) {
|
||||||
|
FieldEntry e = entries[i];
|
||||||
|
Class<?> type = e.getType();
|
||||||
|
if(type.equals(boolean.class)) {
|
||||||
|
res[i] = new BooleanFieldEntry(e);
|
||||||
|
} else if(type.equals(byte.class)) {
|
||||||
|
res[i] = new ByteFieldEntry(e);
|
||||||
|
} else if(type.equals(short.class)) {
|
||||||
|
res[i] = new ShortFieldEntry(e);
|
||||||
|
} else if(type.equals(int.class)) {
|
||||||
|
res[i] = new IntFieldEntry(e);
|
||||||
|
} else if(type.equals(long.class)) {
|
||||||
|
res[i] = new LongFieldEntry(e);
|
||||||
|
} else if(type.equals(float.class)) {
|
||||||
|
res[i] = new FloatFieldEntry(e);
|
||||||
|
} else if(type.equals(double.class)) {
|
||||||
|
res[i] = new DoubleFieldEntry(e);
|
||||||
|
} else {
|
||||||
|
Template tmpl = TemplateRegistry.lookup(e.getGenericType(), true);
|
||||||
|
res[i] = new ObjectFieldEntry(e, tmpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ReflectionTemplate(targetClass, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ReflectionOrdinalEnumTemplate extends AbstractTemplate {
|
||||||
|
protected Enum<?>[] entries;
|
||||||
|
protected Map<Enum<?>, Integer> reverse;
|
||||||
|
|
||||||
|
ReflectionOrdinalEnumTemplate(Enum<?>[] entries) {
|
||||||
|
this.entries = entries;
|
||||||
|
this.reverse = new HashMap<Enum<?>, Integer>();
|
||||||
|
for(int i=0; i < entries.length; i++) {
|
||||||
|
this.reverse.put(entries[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
Integer ord = reverse.get(target);
|
||||||
|
if(ord == null) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
pk.pack((int)ord);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
int ord = pac.unpackInt();
|
||||||
|
if(entries.length <= ord) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
return entries[ord];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
int ord = from.asInt();
|
||||||
|
if(entries.length <= ord) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
return entries[ord];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template buildOrdinalEnumTemplate(Class<?> targetClass, Enum<?>[] entries) {
|
||||||
|
return new ReflectionOrdinalEnumTemplate(entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public class ShortArrayTemplate implements Template {
|
||||||
|
private ShortArrayTemplate() { }
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
if(!(target instanceof short[])) {
|
||||||
|
throw new MessageTypeException();
|
||||||
|
}
|
||||||
|
short[] array = (short[])target;
|
||||||
|
pk.packArray(array.length);
|
||||||
|
for(short a : array) {
|
||||||
|
pk.pack(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
int length = pac.unpackArray();
|
||||||
|
short[] array;
|
||||||
|
if(to != null && to instanceof short[] && ((short[])to).length == length) {
|
||||||
|
array = (short[])to;
|
||||||
|
} else {
|
||||||
|
array = new short[length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < length; i++) {
|
||||||
|
array[i] = pac.unpackShort();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
MessagePackObject[] src = from.asArray();
|
||||||
|
short[] array;
|
||||||
|
if(to != null && to instanceof short[] && ((short[])to).length == src.length) {
|
||||||
|
array = (short[])to;
|
||||||
|
} else {
|
||||||
|
array = new short[src.length];
|
||||||
|
}
|
||||||
|
for(int i=0; i < src.length; i++) {
|
||||||
|
MessagePackObject s = src[i];
|
||||||
|
array[i] = s.asShort();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public ShortArrayTemplate getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final ShortArrayTemplate instance = new ShortArrayTemplate();
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.register(short[].class, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,8 @@ public class ShortTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(Short.class, instance);
|
CustomMessage.register(Short.class, instance);
|
||||||
|
TemplateRegistry.register(Short.class, instance);
|
||||||
|
TemplateRegistry.register(short.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ public class StringTemplate implements Template {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
CustomMessage.register(String.class, instance);
|
CustomMessage.register(String.class, instance);
|
||||||
|
TemplateRegistry.register(String.class, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
307
java/src/main/java/org/msgpack/template/TemplateBuilder.java
Normal file
307
java/src/main/java/org/msgpack/template/TemplateBuilder.java
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import org.msgpack.*;
|
||||||
|
import org.msgpack.annotation.*;
|
||||||
|
|
||||||
|
public abstract class TemplateBuilder {
|
||||||
|
public static class FieldEntry {
|
||||||
|
private Field field = null;
|
||||||
|
private FieldOption option = FieldOption.IGNORE;
|
||||||
|
|
||||||
|
public FieldEntry() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public FieldEntry(Field field, FieldOption option) {
|
||||||
|
this.field = field;
|
||||||
|
this.option = option;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field getField() {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return field.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getType() {
|
||||||
|
return field.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJavaTypeName() {
|
||||||
|
Class<?> type = field.getType();
|
||||||
|
if(type.isArray()) {
|
||||||
|
return arrayTypeToString(type);
|
||||||
|
} else {
|
||||||
|
return type.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getGenericType() {
|
||||||
|
return field.getGenericType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FieldOption getOption() {
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return option != FieldOption.IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRequired() {
|
||||||
|
return option == FieldOption.REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOptional() {
|
||||||
|
return option == FieldOption.OPTIONAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNullable() {
|
||||||
|
return option == FieldOption.NULLABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAnnotated(Class<? extends Annotation> with) {
|
||||||
|
return field.getAnnotation(with) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String arrayTypeToString(Class<?> type) {
|
||||||
|
int dim = 1;
|
||||||
|
Class<?> baseType = type.getComponentType();
|
||||||
|
while(baseType.isArray()) {
|
||||||
|
baseType = baseType.getComponentType();
|
||||||
|
dim += 1;
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(baseType.getName());
|
||||||
|
for (int i = 0; i < dim; ++i) {
|
||||||
|
sb.append("[]");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override this method
|
||||||
|
public abstract Template buildTemplate(Class<?> targetClass, FieldEntry[] entries);
|
||||||
|
|
||||||
|
// Override this method
|
||||||
|
public abstract Template buildOrdinalEnumTemplate(Class<?> targetClass, Enum<?>[] entries);
|
||||||
|
|
||||||
|
|
||||||
|
public Template buildTemplate(Class<?> targetClass) {
|
||||||
|
return buildTemplate(targetClass, readFieldEntries(targetClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template buildTemplate(Class<?> targetClass, FieldOption implicitOption) {
|
||||||
|
return buildTemplate(targetClass, readFieldEntries(targetClass, implicitOption));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template buildTemplate(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||||
|
return buildTemplate(targetClass, convertFieldEntries(targetClass, flist));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template buildOrdinalEnumTemplate(Class<?> targetClass) {
|
||||||
|
Enum<?>[] entries = (Enum<?>[])targetClass.getEnumConstants();
|
||||||
|
return buildOrdinalEnumTemplate(targetClass, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static TemplateBuilder instance;
|
||||||
|
static {
|
||||||
|
// FIXME
|
||||||
|
instance = JavassistTemplateBuilder.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized static void setTemplateBuilder(TemplateBuilder builder) {
|
||||||
|
instance = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Template build(Class<?> targetClass) {
|
||||||
|
return instance.buildTemplate(targetClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Template build(Class<?> targetClass, FieldOption implicitOption) {
|
||||||
|
return instance.buildTemplate(targetClass, implicitOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Template build(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||||
|
return instance.buildTemplate(targetClass, flist);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Template buildOrdinalEnum(Class<?> targetClass) {
|
||||||
|
return instance.buildOrdinalEnumTemplate(targetClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected FieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||||
|
List<FieldList.Entry> src = flist.getList();
|
||||||
|
FieldEntry[] result = new FieldEntry[src.size()];
|
||||||
|
for(int i=0; i < src.size(); i++) {
|
||||||
|
FieldList.Entry s = src.get(i);
|
||||||
|
if(s.isAvailable()) {
|
||||||
|
result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption());
|
||||||
|
} else {
|
||||||
|
result[i] = new FieldEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FieldEntry[] readFieldEntries(Class<?> targetClass) {
|
||||||
|
FieldOption implicitOption = readImplicitFieldOption(targetClass);
|
||||||
|
return readFieldEntries(targetClass, implicitOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption) {
|
||||||
|
Field[] allFields = readAllFields(targetClass);
|
||||||
|
|
||||||
|
/* index:
|
||||||
|
* @Index(0) int a; // 0
|
||||||
|
* int b; // 1
|
||||||
|
* @Index(3) int c; // 3
|
||||||
|
* int e; // 4
|
||||||
|
* @Index(2) int d; // 2
|
||||||
|
* int e; // 5
|
||||||
|
*/
|
||||||
|
List<FieldEntry> indexed = new ArrayList<FieldEntry>();
|
||||||
|
int maxIndex = -1;
|
||||||
|
for(Field f : allFields) {
|
||||||
|
FieldOption opt = readFieldOption(f, implicitOption);
|
||||||
|
if(opt == FieldOption.IGNORE) {
|
||||||
|
// skip
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = readFieldIndex(f, maxIndex);
|
||||||
|
|
||||||
|
if(indexed.size() > index && indexed.get(index) != null) {
|
||||||
|
throw new RuntimeException("duplicated index: "+index); // FIXME exception
|
||||||
|
}
|
||||||
|
if(index < 0) {
|
||||||
|
throw new RuntimeException("invalid index: "+index); // FIXME exception
|
||||||
|
}
|
||||||
|
|
||||||
|
while(indexed.size() <= index) {
|
||||||
|
indexed.add(null);
|
||||||
|
}
|
||||||
|
indexed.set(index, new FieldEntry(f, opt));
|
||||||
|
|
||||||
|
if(maxIndex < index) {
|
||||||
|
maxIndex = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldEntry[] result = new FieldEntry[maxIndex+1];
|
||||||
|
for(int i=0; i < indexed.size(); i++) {
|
||||||
|
FieldEntry e = indexed.get(i);
|
||||||
|
if(e == null) {
|
||||||
|
result[i] = new FieldEntry();
|
||||||
|
} else {
|
||||||
|
result[i] = new FieldEntry(e.getField(), e.getOption());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Field[] readAllFields(Class<?> targetClass) {
|
||||||
|
// order: [fields of super class, ..., fields of this class]
|
||||||
|
List<Field[]> succ = new ArrayList<Field[]>();
|
||||||
|
int total = 0;
|
||||||
|
for(Class<?> c = targetClass; c != Object.class; c = c.getSuperclass()) {
|
||||||
|
Field[] fields = c.getDeclaredFields();
|
||||||
|
total += fields.length;
|
||||||
|
succ.add(fields);
|
||||||
|
}
|
||||||
|
Field[] result = new Field[total];
|
||||||
|
int off = 0;
|
||||||
|
for(int i=succ.size()-1; i >= 0; i--) {
|
||||||
|
Field[] fields = succ.get(i);
|
||||||
|
System.arraycopy(fields, 0, result, off, fields.length);
|
||||||
|
off += fields.length;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldOption readImplicitFieldOption(Class<?> targetClass) {
|
||||||
|
MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class);
|
||||||
|
if(a == null) {
|
||||||
|
return FieldOption.DEFAULT;
|
||||||
|
}
|
||||||
|
return a.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldOption readFieldOption(Field field, FieldOption implicitOption) {
|
||||||
|
int mod = field.getModifiers();
|
||||||
|
if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
|
||||||
|
return FieldOption.IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isAnnotated(field, Ignore.class)) {
|
||||||
|
return FieldOption.IGNORE;
|
||||||
|
} else if(isAnnotated(field, Required.class)) {
|
||||||
|
return FieldOption.REQUIRED;
|
||||||
|
} else if(isAnnotated(field, Optional.class)) {
|
||||||
|
return FieldOption.OPTIONAL;
|
||||||
|
} else if(isAnnotated(field, Nullable.class)) {
|
||||||
|
if(field.getDeclaringClass().isPrimitive()) {
|
||||||
|
return FieldOption.REQUIRED;
|
||||||
|
} else {
|
||||||
|
return FieldOption.NULLABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(implicitOption != FieldOption.DEFAULT) {
|
||||||
|
return implicitOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
// default mode:
|
||||||
|
// transient : Ignore
|
||||||
|
// public : Required
|
||||||
|
// others : Ignore
|
||||||
|
if(Modifier.isTransient(mod)) {
|
||||||
|
return FieldOption.IGNORE;
|
||||||
|
} else if(Modifier.isPublic(mod)) {
|
||||||
|
return FieldOption.REQUIRED;
|
||||||
|
} else {
|
||||||
|
return FieldOption.IGNORE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int readFieldIndex(Field field, int maxIndex) {
|
||||||
|
Index a = field.getAnnotation(Index.class);
|
||||||
|
if(a == null) {
|
||||||
|
return maxIndex + 1;
|
||||||
|
} else {
|
||||||
|
return a.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) {
|
||||||
|
return ao.getAnnotation(with) != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
212
java/src/main/java/org/msgpack/template/TemplateRegistry.java
Normal file
212
java/src/main/java/org/msgpack/template/TemplateRegistry.java
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
//
|
||||||
|
// 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.template;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.lang.reflect.GenericArrayType;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import org.msgpack.annotation.MessagePackMessage;
|
||||||
|
import org.msgpack.annotation.MessagePackDelegate;
|
||||||
|
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||||
|
import org.msgpack.Template;
|
||||||
|
import org.msgpack.Templates;
|
||||||
|
|
||||||
|
public class TemplateRegistry {
|
||||||
|
private static Map<Type, Template> map;
|
||||||
|
private static Map<Type, GenericTemplate> genericMap;
|
||||||
|
|
||||||
|
static {
|
||||||
|
map = new HashMap<Type, Template>();
|
||||||
|
genericMap = new HashMap<Type, GenericTemplate>();
|
||||||
|
BuiltInTemplateLoader.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(Class<?> target) { // auto-detect
|
||||||
|
if(target.isEnum()) {
|
||||||
|
register(target, TemplateBuilder.buildOrdinalEnum(target));
|
||||||
|
} else {
|
||||||
|
register(target, TemplateBuilder.build(target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(Class<?> target, FieldOption implicitOption) {
|
||||||
|
register(target, TemplateBuilder.build(target, implicitOption));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(Class<?> target, FieldList flist) throws NoSuchFieldException {
|
||||||
|
register(target, TemplateBuilder.build(target, flist));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized void register(Type rawType, Template tmpl) {
|
||||||
|
if(rawType instanceof ParameterizedType) {
|
||||||
|
rawType = ((ParameterizedType)rawType).getRawType();
|
||||||
|
}
|
||||||
|
map.put(rawType, tmpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized void registerGeneric(Type rawType, GenericTemplate gtmpl) {
|
||||||
|
if(rawType instanceof ParameterizedType) {
|
||||||
|
rawType = ((ParameterizedType)rawType).getRawType();
|
||||||
|
}
|
||||||
|
genericMap.put(rawType, gtmpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized Template lookup(Type targetType) {
|
||||||
|
return lookupImpl(targetType, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized Template lookup(Type targetType, boolean forceBuild) {
|
||||||
|
return lookupImpl(targetType, forceBuild, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized Template tryLookup(Type targetType) {
|
||||||
|
return lookupImpl(targetType, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized Template tryLookup(Type targetType, boolean forceBuild) {
|
||||||
|
return lookupImpl(targetType, forceBuild, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized Template lookupImpl(Type targetType, boolean forceBuild, boolean fallbackDefault) {
|
||||||
|
Template tmpl;
|
||||||
|
Class<?> target;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
//if((Type)target instanceof GenericArrayType) {
|
||||||
|
// return lookupArrayImpl((GenericArrayType)(Type)target);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if(targetType instanceof ParameterizedType) {
|
||||||
|
tmpl = lookupGenericImpl((ParameterizedType)targetType);
|
||||||
|
if(tmpl != null) {
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
target = (Class<?>)((ParameterizedType)targetType).getRawType();
|
||||||
|
} else {
|
||||||
|
target = (Class<?>)targetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl = map.get(target);
|
||||||
|
if(tmpl != null) {
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isAnnotated(target, MessagePackMessage.class)) {
|
||||||
|
tmpl = TemplateBuilder.build(target);
|
||||||
|
register(target, tmpl);
|
||||||
|
return tmpl;
|
||||||
|
} else if(isAnnotated(target, MessagePackDelegate.class)) {
|
||||||
|
// TODO DelegateTemplate
|
||||||
|
throw new UnsupportedOperationException("not supported yet. : " + target.getName());
|
||||||
|
} else if(isAnnotated(target, MessagePackOrdinalEnum.class)) {
|
||||||
|
tmpl = TemplateBuilder.buildOrdinalEnum(target);
|
||||||
|
register(target, tmpl);
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Class<?> i : target.getInterfaces()) {
|
||||||
|
tmpl = map.get(i);
|
||||||
|
if(tmpl != null) {
|
||||||
|
map.put(target, tmpl);
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> c = target.getSuperclass();
|
||||||
|
if(c != null) {
|
||||||
|
for(; c != Object.class; c = c.getSuperclass()) {
|
||||||
|
tmpl = map.get(c);
|
||||||
|
if(tmpl != null) {
|
||||||
|
map.put(target, tmpl);
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(forceBuild) {
|
||||||
|
tmpl = TemplateBuilder.build(target);
|
||||||
|
register(target, tmpl);
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fallbackDefault) {
|
||||||
|
tmpl = new DefaultTemplate((Class<?>)target);
|
||||||
|
register(target, tmpl);
|
||||||
|
return tmpl;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized Template lookupGeneric(Type targetType) {
|
||||||
|
if(targetType instanceof ParameterizedType) {
|
||||||
|
ParameterizedType parameterizedType = (ParameterizedType)targetType;
|
||||||
|
Template tmpl = lookupGenericImpl(parameterizedType);
|
||||||
|
if(tmpl != null) {
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
return new DefaultTemplate((Class<?>)parameterizedType.getRawType(), parameterizedType);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("actual types of the generic type are erased: "+targetType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized Template lookupGenericImpl(ParameterizedType type) {
|
||||||
|
Type rawType = type.getRawType();
|
||||||
|
GenericTemplate gtmpl = genericMap.get(rawType);
|
||||||
|
if(gtmpl == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type[] types = type.getActualTypeArguments();
|
||||||
|
Template[] tmpls = new Template[types.length];
|
||||||
|
for(int i=0; i < types.length; i++) {
|
||||||
|
tmpls[i] = lookup(types[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return gtmpl.build(tmpls);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized Template lookupArray(Type targetType) {
|
||||||
|
if(targetType instanceof GenericArrayType) {
|
||||||
|
GenericArrayType arrayType = (GenericArrayType)targetType;
|
||||||
|
return lookupArrayImpl(arrayType);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("actual type of the array type is erased: "+targetType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized Template lookupArrayImpl(GenericArrayType arrayType) {
|
||||||
|
Template tmpl = map.get(arrayType);
|
||||||
|
if(tmpl != null) {
|
||||||
|
// TODO primitive types are included?
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
Type component = arrayType.getGenericComponentType();
|
||||||
|
Template componentTemplate = lookup(component);
|
||||||
|
return new ObjectArrayTemplate(componentTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) {
|
||||||
|
return ao.getAnnotation(with) != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
69
java/src/main/java/org/msgpack/type/Raw.java
Normal file
69
java/src/main/java/org/msgpack/type/Raw.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// 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.type;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
public final class Raw {
|
||||||
|
private byte[] bytes;
|
||||||
|
private String string;
|
||||||
|
|
||||||
|
public Raw(byte[] bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
this.string = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Raw(String string) {
|
||||||
|
this.bytes = null;
|
||||||
|
this.string = string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
if(string == null) {
|
||||||
|
try {
|
||||||
|
string = new String(bytes, "UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] toByteArray() {
|
||||||
|
if(bytes == null) {
|
||||||
|
try {
|
||||||
|
bytes = string.getBytes("UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer toByteBuffer() {
|
||||||
|
return ByteBuffer.wrap(toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
RawTemplate.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
51
java/src/main/java/org/msgpack/type/RawTemplate.java
Normal file
51
java/src/main/java/org/msgpack/type/RawTemplate.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// 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.type;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.msgpack.*;
|
||||||
|
import org.msgpack.template.TemplateRegistry;
|
||||||
|
|
||||||
|
public class RawTemplate implements Template {
|
||||||
|
static void load() { }
|
||||||
|
|
||||||
|
private RawTemplate() { }
|
||||||
|
|
||||||
|
public void pack(Packer pk, Object target) throws IOException {
|
||||||
|
pk.packByteArray(((Raw)target).toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
|
return new Raw(pac.unpackByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||||
|
return new Raw(from.asByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
static public RawTemplate getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final RawTemplate instance = new RawTemplate();
|
||||||
|
|
||||||
|
static {
|
||||||
|
TemplateRegistry.register(Raw.class, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -333,6 +333,8 @@ public class DynamicCodeGenBase implements Constants {
|
|||||||
return Templates.tString();
|
return Templates.tString();
|
||||||
} else if (c.equals(BigInteger.class)) {
|
} else if (c.equals(BigInteger.class)) {
|
||||||
return Templates.tBigInteger();
|
return Templates.tBigInteger();
|
||||||
|
} else if (c.equals(byte[].class)) {
|
||||||
|
return Templates.tByteArray();
|
||||||
} else if (c.equals(ByteBuffer.class)) {
|
} else if (c.equals(ByteBuffer.class)) {
|
||||||
return Templates.tByteBuffer();
|
return Templates.tByteBuffer();
|
||||||
} else if (CustomConverter.isRegistered(c)) {// FIXME
|
} else if (CustomConverter.isRegistered(c)) {// FIXME
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package org.msgpack.buffer;
|
||||||
|
|
||||||
|
import org.msgpack.*;
|
||||||
|
import org.msgpack.object.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.net.*;
|
||||||
|
import junit.framework.*;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class VectoredByteBufferTest extends TestCase {
|
||||||
|
public VectoredByteBufferTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIO() throws Exception {
|
||||||
|
VectoredByteBuffer v = new VectoredByteBuffer();
|
||||||
|
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||||
|
byte[] ref = new byte[40];
|
||||||
|
byte[] copy = new byte[3];
|
||||||
|
ref[0] = 10;
|
||||||
|
ref[1] = 20;
|
||||||
|
ref[2] = 30;
|
||||||
|
copy[0] = 40;
|
||||||
|
copy[1] = 50;
|
||||||
|
copy[2] = 60;
|
||||||
|
|
||||||
|
byte[][] src = new byte[][] {
|
||||||
|
copy, ref, ref, copy, ref, copy, copy, ref
|
||||||
|
};
|
||||||
|
|
||||||
|
for(byte[] s : src) {
|
||||||
|
bo.write(s);
|
||||||
|
v.write(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArrayOutputStream check = new ByteArrayOutputStream();
|
||||||
|
v.writeTo(check);
|
||||||
|
|
||||||
|
assertEquals(bo.size(), check.size());
|
||||||
|
assertTrue(Arrays.equals(bo.toByteArray(), check.toByteArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
218
java/src/test/java/org/msgpack/template/TestTemplateBuilder.java
Normal file
218
java/src/test/java/org/msgpack/template/TestTemplateBuilder.java
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
package org.msgpack.template;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.math.*;
|
||||||
|
import org.msgpack.*;
|
||||||
|
import org.msgpack.annotation.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class TestTemplateBuilder extends TestCase {
|
||||||
|
public static class PrimitiveTypeFieldsClass {
|
||||||
|
public byte f0;
|
||||||
|
public short f1;
|
||||||
|
public int f2;
|
||||||
|
public long f3;
|
||||||
|
public float f4;
|
||||||
|
public double f5;
|
||||||
|
public boolean f6;
|
||||||
|
|
||||||
|
public PrimitiveTypeFieldsClass() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GeneralReferenceTypeFieldsClass {
|
||||||
|
public Byte f0;
|
||||||
|
public Short f1;
|
||||||
|
public Integer f2;
|
||||||
|
public Long f3;
|
||||||
|
public Float f4;
|
||||||
|
public Double f5;
|
||||||
|
public Boolean f6;
|
||||||
|
public BigInteger f7;
|
||||||
|
public String f8;
|
||||||
|
public byte[] f9;
|
||||||
|
|
||||||
|
public GeneralReferenceTypeFieldsClass() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SampleListTypes {
|
||||||
|
public List<Integer> f0;
|
||||||
|
public List<Integer> f1;
|
||||||
|
public List<String> f2;
|
||||||
|
public List<List<String>> f3;
|
||||||
|
public List<SampleListNestedType> f4;
|
||||||
|
|
||||||
|
public SampleListTypes() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MessagePackMessage
|
||||||
|
public static class SampleListNestedType {
|
||||||
|
public byte[] f0;
|
||||||
|
public String f1;
|
||||||
|
|
||||||
|
public SampleListNestedType() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SampleMapTypes {
|
||||||
|
public Map<Integer, Integer> f0;
|
||||||
|
public Map<Integer, Integer> f1;
|
||||||
|
public Map<String, Integer> f2;
|
||||||
|
|
||||||
|
public SampleMapTypes() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void buildAndRegisterTemplate(Class<?> targetClass) {
|
||||||
|
MessagePack.register(targetClass,
|
||||||
|
TemplateBuilder.build(targetClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
buildAndRegisterTemplate(PrimitiveTypeFieldsClass.class);
|
||||||
|
buildAndRegisterTemplate(GeneralReferenceTypeFieldsClass.class);
|
||||||
|
buildAndRegisterTemplate(SampleListNestedType.class);
|
||||||
|
buildAndRegisterTemplate(SampleListTypes.class);
|
||||||
|
buildAndRegisterTemplate(SampleMapTypes.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrimitiveTypeFieldsClass00() throws Exception {
|
||||||
|
PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass();
|
||||||
|
src.f0 = (byte) 0;
|
||||||
|
src.f1 = 1;
|
||||||
|
src.f2 = 2;
|
||||||
|
src.f3 = 3;
|
||||||
|
src.f4 = 4;
|
||||||
|
src.f5 = 5;
|
||||||
|
src.f6 = false;
|
||||||
|
|
||||||
|
byte[] raw = MessagePack.pack(src);
|
||||||
|
|
||||||
|
PrimitiveTypeFieldsClass dstu =
|
||||||
|
MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class);
|
||||||
|
assertEquals(src.f0, dstu.f0);
|
||||||
|
assertEquals(src.f1, dstu.f1);
|
||||||
|
assertEquals(src.f2, dstu.f2);
|
||||||
|
assertEquals(src.f3, dstu.f3);
|
||||||
|
assertEquals(src.f4, dstu.f4);
|
||||||
|
assertEquals(src.f5, dstu.f5);
|
||||||
|
assertEquals(src.f6, dstu.f6);
|
||||||
|
|
||||||
|
MessagePackObject o = MessagePack.unpack(raw);
|
||||||
|
PrimitiveTypeFieldsClass dsto =
|
||||||
|
o.convert(PrimitiveTypeFieldsClass.class);
|
||||||
|
|
||||||
|
assertEquals(src.f0, dsto.f0);
|
||||||
|
assertEquals(src.f1, dsto.f1);
|
||||||
|
assertEquals(src.f2, dsto.f2);
|
||||||
|
assertEquals(src.f3, dsto.f3);
|
||||||
|
assertEquals(src.f4, dsto.f4);
|
||||||
|
assertEquals(src.f5, dsto.f5);
|
||||||
|
assertEquals(src.f6, dsto.f6);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGeneralReferenceTypeFieldsClass() throws Exception {
|
||||||
|
GeneralReferenceTypeFieldsClass src = new GeneralReferenceTypeFieldsClass();
|
||||||
|
src.f0 = 0;
|
||||||
|
src.f1 = 1;
|
||||||
|
src.f2 = 2;
|
||||||
|
src.f3 = (long) 3;
|
||||||
|
src.f4 = (float) 4;
|
||||||
|
src.f5 = (double) 5;
|
||||||
|
src.f6 = false;
|
||||||
|
src.f7 = new BigInteger("7");
|
||||||
|
src.f8 = "8";
|
||||||
|
src.f9 = new byte[] { 0x01, 0x02 };
|
||||||
|
|
||||||
|
byte[] raw = MessagePack.pack(src);
|
||||||
|
|
||||||
|
GeneralReferenceTypeFieldsClass dstu =
|
||||||
|
MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class);
|
||||||
|
assertEquals(src.f0, dstu.f0);
|
||||||
|
assertEquals(src.f1, dstu.f1);
|
||||||
|
assertEquals(src.f2, dstu.f2);
|
||||||
|
assertEquals(src.f3, dstu.f3);
|
||||||
|
assertEquals(src.f4, dstu.f4);
|
||||||
|
assertEquals(src.f5, dstu.f5);
|
||||||
|
assertEquals(src.f6, dstu.f6);
|
||||||
|
assertEquals(src.f7, dstu.f7);
|
||||||
|
assertEquals(src.f8, dstu.f8);
|
||||||
|
assertEquals(src.f9[0], dstu.f9[0]);
|
||||||
|
assertEquals(src.f9[1], dstu.f9[1]);
|
||||||
|
|
||||||
|
MessagePackObject o = MessagePack.unpack(raw);
|
||||||
|
GeneralReferenceTypeFieldsClass dsto =
|
||||||
|
o.convert(GeneralReferenceTypeFieldsClass.class);
|
||||||
|
assertEquals(src.f0, dsto.f0);
|
||||||
|
assertEquals(src.f1, dsto.f1);
|
||||||
|
assertEquals(src.f2, dsto.f2);
|
||||||
|
assertEquals(src.f3, dsto.f3);
|
||||||
|
assertEquals(src.f4, dsto.f4);
|
||||||
|
assertEquals(src.f5, dsto.f5);
|
||||||
|
assertEquals(src.f6, dsto.f6);
|
||||||
|
assertEquals(src.f7, dsto.f7);
|
||||||
|
assertEquals(src.f8, dsto.f8);
|
||||||
|
assertEquals(src.f9[0], dsto.f9[0]);
|
||||||
|
assertEquals(src.f9[1], dsto.f9[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testListTypes() throws Exception {
|
||||||
|
SampleListTypes src = new SampleListTypes();
|
||||||
|
src.f0 = new ArrayList<Integer>();
|
||||||
|
src.f1 = new ArrayList<Integer>();
|
||||||
|
src.f1.add(1);
|
||||||
|
src.f1.add(2);
|
||||||
|
src.f1.add(3);
|
||||||
|
src.f2 = new ArrayList<String>();
|
||||||
|
src.f2.add("e1");
|
||||||
|
src.f2.add("e2");
|
||||||
|
src.f2.add("e3");
|
||||||
|
src.f3 = new ArrayList<List<String>>();
|
||||||
|
src.f3.add(src.f2);
|
||||||
|
src.f4 = new ArrayList<SampleListNestedType>();
|
||||||
|
SampleListNestedType slnt = new SampleListNestedType();
|
||||||
|
slnt.f0 = new byte[] { 0x01, 0x02 };
|
||||||
|
slnt.f1 = "muga";
|
||||||
|
src.f4.add(slnt);
|
||||||
|
|
||||||
|
byte[] raw = MessagePack.pack(src);
|
||||||
|
|
||||||
|
SampleListTypes dstu =
|
||||||
|
MessagePack.unpack(raw, SampleListTypes.class);
|
||||||
|
assertEquals(src.f0.size(), dstu.f0.size());
|
||||||
|
assertEquals(src.f1.size(), dstu.f1.size());
|
||||||
|
for (int i = 0; i < src.f1.size(); ++i) {
|
||||||
|
assertEquals(src.f1.get(i), dstu.f1.get(i));
|
||||||
|
}
|
||||||
|
assertEquals(src.f2.size(), dstu.f2.size());
|
||||||
|
for (int i = 0; i < src.f2.size(); ++i) {
|
||||||
|
assertEquals(src.f2.get(i), dstu.f2.get(i));
|
||||||
|
}
|
||||||
|
assertEquals(src.f3.size(), dstu.f3.size());
|
||||||
|
for (int i = 0; i < src.f3.size(); ++i) {
|
||||||
|
List<String> srclist = src.f3.get(i);
|
||||||
|
List<String> dstlist = dstu.f3.get(i);
|
||||||
|
assertEquals(srclist.size(), dstlist.size());
|
||||||
|
for (int j = 0; j < srclist.size(); ++j) {
|
||||||
|
assertEquals(srclist.get(j), dstlist.get(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertEquals(src.f4.size(), dstu.f4.size());
|
||||||
|
for (int i = 0; i < src.f4.size(); ++i) {
|
||||||
|
SampleListNestedType s = src.f4.get(i);
|
||||||
|
SampleListNestedType d = dstu.f4.get(i);
|
||||||
|
assertEquals(s.f0[0], d.f0[0]);
|
||||||
|
assertEquals(s.f0[1], d.f0[1]);
|
||||||
|
assertEquals(s.f1, d.f1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,8 +18,9 @@
|
|||||||
#ifndef MSGPACK_SYSDEP_H__
|
#ifndef MSGPACK_SYSDEP_H__
|
||||||
#define MSGPACK_SYSDEP_H__
|
#define MSGPACK_SYSDEP_H__
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#ifdef _MSC_VER
|
#include <stddef.h>
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||||
typedef __int8 int8_t;
|
typedef __int8 int8_t;
|
||||||
typedef unsigned __int8 uint8_t;
|
typedef unsigned __int8 uint8_t;
|
||||||
typedef __int16 int16_t;
|
typedef __int16 int16_t;
|
||||||
@ -28,8 +29,9 @@ typedef __int32 int32_t;
|
|||||||
typedef unsigned __int32 uint32_t;
|
typedef unsigned __int32 uint32_t;
|
||||||
typedef __int64 int64_t;
|
typedef __int64 int64_t;
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
|
#elif defined(_MSC_VER) // && _MSC_VER >= 1600
|
||||||
|
#include <stdint.h>
|
||||||
#else
|
#else
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#endif
|
#endif
|
||||||
@ -76,7 +78,7 @@ typedef unsigned int _msgpack_atomic_counter_t;
|
|||||||
#define _msgpack_be16(x) ntohs(x)
|
#define _msgpack_be16(x) ntohs(x)
|
||||||
#define _msgpack_be32(x) ntohl(x)
|
#define _msgpack_be32(x) ntohl(x)
|
||||||
|
|
||||||
#if defined(_byteswap_uint64)
|
#if defined(_byteswap_uint64) || _MSC_VER >= 1400
|
||||||
# define _msgpack_be64(x) (_byteswap_uint64(x))
|
# define _msgpack_be64(x) (_byteswap_uint64(x))
|
||||||
#elif defined(bswap_64)
|
#elif defined(bswap_64)
|
||||||
# define _msgpack_be64(x) bswap_64(x)
|
# define _msgpack_be64(x) bswap_64(x)
|
||||||
|
@ -8,6 +8,7 @@ cp pack.h ext/
|
|||||||
cp rbinit.c ext/
|
cp rbinit.c ext/
|
||||||
cp unpack.c ext/
|
cp unpack.c ext/
|
||||||
cp unpack.h ext/
|
cp unpack.h ext/
|
||||||
|
cp compat.h ext/
|
||||||
cp version.rb ext/
|
cp version.rb ext/
|
||||||
cp ../msgpack/pack_define.h msgpack/
|
cp ../msgpack/pack_define.h msgpack/
|
||||||
cp ../msgpack/pack_template.h msgpack/
|
cp ../msgpack/pack_template.h msgpack/
|
||||||
|
@ -227,8 +227,9 @@ class MessagePackTestPackUnpack < Test::Unit::TestCase
|
|||||||
assert(fe.length > 0)
|
assert(fe.length > 0)
|
||||||
off += fe.length
|
off += fe.length
|
||||||
|
|
||||||
pac.feed fe
|
#pac.feed fe
|
||||||
pac.each {|obj|
|
#pac.each {|obj|
|
||||||
|
pac.feed_each(fe) {|obj|
|
||||||
assert(!parsed)
|
assert(!parsed)
|
||||||
assert_equal(obj, str)
|
assert_equal(obj, str)
|
||||||
parsed = true
|
parsed = true
|
||||||
@ -245,8 +246,8 @@ class MessagePackTestPackUnpack < Test::Unit::TestCase
|
|||||||
pac = MessagePack::Unpacker.new
|
pac = MessagePack::Unpacker.new
|
||||||
parsed = 0
|
parsed = 0
|
||||||
raw.split(//).each do |b|
|
raw.split(//).each do |b|
|
||||||
pac.feed(b)
|
#pac.feed(b)
|
||||||
pac.each {|o|
|
pac.feed_each(b) {|o|
|
||||||
GC.start
|
GC.start
|
||||||
assert_equal(obj, o)
|
assert_equal(obj, o)
|
||||||
parsed += 1
|
parsed += 1
|
||||||
|
242
ruby/unpack.c
242
ruby/unpack.c
@ -24,7 +24,7 @@ static ID s_sysread;
|
|||||||
static ID s_readpartial;
|
static ID s_readpartial;
|
||||||
|
|
||||||
struct unpack_buffer {
|
struct unpack_buffer {
|
||||||
size_t size;
|
size_t used;
|
||||||
size_t free;
|
size_t free;
|
||||||
char* ptr;
|
char* ptr;
|
||||||
};
|
};
|
||||||
@ -37,6 +37,7 @@ typedef struct {
|
|||||||
VALUE stream;
|
VALUE stream;
|
||||||
VALUE streambuf;
|
VALUE streambuf;
|
||||||
ID stream_append_method;
|
ID stream_append_method;
|
||||||
|
size_t buffer_free_size;
|
||||||
} unpack_user;
|
} unpack_user;
|
||||||
|
|
||||||
|
|
||||||
@ -241,6 +242,13 @@ static VALUE eUnpackError;
|
|||||||
#define MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE (8*1024)
|
#define MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE (8*1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
#ifndef MSGPACK_BUFFER_FREE_SIZE
|
||||||
|
#define MSGPACK_BUFFER_FREE_SIZE (1024*1024)
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
#define MSGPACK_BUFFER_FREE_SIZE 0
|
||||||
|
|
||||||
static void MessagePack_Unpacker_free(void* data)
|
static void MessagePack_Unpacker_free(void* data)
|
||||||
{
|
{
|
||||||
if(data) {
|
if(data) {
|
||||||
@ -273,7 +281,7 @@ static VALUE MessagePack_Unpacker_alloc(VALUE klass)
|
|||||||
|
|
||||||
mp->user.finished = 0;
|
mp->user.finished = 0;
|
||||||
mp->user.offset = 0;
|
mp->user.offset = 0;
|
||||||
mp->user.buffer.size = 0;
|
mp->user.buffer.used = 0;
|
||||||
mp->user.buffer.free = 0;
|
mp->user.buffer.free = 0;
|
||||||
mp->user.buffer.ptr = NULL;
|
mp->user.buffer.ptr = NULL;
|
||||||
|
|
||||||
@ -326,6 +334,7 @@ static VALUE MessagePack_Unpacker_initialize(int argc, VALUE *argv, VALUE self)
|
|||||||
mp->user.stream = stream;
|
mp->user.stream = stream;
|
||||||
mp->user.streambuf = rb_str_buf_new(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE);
|
mp->user.streambuf = rb_str_buf_new(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE);
|
||||||
mp->user.stream_append_method = append_method_of(stream);
|
mp->user.stream_append_method = append_method_of(stream);
|
||||||
|
mp->user.buffer_free_size = MSGPACK_BUFFER_FREE_SIZE;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -366,22 +375,27 @@ static void reserve_buffer(msgpack_unpack_t* mp, size_t require)
|
|||||||
{
|
{
|
||||||
struct unpack_buffer* buffer = &mp->user.buffer;
|
struct unpack_buffer* buffer = &mp->user.buffer;
|
||||||
|
|
||||||
if(buffer->size == 0) {
|
if(buffer->used == 0) {
|
||||||
size_t nsize = MSGPACK_UNPACKER_BUFFER_INIT_SIZE;
|
if(require <= buffer->free) {
|
||||||
|
/* enough free space */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* no used buffer: realloc only */
|
||||||
|
size_t nsize = buffer->free == 0 ?
|
||||||
|
MSGPACK_UNPACKER_BUFFER_INIT_SIZE : buffer->free*2;
|
||||||
while(nsize < require) {
|
while(nsize < require) {
|
||||||
nsize *= 2;
|
nsize *= 2;
|
||||||
}
|
}
|
||||||
char* tmp = ALLOC_N(char, nsize);
|
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
||||||
buffer->ptr = tmp;
|
|
||||||
buffer->free = nsize;
|
buffer->free = nsize;
|
||||||
buffer->size = 0;
|
buffer->ptr = tmp;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(buffer->size <= mp->user.offset) {
|
if(buffer->used <= mp->user.offset) {
|
||||||
/* clear buffer and rewind offset */
|
/* clear buffer and rewind offset */
|
||||||
buffer->free += buffer->size;
|
buffer->free += buffer->used;
|
||||||
buffer->size = 0;
|
buffer->used = 0;
|
||||||
mp->user.offset = 0;
|
mp->user.offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,41 +404,91 @@ static void reserve_buffer(msgpack_unpack_t* mp, size_t require)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nsize = (buffer->size + buffer->free) * 2;
|
size_t nsize = (buffer->used + buffer->free) * 2;
|
||||||
|
|
||||||
if(mp->user.offset <= buffer->size / 2) {
|
if(mp->user.offset <= buffer->used / 2) {
|
||||||
/* parsed less than half: realloc only */
|
/* parsed less than half: realloc only */
|
||||||
while(nsize < buffer->size + require) {
|
while(nsize < buffer->used + require) {
|
||||||
nsize *= 2;
|
nsize *= 2;
|
||||||
}
|
}
|
||||||
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
||||||
buffer->free = nsize - buffer->size;
|
buffer->free = nsize - buffer->used;
|
||||||
buffer->ptr = tmp;
|
buffer->ptr = tmp;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* parsed more than half: realloc and move */
|
/* parsed more than half: realloc and move */
|
||||||
size_t not_parsed = buffer->size - mp->user.offset;
|
size_t not_parsed = buffer->used - mp->user.offset;
|
||||||
while(nsize < not_parsed + require) {
|
while(nsize < not_parsed + require) {
|
||||||
nsize *= 2;
|
nsize *= 2;
|
||||||
}
|
}
|
||||||
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
||||||
memcpy(tmp, tmp + mp->user.offset, not_parsed);
|
memcpy(tmp, tmp + mp->user.offset, not_parsed);
|
||||||
buffer->free = nsize - buffer->size;
|
buffer->free = nsize - not_parsed;
|
||||||
buffer->size = not_parsed;
|
buffer->used = not_parsed;
|
||||||
buffer->ptr = tmp;
|
buffer->ptr = tmp;
|
||||||
mp->user.offset = 0;
|
mp->user.offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void feed_buffer(msgpack_unpack_t* mp, const char* ptr, size_t len)
|
static inline void try_free_buffer(msgpack_unpack_t* mp, size_t require)
|
||||||
|
{
|
||||||
|
if(mp->user.buffer_free_size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct unpack_buffer* buffer = &mp->user.buffer;
|
||||||
|
size_t csize = buffer->used + buffer->free;
|
||||||
|
|
||||||
|
if(csize <= mp->user.buffer_free_size) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mp->user.offset <= buffer->used / 2) {
|
||||||
|
/* parsed less than half: do nothing */
|
||||||
|
|
||||||
|
} else if(mp->user.offset < buffer->used) {
|
||||||
|
/* parsed more than half but not all: realloc and move */
|
||||||
|
size_t nsize = MSGPACK_UNPACKER_BUFFER_INIT_SIZE;
|
||||||
|
size_t not_parsed = buffer->used - mp->user.offset;
|
||||||
|
while(nsize < not_parsed + require) {
|
||||||
|
nsize *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nsize >= csize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* tmp;
|
||||||
|
if(mp->user.offset == 0) {
|
||||||
|
tmp = ALLOC_N(char, nsize);
|
||||||
|
memcpy(tmp, buffer->ptr + mp->user.offset, not_parsed);
|
||||||
|
free(buffer->ptr);
|
||||||
|
} else {
|
||||||
|
tmp = REALLOC_N(buffer->ptr, char, nsize);
|
||||||
|
}
|
||||||
|
buffer->free = nsize - not_parsed;
|
||||||
|
buffer->used = not_parsed;
|
||||||
|
buffer->ptr = tmp;
|
||||||
|
mp->user.offset = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* all parsed: free all */
|
||||||
|
free(buffer->ptr);
|
||||||
|
buffer->free = 0;
|
||||||
|
buffer->used = 0;
|
||||||
|
buffer->ptr = NULL;
|
||||||
|
mp->user.offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void feed_buffer(msgpack_unpack_t* mp, const char* ptr, size_t len)
|
||||||
{
|
{
|
||||||
struct unpack_buffer* buffer = &mp->user.buffer;
|
struct unpack_buffer* buffer = &mp->user.buffer;
|
||||||
|
|
||||||
if(buffer->free < len) {
|
reserve_buffer(mp, len);
|
||||||
reserve_buffer(mp, len);
|
|
||||||
}
|
memcpy(buffer->ptr + buffer->used, ptr, len);
|
||||||
memcpy(buffer->ptr + buffer->size, ptr, len);
|
buffer->used += len;
|
||||||
buffer->size += len;
|
|
||||||
buffer->free -= len;
|
buffer->free -= len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,7 +562,7 @@ static VALUE MessagePack_Unpacker_each(VALUE self)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(mp->user.buffer.size <= mp->user.offset) {
|
if(mp->user.buffer.used <= mp->user.offset) {
|
||||||
do_fill:
|
do_fill:
|
||||||
{
|
{
|
||||||
VALUE len = MessagePack_Unpacker_fill(self);
|
VALUE len = MessagePack_Unpacker_fill(self);
|
||||||
@ -509,7 +573,7 @@ static VALUE MessagePack_Unpacker_each(VALUE self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = template_execute_wrap_each(mp,
|
ret = template_execute_wrap_each(mp,
|
||||||
mp->user.buffer.ptr, mp->user.buffer.size,
|
mp->user.buffer.ptr, mp->user.buffer.used,
|
||||||
&mp->user.offset);
|
&mp->user.offset);
|
||||||
|
|
||||||
if(ret < 0) {
|
if(ret < 0) {
|
||||||
@ -525,9 +589,131 @@ static VALUE MessagePack_Unpacker_each(VALUE self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try_free_buffer(mp, 0);
|
||||||
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE feed_each_impl(VALUE args)
|
||||||
|
{
|
||||||
|
VALUE self = ((VALUE*)args)[0];
|
||||||
|
VALUE data = ((VALUE*)args)[1];
|
||||||
|
size_t* pconsumed = (size_t*)((VALUE*)args)[2];
|
||||||
|
|
||||||
|
UNPACKER(self, mp);
|
||||||
|
int ret;
|
||||||
|
const char* ptr = RSTRING_PTR(data);
|
||||||
|
size_t len = RSTRING_LEN(data);
|
||||||
|
|
||||||
|
if(mp->user.buffer.used > 0) {
|
||||||
|
while(1) {
|
||||||
|
ret = template_execute_wrap_each(mp,
|
||||||
|
mp->user.buffer.ptr, mp->user.buffer.used,
|
||||||
|
&mp->user.offset);
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
rb_raise(eUnpackError, "parse error.");
|
||||||
|
|
||||||
|
} else if(ret > 0) {
|
||||||
|
VALUE data = template_data(mp);
|
||||||
|
template_init(mp);
|
||||||
|
rb_yield(data);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len <= 0) {
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mp->user.buffer.used <= mp->user.offset) {
|
||||||
|
// wrap & execute & feed
|
||||||
|
while(1) {
|
||||||
|
ret = template_execute_wrap_each(mp,
|
||||||
|
ptr, len, pconsumed);
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
rb_raise(eUnpackError, "parse error.");
|
||||||
|
|
||||||
|
} else if(ret > 0) {
|
||||||
|
VALUE data = template_data(mp);
|
||||||
|
template_init(mp);
|
||||||
|
rb_yield(data);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// feed & execute
|
||||||
|
feed_buffer(mp, ptr, len);
|
||||||
|
*pconsumed = len;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
ret = template_execute_wrap_each(mp,
|
||||||
|
mp->user.buffer.ptr, mp->user.buffer.used,
|
||||||
|
&mp->user.offset);
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
rb_raise(eUnpackError, "parse error.");
|
||||||
|
|
||||||
|
} else if(ret > 0) {
|
||||||
|
VALUE data = template_data(mp);
|
||||||
|
template_init(mp);
|
||||||
|
rb_yield(data);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE feed_each_ensure(VALUE args) {
|
||||||
|
VALUE self = ((VALUE*)args)[0];
|
||||||
|
VALUE data = ((VALUE*)args)[1];
|
||||||
|
size_t* pconsumed = (size_t*)((VALUE*)args)[2];
|
||||||
|
|
||||||
|
const char* dptr = RSTRING_PTR(data) + *pconsumed;
|
||||||
|
size_t dlen = RSTRING_LEN(data) - *pconsumed;
|
||||||
|
|
||||||
|
if(dlen > 0) {
|
||||||
|
UNPACKER(self, mp);
|
||||||
|
try_free_buffer(mp, dlen);
|
||||||
|
feed_buffer(mp, dptr, dlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Document-method: MessagePack::Unpacker#feed_each
|
||||||
|
*
|
||||||
|
* call-seq:
|
||||||
|
* unpacker.feed_each(data) {|object| }
|
||||||
|
*
|
||||||
|
* Same as feed(data) + each {|object| }, but tries to avoid copying of the buffer.
|
||||||
|
*/
|
||||||
|
static VALUE MessagePack_Unpacker_feed_each(VALUE self, VALUE data)
|
||||||
|
{
|
||||||
|
size_t consumed = 0;
|
||||||
|
StringValue(data);
|
||||||
|
|
||||||
|
VALUE args[3];
|
||||||
|
args[0] = self;
|
||||||
|
args[1] = data;
|
||||||
|
args[2] = (VALUE)&consumed;
|
||||||
|
|
||||||
|
return rb_ensure(feed_each_impl, (VALUE)args,
|
||||||
|
feed_each_ensure, (VALUE)args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline VALUE MessagePack_unpack_impl(VALUE self, VALUE data, unsigned long dlen)
|
static inline VALUE MessagePack_unpack_impl(VALUE self, VALUE data, unsigned long dlen)
|
||||||
{
|
{
|
||||||
@ -620,7 +806,7 @@ static VALUE MessagePack_Unpacker_execute_impl(VALUE self, VALUE data,
|
|||||||
*
|
*
|
||||||
* This method doesn't use the internal buffer.
|
* This method doesn't use the internal buffer.
|
||||||
*
|
*
|
||||||
* Call *reset()* method before calling this method again.
|
* Call *reset* method before calling this method again.
|
||||||
*
|
*
|
||||||
* UnpackError is throw when parse error is occured.
|
* UnpackError is throw when parse error is occured.
|
||||||
*/
|
*/
|
||||||
@ -642,7 +828,7 @@ static VALUE MessagePack_Unpacker_execute_limit(VALUE self, VALUE data,
|
|||||||
*
|
*
|
||||||
* This method doesn't use the internal buffer.
|
* This method doesn't use the internal buffer.
|
||||||
*
|
*
|
||||||
* Call *reset()* method before calling this method again.
|
* Call *reset* method before calling this method again.
|
||||||
*
|
*
|
||||||
* This returns offset that was parsed to.
|
* This returns offset that was parsed to.
|
||||||
* Use *finished?* method to check an object is deserialized and call *data*
|
* Use *finished?* method to check an object is deserialized and call *data*
|
||||||
@ -705,6 +891,7 @@ static VALUE MessagePack_Unpacker_reset(VALUE self)
|
|||||||
UNPACKER(self, mp);
|
UNPACKER(self, mp);
|
||||||
template_init(mp);
|
template_init(mp);
|
||||||
mp->user.finished = 0;
|
mp->user.finished = 0;
|
||||||
|
try_free_buffer(mp, 0);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,6 +913,7 @@ void Init_msgpack_unpack(VALUE mMessagePack)
|
|||||||
rb_define_method(cUnpacker, "each", MessagePack_Unpacker_each, 0);
|
rb_define_method(cUnpacker, "each", MessagePack_Unpacker_each, 0);
|
||||||
rb_define_method(cUnpacker, "stream", MessagePack_Unpacker_stream_get, 0);
|
rb_define_method(cUnpacker, "stream", MessagePack_Unpacker_stream_get, 0);
|
||||||
rb_define_method(cUnpacker, "stream=", MessagePack_Unpacker_stream_set, 1);
|
rb_define_method(cUnpacker, "stream=", MessagePack_Unpacker_stream_set, 1);
|
||||||
|
rb_define_method(cUnpacker, "feed_each", MessagePack_Unpacker_feed_each, 1);
|
||||||
|
|
||||||
/* Unbuffered API */
|
/* Unbuffered API */
|
||||||
rb_define_method(cUnpacker, "execute", MessagePack_Unpacker_execute, 2);
|
rb_define_method(cUnpacker, "execute", MessagePack_Unpacker_execute, 2);
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
module MessagePack
|
module MessagePack
|
||||||
VERSION = "0.4.3"
|
VERSION = "0.4.4"
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user