mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-19 13:02:13 +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;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import org.msgpack.template.TemplateRegistry;
|
||||
|
||||
public class CustomMessage {
|
||||
public static void registerPacker(Class<?> target, MessagePacker packer) {
|
||||
@ -33,6 +34,7 @@ public class CustomMessage {
|
||||
}
|
||||
|
||||
public static void register(Class<?> target, Template tmpl) {
|
||||
TemplateRegistry.register(target, tmpl);
|
||||
CustomPacker.register(target, tmpl);
|
||||
CustomConverter.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.DynamicOrdinalEnumTemplate;
|
||||
import org.msgpack.util.codegen.FieldList;
|
||||
import org.msgpack.template.TemplateRegistry;
|
||||
import org.msgpack.template.TemplateBuilder;
|
||||
|
||||
public class MessagePack {
|
||||
public static byte[] pack(Object obj) {
|
||||
@ -150,6 +152,8 @@ public class MessagePack {
|
||||
}
|
||||
|
||||
public static void register(Class<?> target) { // auto-detect
|
||||
TemplateRegistry.register(target);
|
||||
|
||||
Template tmpl;
|
||||
if(target.isEnum()) {
|
||||
tmpl = DynamicOrdinalEnumTemplate.create(target);
|
||||
@ -194,6 +198,7 @@ public class MessagePack {
|
||||
}
|
||||
|
||||
public static void register(Class<?> target, FieldList opts) {
|
||||
TemplateRegistry.register(target); // FIXME FieldList
|
||||
Template tmpl = DynamicTemplate.create(target, opts);
|
||||
CustomPacker.register(target, tmpl);
|
||||
CustomConverter.register(target, tmpl);
|
||||
@ -201,6 +206,7 @@ public class MessagePack {
|
||||
}
|
||||
|
||||
public static void register(Class<?> target, Template tmpl) {
|
||||
TemplateRegistry.register(target, tmpl);
|
||||
CustomPacker.register(target, tmpl);
|
||||
CustomConverter.register(target, tmpl);
|
||||
CustomUnpacker.register(target, tmpl);
|
||||
|
@ -21,14 +21,9 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
import java.math.BigInteger;
|
||||
import org.msgpack.template.ClassTemplate;
|
||||
import org.msgpack.template.NullableTemplate;
|
||||
import org.msgpack.template.TemplateRegistry;
|
||||
|
||||
public abstract class MessagePackObject implements Cloneable, MessagePackable {
|
||||
static {
|
||||
Templates.load();
|
||||
}
|
||||
|
||||
public boolean isNil() {
|
||||
return false;
|
||||
}
|
||||
@ -155,9 +150,11 @@ public abstract class MessagePackObject implements Cloneable, MessagePackable {
|
||||
return convert((Class<T>)to.getClass(), to);
|
||||
}
|
||||
|
||||
private <T> T convert(Class<T> klass, T to) throws MessageTypeException {
|
||||
// FIXME nullable?
|
||||
return (T)convert(new NullableTemplate(new ClassTemplate(klass)), to);
|
||||
public <T> T convert(Class<T> klass, T to) throws MessageTypeException {
|
||||
if(isNil()) {
|
||||
return null;
|
||||
}
|
||||
return (T)convert(TemplateRegistry.lookup(klass), to);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,5 +27,9 @@ public class MessageTypeException extends RuntimeException {
|
||||
public MessageTypeException(String s, Throwable 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.Collection;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.msgpack.annotation.MessagePackDelegate;
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||
import org.msgpack.util.codegen.DynamicTemplate;
|
||||
import org.msgpack.template.TemplateRegistry;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public class Packer {
|
||||
static {
|
||||
Templates.load();
|
||||
}
|
||||
|
||||
public static void load() { }
|
||||
|
||||
protected byte[] castBytes = new byte[9];
|
||||
protected ByteBuffer castBuffer = ByteBuffer.wrap(castBytes);
|
||||
//protected ByteBuffer castBuffer = ByteBuffer.wrap(castBytes);
|
||||
protected OutputStream out;
|
||||
|
||||
public Packer(OutputStream out) {
|
||||
@ -78,7 +70,9 @@ public class Packer {
|
||||
if(d < -(1<<7)) {
|
||||
// signed 16
|
||||
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);
|
||||
} else {
|
||||
// signed 8
|
||||
@ -98,7 +92,9 @@ public class Packer {
|
||||
} else {
|
||||
// unsigned 16
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -110,12 +106,18 @@ public class Packer {
|
||||
if(d < -(1<<15)) {
|
||||
// signed 32
|
||||
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);
|
||||
} else if(d < -(1<<7)) {
|
||||
// signed 16
|
||||
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);
|
||||
} else {
|
||||
// signed 8
|
||||
@ -135,12 +137,18 @@ public class Packer {
|
||||
} else if(d < (1<<16)) {
|
||||
// unsigned 16
|
||||
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);
|
||||
} else {
|
||||
// unsigned 32
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -153,19 +161,33 @@ public class Packer {
|
||||
if(d < -(1L<<31)) {
|
||||
// signed 64
|
||||
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);
|
||||
} else {
|
||||
// signed 32
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
if(d < -(1<<7)) {
|
||||
// signed 16
|
||||
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);
|
||||
} else {
|
||||
// signed 8
|
||||
@ -187,7 +209,9 @@ public class Packer {
|
||||
} else {
|
||||
// unsigned 16
|
||||
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);
|
||||
//System.out.println("pack uint 16 "+(short)d);
|
||||
}
|
||||
@ -195,12 +219,24 @@ public class Packer {
|
||||
if(d < (1L<<32)) {
|
||||
// unsigned 32
|
||||
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);
|
||||
} else {
|
||||
// unsigned 64
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -222,7 +258,7 @@ public class Packer {
|
||||
castBytes[6] = barray[barray.length-3];
|
||||
castBytes[7] = barray[barray.length-2];
|
||||
castBytes[8] = barray[barray.length-1];
|
||||
out.write(castBytes);
|
||||
out.write(castBytes, 0, 9);
|
||||
return this;
|
||||
} else {
|
||||
throw new MessageTypeException("can't pack BigInteger larger than 0xffffffffffffffff");
|
||||
@ -231,14 +267,28 @@ public class Packer {
|
||||
|
||||
public Packer packFloat(float d) throws IOException {
|
||||
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);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packDouble(double d) throws IOException {
|
||||
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);
|
||||
return this;
|
||||
}
|
||||
@ -268,11 +318,17 @@ public class Packer {
|
||||
out.write((byte)d);
|
||||
} else if(n < 65536) {
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
return this;
|
||||
@ -284,11 +340,17 @@ public class Packer {
|
||||
out.write((byte)d);
|
||||
} else if(n < 65536) {
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
return this;
|
||||
@ -300,11 +362,17 @@ public class Packer {
|
||||
out.write((byte)d);
|
||||
} else if(n < 65536) {
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
return this;
|
||||
@ -449,7 +517,8 @@ public class Packer {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,6 @@ package org.msgpack;
|
||||
import org.msgpack.template.*;
|
||||
|
||||
public class Templates {
|
||||
public static void load() { }
|
||||
|
||||
public static Template tNullable(Template elementTemplate) {
|
||||
return new NullableTemplate(elementTemplate);
|
||||
}
|
||||
@ -46,7 +44,11 @@ public class Templates {
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -23,8 +23,7 @@ import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.math.BigInteger;
|
||||
import org.msgpack.template.ClassTemplate;
|
||||
import org.msgpack.template.NullableTemplate;
|
||||
import org.msgpack.template.TemplateRegistry;
|
||||
|
||||
/**
|
||||
* Unpacker enables you to deserialize objects from stream.
|
||||
@ -105,10 +104,6 @@ import org.msgpack.template.NullableTemplate;
|
||||
* </pre>
|
||||
*/
|
||||
public class Unpacker implements Iterable<MessagePackObject> {
|
||||
static {
|
||||
Templates.load();
|
||||
}
|
||||
|
||||
// buffer:
|
||||
// +---------------------------------------------+
|
||||
// | [object] | [obje| unparsed ... | unused ...|
|
||||
@ -578,6 +573,19 @@ public class Unpacker implements Iterable<MessagePackObject> {
|
||||
// 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 {
|
||||
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 {
|
||||
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)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MessagePackDelegate {
|
||||
String value();
|
||||
}
|
||||
|
@ -21,8 +21,10 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.msgpack.template.FieldOption;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
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() { }
|
||||
|
||||
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();
|
||||
} 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 {
|
||||
CustomMessage.register(MessagePackObject.class, instance);
|
||||
TemplateRegistry.register(MessagePackObject.class, instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ public class BigIntegerTemplate implements Template {
|
||||
|
||||
static {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
TemplateRegistry.register(ByteBuffer.class, instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,8 @@ public class ByteTemplate implements Template {
|
||||
|
||||
static {
|
||||
CustomMessage.register(Byte.class, instance);
|
||||
TemplateRegistry.register(Byte.class, instance);
|
||||
TemplateRegistry.register(byte.class, instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.annotation.Annotation;
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.annotation.MessagePackDelegate;
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
@ -30,10 +32,6 @@ import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class ClassTemplate implements Template {
|
||||
static {
|
||||
Templates.load();
|
||||
}
|
||||
|
||||
private Class<?> klass;
|
||||
|
||||
public ClassTemplate(Class<?> klass) {
|
||||
@ -119,14 +117,14 @@ public class ClassTemplate implements Template {
|
||||
// pk.packDouble((Double)o);
|
||||
// return;
|
||||
//}
|
||||
if(o instanceof BigInteger) {
|
||||
pk.packBigInteger((BigInteger)o);
|
||||
return;
|
||||
}
|
||||
if (o instanceof ByteBuffer) { // FIXME
|
||||
Templates.tByteBuffer().pack(pk, o);
|
||||
return;
|
||||
}
|
||||
//if(o instanceof BigInteger) {
|
||||
// pk.packBigInteger((BigInteger)o);
|
||||
// return;
|
||||
//}
|
||||
//if (o instanceof ByteBuffer) {
|
||||
// Templates.tByteBuffer().pack(pk, o);
|
||||
// return;
|
||||
//}
|
||||
|
||||
MessagePacker packer = CustomPacker.get(klass);
|
||||
if(packer != null) {
|
||||
@ -134,15 +132,15 @@ public class ClassTemplate implements Template {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
||||
if (isAnnotated(klass, MessagePackMessage.class)) {
|
||||
Template tmpl = DynamicTemplate.create(klass);
|
||||
CustomMessage.register(klass, tmpl);
|
||||
tmpl.pack(pk, o);
|
||||
return;
|
||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
} else if (isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
// FIXME DelegatePacker
|
||||
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);
|
||||
CustomMessage.register(klass, tmpl);
|
||||
tmpl.pack(pk, o);
|
||||
@ -171,14 +169,14 @@ public class ClassTemplate implements Template {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
||||
if (isAnnotated(klass, MessagePackMessage.class)) {
|
||||
Template tmpl = DynamicTemplate.create(klass);
|
||||
CustomMessage.register(klass, tmpl);
|
||||
return tmpl.unpack(pac, to);
|
||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
} else if (isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
// TODO DelegateUnpacker
|
||||
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);
|
||||
CustomMessage.register(klass, tmpl);
|
||||
return tmpl.unpack(pac, to);
|
||||
@ -187,20 +185,20 @@ public class ClassTemplate implements Template {
|
||||
// fallback
|
||||
MessageConverter converter = null;
|
||||
|
||||
if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
||||
if (isAnnotated(klass, MessagePackMessage.class)) {
|
||||
Template tmpl = DynamicTemplate.create(klass);
|
||||
CustomMessage.register(klass, tmpl);
|
||||
return tmpl.convert(pac.unpackObject(), to);
|
||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
} else if (isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
// TODO DelegateConverter
|
||||
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);
|
||||
CustomMessage.register(klass, tmpl);
|
||||
return tmpl.convert(pac.unpackObject(), to);
|
||||
}
|
||||
|
||||
throw new MessageTypeException();
|
||||
throw new MessageTypeException("unknown type: "+klass);
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MessageTypeException(e.getMessage()); // FIXME
|
||||
@ -228,14 +226,14 @@ public class ClassTemplate implements Template {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
||||
if (isAnnotated(klass, MessagePackMessage.class)) {
|
||||
Template tmpl = DynamicTemplate.create(klass);
|
||||
CustomMessage.register(klass, tmpl);
|
||||
return tmpl.convert(from, to);
|
||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
} else if (isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
// TODO DelegateConverter
|
||||
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);
|
||||
CustomMessage.register(klass, tmpl);
|
||||
return tmpl.convert(from, to);
|
||||
@ -249,5 +247,9 @@ public class ClassTemplate implements Template {
|
||||
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.*;
|
||||
|
||||
public class CollectionTemplate implements Template {
|
||||
public static void load() { }
|
||||
|
||||
private Template elementTemplate;
|
||||
|
||||
public CollectionTemplate(Template elementTemplate) {
|
||||
@ -72,5 +74,10 @@ public class CollectionTemplate implements Template {
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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.*;
|
||||
|
||||
public class ListTemplate implements Template {
|
||||
static void load() { }
|
||||
|
||||
private Template elementTemplate;
|
||||
|
||||
public ListTemplate(Template elementTemplate) {
|
||||
@ -75,5 +77,10 @@ public class ListTemplate implements Template {
|
||||
}
|
||||
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 {
|
||||
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.*;
|
||||
|
||||
public class MapTemplate implements Template {
|
||||
static void load() { }
|
||||
|
||||
private Template keyTemplate;
|
||||
private Template valueTemplate;
|
||||
|
||||
@ -86,5 +88,10 @@ public class MapTemplate implements Template {
|
||||
}
|
||||
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.*;
|
||||
|
||||
public class NullableTemplate implements Template {
|
||||
static void load() { }
|
||||
|
||||
private 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 {
|
||||
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 {
|
||||
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();
|
||||
} else if (c.equals(BigInteger.class)) {
|
||||
return Templates.tBigInteger();
|
||||
} else if (c.equals(byte[].class)) {
|
||||
return Templates.tByteArray();
|
||||
} else if (c.equals(ByteBuffer.class)) {
|
||||
return Templates.tByteBuffer();
|
||||
} 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__
|
||||
#define MSGPACK_SYSDEP_H__
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int16 int16_t;
|
||||
@ -28,8 +29,9 @@ typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#elif defined(_MSC_VER) // && _MSC_VER >= 1600
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
@ -76,7 +78,7 @@ typedef unsigned int _msgpack_atomic_counter_t;
|
||||
#define _msgpack_be16(x) ntohs(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))
|
||||
#elif defined(bswap_64)
|
||||
# define _msgpack_be64(x) bswap_64(x)
|
||||
|
@ -8,6 +8,7 @@ cp pack.h ext/
|
||||
cp rbinit.c ext/
|
||||
cp unpack.c ext/
|
||||
cp unpack.h ext/
|
||||
cp compat.h ext/
|
||||
cp version.rb ext/
|
||||
cp ../msgpack/pack_define.h msgpack/
|
||||
cp ../msgpack/pack_template.h msgpack/
|
||||
|
@ -227,8 +227,9 @@ class MessagePackTestPackUnpack < Test::Unit::TestCase
|
||||
assert(fe.length > 0)
|
||||
off += fe.length
|
||||
|
||||
pac.feed fe
|
||||
pac.each {|obj|
|
||||
#pac.feed fe
|
||||
#pac.each {|obj|
|
||||
pac.feed_each(fe) {|obj|
|
||||
assert(!parsed)
|
||||
assert_equal(obj, str)
|
||||
parsed = true
|
||||
@ -245,8 +246,8 @@ class MessagePackTestPackUnpack < Test::Unit::TestCase
|
||||
pac = MessagePack::Unpacker.new
|
||||
parsed = 0
|
||||
raw.split(//).each do |b|
|
||||
pac.feed(b)
|
||||
pac.each {|o|
|
||||
#pac.feed(b)
|
||||
pac.feed_each(b) {|o|
|
||||
GC.start
|
||||
assert_equal(obj, o)
|
||||
parsed += 1
|
||||
|
240
ruby/unpack.c
240
ruby/unpack.c
@ -24,7 +24,7 @@ static ID s_sysread;
|
||||
static ID s_readpartial;
|
||||
|
||||
struct unpack_buffer {
|
||||
size_t size;
|
||||
size_t used;
|
||||
size_t free;
|
||||
char* ptr;
|
||||
};
|
||||
@ -37,6 +37,7 @@ typedef struct {
|
||||
VALUE stream;
|
||||
VALUE streambuf;
|
||||
ID stream_append_method;
|
||||
size_t buffer_free_size;
|
||||
} unpack_user;
|
||||
|
||||
|
||||
@ -241,6 +242,13 @@ static VALUE eUnpackError;
|
||||
#define MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE (8*1024)
|
||||
#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)
|
||||
{
|
||||
if(data) {
|
||||
@ -273,7 +281,7 @@ static VALUE MessagePack_Unpacker_alloc(VALUE klass)
|
||||
|
||||
mp->user.finished = 0;
|
||||
mp->user.offset = 0;
|
||||
mp->user.buffer.size = 0;
|
||||
mp->user.buffer.used = 0;
|
||||
mp->user.buffer.free = 0;
|
||||
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.streambuf = rb_str_buf_new(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE);
|
||||
mp->user.stream_append_method = append_method_of(stream);
|
||||
mp->user.buffer_free_size = MSGPACK_BUFFER_FREE_SIZE;
|
||||
|
||||
return self;
|
||||
}
|
||||
@ -366,22 +375,27 @@ static void reserve_buffer(msgpack_unpack_t* mp, size_t require)
|
||||
{
|
||||
struct unpack_buffer* buffer = &mp->user.buffer;
|
||||
|
||||
if(buffer->size == 0) {
|
||||
size_t nsize = MSGPACK_UNPACKER_BUFFER_INIT_SIZE;
|
||||
if(buffer->used == 0) {
|
||||
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) {
|
||||
nsize *= 2;
|
||||
}
|
||||
char* tmp = ALLOC_N(char, nsize);
|
||||
buffer->ptr = tmp;
|
||||
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
||||
buffer->free = nsize;
|
||||
buffer->size = 0;
|
||||
buffer->ptr = tmp;
|
||||
return;
|
||||
}
|
||||
|
||||
if(buffer->size <= mp->user.offset) {
|
||||
if(buffer->used <= mp->user.offset) {
|
||||
/* clear buffer and rewind offset */
|
||||
buffer->free += buffer->size;
|
||||
buffer->size = 0;
|
||||
buffer->free += buffer->used;
|
||||
buffer->used = 0;
|
||||
mp->user.offset = 0;
|
||||
}
|
||||
|
||||
@ -390,41 +404,91 @@ static void reserve_buffer(msgpack_unpack_t* mp, size_t require)
|
||||
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 */
|
||||
while(nsize < buffer->size + require) {
|
||||
while(nsize < buffer->used + require) {
|
||||
nsize *= 2;
|
||||
}
|
||||
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
||||
buffer->free = nsize - buffer->size;
|
||||
buffer->free = nsize - buffer->used;
|
||||
buffer->ptr = tmp;
|
||||
|
||||
} else {
|
||||
/* 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) {
|
||||
nsize *= 2;
|
||||
}
|
||||
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
||||
memcpy(tmp, tmp + mp->user.offset, not_parsed);
|
||||
buffer->free = nsize - buffer->size;
|
||||
buffer->size = not_parsed;
|
||||
buffer->free = nsize - not_parsed;
|
||||
buffer->used = not_parsed;
|
||||
buffer->ptr = tmp;
|
||||
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;
|
||||
|
||||
if(buffer->free < len) {
|
||||
reserve_buffer(mp, len);
|
||||
}
|
||||
memcpy(buffer->ptr + buffer->size, ptr, len);
|
||||
buffer->size += len;
|
||||
|
||||
memcpy(buffer->ptr + buffer->used, ptr, len);
|
||||
buffer->used += len;
|
||||
buffer->free -= len;
|
||||
}
|
||||
|
||||
@ -498,7 +562,7 @@ static VALUE MessagePack_Unpacker_each(VALUE self)
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
if(mp->user.buffer.size <= mp->user.offset) {
|
||||
if(mp->user.buffer.used <= mp->user.offset) {
|
||||
do_fill:
|
||||
{
|
||||
VALUE len = MessagePack_Unpacker_fill(self);
|
||||
@ -509,7 +573,7 @@ static VALUE MessagePack_Unpacker_each(VALUE self)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if(ret < 0) {
|
||||
@ -525,9 +589,131 @@ static VALUE MessagePack_Unpacker_each(VALUE self)
|
||||
}
|
||||
}
|
||||
|
||||
try_free_buffer(mp, 0);
|
||||
|
||||
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)
|
||||
{
|
||||
@ -620,7 +806,7 @@ static VALUE MessagePack_Unpacker_execute_impl(VALUE self, VALUE data,
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@ -642,7 +828,7 @@ static VALUE MessagePack_Unpacker_execute_limit(VALUE self, VALUE data,
|
||||
*
|
||||
* 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.
|
||||
* 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);
|
||||
template_init(mp);
|
||||
mp->user.finished = 0;
|
||||
try_free_buffer(mp, 0);
|
||||
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, "stream", MessagePack_Unpacker_stream_get, 0);
|
||||
rb_define_method(cUnpacker, "stream=", MessagePack_Unpacker_stream_set, 1);
|
||||
rb_define_method(cUnpacker, "feed_each", MessagePack_Unpacker_feed_each, 1);
|
||||
|
||||
/* Unbuffered API */
|
||||
rb_define_method(cUnpacker, "execute", MessagePack_Unpacker_execute, 2);
|
||||
|
@ -1,3 +1,3 @@
|
||||
module MessagePack
|
||||
VERSION = "0.4.3"
|
||||
VERSION = "0.4.4"
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user