mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-22 16:33:49 +01:00
import MessagePack for Java implementation plan 2
This commit is contained in:
parent
93a95725fc
commit
e39e1d4f60
@ -29,3 +29,9 @@ public class MessagePack {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public interface MessagePackable {
|
||||
public void toMessagePack(Packer pk);
|
||||
}
|
||||
*/
|
||||
|
||||
|
15
java-plan2/build.xml
Normal file
15
java-plan2/build.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<project name="MessagePack for Java">
|
||||
<target name="prepare">
|
||||
<mkdir dir="build" />
|
||||
<mkdir dir="dist" />
|
||||
</target>
|
||||
<target name="clean">
|
||||
<delete dir="build"/>
|
||||
<delete dir="dist"/>
|
||||
</target>
|
||||
<target name="compile" depends="prepare">
|
||||
<javac srcdir="src" destdir="build" classpath="lib" source="1.5" target="1.5">
|
||||
<classpath><fileset dir="lib" /> </classpath>
|
||||
</javac>
|
||||
</target>
|
||||
</project>
|
25
java-plan2/src/org/msgpack/GenericArray.java
Normal file
25
java-plan2/src/org/msgpack/GenericArray.java
Normal file
@ -0,0 +1,25 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GenericArray extends GenericObject {
|
||||
private ArrayList<GenericObject> array;
|
||||
|
||||
public GenericArray(int length)
|
||||
{
|
||||
this.array = new ArrayList<GenericObject>(length);
|
||||
}
|
||||
|
||||
public void add(GenericObject element)
|
||||
{
|
||||
array.add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GenericObject> asArray()
|
||||
{
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
17
java-plan2/src/org/msgpack/GenericBoolean.java
Normal file
17
java-plan2/src/org/msgpack/GenericBoolean.java
Normal file
@ -0,0 +1,17 @@
|
||||
package org.msgpack;
|
||||
|
||||
public class GenericBoolean extends GenericObject {
|
||||
boolean value;
|
||||
|
||||
public GenericBoolean(boolean value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean asBoolean()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
17
java-plan2/src/org/msgpack/GenericLong.java
Normal file
17
java-plan2/src/org/msgpack/GenericLong.java
Normal file
@ -0,0 +1,17 @@
|
||||
package org.msgpack;
|
||||
|
||||
public class GenericLong extends GenericObject {
|
||||
long value;
|
||||
|
||||
public GenericLong(long value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asLong()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
25
java-plan2/src/org/msgpack/GenericMap.java
Normal file
25
java-plan2/src/org/msgpack/GenericMap.java
Normal file
@ -0,0 +1,25 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class GenericMap extends GenericObject {
|
||||
private HashMap<GenericObject,GenericObject> map;
|
||||
|
||||
public GenericMap(int length)
|
||||
{
|
||||
this.map = new HashMap<GenericObject,GenericObject>(length);
|
||||
}
|
||||
|
||||
public void put(GenericObject key, GenericObject value)
|
||||
{
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<GenericObject,GenericObject> asMap()
|
||||
{
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
52
java-plan2/src/org/msgpack/GenericObject.java
Normal file
52
java-plan2/src/org/msgpack/GenericObject.java
Normal file
@ -0,0 +1,52 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class GenericObject {
|
||||
public boolean asBoolean()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public byte asByte()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public short asShort()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public int asInt()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public long asLong()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public String asString()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public byte[] asBytes()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public List<GenericObject> asArray()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public Map<GenericObject,GenericObject> asMap()
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
}
|
||||
|
59
java-plan2/src/org/msgpack/GenericRaw.java
Normal file
59
java-plan2/src/org/msgpack/GenericRaw.java
Normal file
@ -0,0 +1,59 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class GenericRaw extends GenericObject {
|
||||
byte[] bytes;
|
||||
String string;
|
||||
|
||||
public GenericRaw()
|
||||
{
|
||||
this.bytes = new byte[0];
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
public GenericRaw(byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
public GenericRaw(String string)
|
||||
{
|
||||
this.bytes = null;
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public synchronized void setString(String string)
|
||||
{
|
||||
this.string = string;
|
||||
this.bytes = null;
|
||||
}
|
||||
|
||||
public synchronized void setBytes(byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
private static Charset UTF8_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
@Override
|
||||
public synchronized String asString()
|
||||
{
|
||||
if(string == null) {
|
||||
return string = new String(bytes, UTF8_CHARSET);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized byte[] asBytes()
|
||||
{
|
||||
if(bytes == null) {
|
||||
return bytes = string.getBytes(UTF8_CHARSET);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
55
java-plan2/src/org/msgpack/GenericRawRef.java
Normal file
55
java-plan2/src/org/msgpack/GenericRawRef.java
Normal file
@ -0,0 +1,55 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class GenericRawRef extends GenericRaw {
|
||||
int offset;
|
||||
int length;
|
||||
|
||||
public GenericRawRef(byte[] bytes, int offset, int length)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
public GenericRawRef(String string)
|
||||
{
|
||||
this.bytes = null;
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public synchronized void setString(String string)
|
||||
{
|
||||
this.string = string;
|
||||
this.bytes = null;
|
||||
}
|
||||
|
||||
public synchronized void setBytes(byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
this.string = null;
|
||||
}
|
||||
|
||||
private static Charset UTF8_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
@Override
|
||||
public synchronized String asString()
|
||||
{
|
||||
if(string == null) {
|
||||
return string = new String(bytes, UTF8_CHARSET);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized byte[] asBytes()
|
||||
{
|
||||
if(bytes == null) {
|
||||
return bytes = string.getBytes(UTF8_CHARSET);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
29
java-plan2/src/org/msgpack/GenericShort.java
Normal file
29
java-plan2/src/org/msgpack/GenericShort.java
Normal file
@ -0,0 +1,29 @@
|
||||
package org.msgpack;
|
||||
|
||||
public class GenericShort extends GenericObject {
|
||||
short value;
|
||||
|
||||
public GenericShort(short value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short asShort()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int asInt()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asLong()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
7
java-plan2/src/org/msgpack/MessageConvertable.java
Normal file
7
java-plan2/src/org/msgpack/MessageConvertable.java
Normal file
@ -0,0 +1,7 @@
|
||||
package org.msgpack;
|
||||
|
||||
public interface MessageConvertable
|
||||
{
|
||||
public void messageConvert(GenericObject obj);
|
||||
}
|
||||
|
7
java-plan2/src/org/msgpack/MessageMergeable.java
Normal file
7
java-plan2/src/org/msgpack/MessageMergeable.java
Normal file
@ -0,0 +1,7 @@
|
||||
package org.msgpack;
|
||||
|
||||
public interface MessageMergeable {
|
||||
public void setField(int index, Object value);
|
||||
public Object getField(int index);
|
||||
}
|
||||
|
10
java-plan2/src/org/msgpack/MessagePackException.java
Normal file
10
java-plan2/src/org/msgpack/MessagePackException.java
Normal file
@ -0,0 +1,10 @@
|
||||
package org.msgpack;
|
||||
|
||||
public class MessagePackException extends RuntimeException
|
||||
{
|
||||
public MessagePackException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
9
java-plan2/src/org/msgpack/MessagePackable.java
Normal file
9
java-plan2/src/org/msgpack/MessagePackable.java
Normal file
@ -0,0 +1,9 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface MessagePackable
|
||||
{
|
||||
public void messagePack(Packer pk) throws IOException;
|
||||
}
|
||||
|
332
java-plan2/src/org/msgpack/Packer.java
Normal file
332
java-plan2/src/org/msgpack/Packer.java
Normal file
@ -0,0 +1,332 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Packer {
|
||||
protected byte[] castBytes = new byte[9];
|
||||
protected ByteBuffer castBuffer = ByteBuffer.wrap(castBytes);
|
||||
protected OutputStream out;
|
||||
|
||||
public Packer(OutputStream out)
|
||||
{
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public Packer packByte(byte d) throws IOException
|
||||
{
|
||||
if(d < -(1<<5)) {
|
||||
castBytes[0] = (byte)0xd1;
|
||||
castBytes[1] = d;
|
||||
out.write(castBytes, 0, 2);
|
||||
} else {
|
||||
out.write(d);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packShort(short d) throws IOException
|
||||
{
|
||||
if(d < -(1<<5)) {
|
||||
if(d < -(1<<7)) {
|
||||
// signed 16
|
||||
castBytes[0] = (byte)0xd1;
|
||||
castBuffer.putShort(1, d);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
// signed 8
|
||||
castBytes[0] = (byte)0xd0;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
}
|
||||
} else if(d < (1<<7)) {
|
||||
// fixnum
|
||||
out.write((byte)d);
|
||||
} else {
|
||||
if(d < (1<<8)) {
|
||||
// unsigned 8
|
||||
castBytes[0] = (byte)0xcc;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
} else {
|
||||
// unsigned 16
|
||||
castBytes[0] = (byte)0xcd;
|
||||
castBuffer.putShort(1, d);
|
||||
out.write(castBytes, 0, 3);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packInt(int d) throws IOException
|
||||
{
|
||||
if(d < -(1<<5)) {
|
||||
if(d < -(1<<15)) {
|
||||
// signed 32
|
||||
castBytes[0] = (byte)0xd2;
|
||||
castBuffer.putInt(1, d);
|
||||
out.write(castBytes, 0, 5);
|
||||
} else if(d < -(1<<7)) {
|
||||
// signed 16
|
||||
castBytes[0] = (byte)0xd1;
|
||||
castBuffer.putShort(1, (short)d);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
// signed 8
|
||||
castBytes[0] = (byte)0xd0;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
}
|
||||
} else if(d < (1<<7)) {
|
||||
// fixnum
|
||||
out.write((byte)d);
|
||||
} else {
|
||||
if(d < (1<<8)) {
|
||||
// unsigned 8
|
||||
castBytes[0] = (byte)0xcc;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
} else if(d < (1<<16)) {
|
||||
// unsigned 16
|
||||
castBytes[0] = (byte)0xcd;
|
||||
castBuffer.putShort(1, (short)d);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
// unsigned 32
|
||||
castBytes[0] = (byte)0xce;
|
||||
castBuffer.putInt(1, d);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packLong(long d) throws IOException
|
||||
{
|
||||
if(d < -(1L<<5)) {
|
||||
if(d < -(1L<<15)) {
|
||||
if(d < -(1L<<31)) {
|
||||
// signed 64
|
||||
castBytes[0] = (byte)0xd3;
|
||||
castBuffer.putLong(1, d);
|
||||
out.write(castBytes, 0, 9);
|
||||
} else {
|
||||
// signed 32
|
||||
castBytes[0] = (byte)0xd2;
|
||||
castBuffer.putInt(1, (int)d);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
} else {
|
||||
if(d < -(1<<7)) {
|
||||
// signed 16
|
||||
castBytes[0] = (byte)0xd1;
|
||||
castBuffer.putShort(1, (short)d);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
// signed 8
|
||||
castBytes[0] = (byte)0xd0;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
}
|
||||
}
|
||||
} else if(d < (1<<7)) {
|
||||
// fixnum
|
||||
out.write((byte)d);
|
||||
} else {
|
||||
if(d < (1L<<16)) {
|
||||
if(d < (1<<8)) {
|
||||
// unsigned 8
|
||||
castBytes[0] = (byte)0xcc;
|
||||
castBytes[1] = (byte)d;
|
||||
out.write(castBytes, 0, 2);
|
||||
} else {
|
||||
// unsigned 16
|
||||
castBytes[0] = (byte)0xcd;
|
||||
castBuffer.putShort(1, (short)d);
|
||||
out.write(castBytes, 0, 3);
|
||||
//System.out.println("pack uint 16 "+(short)d);
|
||||
}
|
||||
} else {
|
||||
if(d < (1L<<32)) {
|
||||
// unsigned 32
|
||||
castBytes[0] = (byte)0xce;
|
||||
castBuffer.putInt(1, (int)d);
|
||||
out.write(castBytes, 0, 5);
|
||||
} else {
|
||||
// unsigned 64
|
||||
castBytes[0] = (byte)0xcf;
|
||||
castBuffer.putLong(1, d);
|
||||
out.write(castBytes, 0, 9);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packFloat(float d) throws IOException
|
||||
{
|
||||
castBytes[0] = (byte)0xca;
|
||||
castBuffer.putFloat(1, d);
|
||||
out.write(castBytes, 0, 5);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packDouble(double d) throws IOException
|
||||
{
|
||||
castBytes[0] = (byte)0xcb;
|
||||
castBuffer.putDouble(1, d);
|
||||
out.write(castBytes, 0, 9);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packNil() throws IOException
|
||||
{
|
||||
out.write((byte)0xc0);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packTrue() throws IOException
|
||||
{
|
||||
out.write((byte)0xc3);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packFalse() throws IOException
|
||||
{
|
||||
out.write((byte)0xc2);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packArray(int n) throws IOException
|
||||
{
|
||||
if(n < 16) {
|
||||
final int d = 0x90 | n;
|
||||
out.write((byte)d);
|
||||
} else if(n < 65536) {
|
||||
castBytes[0] = (byte)0xdc;
|
||||
castBuffer.putShort(1, (short)n);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
castBytes[0] = (byte)0xdd;
|
||||
castBuffer.putInt(1, n);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packMap(int n) throws IOException
|
||||
{
|
||||
if(n < 16) {
|
||||
final int d = 0x80 | n;
|
||||
out.write((byte)d);
|
||||
} else if(n < 65536) {
|
||||
castBytes[0] = (byte)0xde;
|
||||
castBuffer.putShort(1, (short)n);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
castBytes[0] = (byte)0xdf;
|
||||
castBuffer.putInt(1, n);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packRaw(int n) throws IOException
|
||||
{
|
||||
if(n < 32) {
|
||||
final int d = 0xa0 | n;
|
||||
out.write((byte)d);
|
||||
} else if(n < 65536) {
|
||||
castBytes[0] = (byte)0xda;
|
||||
castBuffer.putShort(1, (short)n);
|
||||
out.write(castBytes, 0, 3);
|
||||
} else {
|
||||
castBytes[0] = (byte)0xdb;
|
||||
castBuffer.putInt(1, n);
|
||||
out.write(castBytes, 0, 5);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packRawBody(byte[] b) throws IOException
|
||||
{
|
||||
out.write(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer packRawBody(byte[] b, int off, int length) throws IOException
|
||||
{
|
||||
out.write(b, off, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
private static Charset UTF8_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
public Packer packString(String s) throws IOException
|
||||
{
|
||||
byte[] b = ((String)s).getBytes(UTF8_CHARSET);
|
||||
packRaw(b.length);
|
||||
packRawBody(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer pack(MessagePackable o) throws IOException
|
||||
{
|
||||
o.messagePack(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Packer pack(Object o) throws IOException
|
||||
{
|
||||
if(o == null) {
|
||||
packNil();
|
||||
} else if(o instanceof String) {
|
||||
byte[] b = ((String)o).getBytes(UTF8_CHARSET);
|
||||
packRaw(b.length);
|
||||
packRawBody(b);
|
||||
} else if(o instanceof byte[]) {
|
||||
byte[] b = (byte[])o;
|
||||
packRaw(b.length);
|
||||
packRawBody(b);
|
||||
} else if(o instanceof List) {
|
||||
List<Object> l = (List<Object>)o;
|
||||
packArray(l.size());
|
||||
for(Object i : l) { pack(i); }
|
||||
} else if(o instanceof Map) {
|
||||
Map<Object,Object> m = (Map<Object,Object>)o;
|
||||
packMap(m.size());
|
||||
for(Map.Entry e : m.entrySet()) {
|
||||
pack(e.getKey());
|
||||
pack(e.getValue());
|
||||
}
|
||||
} else if(o instanceof Boolean) {
|
||||
if((Boolean)o) {
|
||||
packTrue();
|
||||
} else {
|
||||
packFalse();
|
||||
}
|
||||
} else if(o instanceof Integer) {
|
||||
packInt((Integer)o);
|
||||
} else if(o instanceof Long) {
|
||||
packLong((Long)o);
|
||||
} else if(o instanceof Short) {
|
||||
packShort((Short)o);
|
||||
} else if(o instanceof Byte) {
|
||||
packByte((Byte)o);
|
||||
} else if(o instanceof Float) {
|
||||
packFloat((Float)o);
|
||||
} else if(o instanceof Double) {
|
||||
packDouble((Double)o);
|
||||
} else if(o instanceof MessagePackable) {
|
||||
((MessagePackable)o).messagePack(this);
|
||||
} else {
|
||||
throw new IOException("unknown object "+o+" ("+o.getClass()+")");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
74
java-plan2/src/org/msgpack/UnbufferedUnpacker.java
Normal file
74
java-plan2/src/org/msgpack/UnbufferedUnpacker.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.lang.Iterable;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import org.msgpack.impl.*;
|
||||
import org.msgpack.schema.Schema;
|
||||
|
||||
public class UnbufferedUnpacker extends UnpackerImpl {
|
||||
private int offset;
|
||||
private boolean finished;
|
||||
private Object data;
|
||||
|
||||
public UnbufferedUnpacker()
|
||||
{
|
||||
super(new GenericObjectBuilder());
|
||||
this.offset = 0;
|
||||
this.finished = false;
|
||||
}
|
||||
|
||||
public UnbufferedUnpacker useSchema(Schema s)
|
||||
{
|
||||
super.setBuilder(new SpecificObjectBuilder(s));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
public boolean isFinished()
|
||||
{
|
||||
return finished;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
int getOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
void setOffset(int offset)
|
||||
{
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public int execute(byte[] buffer) throws UnpackException
|
||||
{
|
||||
return execute(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
public int execute(byte[] buffer, int offset, int length) throws UnpackException
|
||||
{
|
||||
int noffset = super.execute(buffer, offset + this.offset, length);
|
||||
this.offset = noffset - offset;
|
||||
if(super.isFinished()) {
|
||||
this.data = super.getData();
|
||||
this.finished = true;
|
||||
super.reset();
|
||||
} else {
|
||||
this.finished = false;
|
||||
}
|
||||
return noffset;
|
||||
}
|
||||
}
|
||||
|
35
java-plan2/src/org/msgpack/UnpackException.java
Normal file
35
java-plan2/src/org/msgpack/UnpackException.java
Normal file
@ -0,0 +1,35 @@
|
||||
package org.msgpack;
|
||||
|
||||
public class UnpackException extends MessagePackException
|
||||
{
|
||||
public static final int EXTRA_BYTES = 1;
|
||||
public static final int INSUFFICIENT_BYTES = 0;
|
||||
public static final int PARSE_ERROR = -1;
|
||||
|
||||
private int errorCode;
|
||||
private Object data;
|
||||
|
||||
public UnpackException(String message, int errorCode)
|
||||
{
|
||||
super(message);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public UnpackException(String message, int errorCode, Object data)
|
||||
{
|
||||
super(message);
|
||||
this.errorCode = errorCode;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getErrorCode()
|
||||
{
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public Object getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
53
java-plan2/src/org/msgpack/UnpackIterator.java
Normal file
53
java-plan2/src/org/msgpack/UnpackIterator.java
Normal file
@ -0,0 +1,53 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class UnpackIterator implements Iterator<Object> {
|
||||
private Unpacker pac;
|
||||
private boolean have;
|
||||
private Object data;
|
||||
|
||||
UnpackIterator(Unpacker pac)
|
||||
{
|
||||
this.pac = pac;
|
||||
this.have = false;
|
||||
}
|
||||
|
||||
public boolean hasNext()
|
||||
{
|
||||
if(have) { return true; }
|
||||
try {
|
||||
while(true) {
|
||||
if(pac.execute()) {
|
||||
data = pac.getData();
|
||||
pac.reset();
|
||||
have = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!pac.fill()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Object next()
|
||||
{
|
||||
if(!have) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
have = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
public void remove()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
269
java-plan2/src/org/msgpack/Unpacker.java
Normal file
269
java-plan2/src/org/msgpack/Unpacker.java
Normal file
@ -0,0 +1,269 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.lang.Iterable;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import org.msgpack.impl.*;
|
||||
import org.msgpack.schema.Schema;
|
||||
|
||||
public class Unpacker extends UnpackerImpl implements Iterable<Object> {
|
||||
|
||||
public static final int DEFAULT_BUFFER_SIZE = 32*1024;
|
||||
|
||||
private int used;
|
||||
private int offset;
|
||||
private int parsed;
|
||||
private byte[] buffer;
|
||||
private int bufferReserveSize;
|
||||
private InputStream stream;
|
||||
|
||||
public Unpacker()
|
||||
{
|
||||
super(new GenericZeroCopyObjectBuilder());
|
||||
this.used = 0;
|
||||
this.offset = 0;
|
||||
this.parsed = 0;
|
||||
this.buffer = new byte[DEFAULT_BUFFER_SIZE];
|
||||
this.bufferReserveSize = DEFAULT_BUFFER_SIZE/2;
|
||||
this.stream = null;
|
||||
}
|
||||
|
||||
public Unpacker(int bufferReserveSize)
|
||||
{
|
||||
super(new GenericZeroCopyObjectBuilder());
|
||||
this.used = 0;
|
||||
this.offset = 0;
|
||||
this.parsed = 0;
|
||||
this.buffer = new byte[bufferReserveSize];
|
||||
this.bufferReserveSize = bufferReserveSize/2;
|
||||
this.stream = null;
|
||||
}
|
||||
|
||||
public Unpacker(InputStream stream)
|
||||
{
|
||||
super(new GenericZeroCopyObjectBuilder());
|
||||
this.used = 0;
|
||||
this.offset = 0;
|
||||
this.parsed = 0;
|
||||
this.buffer = new byte[DEFAULT_BUFFER_SIZE];
|
||||
this.bufferReserveSize = DEFAULT_BUFFER_SIZE/2;
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public Unpacker(InputStream stream, int bufferReserveSize)
|
||||
{
|
||||
super(new GenericZeroCopyObjectBuilder());
|
||||
this.used = 0;
|
||||
this.offset = 0;
|
||||
this.parsed = 0;
|
||||
this.buffer = new byte[bufferReserveSize];
|
||||
this.bufferReserveSize = bufferReserveSize/2;
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public Unpacker useSchema(Schema s)
|
||||
{
|
||||
super.setBuilder(new SpecificObjectBuilder(s));
|
||||
return this;
|
||||
}
|
||||
|
||||
public void reserveBuffer(int size)
|
||||
{
|
||||
if(buffer.length - used >= size) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
if(used == parsed && buffer.length >= size) {
|
||||
// rewind buffer
|
||||
used = 0;
|
||||
offset = 0;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
int nextSize = buffer.length * 2;
|
||||
while(nextSize < size + used) {
|
||||
nextSize *= 2;
|
||||
}
|
||||
|
||||
byte[] tmp = new byte[nextSize];
|
||||
System.arraycopy(buffer, offset, tmp, 0, used - offset);
|
||||
|
||||
buffer = tmp;
|
||||
used -= offset;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
public byte[] getBuffer()
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getBufferOffset()
|
||||
{
|
||||
return used;
|
||||
}
|
||||
|
||||
public int getBufferCapacity()
|
||||
{
|
||||
return buffer.length - used;
|
||||
}
|
||||
|
||||
public void bufferConsumed(int size)
|
||||
{
|
||||
used += size;
|
||||
}
|
||||
|
||||
public void feed(byte[] buffer)
|
||||
{
|
||||
feed(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
public void feed(byte[] buffer, int offset, int length)
|
||||
{
|
||||
reserveBuffer(length);
|
||||
System.arraycopy(buffer, offset, this.buffer, this.offset, length);
|
||||
bufferConsumed(length);
|
||||
}
|
||||
|
||||
public boolean fill() throws IOException
|
||||
{
|
||||
if(stream == null) {
|
||||
return false;
|
||||
}
|
||||
reserveBuffer(bufferReserveSize);
|
||||
int rl = stream.read(getBuffer(), getBufferOffset(), getBufferCapacity());
|
||||
if(rl <= 0) {
|
||||
return false;
|
||||
}
|
||||
bufferConsumed(rl);
|
||||
return true;
|
||||
}
|
||||
|
||||
public Iterator<Object> iterator()
|
||||
{
|
||||
return new UnpackIterator(this);
|
||||
}
|
||||
|
||||
public boolean execute() throws UnpackException
|
||||
{
|
||||
int noffset = super.execute(buffer, offset, used);
|
||||
if(noffset <= offset) {
|
||||
return false;
|
||||
}
|
||||
parsed += noffset - offset;
|
||||
offset = noffset;
|
||||
return super.isFinished();
|
||||
}
|
||||
|
||||
public Object getData()
|
||||
{
|
||||
return super.getData();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
parsed = 0;
|
||||
}
|
||||
|
||||
public int getMessageSize()
|
||||
{
|
||||
return parsed - offset + used;
|
||||
}
|
||||
|
||||
public int getParsedSize()
|
||||
{
|
||||
return parsed;
|
||||
}
|
||||
|
||||
public int getNonParsedSize()
|
||||
{
|
||||
return used - offset;
|
||||
}
|
||||
|
||||
public void skipNonparsedBuffer(int size)
|
||||
{
|
||||
offset += size;
|
||||
}
|
||||
|
||||
public void removeNonparsedBuffer()
|
||||
{
|
||||
used = offset;
|
||||
}
|
||||
|
||||
/*
|
||||
public static class Context {
|
||||
private boolean finished;
|
||||
private Object data;
|
||||
private int offset;
|
||||
private UnpackerImpl impl;
|
||||
|
||||
public Context()
|
||||
{
|
||||
this.finished = false;
|
||||
this.impl = new UnpackerImpl();
|
||||
}
|
||||
|
||||
public boolean isFinished()
|
||||
{
|
||||
return finished;
|
||||
}
|
||||
|
||||
public Object getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
int getOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
void setFinished(boolean finished)
|
||||
{
|
||||
this.finished = finished;
|
||||
}
|
||||
|
||||
void setData(Object data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
void setOffset(int offset)
|
||||
{
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
UnpackerImpl getImpl()
|
||||
{
|
||||
return impl;
|
||||
}
|
||||
}
|
||||
|
||||
public static int unpack(Context ctx, byte[] buffer) throws UnpackException
|
||||
{
|
||||
return unpack(ctx, buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
public static int unpack(Context ctx, byte[] buffer, int offset, int length) throws UnpackException
|
||||
{
|
||||
UnpackerImpl impl = ctx.getImpl();
|
||||
int noffset = impl.execute(buffer, offset + ctx.getOffset(), length);
|
||||
ctx.setOffset(noffset - offset);
|
||||
if(impl.isFinished()) {
|
||||
ctx.setData(impl.getData());
|
||||
ctx.setFinished(false);
|
||||
impl.reset();
|
||||
} else {
|
||||
ctx.setData(null);
|
||||
ctx.setFinished(true);
|
||||
}
|
||||
int parsed = noffset - offset;
|
||||
ctx.setOffset(parsed);
|
||||
return noffset;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
7
java-plan2/src/org/msgpack/impl/ArrayBuilder.java
Normal file
7
java-plan2/src/org/msgpack/impl/ArrayBuilder.java
Normal file
@ -0,0 +1,7 @@
|
||||
package org.msgpack.impl;
|
||||
|
||||
public interface ArrayBuilder {
|
||||
public void add(Object element);
|
||||
public Object finish();
|
||||
}
|
||||
|
127
java-plan2/src/org/msgpack/impl/GenericObjectBuilder.java
Normal file
127
java-plan2/src/org/msgpack/impl/GenericObjectBuilder.java
Normal file
@ -0,0 +1,127 @@
|
||||
package org.msgpack.impl;
|
||||
|
||||
import org.msgpack.*;
|
||||
|
||||
public class GenericObjectBuilder implements ObjectBuilder {
|
||||
public Object createNil()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createBoolean(boolean v)
|
||||
{
|
||||
return new GenericBoolean(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createByte(byte v)
|
||||
{
|
||||
//return new GenericByte(v);
|
||||
return null; // FIXME
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createShort(short v)
|
||||
{
|
||||
return new GenericShort(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createInt(int v)
|
||||
{
|
||||
//return new GenericInt(v);
|
||||
return null; // FIXME
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createLong(long v)
|
||||
{
|
||||
return new GenericLong(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createFloat(float v)
|
||||
{
|
||||
//return new GenericFloat(v);
|
||||
return null; // FIXME
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createDouble(double v)
|
||||
{
|
||||
//return new GenericDouble(v);
|
||||
return null; // FIXME
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createRaw(byte[] b, int offset, int length)
|
||||
{
|
||||
byte[] copy = new byte[length];
|
||||
System.arraycopy(b, offset, copy, 0, length);
|
||||
return new GenericRaw(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayBuilder createArray(int length)
|
||||
{
|
||||
return new GenericArrayBuilder(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapBuilder createMap(int length)
|
||||
{
|
||||
return new GenericMapBuilder(length);
|
||||
}
|
||||
}
|
||||
|
||||
final class GenericArrayBuilder implements ArrayBuilder {
|
||||
private GenericArray a;
|
||||
|
||||
GenericArrayBuilder(int length)
|
||||
{
|
||||
this.a = new GenericArray(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Object element)
|
||||
{
|
||||
a.add((GenericObject)element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object finish()
|
||||
{
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
final class GenericMapBuilder implements MapBuilder {
|
||||
private GenericMap m;
|
||||
private GenericObject key;
|
||||
|
||||
GenericMapBuilder(int length)
|
||||
{
|
||||
this.m = new GenericMap(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putKey(Object key)
|
||||
{
|
||||
this.key = (GenericObject)key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putValue(Object value)
|
||||
{
|
||||
m.put(this.key, (GenericObject)value);
|
||||
this.key = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object finish()
|
||||
{
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
package org.msgpack.impl;
|
||||
|
||||
import org.msgpack.*;
|
||||
|
||||
public class GenericZeroCopyObjectBuilder extends GenericObjectBuilder {
|
||||
@Override
|
||||
public Object createRaw(byte[] b, int offset, int length)
|
||||
{
|
||||
return new GenericRawRef(b, offset, length);
|
||||
}
|
||||
}
|
||||
|
8
java-plan2/src/org/msgpack/impl/MapBuilder.java
Normal file
8
java-plan2/src/org/msgpack/impl/MapBuilder.java
Normal file
@ -0,0 +1,8 @@
|
||||
package org.msgpack.impl;
|
||||
|
||||
public interface MapBuilder {
|
||||
public void putKey(Object key);
|
||||
public void putValue(Object value);
|
||||
public Object finish();
|
||||
}
|
||||
|
16
java-plan2/src/org/msgpack/impl/ObjectBuilder.java
Normal file
16
java-plan2/src/org/msgpack/impl/ObjectBuilder.java
Normal file
@ -0,0 +1,16 @@
|
||||
package org.msgpack.impl;
|
||||
|
||||
public interface ObjectBuilder {
|
||||
public Object createNil();
|
||||
public Object createBoolean(boolean v);
|
||||
public Object createByte(byte v);
|
||||
public Object createShort(short v);
|
||||
public Object createInt(int v);
|
||||
public Object createLong(long v);
|
||||
public Object createFloat(float v);
|
||||
public Object createDouble(double v);
|
||||
public Object createRaw(byte[] b, int offset, int length);
|
||||
public ArrayBuilder createArray(int length);
|
||||
public MapBuilder createMap(int length);
|
||||
}
|
||||
|
203
java-plan2/src/org/msgpack/impl/SpecificObjectBuilder.java
Normal file
203
java-plan2/src/org/msgpack/impl/SpecificObjectBuilder.java
Normal file
@ -0,0 +1,203 @@
|
||||
package org.msgpack.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import org.msgpack.schema.*;
|
||||
|
||||
public final class SpecificObjectBuilder implements ObjectBuilder {
|
||||
private int top;
|
||||
private Schema schema;
|
||||
|
||||
public SpecificObjectBuilder(Schema schema)
|
||||
{
|
||||
this.top = 0;
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
void setSchema(Schema s)
|
||||
{
|
||||
schema = s;
|
||||
}
|
||||
|
||||
Schema swapSchema(Schema s)
|
||||
{
|
||||
Schema old = schema;
|
||||
schema = s;
|
||||
return old;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createNil()
|
||||
{
|
||||
return schema.createNil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createBoolean(boolean v)
|
||||
{
|
||||
return schema.createBoolean(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createByte(byte v)
|
||||
{
|
||||
return schema.createByte(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createShort(short v)
|
||||
{
|
||||
return schema.createShort(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createInt(int v)
|
||||
{
|
||||
return schema.createInt(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createLong(long v)
|
||||
{
|
||||
return schema.createLong(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createFloat(float v)
|
||||
{
|
||||
return schema.createFloat(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createDouble(double v)
|
||||
{
|
||||
return schema.createDouble(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createRaw(byte[] b, int offset, int length)
|
||||
{
|
||||
return schema.createRaw(b, offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayBuilder createArray(int length)
|
||||
{
|
||||
if(schema instanceof ClassSchema) {
|
||||
return new ClassBuilder(length, (ClassSchema)schema, this);
|
||||
}
|
||||
ArraySchema as = (ArraySchema)schema;
|
||||
return new SpecificArrayBuilder(length, as.getElementType(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapBuilder createMap(int length)
|
||||
{
|
||||
MapSchema ms = (MapSchema)schema;
|
||||
return new SpecificMapBuilder(length, ms.getKeyType(), ms.getValueType(), this);
|
||||
}
|
||||
}
|
||||
|
||||
final class SpecificArrayBuilder implements ArrayBuilder {
|
||||
private ArrayList a;
|
||||
private SpecificObjectBuilder builder;
|
||||
private Schema parentSchema;
|
||||
|
||||
SpecificArrayBuilder(int length, Schema elementSchema, SpecificObjectBuilder builder)
|
||||
{
|
||||
this.a = new ArrayList(length);
|
||||
this.builder = builder;
|
||||
this.parentSchema = builder.swapSchema(elementSchema);
|
||||
}
|
||||
|
||||
public void add(Object element)
|
||||
{
|
||||
a.add(element);
|
||||
}
|
||||
|
||||
public Object finish()
|
||||
{
|
||||
builder.swapSchema(parentSchema);
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
final class SpecificMapBuilder implements MapBuilder {
|
||||
private HashMap m;
|
||||
private Object key;
|
||||
private Schema keySchema;
|
||||
private Schema valueSchema;
|
||||
private SpecificObjectBuilder builder;
|
||||
private Schema parentSchema;
|
||||
|
||||
SpecificMapBuilder(int length, Schema keySchema, Schema valueSchema, SpecificObjectBuilder builder)
|
||||
{
|
||||
this.m = new HashMap(length);
|
||||
this.keySchema = keySchema;
|
||||
this.valueSchema = valueSchema;
|
||||
this.builder = builder;
|
||||
this.parentSchema = builder.swapSchema(keySchema);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putKey(Object key)
|
||||
{
|
||||
this.key = key;
|
||||
this.builder.setSchema(valueSchema);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putValue(Object value)
|
||||
{
|
||||
m.put(this.key, value);
|
||||
this.key = null;
|
||||
this.builder.setSchema(keySchema);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object finish()
|
||||
{
|
||||
builder.swapSchema(parentSchema);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
final class ClassBuilder implements ArrayBuilder {
|
||||
private Object object;
|
||||
private int index;
|
||||
private List<? extends FieldSchema> fields;
|
||||
private SpecificObjectBuilder builder;
|
||||
private Schema parentSchema;
|
||||
|
||||
ClassBuilder(int length, ClassSchema schema, SpecificObjectBuilder builder)
|
||||
{
|
||||
this.object = schema.newInstance();
|
||||
this.index = 0;
|
||||
this.fields = schema.getFields();
|
||||
this.builder = builder;
|
||||
this.parentSchema = builder.swapSchema(fields.get(0).getType());
|
||||
// FIXME check length
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Object element)
|
||||
{
|
||||
FieldSchema f = fields.get(index++); // FIXME check fields.size
|
||||
f.setFieldValue(object, element); // XXX FIXME debug
|
||||
if(fields.size() > index) {
|
||||
builder.setSchema( fields.get(index).getType() );
|
||||
} else {
|
||||
builder.setSchema( null );
|
||||
// FIXME: builder.setSchema(new InvalidFieldSchema);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object finish()
|
||||
{
|
||||
builder.swapSchema(parentSchema);
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
395
java-plan2/src/org/msgpack/impl/UnpackerImpl.java
Normal file
395
java-plan2/src/org/msgpack/impl/UnpackerImpl.java
Normal file
@ -0,0 +1,395 @@
|
||||
package org.msgpack.impl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
//import java.math.BigInteger;
|
||||
import org.msgpack.UnpackException;
|
||||
|
||||
public class UnpackerImpl {
|
||||
static final int CS_HEADER = 0x00;
|
||||
static final int CS_FLOAT = 0x0a;
|
||||
static final int CS_DOUBLE = 0x0b;
|
||||
static final int CS_UINT_8 = 0x0c;
|
||||
static final int CS_UINT_16 = 0x0d;
|
||||
static final int CS_UINT_32 = 0x0e;
|
||||
static final int CS_UINT_64 = 0x0f;
|
||||
static final int CS_INT_8 = 0x10;
|
||||
static final int CS_INT_16 = 0x11;
|
||||
static final int CS_INT_32 = 0x12;
|
||||
static final int CS_INT_64 = 0x13;
|
||||
static final int CS_RAW_16 = 0x1a;
|
||||
static final int CS_RAW_32 = 0x1b;
|
||||
static final int CS_ARRAY_16 = 0x1c;
|
||||
static final int CS_ARRAY_32 = 0x1d;
|
||||
static final int CS_MAP_16 = 0x1e;
|
||||
static final int CS_MAP_32 = 0x1f;
|
||||
static final int ACS_RAW_VALUE = 0x20;
|
||||
static final int CT_ARRAY_ITEM = 0x00;
|
||||
static final int CT_MAP_KEY = 0x01;
|
||||
static final int CT_MAP_VALUE = 0x02;
|
||||
|
||||
static final int MAX_STACK_SIZE = 16;
|
||||
|
||||
protected int cs = CS_HEADER;
|
||||
protected int trail = 0;
|
||||
protected int top = -1;
|
||||
protected boolean finished = false;
|
||||
protected Object data = null;
|
||||
protected int[] stack_ct = new int[MAX_STACK_SIZE];
|
||||
protected int[] stack_count = new int[MAX_STACK_SIZE];
|
||||
protected Object[] stack_obj = new Object[MAX_STACK_SIZE];
|
||||
protected ByteBuffer castBuffer = ByteBuffer.allocate(8);
|
||||
protected ObjectBuilder builder;
|
||||
|
||||
protected UnpackerImpl(ObjectBuilder builder)
|
||||
{
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
protected void setBuilder(ObjectBuilder builder)
|
||||
{
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
protected Object getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
protected boolean isFinished()
|
||||
{
|
||||
return finished;
|
||||
}
|
||||
|
||||
protected void reset()
|
||||
{
|
||||
for(int i=0; i <= top; ++top) {
|
||||
stack_ct[top] = 0;
|
||||
stack_count[top] = 0;
|
||||
stack_obj[top] = null;
|
||||
}
|
||||
cs = CS_HEADER;
|
||||
trail = 0;
|
||||
top = -1;
|
||||
finished = false;
|
||||
data = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected int execute(byte[] src, int off, int length) throws UnpackException
|
||||
{
|
||||
if(off >= length) { return off; }
|
||||
|
||||
int limit = length;
|
||||
int i = off;
|
||||
int count;
|
||||
|
||||
Object obj = null;
|
||||
|
||||
_out: do {
|
||||
_header_again: {
|
||||
//System.out.println("while i:"+i+" limit:"+limit);
|
||||
|
||||
int b = src[i];
|
||||
|
||||
_push: {
|
||||
_fixed_trail_again:
|
||||
if(cs == CS_HEADER) {
|
||||
|
||||
if((b & 0x80) == 0) { // Positive Fixnum
|
||||
//System.out.println("positive fixnum "+b);
|
||||
obj = builder.createByte((byte)b);
|
||||
break _push;
|
||||
}
|
||||
|
||||
if((b & 0xe0) == 0xe0) { // Negative Fixnum
|
||||
//System.out.println("negative fixnum "+b);
|
||||
obj = builder.createByte((byte)b);
|
||||
break _push;
|
||||
}
|
||||
|
||||
if((b & 0xe0) == 0xa0) { // FixRaw
|
||||
trail = b & 0x1f;
|
||||
if(trail == 0) {
|
||||
obj = builder.createRaw(new byte[0], 0, 0);
|
||||
break _push;
|
||||
}
|
||||
cs = ACS_RAW_VALUE;
|
||||
break _fixed_trail_again;
|
||||
}
|
||||
|
||||
if((b & 0xf0) == 0x90) { // FixArray
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new UnpackException("parse error", UnpackException.PARSE_ERROR);
|
||||
}
|
||||
count = b & 0x0f;
|
||||
++top;
|
||||
stack_obj[top] = builder.createArray(count);
|
||||
stack_ct[top] = CT_ARRAY_ITEM;
|
||||
stack_count[top] = count;
|
||||
//System.out.println("fixarray count:"+count);
|
||||
break _header_again;
|
||||
}
|
||||
|
||||
if((b & 0xf0) == 0x80) { // FixMap
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new UnpackException("parse error", UnpackException.PARSE_ERROR);
|
||||
}
|
||||
count = b & 0x0f;
|
||||
++top;
|
||||
stack_obj[top] = builder.createMap(count);
|
||||
stack_ct[top] = CT_MAP_KEY;
|
||||
stack_count[top] = count;
|
||||
//System.out.println("fixmap count:"+count);
|
||||
break _header_again;
|
||||
}
|
||||
|
||||
switch(b & 0xff) { // FIXME
|
||||
case 0xc0: // nil
|
||||
obj = builder.createNil();
|
||||
break _push;
|
||||
case 0xc2: // false
|
||||
obj = builder.createBoolean(false);
|
||||
break _push;
|
||||
case 0xc3: // true
|
||||
obj = builder.createBoolean(true);
|
||||
break _push;
|
||||
case 0xca: // float
|
||||
case 0xcb: // double
|
||||
case 0xcc: // unsigned int 8
|
||||
case 0xcd: // unsigned int 16
|
||||
case 0xce: // unsigned int 32
|
||||
case 0xcf: // unsigned int 64
|
||||
case 0xd0: // signed int 8
|
||||
case 0xd1: // signed int 16
|
||||
case 0xd2: // signed int 32
|
||||
case 0xd3: // signed int 64
|
||||
trail = 1 << (b & 0x03);
|
||||
cs = b & 0x1f;
|
||||
//System.out.println("a trail "+trail+" cs:"+cs);
|
||||
break _fixed_trail_again;
|
||||
case 0xda: // raw 16
|
||||
case 0xdb: // raw 32
|
||||
case 0xdc: // array 16
|
||||
case 0xdd: // array 32
|
||||
case 0xde: // map 16
|
||||
case 0xdf: // map 32
|
||||
trail = 2 << (b & 0x01);
|
||||
cs = b & 0x1f;
|
||||
//System.out.println("b trail "+trail+" cs:"+cs);
|
||||
break _fixed_trail_again;
|
||||
default:
|
||||
//System.out.println("unknown b "+(b&0xff));
|
||||
throw new UnpackException("parse error", UnpackException.PARSE_ERROR);
|
||||
}
|
||||
|
||||
} // _fixed_trail_again
|
||||
|
||||
do {
|
||||
_fixed_trail_again: {
|
||||
|
||||
if(limit - i <= trail) { break _out; }
|
||||
int n = i + 1;
|
||||
i += trail;
|
||||
|
||||
switch(cs) {
|
||||
case CS_FLOAT:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
obj = builder.createFloat( castBuffer.getFloat(0) );
|
||||
//System.out.println("float "+obj);
|
||||
break _push;
|
||||
case CS_DOUBLE:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 8);
|
||||
obj = builder.createDouble( castBuffer.getDouble(0) );
|
||||
//System.out.println("double "+obj);
|
||||
break _push;
|
||||
case CS_UINT_8:
|
||||
//System.out.println(n);
|
||||
//System.out.println(src[n]);
|
||||
//System.out.println(src[n+1]);
|
||||
//System.out.println(src[n-1]);
|
||||
obj = builder.createShort( (short)((src[n]) & 0xff) );
|
||||
//System.out.println("uint8 "+obj);
|
||||
break _push;
|
||||
case CS_UINT_16:
|
||||
//System.out.println(src[n]);
|
||||
//System.out.println(src[n+1]);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
obj = builder.createInt( ((int)castBuffer.getShort(0)) & 0xffff );
|
||||
//System.out.println("uint 16 "+obj);
|
||||
break _push;
|
||||
case CS_UINT_32:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
obj = builder.createLong( ((long)castBuffer.getInt(0)) & 0xffffffffL );
|
||||
//System.out.println("uint 32 "+obj);
|
||||
break _push;
|
||||
case CS_UINT_64:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 8);
|
||||
{
|
||||
long o = castBuffer.getLong(0);
|
||||
if(o < 0) {
|
||||
// FIXME
|
||||
//obj = GenericBigInteger.valueOf(o & 0x7fffffffL).setBit(31);
|
||||
} else {
|
||||
obj = builder.createLong( o );
|
||||
}
|
||||
}
|
||||
throw new UnpackException("uint 64 bigger than 0x7fffffff is not supported", UnpackException.PARSE_ERROR);
|
||||
case CS_INT_8:
|
||||
obj = builder.createByte( src[n] );
|
||||
break _push;
|
||||
case CS_INT_16:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
obj = builder.createShort( castBuffer.getShort(0) );
|
||||
break _push;
|
||||
case CS_INT_32:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
obj = builder.createInt( castBuffer.getInt(0) );
|
||||
break _push;
|
||||
case CS_INT_64:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 8);
|
||||
obj = builder.createLong( castBuffer.getLong(0) );
|
||||
break _push;
|
||||
case CS_RAW_16:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
trail = ((int)castBuffer.getShort(0)) & 0xffff;
|
||||
if(trail == 0) {
|
||||
obj = builder.createRaw(new byte[0], 0, 0);
|
||||
break _push;
|
||||
}
|
||||
cs = ACS_RAW_VALUE;
|
||||
break _fixed_trail_again;
|
||||
case CS_RAW_32:
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
// FIXME overflow check
|
||||
trail = castBuffer.getInt(0) & 0x7fffffff;
|
||||
if(trail == 0) {
|
||||
obj = builder.createRaw(new byte[0], 0, 0);
|
||||
break _push;
|
||||
}
|
||||
cs = ACS_RAW_VALUE;
|
||||
case ACS_RAW_VALUE:
|
||||
obj = builder.createRaw(src, n, trail);
|
||||
break _push;
|
||||
case CS_ARRAY_16:
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new UnpackException("parse error", UnpackException.PARSE_ERROR);
|
||||
}
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
count = ((int)castBuffer.getShort(0)) & 0xffff;
|
||||
++top;
|
||||
stack_obj[top] = builder.createArray(count);
|
||||
stack_ct[top] = CT_ARRAY_ITEM;
|
||||
stack_count[top] = count;
|
||||
break _header_again;
|
||||
case CS_ARRAY_32:
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new UnpackException("parse error", UnpackException.PARSE_ERROR);
|
||||
}
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
// FIXME overflow check
|
||||
count = castBuffer.getInt(0) & 0x7fffffff;
|
||||
++top;
|
||||
stack_obj[top] = builder.createArray(count);
|
||||
stack_ct[top] = CT_ARRAY_ITEM;
|
||||
stack_count[top] = count;
|
||||
break _header_again;
|
||||
case CS_MAP_16:
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new UnpackException("parse error", UnpackException.PARSE_ERROR);
|
||||
}
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 2);
|
||||
count = ((int)castBuffer.getShort(0)) & 0xffff;
|
||||
++top;
|
||||
stack_obj[top] = builder.createMap(count);
|
||||
stack_ct[top] = CT_MAP_KEY;
|
||||
stack_count[top] = count;
|
||||
//System.out.println("fixmap count:"+count);
|
||||
break _header_again;
|
||||
case CS_MAP_32:
|
||||
if(top >= MAX_STACK_SIZE) {
|
||||
throw new UnpackException("parse error", UnpackException.PARSE_ERROR);
|
||||
}
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(src, n, 4);
|
||||
// FIXME overflow check
|
||||
count = castBuffer.getInt(0) & 0x7fffffff;
|
||||
++top;
|
||||
stack_obj[top] = builder.createMap(count);
|
||||
stack_ct[top] = CT_MAP_KEY;
|
||||
stack_count[top] = count;
|
||||
//System.out.println("fixmap count:"+count);
|
||||
break _header_again;
|
||||
default:
|
||||
throw new UnpackException("parse error", UnpackException.PARSE_ERROR);
|
||||
}
|
||||
|
||||
} // _fixed_trail_again
|
||||
} while(true);
|
||||
} // _push
|
||||
|
||||
do {
|
||||
_push: {
|
||||
//System.out.println("push top:"+top);
|
||||
if(top == -1) {
|
||||
++i;
|
||||
data = obj;
|
||||
finished = true;
|
||||
break _out;
|
||||
}
|
||||
|
||||
switch(stack_ct[top]) {
|
||||
case CT_ARRAY_ITEM:
|
||||
//System.out.println("array item "+obj);
|
||||
((ArrayBuilder)stack_obj[top]).add(obj);
|
||||
if(--stack_count[top] == 0) {
|
||||
obj = ((ArrayBuilder)stack_obj[top]).finish();
|
||||
stack_obj[top] = null;
|
||||
--top;
|
||||
break _push;
|
||||
}
|
||||
break _header_again;
|
||||
case CT_MAP_KEY:
|
||||
//System.out.println("map key:"+top+" "+obj);
|
||||
MapBuilder mb = (MapBuilder)stack_obj[top];
|
||||
mb.putKey(obj);
|
||||
stack_ct[top] = CT_MAP_VALUE;
|
||||
break _header_again;
|
||||
case CT_MAP_VALUE:
|
||||
//System.out.println("map value:"+top+" "+obj);
|
||||
((MapBuilder)stack_obj[top]).putValue(obj);
|
||||
if(--stack_count[top] == 0) {
|
||||
obj = ((MapBuilder)stack_obj[top]).finish();
|
||||
stack_obj[top] = null;
|
||||
--top;
|
||||
break _push;
|
||||
}
|
||||
stack_ct[top] = CT_MAP_KEY;
|
||||
break _header_again;
|
||||
default:
|
||||
throw new UnpackException("parse error", UnpackException.PARSE_ERROR);
|
||||
}
|
||||
} // _push
|
||||
} while(true);
|
||||
|
||||
} // _header_again
|
||||
cs = CS_HEADER;
|
||||
++i;
|
||||
} while(i < limit); // _out
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
61
java-plan2/src/org/msgpack/schema/ArraySchema.java
Normal file
61
java-plan2/src/org/msgpack/schema/ArraySchema.java
Normal file
@ -0,0 +1,61 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.io.IOException;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class ArraySchema extends Schema {
|
||||
private Schema elementType;
|
||||
|
||||
public ArraySchema(Schema elementType)
|
||||
{
|
||||
super("array");
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public Schema getElementType()
|
||||
{
|
||||
return elementType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName()
|
||||
{
|
||||
return "ArrayList<"+elementType.getFullName()+">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpression()
|
||||
{
|
||||
return "(array "+elementType.getExpression()+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
List<Object> d = (List<Object>)obj;
|
||||
pk.packArray(d.size());
|
||||
for(Object e : d) {
|
||||
elementType.pack(pk, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
List<GenericObject> d = obj.asArray();
|
||||
List<Object> g = new ArrayList<Object>();
|
||||
for(GenericObject o : d) {
|
||||
g.add( elementType.convert(o) );
|
||||
}
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
230
java-plan2/src/org/msgpack/schema/ClassGenerator.java
Normal file
230
java-plan2/src/org/msgpack/schema/ClassGenerator.java
Normal file
@ -0,0 +1,230 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.Writer;
|
||||
|
||||
public class ClassGenerator {
|
||||
private ClassSchema schema;
|
||||
private Writer writer;
|
||||
private int indent;
|
||||
|
||||
private ClassGenerator(Writer writer)
|
||||
{
|
||||
this.writer = writer;
|
||||
this.indent = 0;
|
||||
}
|
||||
|
||||
public static void write(Schema schema, Writer dest) throws IOException
|
||||
{
|
||||
if(!(schema instanceof ClassSchema)) {
|
||||
throw new RuntimeException("schema is not class schema");
|
||||
}
|
||||
ClassSchema cs = (ClassSchema)schema;
|
||||
new ClassGenerator(dest).run(cs);
|
||||
}
|
||||
|
||||
private void run(ClassSchema cs) throws IOException
|
||||
{
|
||||
List<ClassSchema> subclasses = new ArrayList<ClassSchema>();
|
||||
for(FieldSchema f : cs.getFields()) {
|
||||
findSubclassSchema(subclasses, f.getType());
|
||||
}
|
||||
|
||||
for(ClassSchema sub : subclasses) {
|
||||
sub.setNamespace(cs.getNamespace());
|
||||
sub.setImports(cs.getImports());
|
||||
}
|
||||
|
||||
this.schema = cs;
|
||||
|
||||
writeHeader();
|
||||
|
||||
writeClass();
|
||||
|
||||
for(ClassSchema sub : subclasses) {
|
||||
this.schema = sub;
|
||||
writeSubclass();
|
||||
}
|
||||
|
||||
writeFooter();
|
||||
|
||||
this.schema = null;
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
private void findSubclassSchema(List<ClassSchema> dst, Schema s)
|
||||
{
|
||||
if(s instanceof ClassSchema) {
|
||||
ClassSchema cs = (ClassSchema)s;
|
||||
if(!dst.contains(cs)) { dst.add(cs); }
|
||||
for(FieldSchema f : cs.getFields()) {
|
||||
findSubclassSchema(dst, f.getType());
|
||||
}
|
||||
} else if(s instanceof ArraySchema) {
|
||||
ArraySchema as = (ArraySchema)s;
|
||||
findSubclassSchema(dst, as.getElementType());
|
||||
} else if(s instanceof MapSchema) {
|
||||
MapSchema as = (MapSchema)s;
|
||||
findSubclassSchema(dst, as.getKeyType());
|
||||
findSubclassSchema(dst, as.getValueType());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeHeader() throws IOException
|
||||
{
|
||||
if(schema.getNamespace() != null) {
|
||||
line("package "+schema.getNamespace()+";");
|
||||
line();
|
||||
}
|
||||
line("import java.util.*;");
|
||||
line("import java.io.*;");
|
||||
line("import org.msgpack.*;");
|
||||
line("import org.msgpack.schema.*;");
|
||||
}
|
||||
|
||||
private void writeFooter() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
private void writeClass() throws IOException
|
||||
{
|
||||
line();
|
||||
line("public final class "+schema.getName()+" implements MessagePackable, MessageConvertable");
|
||||
line("{");
|
||||
pushIndent();
|
||||
writeSchema();
|
||||
writeMemberVariables();
|
||||
writeMemberFunctions();
|
||||
popIndent();
|
||||
line("}");
|
||||
}
|
||||
|
||||
private void writeSubclass() throws IOException
|
||||
{
|
||||
line();
|
||||
line("final class "+schema.getName()+" implements MessagePackable, MessageConvertable");
|
||||
line("{");
|
||||
pushIndent();
|
||||
writeSchema();
|
||||
writeMemberVariables();
|
||||
writeMemberFunctions();
|
||||
popIndent();
|
||||
line("}");
|
||||
}
|
||||
|
||||
private void writeSchema() throws IOException
|
||||
{
|
||||
line("private static final ClassSchema _SCHEMA = (ClassSchema)Schema.load(\""+schema.getExpression()+"\");");
|
||||
line("public static ClassSchema getSchema() { return _SCHEMA; }");
|
||||
}
|
||||
|
||||
private void writeMemberVariables() throws IOException
|
||||
{
|
||||
line();
|
||||
for(FieldSchema f : schema.getFields()) {
|
||||
line("public "+f.getType().getFullName()+" "+f.getName()+";");
|
||||
}
|
||||
}
|
||||
|
||||
private void writeMemberFunctions() throws IOException
|
||||
{
|
||||
// void messagePack(Packer pk)
|
||||
// boolean equals(Object obj)
|
||||
// int hashCode()
|
||||
// void set(int _index, Object _value)
|
||||
// Object get(int _index);
|
||||
// getXxx()
|
||||
// setXxx(Xxx xxx)
|
||||
writeConstructors();
|
||||
writeAccessors();
|
||||
writePackFunction();
|
||||
writeConvertFunction();
|
||||
}
|
||||
|
||||
private void writeConstructors() throws IOException
|
||||
{
|
||||
line();
|
||||
line("public "+schema.getName()+"() { }");
|
||||
}
|
||||
|
||||
private void writeAccessors() throws IOException
|
||||
{
|
||||
// FIXME
|
||||
//line();
|
||||
//for(FieldSchema f : schema.getFields()) {
|
||||
// line("");
|
||||
//}
|
||||
}
|
||||
|
||||
private void writePackFunction() throws IOException
|
||||
{
|
||||
line();
|
||||
line("@Override");
|
||||
line("public void messagePack(Packer pk) throws IOException");
|
||||
line("{");
|
||||
pushIndent();
|
||||
line("List<? extends FieldSchema> _f = _SCHEMA.getFields();");
|
||||
line("pk.packArray("+schema.getFields().size()+");");
|
||||
int i = 0;
|
||||
for(FieldSchema f : schema.getFields()) {
|
||||
line("_f.get("+i+").getType().pack(pk, "+f.getName()+");");
|
||||
++i;
|
||||
}
|
||||
popIndent();
|
||||
line("}");
|
||||
}
|
||||
|
||||
private void writeConvertFunction() throws IOException
|
||||
{
|
||||
line();
|
||||
line("@Override");
|
||||
line("@SuppressWarnings(\"unchecked\")");
|
||||
line("public void messageConvert(GenericObject obj)");
|
||||
line("{");
|
||||
pushIndent();
|
||||
line("List<GenericObject> _l = obj.asArray();");
|
||||
line("List<? extends FieldSchema> _f = _SCHEMA.getFields();");
|
||||
int i = 0;
|
||||
for(FieldSchema f : schema.getFields()) {
|
||||
line("if(_l.size() <= "+i+") { return; } "+f.getName()+" = ("+f.getType().getFullName()+")_f.get("+i+").getType().convert(_l.get("+i+"));");
|
||||
++i;
|
||||
}
|
||||
popIndent();
|
||||
line("}");
|
||||
line();
|
||||
line("public static "+schema.getName()+" convert(GenericObject obj)");
|
||||
line("{");
|
||||
pushIndent();
|
||||
line("return ("+schema.getName()+")_SCHEMA.convert(obj);");
|
||||
popIndent();
|
||||
line("}");
|
||||
}
|
||||
|
||||
private void line(String str) throws IOException
|
||||
{
|
||||
for(int i=0; i < indent; ++i) {
|
||||
writer.write("\t");
|
||||
}
|
||||
writer.write(str+"\n");
|
||||
}
|
||||
|
||||
private void line() throws IOException
|
||||
{
|
||||
writer.write("\n");
|
||||
}
|
||||
|
||||
private void pushIndent()
|
||||
{
|
||||
indent += 1;
|
||||
}
|
||||
|
||||
private void popIndent()
|
||||
{
|
||||
indent -= 1;
|
||||
}
|
||||
}
|
||||
|
39
java-plan2/src/org/msgpack/schema/ClassSchema.java
Normal file
39
java-plan2/src/org/msgpack/schema/ClassSchema.java
Normal file
@ -0,0 +1,39 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ClassSchema extends Schema {
|
||||
protected String namespace;
|
||||
protected List<String> imports;
|
||||
|
||||
public ClassSchema(String name, String namespace, List<String> imports)
|
||||
{
|
||||
super(name);
|
||||
this.namespace = namespace;
|
||||
this.imports = imports;
|
||||
}
|
||||
|
||||
public String getNamespace()
|
||||
{
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public List<String> getImports()
|
||||
{
|
||||
return imports;
|
||||
}
|
||||
|
||||
void setNamespace(String namespace)
|
||||
{
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
void setImports(List<String> imports)
|
||||
{
|
||||
this.imports = imports;
|
||||
}
|
||||
|
||||
public abstract List<? extends FieldSchema> getFields();
|
||||
public abstract Object newInstance();
|
||||
}
|
||||
|
31
java-plan2/src/org/msgpack/schema/FieldSchema.java
Normal file
31
java-plan2/src/org/msgpack/schema/FieldSchema.java
Normal file
@ -0,0 +1,31 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
public abstract class FieldSchema {
|
||||
private String name;
|
||||
private Schema type;
|
||||
|
||||
public FieldSchema(String name, Schema type)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Schema getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getExpression()
|
||||
{
|
||||
return "(field "+name+" "+type.getExpression()+")";
|
||||
}
|
||||
|
||||
public abstract Object getFieldValue(Object obj);
|
||||
public abstract void setFieldValue(Object obj, Object value);
|
||||
}
|
||||
|
89
java-plan2/src/org/msgpack/schema/GenericClassSchema.java
Normal file
89
java-plan2/src/org/msgpack/schema/GenericClassSchema.java
Normal file
@ -0,0 +1,89 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import org.msgpack.*;
|
||||
|
||||
|
||||
public class GenericClassSchema extends ClassSchema {
|
||||
private List<GenericFieldSchema> fields;
|
||||
|
||||
private String fqdn;
|
||||
private Constructor constructorCache;
|
||||
|
||||
public GenericClassSchema(String name, List<GenericFieldSchema> fields, String namespace, List<String> imports)
|
||||
{
|
||||
super(name, namespace, imports);
|
||||
this.fields = fields;
|
||||
if(namespace == null) {
|
||||
this.fqdn = name;
|
||||
} else {
|
||||
this.fqdn = namespace+"."+name;
|
||||
}
|
||||
}
|
||||
|
||||
//@Override
|
||||
//public String getFullName()
|
||||
//{
|
||||
// if(namespace == null) {
|
||||
// return getName();
|
||||
// } else {
|
||||
// return namespace+"."+getName();
|
||||
// }
|
||||
//}
|
||||
|
||||
public List<? extends FieldSchema> getFields()
|
||||
{
|
||||
return fields;
|
||||
}
|
||||
|
||||
public String getNamespace()
|
||||
{
|
||||
return namespace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpression()
|
||||
{
|
||||
StringBuffer b = new StringBuffer();
|
||||
b.append("(class ");
|
||||
b.append(getName());
|
||||
if(namespace != null) {
|
||||
b.append(" (package "+namespace+")");
|
||||
}
|
||||
for(GenericFieldSchema f : fields) {
|
||||
b.append(" "+f.getExpression());
|
||||
}
|
||||
b.append(")");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
// FIXME
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
// FIXME
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object newInstance()
|
||||
{
|
||||
return new HashMap(fields.size());
|
||||
}
|
||||
}
|
||||
|
25
java-plan2/src/org/msgpack/schema/GenericFieldSchema.java
Normal file
25
java-plan2/src/org/msgpack/schema/GenericFieldSchema.java
Normal file
@ -0,0 +1,25 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.util.Map;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class GenericFieldSchema extends FieldSchema {
|
||||
public GenericFieldSchema(String name, Schema type)
|
||||
{
|
||||
super(name, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getFieldValue(Object obj)
|
||||
{
|
||||
return ((Map)obj).get(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setFieldValue(Object obj, Object value)
|
||||
{
|
||||
((Map)obj).put(getName(), value);
|
||||
}
|
||||
}
|
||||
|
58
java-plan2/src/org/msgpack/schema/IntSchema.java
Normal file
58
java-plan2/src/org/msgpack/schema/IntSchema.java
Normal file
@ -0,0 +1,58 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class IntSchema extends Schema {
|
||||
public IntSchema()
|
||||
{
|
||||
super("Integer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpression()
|
||||
{
|
||||
return "int";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
pk.packInt((Integer)obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
return obj.asInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createByte(byte v)
|
||||
{
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createShort(short v)
|
||||
{
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createInt(int v)
|
||||
{
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createLong(long v)
|
||||
{
|
||||
return (int)v;
|
||||
}
|
||||
}
|
||||
|
58
java-plan2/src/org/msgpack/schema/LongSchema.java
Normal file
58
java-plan2/src/org/msgpack/schema/LongSchema.java
Normal file
@ -0,0 +1,58 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class LongSchema extends Schema {
|
||||
public LongSchema()
|
||||
{
|
||||
super("Long");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpression()
|
||||
{
|
||||
return "long";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
pk.packLong((Long)obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
return obj.asLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createByte(byte v)
|
||||
{
|
||||
return (long)v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createShort(short v)
|
||||
{
|
||||
return (long)v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createInt(int v)
|
||||
{
|
||||
return (long)v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createLong(long v)
|
||||
{
|
||||
return (long)v;
|
||||
}
|
||||
}
|
||||
|
70
java-plan2/src/org/msgpack/schema/MapSchema.java
Normal file
70
java-plan2/src/org/msgpack/schema/MapSchema.java
Normal file
@ -0,0 +1,70 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.io.IOException;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class MapSchema extends Schema {
|
||||
private Schema keyType;
|
||||
private Schema valueType;
|
||||
|
||||
public MapSchema(Schema keyType, Schema valueType)
|
||||
{
|
||||
super("map");
|
||||
this.keyType = keyType;
|
||||
this.valueType = valueType;
|
||||
}
|
||||
|
||||
public Schema getKeyType()
|
||||
{
|
||||
return keyType;
|
||||
}
|
||||
|
||||
public Schema getValueType()
|
||||
{
|
||||
return valueType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName()
|
||||
{
|
||||
return "HashList<"+keyType.getFullName()+", "+valueType.getFullName()+">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpression()
|
||||
{
|
||||
return "(map "+keyType.getExpression()+" "+valueType.getExpression()+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
Map<Object,Object> d = (Map<Object,Object>)obj;
|
||||
pk.packMap(d.size());
|
||||
for(Map.Entry<Object,Object> e : d.entrySet()) {
|
||||
keyType.pack(pk, e.getKey());
|
||||
valueType.pack(pk, e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
Map<GenericObject,GenericObject> d = obj.asMap();
|
||||
Map<Object,Object> g = new HashMap<Object,Object>();
|
||||
for(Map.Entry<GenericObject,GenericObject> e : d.entrySet()) {
|
||||
g.put(keyType.convert(e.getKey()), valueType.convert(e.getValue()));
|
||||
}
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
33
java-plan2/src/org/msgpack/schema/ObjectSchema.java
Normal file
33
java-plan2/src/org/msgpack/schema/ObjectSchema.java
Normal file
@ -0,0 +1,33 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class ObjectSchema extends Schema {
|
||||
public ObjectSchema()
|
||||
{
|
||||
super("object");
|
||||
}
|
||||
|
||||
public String getFullName()
|
||||
{
|
||||
return "GenericObject";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
pk.pack(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
21
java-plan2/src/org/msgpack/schema/PrimitiveSchema.java
Normal file
21
java-plan2/src/org/msgpack/schema/PrimitiveSchema.java
Normal file
@ -0,0 +1,21 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
public abstract class PrimitiveSchema extends Schema {
|
||||
public static enum PrimitiveType {
|
||||
BYTE,
|
||||
SHORT,
|
||||
INT,
|
||||
LONG,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
}
|
||||
|
||||
public final PrimitiveType type;
|
||||
|
||||
protected PrimitiveSchema(String name, PrimitiveType type)
|
||||
{
|
||||
super(name);
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
44
java-plan2/src/org/msgpack/schema/RawSchema.java
Normal file
44
java-plan2/src/org/msgpack/schema/RawSchema.java
Normal file
@ -0,0 +1,44 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class RawSchema extends Schema {
|
||||
public RawSchema()
|
||||
{
|
||||
super("raw");
|
||||
}
|
||||
|
||||
public String getFullName()
|
||||
{
|
||||
return "byte[]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
byte[] d = (byte[])obj;
|
||||
pk.packRaw(d.length);
|
||||
pk.packRawBody(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
return obj.asBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createRaw(byte[] b, int offset, int length)
|
||||
{
|
||||
byte[] d = new byte[length];
|
||||
System.arraycopy(b, offset, d, 0, length);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
246
java-plan2/src/org/msgpack/schema/SSchemaParser.java
Normal file
246
java-plan2/src/org/msgpack/schema/SSchemaParser.java
Normal file
@ -0,0 +1,246 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
// FIXME exception class
|
||||
|
||||
class SSchemaParser {
|
||||
public static Schema parse(String source)
|
||||
{
|
||||
return new SSchemaParser(false).run(source);
|
||||
}
|
||||
|
||||
public static Schema load(String source)
|
||||
{
|
||||
return new SSchemaParser(true).run(source);
|
||||
}
|
||||
|
||||
private static abstract class SExp {
|
||||
boolean isAtom() { return false; }
|
||||
public String getAtom() { return null; }
|
||||
|
||||
boolean isTuple() { return false; }
|
||||
public SExp getTuple(int i) { return null; }
|
||||
public int size() { return 0; }
|
||||
public boolean empty() { return size() == 0; }
|
||||
Iterator<SExp> iterator(int offset) { return null; }
|
||||
}
|
||||
|
||||
private static class SAtom extends SExp {
|
||||
private String atom;
|
||||
|
||||
SAtom(String atom) { this.atom = atom; }
|
||||
|
||||
boolean isAtom() { return true; }
|
||||
public String getAtom() { return atom; }
|
||||
|
||||
public String toString() { return atom; }
|
||||
}
|
||||
|
||||
private static class STuple extends SExp {
|
||||
private List<SExp> tuple;
|
||||
|
||||
STuple() { this.tuple = new ArrayList<SExp>(); }
|
||||
|
||||
public void add(SExp e) { tuple.add(e); }
|
||||
|
||||
boolean isTuple() { return true; }
|
||||
public SExp getTuple(int i) { return tuple.get(i); }
|
||||
public int size() { return tuple.size(); }
|
||||
|
||||
Iterator<SExp> iterator(int skip) {
|
||||
Iterator<SExp> i = tuple.iterator();
|
||||
for(int s=0; s < skip; ++s) { i.next(); }
|
||||
return i;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if(tuple.isEmpty()) { return "()"; }
|
||||
Iterator<SExp> i = tuple.iterator();
|
||||
StringBuffer o = new StringBuffer();
|
||||
o.append("(").append(i.next());
|
||||
while(i.hasNext()) { o.append(" ").append(i.next()); }
|
||||
o.append(")");
|
||||
return o.toString();
|
||||
}
|
||||
}
|
||||
|
||||
boolean specificClass;
|
||||
|
||||
private SSchemaParser(boolean specificClass)
|
||||
{
|
||||
this.specificClass = specificClass;
|
||||
}
|
||||
|
||||
private static Pattern pattern = Pattern.compile(
|
||||
"(?:\\s+)|([\\(\\)]|[\\d\\w\\.]+)");
|
||||
|
||||
private Schema run(String source)
|
||||
{
|
||||
Matcher m = pattern.matcher(source);
|
||||
|
||||
Stack<STuple> stack = new Stack<STuple>();
|
||||
String token;
|
||||
|
||||
while(true) {
|
||||
while(true) {
|
||||
if(!m.find()) { throw new RuntimeException("unexpected end of file"); }
|
||||
token = m.group(1);
|
||||
if(token != null) { break; }
|
||||
}
|
||||
|
||||
if(token.equals("(")) {
|
||||
stack.push(new STuple());
|
||||
} else if(token.equals(")")) {
|
||||
STuple top = stack.pop();
|
||||
if(stack.empty()) {
|
||||
stack.push(top);
|
||||
break;
|
||||
}
|
||||
stack.peek().add(top);
|
||||
} else {
|
||||
if(stack.empty()) {
|
||||
throw new RuntimeException("unexpected token '"+token+"'");
|
||||
}
|
||||
stack.peek().add(new SAtom(token));
|
||||
}
|
||||
}
|
||||
|
||||
while(true) {
|
||||
if(!m.find()) { break; }
|
||||
token = m.group(1);
|
||||
if(token != null) { throw new RuntimeException("unexpected token '"+token+"'"); }
|
||||
}
|
||||
|
||||
return readType( stack.pop() );
|
||||
}
|
||||
|
||||
private Schema readType(SExp exp)
|
||||
{
|
||||
if(exp.isAtom()) {
|
||||
String type = exp.getAtom();
|
||||
// FIXME
|
||||
if(type.equals("string")) {
|
||||
return new StringSchema();
|
||||
} else if(type.equals("raw")) {
|
||||
return new RawSchema();
|
||||
} else if(type.equals("short")) {
|
||||
return new ShortSchema();
|
||||
} else if(type.equals("int")) {
|
||||
return new IntSchema();
|
||||
} else if(type.equals("long")) {
|
||||
return new LongSchema();
|
||||
} else if(type.equals("object")) {
|
||||
return new ObjectSchema();
|
||||
} else {
|
||||
throw new RuntimeException("byte, short, int, long, float, double, raw, string or object is expected but got '"+type+"': "+exp);
|
||||
}
|
||||
} else {
|
||||
String type = exp.getTuple(0).getAtom();
|
||||
if(type.equals("class")) {
|
||||
return parseClass(exp);
|
||||
} else if(type.equals("array")) {
|
||||
return parseArray(exp);
|
||||
} else if(type.equals("map")) {
|
||||
return parseMap(exp);
|
||||
} else {
|
||||
throw new RuntimeException("class, array or map is expected but got '"+type+"': "+exp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClassSchema parseClass(SExp exp)
|
||||
{
|
||||
if(exp.size() < 3 || !exp.getTuple(1).isAtom()) {
|
||||
throw new RuntimeException("class is (class NAME CLASS_BODY): "+exp);
|
||||
}
|
||||
|
||||
String namespace = null;
|
||||
List<String> imports = new ArrayList<String>();
|
||||
String name = exp.getTuple(1).getAtom();
|
||||
List fields = new ArrayList();
|
||||
|
||||
for(Iterator<SExp> i=exp.iterator(2); i.hasNext();) {
|
||||
SExp subexp = i.next();
|
||||
if(!subexp.isTuple() || subexp.empty() || !subexp.getTuple(0).isAtom()) {
|
||||
throw new RuntimeException("field, package or import is expected: "+subexp);
|
||||
}
|
||||
String type = subexp.getTuple(0).getAtom();
|
||||
if(type.equals("field")) {
|
||||
fields.add( parseField(subexp) );
|
||||
} else if(type.equals("package")) {
|
||||
if(namespace != null) {
|
||||
throw new RuntimeException("duplicated package definition: "+subexp);
|
||||
}
|
||||
namespace = parseNamespace(subexp);
|
||||
} else if(type.equals("import")) {
|
||||
imports.add( parseImport(subexp) );
|
||||
} else {
|
||||
throw new RuntimeException("field, package or import is expected but got '"+type+"': "+subexp);
|
||||
}
|
||||
}
|
||||
|
||||
if(specificClass) {
|
||||
return new SpecificClassSchema(name, fields, namespace, imports);
|
||||
} else {
|
||||
return new GenericClassSchema(name, fields, namespace, imports);
|
||||
}
|
||||
}
|
||||
|
||||
private ArraySchema parseArray(SExp exp)
|
||||
{
|
||||
if(exp.size() != 2) {
|
||||
throw new RuntimeException("array is (array ELEMENT_TYPE): "+exp);
|
||||
}
|
||||
Schema elementType = readType(exp.getTuple(1));
|
||||
return new ArraySchema(elementType);
|
||||
}
|
||||
|
||||
private MapSchema parseMap(SExp exp)
|
||||
{
|
||||
if(exp.size() != 3 || !exp.getTuple(1).isAtom()) {
|
||||
throw new RuntimeException("map is (map KEY_TYPE VALUE_TYPE): "+exp);
|
||||
}
|
||||
Schema keyType = readType(exp.getTuple(1));
|
||||
Schema valueType = readType(exp.getTuple(2));
|
||||
return new MapSchema(keyType, valueType);
|
||||
}
|
||||
|
||||
private String parseNamespace(SExp exp)
|
||||
{
|
||||
if(exp.size() != 2 || !exp.getTuple(1).isAtom()) {
|
||||
throw new RuntimeException("package is (package NAME): "+exp);
|
||||
}
|
||||
String name = exp.getTuple(1).getAtom();
|
||||
return name;
|
||||
}
|
||||
|
||||
private String parseImport(SExp exp)
|
||||
{
|
||||
if(exp.size() != 2 || !exp.getTuple(1).isAtom()) {
|
||||
throw new RuntimeException("import is (import NAME): "+exp);
|
||||
}
|
||||
String name = exp.getTuple(1).getAtom();
|
||||
return name;
|
||||
}
|
||||
|
||||
private FieldSchema parseField(SExp exp)
|
||||
{
|
||||
if(exp.size() != 3 || !exp.getTuple(1).isAtom()) {
|
||||
throw new RuntimeException("field is (field NAME TYPE): "+exp);
|
||||
}
|
||||
String name = exp.getTuple(1).getAtom();
|
||||
Schema type = readType(exp.getTuple(2));
|
||||
if(specificClass) {
|
||||
return new SpecificFieldSchema(name, type);
|
||||
} else {
|
||||
return new GenericFieldSchema(name, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
93
java-plan2/src/org/msgpack/schema/Schema.java
Normal file
93
java-plan2/src/org/msgpack/schema/Schema.java
Normal file
@ -0,0 +1,93 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.msgpack.impl.*;
|
||||
import org.msgpack.Packer;
|
||||
import org.msgpack.GenericObject;
|
||||
|
||||
public abstract class Schema {
|
||||
private String expression;
|
||||
private String name;
|
||||
|
||||
public Schema(String name)
|
||||
{
|
||||
this.expression = expression;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getFullName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getExpression()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public static Schema parse(String source)
|
||||
{
|
||||
return SSchemaParser.parse(source);
|
||||
}
|
||||
|
||||
public static Schema load(String source)
|
||||
{
|
||||
return SSchemaParser.load(source);
|
||||
}
|
||||
|
||||
public abstract void pack(Packer pk, Object obj) throws IOException;
|
||||
public abstract Object convert(GenericObject obj);
|
||||
//public abstract Object convertGeneric(GenericObject obj);
|
||||
|
||||
|
||||
public Object createNil()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object createBoolean(boolean v)
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public Object createByte(byte v)
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public Object createShort(short v)
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public Object createInt(int v)
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public Object createLong(long v)
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public Object createFloat(float v)
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public Object createDouble(double v)
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
|
||||
public Object createRaw(byte[] b, int offset, int length)
|
||||
{
|
||||
throw new RuntimeException("type error");
|
||||
}
|
||||
}
|
||||
|
46
java-plan2/src/org/msgpack/schema/ShortSchema.java
Normal file
46
java-plan2/src/org/msgpack/schema/ShortSchema.java
Normal file
@ -0,0 +1,46 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class ShortSchema extends Schema {
|
||||
public ShortSchema()
|
||||
{
|
||||
super("Short");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpression()
|
||||
{
|
||||
return "short";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
pk.packShort((Short)obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
return obj.asShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createByte(byte v)
|
||||
{
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createShort(short v)
|
||||
{
|
||||
return (int)v;
|
||||
}
|
||||
}
|
||||
|
156
java-plan2/src/org/msgpack/schema/SpecificClassSchema.java
Normal file
156
java-plan2/src/org/msgpack/schema/SpecificClassSchema.java
Normal file
@ -0,0 +1,156 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class SpecificClassSchema extends ClassSchema {
|
||||
private List<SpecificFieldSchema> fields;
|
||||
private String namespace;
|
||||
private List<String> imports;
|
||||
|
||||
private String fqdn;
|
||||
private Constructor constructorCache;
|
||||
|
||||
public SpecificClassSchema(String name, List<SpecificFieldSchema> fields, String namespace, List<String> imports)
|
||||
{
|
||||
super(name, namespace, imports);
|
||||
this.fields = fields;
|
||||
if(namespace == null) {
|
||||
this.fqdn = name;
|
||||
} else {
|
||||
this.fqdn = namespace+"."+name;
|
||||
}
|
||||
}
|
||||
|
||||
//@Override
|
||||
//public String getFullName()
|
||||
//{
|
||||
// if(namespace == null) {
|
||||
// return getName();
|
||||
// } else {
|
||||
// return namespace+"."+getName();
|
||||
// }
|
||||
//}
|
||||
|
||||
public List<? extends FieldSchema> getFields()
|
||||
{
|
||||
return fields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpression()
|
||||
{
|
||||
StringBuffer b = new StringBuffer();
|
||||
b.append("(class ");
|
||||
b.append(getName());
|
||||
if(namespace != null) {
|
||||
b.append(" (package "+namespace+")");
|
||||
}
|
||||
for(SpecificFieldSchema f : fields) {
|
||||
b.append(" "+f.getExpression());
|
||||
}
|
||||
b.append(")");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
|
||||
if(constructorCache == null) {
|
||||
cacheConstructor();
|
||||
}
|
||||
|
||||
pk.packArray(fields.size());
|
||||
for(SpecificFieldSchema f : fields) {
|
||||
f.getType().pack(pk, f.getFieldValue(obj));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
if(constructorCache == null) {
|
||||
cacheConstructor();
|
||||
}
|
||||
|
||||
List<GenericObject> d = obj.asArray();
|
||||
|
||||
try {
|
||||
Object g = constructorCache.newInstance((Object[])null);
|
||||
|
||||
Iterator<GenericObject> vi = d.iterator();
|
||||
Iterator<SpecificFieldSchema> fi = fields.iterator();
|
||||
while(fi.hasNext() && vi.hasNext()) {
|
||||
SpecificFieldSchema f = fi.next();
|
||||
GenericObject v = vi.next();
|
||||
f.setFieldValue(g, f.getType().convert(v));
|
||||
}
|
||||
// leave it as uninitialized
|
||||
//while(fi.hasNext()) {
|
||||
// SpecificFieldSchema f = fi.next();
|
||||
// g.put(f.getName(), null);
|
||||
//}
|
||||
|
||||
return g;
|
||||
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void cacheConstructor()
|
||||
{
|
||||
try {
|
||||
Class c = Class.forName(fqdn);
|
||||
int index = 0;
|
||||
for(SpecificFieldSchema f : fields) {
|
||||
f.cacheField(c, index++);
|
||||
}
|
||||
constructorCache = c.getDeclaredConstructor((Class[])null);
|
||||
constructorCache.setAccessible(true);
|
||||
} catch(ClassNotFoundException e) {
|
||||
throw new RuntimeException("class not found: "+fqdn);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("class not found: "+fqdn+": "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object newInstance()
|
||||
{
|
||||
if(constructorCache == null) {
|
||||
cacheConstructor();
|
||||
}
|
||||
try {
|
||||
return constructorCache.newInstance((Object[])null);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(SpecificClassSchema o)
|
||||
{
|
||||
return (namespace != null ? namespace.equals(o.getNamespace()) : o.getNamespace() == null) &&
|
||||
getName().equals(o.getName());
|
||||
}
|
||||
}
|
||||
|
78
java-plan2/src/org/msgpack/schema/SpecificFieldSchema.java
Normal file
78
java-plan2/src/org/msgpack/schema/SpecificFieldSchema.java
Normal file
@ -0,0 +1,78 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Arrays;
|
||||
import java.lang.reflect.Field;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class SpecificFieldSchema extends FieldSchema {
|
||||
public Field fieldCache;
|
||||
private int index;
|
||||
|
||||
public SpecificFieldSchema(String name, Schema type)
|
||||
{
|
||||
super(name, type);
|
||||
this.index = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getFieldValue(Object obj)
|
||||
{
|
||||
if(index >= 0) {
|
||||
return ((MessageMergeable)obj).getField(index);
|
||||
}
|
||||
|
||||
try {
|
||||
return fieldCache.get(obj);
|
||||
} catch(IllegalArgumentException e) {
|
||||
throw new RuntimeException("can't get value from '"+getName()+"' field of '"+obj.getClass().getName()+"' class: "+e.getMessage());
|
||||
} catch(IllegalAccessException e) {
|
||||
throw new RuntimeException("can't get value from '"+getName()+"' field of '"+obj.getClass().getName()+"' class: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFieldValue(Object obj, Object value)
|
||||
{
|
||||
if(index >= 0) {
|
||||
((MessageMergeable)obj).setField(index, value);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
fieldCache.set(obj, value);
|
||||
} catch(IllegalArgumentException e) {
|
||||
throw new RuntimeException("can't set value into '"+getName()+"' field of '"+obj.getClass().getName()+"' class: "+e.getMessage());
|
||||
} catch(IllegalAccessException e) {
|
||||
throw new RuntimeException("can't set value into '"+getName()+"' field of '"+obj.getClass().getName()+"' class: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void cacheField(Class c, int index)
|
||||
{
|
||||
for(Class i : c.getInterfaces()) {
|
||||
if(i.equals(MessageMergeable.class)) {
|
||||
this.index = index;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
fieldCache = c.getDeclaredField(getName());
|
||||
if(!fieldCache.isAccessible()) {
|
||||
fieldCache.setAccessible(true);
|
||||
}
|
||||
} catch(NoSuchFieldException e) {
|
||||
throw new RuntimeException("can't get '"+getName()+"' field of '"+c.getName()+"' class: "+e.getMessage());
|
||||
} catch(SecurityException e) {
|
||||
throw new RuntimeException("can't get '"+getName()+"' field of '"+c.getName()+"' class: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
//public void setFieldInt(Object obj, int value)
|
||||
//{
|
||||
// if(type instanceof PrimitiveSchema) {
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
48
java-plan2/src/org/msgpack/schema/StringSchema.java
Normal file
48
java-plan2/src/org/msgpack/schema/StringSchema.java
Normal file
@ -0,0 +1,48 @@
|
||||
package org.msgpack.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import org.msgpack.*;
|
||||
|
||||
public class StringSchema extends Schema {
|
||||
public StringSchema()
|
||||
{
|
||||
super("string");
|
||||
}
|
||||
|
||||
public String getFullName()
|
||||
{
|
||||
return "String";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(Packer pk, Object obj) throws IOException
|
||||
{
|
||||
if(obj == null) {
|
||||
pk.packNil();
|
||||
return;
|
||||
}
|
||||
String s = (String)obj;
|
||||
byte[] d = s.getBytes("UTF-8");
|
||||
pk.packRaw(d.length);
|
||||
pk.packRawBody(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(GenericObject obj)
|
||||
{
|
||||
return obj.asString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createRaw(byte[] b, int offset, int length)
|
||||
{
|
||||
try {
|
||||
return new String(b, offset, length, "UTF-8"); // XXX FIXME debug
|
||||
} catch (Exception e) {
|
||||
// FIXME
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
java-plan2/test/Generate.java
Normal file
18
java-plan2/test/Generate.java
Normal file
@ -0,0 +1,18 @@
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.schema.*;
|
||||
|
||||
public class Generate {
|
||||
public static void main(String[] args) throws IOException
|
||||
{
|
||||
Writer output = new OutputStreamWriter(System.out);
|
||||
|
||||
Schema s1 = Schema.parse("(class Test (field uri raw) (field width int))");
|
||||
ClassGenerator.write(s1, output);
|
||||
|
||||
Schema s1 = Schema.parse("(class MediaContent (package serializers.msgpack) (field image (array (class Image (field uri string) (field title string) (field width int) (field height int) (field size int)))) (field media (class Media (field uri string) (field title string) (field width int) (field height int) (field format string) (field duration long) (field size long) (field bitrate int) (field person (array string)) (field player int) (field copyright string))))");
|
||||
ClassGenerator.write(s2, output);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,277 @@
|
||||
package serializers.msgpack;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.schema.*;
|
||||
|
||||
public final class MediaContent implements MessagePackable, MessageConvertable, MessageMergeable
|
||||
{
|
||||
private static final ClassSchema _SCHEMA = (ClassSchema)Schema.load("(class MediaContent (package serializers.msgpack) (field image (array (class Image (package serializers.msgpack) (field uri string) (field title string) (field width int) (field height int) (field size int)))) (field media (class Media (package serializers.msgpack) (field uri string) (field title string) (field width int) (field height int) (field format string) (field duration long) (field size long) (field bitrate int) (field person (array string)) (field player int) (field copyright string))))");
|
||||
public static ClassSchema getSchema() { return _SCHEMA; }
|
||||
|
||||
public ArrayList<Image> image;
|
||||
public Media media;
|
||||
|
||||
public MediaContent() { }
|
||||
|
||||
@Override
|
||||
public void messagePack(Packer pk) throws IOException
|
||||
{
|
||||
List<? extends FieldSchema> _f = _SCHEMA.getFields();
|
||||
pk.packArray(2);
|
||||
_f.get(0).getType().pack(pk, image);
|
||||
_f.get(1).getType().pack(pk, media);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void messageConvert(GenericObject obj)
|
||||
{
|
||||
List<GenericObject> _l = obj.asArray();
|
||||
List<? extends FieldSchema> _f = _SCHEMA.getFields();
|
||||
if(_l.size() <= 0) { return; } image = (ArrayList<Image>)_f.get(0).getType().convert(_l.get(0));
|
||||
if(_l.size() <= 1) { return; } media = (Media)_f.get(1).getType().convert(_l.get(1));
|
||||
}
|
||||
|
||||
public static MediaContent convert(GenericObject obj)
|
||||
{
|
||||
return (MediaContent)_SCHEMA.convert(obj);
|
||||
}
|
||||
|
||||
public void setField(int index, Object value)
|
||||
{
|
||||
switch(index) {
|
||||
case 0:
|
||||
image = (ArrayList<Image>)value;
|
||||
break;
|
||||
case 1:
|
||||
media = (Media)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Object getField(int index)
|
||||
{
|
||||
switch(index) {
|
||||
case 0:
|
||||
return image;
|
||||
case 1:
|
||||
return media;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final class Image implements MessagePackable, MessageConvertable, MessageMergeable
|
||||
{
|
||||
private static final ClassSchema _SCHEMA = (ClassSchema)Schema.load("(class Image (package serializers.msgpack) (field uri string) (field title string) (field width int) (field height int) (field size int))");
|
||||
public static ClassSchema getSchema() { return _SCHEMA; }
|
||||
|
||||
public String uri;
|
||||
public String title;
|
||||
public Integer width;
|
||||
public Integer height;
|
||||
public Integer size;
|
||||
|
||||
public Image() { }
|
||||
|
||||
@Override
|
||||
public void messagePack(Packer pk) throws IOException
|
||||
{
|
||||
List<? extends FieldSchema> _f = _SCHEMA.getFields();
|
||||
pk.packArray(5);
|
||||
_f.get(0).getType().pack(pk, uri);
|
||||
_f.get(1).getType().pack(pk, title);
|
||||
_f.get(2).getType().pack(pk, width);
|
||||
_f.get(3).getType().pack(pk, height);
|
||||
_f.get(4).getType().pack(pk, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void messageConvert(GenericObject obj)
|
||||
{
|
||||
List<GenericObject> _l = obj.asArray();
|
||||
List<? extends FieldSchema> _f = _SCHEMA.getFields();
|
||||
if(_l.size() <= 0) { return; } uri = (String)_f.get(0).getType().convert(_l.get(0));
|
||||
if(_l.size() <= 1) { return; } title = (String)_f.get(1).getType().convert(_l.get(1));
|
||||
if(_l.size() <= 2) { return; } width = (Integer)_f.get(2).getType().convert(_l.get(2));
|
||||
if(_l.size() <= 3) { return; } height = (Integer)_f.get(3).getType().convert(_l.get(3));
|
||||
if(_l.size() <= 4) { return; } size = (Integer)_f.get(4).getType().convert(_l.get(4));
|
||||
}
|
||||
|
||||
public static Image convert(GenericObject obj)
|
||||
{
|
||||
return (Image)_SCHEMA.convert(obj);
|
||||
}
|
||||
|
||||
public void setField(int index, Object value)
|
||||
{
|
||||
switch(index) {
|
||||
case 0:
|
||||
uri = (String)value;
|
||||
break;
|
||||
case 1:
|
||||
title = (String)value;
|
||||
break;
|
||||
case 2:
|
||||
width = (Integer)value;
|
||||
break;
|
||||
case 3:
|
||||
height = (Integer)value;
|
||||
break;
|
||||
case 4:
|
||||
size = (Integer)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Object getField(int index)
|
||||
{
|
||||
switch(index) {
|
||||
case 0:
|
||||
return uri;
|
||||
case 1:
|
||||
return title;
|
||||
case 2:
|
||||
return width;
|
||||
case 3:
|
||||
return height;
|
||||
case 4:
|
||||
return size;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final class Media implements MessagePackable, MessageConvertable, MessageMergeable
|
||||
{
|
||||
private static final ClassSchema _SCHEMA = (ClassSchema)Schema.load("(class Media (package serializers.msgpack) (field uri string) (field title string) (field width int) (field height int) (field format string) (field duration long) (field size long) (field bitrate int) (field person (array string)) (field player int) (field copyright string))");
|
||||
public static ClassSchema getSchema() { return _SCHEMA; }
|
||||
|
||||
public String uri;
|
||||
public String title;
|
||||
public Integer width;
|
||||
public Integer height;
|
||||
public String format;
|
||||
public Long duration;
|
||||
public Long size;
|
||||
public Integer bitrate;
|
||||
public ArrayList<String> person;
|
||||
public Integer player;
|
||||
public String copyright;
|
||||
|
||||
public Media() { }
|
||||
|
||||
@Override
|
||||
public void messagePack(Packer pk) throws IOException
|
||||
{
|
||||
List<? extends FieldSchema> _f = _SCHEMA.getFields();
|
||||
pk.packArray(11);
|
||||
_f.get(0).getType().pack(pk, uri);
|
||||
_f.get(1).getType().pack(pk, title);
|
||||
_f.get(2).getType().pack(pk, width);
|
||||
_f.get(3).getType().pack(pk, height);
|
||||
_f.get(4).getType().pack(pk, format);
|
||||
_f.get(5).getType().pack(pk, duration);
|
||||
_f.get(6).getType().pack(pk, size);
|
||||
_f.get(7).getType().pack(pk, bitrate);
|
||||
_f.get(8).getType().pack(pk, person);
|
||||
_f.get(9).getType().pack(pk, player);
|
||||
_f.get(10).getType().pack(pk, copyright);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void messageConvert(GenericObject obj)
|
||||
{
|
||||
List<GenericObject> _l = obj.asArray();
|
||||
List<? extends FieldSchema> _f = _SCHEMA.getFields();
|
||||
if(_l.size() <= 0) { return; } uri = (String)_f.get(0).getType().convert(_l.get(0));
|
||||
if(_l.size() <= 1) { return; } title = (String)_f.get(1).getType().convert(_l.get(1));
|
||||
if(_l.size() <= 2) { return; } width = (Integer)_f.get(2).getType().convert(_l.get(2));
|
||||
if(_l.size() <= 3) { return; } height = (Integer)_f.get(3).getType().convert(_l.get(3));
|
||||
if(_l.size() <= 4) { return; } format = (String)_f.get(4).getType().convert(_l.get(4));
|
||||
if(_l.size() <= 5) { return; } duration = (Long)_f.get(5).getType().convert(_l.get(5));
|
||||
if(_l.size() <= 6) { return; } size = (Long)_f.get(6).getType().convert(_l.get(6));
|
||||
if(_l.size() <= 7) { return; } bitrate = (Integer)_f.get(7).getType().convert(_l.get(7));
|
||||
if(_l.size() <= 8) { return; } person = (ArrayList<String>)_f.get(8).getType().convert(_l.get(8));
|
||||
if(_l.size() <= 9) { return; } player = (Integer)_f.get(9).getType().convert(_l.get(9));
|
||||
if(_l.size() <= 10) { return; } copyright = (String)_f.get(10).getType().convert(_l.get(10));
|
||||
}
|
||||
|
||||
public static Media convert(GenericObject obj)
|
||||
{
|
||||
return (Media)_SCHEMA.convert(obj);
|
||||
}
|
||||
|
||||
public void setField(int index, Object value)
|
||||
{
|
||||
switch(index) {
|
||||
case 0:
|
||||
uri = (String)value;
|
||||
break;
|
||||
case 1:
|
||||
title = (String)value;
|
||||
break;
|
||||
case 2:
|
||||
width = (Integer)value;
|
||||
break;
|
||||
case 3:
|
||||
height = (Integer)value;
|
||||
break;
|
||||
case 4:
|
||||
format = (String)value;
|
||||
break;
|
||||
case 5:
|
||||
duration = (Long)value;
|
||||
break;
|
||||
case 6:
|
||||
size = (Long)value;
|
||||
break;
|
||||
case 7:
|
||||
bitrate = (Integer)value;
|
||||
break;
|
||||
case 8:
|
||||
person = (ArrayList<String>)value;
|
||||
break;
|
||||
case 9:
|
||||
player = (Integer)value;
|
||||
break;
|
||||
case 10:
|
||||
copyright = (String)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Object getField(int index)
|
||||
{
|
||||
switch(index) {
|
||||
case 0:
|
||||
return uri;
|
||||
case 1:
|
||||
return title;
|
||||
case 2:
|
||||
return width;
|
||||
case 3:
|
||||
return height;
|
||||
case 4:
|
||||
return format;
|
||||
case 5:
|
||||
return duration;
|
||||
case 6:
|
||||
return size;
|
||||
case 7:
|
||||
return bitrate;
|
||||
case 8:
|
||||
return person;
|
||||
case 9:
|
||||
return player;
|
||||
case 10:
|
||||
return copyright;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
(class MediaContent
|
||||
(package serializers.msgpack)
|
||||
(field image (array (class Image
|
||||
(field uri string)
|
||||
(field title string)
|
||||
(field width int)
|
||||
(field height int)
|
||||
(field size int))))
|
||||
(field media (class Media
|
||||
(field uri string)
|
||||
(field title string)
|
||||
(field width int)
|
||||
(field height int)
|
||||
(field format string)
|
||||
(field duration long)
|
||||
(field size long)
|
||||
(field bitrate int)
|
||||
(field person (array string))
|
||||
(field player int)
|
||||
(field copyright string)))
|
||||
)
|
@ -0,0 +1,70 @@
|
||||
package serializers.msgpack;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.schema.*;
|
||||
import serializers.msgpack.*;
|
||||
|
||||
import serializers.ObjectSerializer;
|
||||
|
||||
public class MessagePackSerializer implements ObjectSerializer<MediaContent>
|
||||
{
|
||||
public String getName() {
|
||||
return "msgpack-specific";
|
||||
}
|
||||
|
||||
public MediaContent create() throws Exception {
|
||||
Media media = new Media();
|
||||
media.uri = "http://javaone.com/keynote.mpg";
|
||||
media.format = "video/mpg4";
|
||||
media.title = "Javaone Keynote";
|
||||
media.duration = 1234567L;
|
||||
media.bitrate = 0;
|
||||
media.person = new ArrayList<String>(2);
|
||||
media.person.add("Bill Gates");
|
||||
media.person.add("Steve Jobs");
|
||||
media.player = 0;
|
||||
media.height = 0;
|
||||
media.width = 0;
|
||||
media.size = 123L;
|
||||
media.copyright = "";
|
||||
|
||||
Image image1 = new Image();
|
||||
image1.uri = "http://javaone.com/keynote_large.jpg";
|
||||
image1.width = 0;
|
||||
image1.height = 0;
|
||||
image1.size = 2;
|
||||
image1.title = "Javaone Keynote";
|
||||
|
||||
Image image2 = new Image();
|
||||
image2.uri = "http://javaone.com/keynote_thumbnail.jpg";
|
||||
image2.width = 0;
|
||||
image2.height = 0;
|
||||
image2.size = 1;
|
||||
image2.title = "Javaone Keynote";
|
||||
|
||||
MediaContent content = new MediaContent();
|
||||
content.media = media;
|
||||
content.image = new ArrayList<Image>(2);
|
||||
content.image.add(image1);
|
||||
content.image.add(image2);
|
||||
return content;
|
||||
}
|
||||
|
||||
public MediaContent deserialize(byte[] array) throws Exception {
|
||||
UnbufferedUnpacker pac = new UnbufferedUnpacker().useSchema(MediaContent.getSchema());
|
||||
pac.execute(array);
|
||||
return (MediaContent)pac.getData();
|
||||
}
|
||||
|
||||
public byte[] serialize(MediaContent content) throws Exception {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
Packer pk = new Packer(os);
|
||||
pk.pack(content);
|
||||
return os.toByteArray();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user