Merge branch 'master' of git://git.sourceforge.jp/gitroot/msgpack/msgpack

This commit is contained in:
tokuhirom 2010-01-04 11:23:40 +09:00
commit 519716bbe4
129 changed files with 9255 additions and 488 deletions

View File

@ -8,5 +8,6 @@ nobase_include_HEADERS = \
msgpack/pack_define.h \ msgpack/pack_define.h \
msgpack/pack_template.h \ msgpack/pack_template.h \
msgpack/unpack_define.h \ msgpack/unpack_define.h \
msgpack/unpack_template.h msgpack/unpack_template.h \
msgpack/sysdep.h

View File

@ -18,7 +18,17 @@
#include "msgpack/object.h" #include "msgpack/object.h"
#include "msgpack/pack.h" #include "msgpack/pack.h"
#include <stdio.h> #include <stdio.h>
#ifndef _MSC_VER
#include <inttypes.h> #include <inttypes.h>
#else
#ifndef PRIu64
#define PRIu64 "I64u"
#endif
#ifndef PRIi64
#define PRIi64 "I64d"
#endif
#endif
int msgpack_pack_object(msgpack_packer* pk, msgpack_object d) int msgpack_pack_object(msgpack_packer* pk, msgpack_object d)

View File

@ -19,9 +19,7 @@
#define MSGPACK_OBJECT_H__ #define MSGPACK_OBJECT_H__
#include "msgpack/zone.h" #include "msgpack/zone.h"
#include <stdint.h> #include "msgpack/sysdep.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -18,11 +18,9 @@
#ifndef MSGPACK_PACK_H__ #ifndef MSGPACK_PACK_H__
#define MSGPACK_PACK_H__ #define MSGPACK_PACK_H__
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "msgpack/pack_define.h" #include "msgpack/pack_define.h"
#include "msgpack/object.h" #include "msgpack/object.h"
#include <stdlib.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -101,7 +101,7 @@ static inline int template_callback_array(unpack_user* u, unsigned int n, msgpac
{ {
o->type = MSGPACK_OBJECT_ARRAY; o->type = MSGPACK_OBJECT_ARRAY;
o->via.array.size = 0; o->via.array.size = 0;
o->via.array.ptr = msgpack_zone_malloc(u->z, n*sizeof(msgpack_object)); o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object));
if(o->via.array.ptr == NULL) { return -1; } if(o->via.array.ptr == NULL) { return -1; }
return 0; return 0;
} }
@ -141,31 +141,31 @@ static inline int template_callback_raw(unpack_user* u, const char* b, const cha
#define CTX_CAST(m) ((template_context*)(m)) #define CTX_CAST(m) ((template_context*)(m))
#define CTX_REFERENCED(mpac) CTX_CAST((mpac)->ctx)->user.referenced #define CTX_REFERENCED(mpac) CTX_CAST((mpac)->ctx)->user.referenced
#define COUNTER_SIZE (sizeof(_msgpack_atomic_counter_t))
static const size_t COUNTER_SIZE = sizeof(unsigned int);
static inline void init_count(void* buffer) static inline void init_count(void* buffer)
{ {
*(volatile unsigned int*)buffer = 1; *(volatile _msgpack_atomic_counter_t*)buffer = 1;
} }
static inline void decl_count(void* buffer) static inline void decl_count(void* buffer)
{ {
//if(--*(unsigned int*)buffer == 0) { // atomic if(--*(_msgpack_atomic_counter_t*)buffer == 0) { free(buffer); }
if(__sync_sub_and_fetch((unsigned int*)buffer, 1) == 0) { if(_msgpack_sync_decr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer) == 0) {
free(buffer); free(buffer);
} }
} }
static inline void incr_count(void* buffer) static inline void incr_count(void* buffer)
{ {
//++*(unsigned int*)buffer; // atomic ++*(_msgpack_atomic_counter_t*)buffer;
__sync_add_and_fetch((unsigned int*)buffer, 1); _msgpack_sync_incr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer);
} }
static inline unsigned int get_count(void* buffer) static inline _msgpack_atomic_counter_t get_count(void* buffer)
{ {
return *(volatile unsigned int*)buffer; return *(volatile _msgpack_atomic_counter_t*)buffer;
} }

View File

@ -15,13 +15,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#ifndef msgpack_unpacker_H__ #ifndef MSGPACK_UNPACKER_H__
#define msgpack_unpacker_H__ #define MSGPACK_UNPACKER_H__
#include "msgpack/zone.h" #include "msgpack/zone.h"
#include "msgpack/object.h" #include "msgpack/object.h"
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -77,7 +77,7 @@ int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
const char* buf, unsigned int len) const char* buf, unsigned int len)
{ {
if(vbuf->tail == vbuf->end) { if(vbuf->tail == vbuf->end) {
const size_t nused = vbuf->end - vbuf->array; const size_t nused = vbuf->tail - vbuf->array;
const size_t nnext = nused * 2; const size_t nnext = nused * 2;
struct iovec* nvec = (struct iovec*)realloc( struct iovec* nvec = (struct iovec*)realloc(
@ -133,3 +133,30 @@ int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
} }
} }
int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to)
{
const size_t tosize = to->tail - to->array;
if(vbuf->tail + tosize < vbuf->end) {
const size_t nused = vbuf->tail - vbuf->array;
const size_t nsize = vbuf->end - vbuf->array;
const size_t reqsize = nused + tosize;
size_t nnext = nsize * 2;
while(nnext < reqsize) {
nnext *= 2;
}
struct iovec* nvec = (struct iovec*)realloc(
vbuf->array, sizeof(struct iovec)*nnext);
if(nvec == NULL) {
return -1;
}
vbuf->array = nvec;
vbuf->end = nvec + nnext;
vbuf->tail = nvec + nused;
}
memcpy(vbuf->tail, vbuf->array, sizeof(struct iovec)*tosize);
return 0;
}

View File

@ -19,7 +19,16 @@
#define MSGPACK_VREFBUFFER_H__ #define MSGPACK_VREFBUFFER_H__
#include "msgpack/zone.h" #include "msgpack/zone.h"
#ifndef _WIN32
#include <sys/uio.h> #include <sys/uio.h>
#else
struct iovec {
void *iov_base;
size_t iov_len;
};
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -67,6 +76,7 @@ int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf, int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
const char* buf, unsigned int len); const char* buf, unsigned int len);
int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to);
int msgpack_vrefbuffer_write(void* data, const char* buf, unsigned int len) int msgpack_vrefbuffer_write(void* data, const char* buf, unsigned int len)
{ {

View File

@ -1,6 +1,6 @@
AC_INIT(msgpack/unpack_template.h) AC_INIT(msgpack/unpack_template.h)
AC_CONFIG_AUX_DIR(ac) AC_CONFIG_AUX_DIR(ac)
AM_INIT_AUTOMAKE(msgpack, 0.3.8) AM_INIT_AUTOMAKE(msgpack, 0.3.9)
AC_CONFIG_HEADER(config.h) AC_CONFIG_HEADER(config.h)
AC_SUBST(CFLAGS) AC_SUBST(CFLAGS)

View File

@ -20,7 +20,6 @@
#include "msgpack/object.h" #include "msgpack/object.h"
#include "msgpack/pack.hpp" #include "msgpack/pack.hpp"
#include <stdint.h>
#include <string.h> #include <string.h>
#include <stdexcept> #include <stdexcept>
#include <typeinfo> #include <typeinfo>

View File

@ -18,10 +18,9 @@
#ifndef MSGPACK_PACK_HPP__ #ifndef MSGPACK_PACK_HPP__
#define MSGPACK_PACK_HPP__ #define MSGPACK_PACK_HPP__
#include <arpa/inet.h> // __BYTE_ORDER #include "msgpack/pack_define.h"
#include <stdexcept> #include <stdexcept>
#include <limits.h> #include <limits.h>
#include "msgpack/pack_define.h"
namespace msgpack { namespace msgpack {

View File

@ -71,6 +71,13 @@ public:
return msgpack_vrefbuffer_veclen(this); return msgpack_vrefbuffer_veclen(this);
} }
void migrate(vrefbuffer* to)
{
if(msgpack_vrefbuffer_migrate(this, to) < 0) {
throw std::bad_alloc();
}
}
private: private:
typedef msgpack_vrefbuffer base; typedef msgpack_vrefbuffer base;

View File

@ -21,6 +21,7 @@
#include "msgpack/object.hpp" #include "msgpack/object.hpp"
#include "msgpack/zone.h" #include "msgpack/zone.h"
#include <cstdlib> #include <cstdlib>
#include <memory>
#include <vector> #include <vector>
<% GENERATION_LIMIT = 15 %> <% GENERATION_LIMIT = 15 %>
@ -38,6 +39,9 @@ public:
void push_finalizer(void (*func)(void*), void* data); void push_finalizer(void (*func)(void*), void* data);
template <typename T>
void push_finalizer(std::auto_ptr<T> obj);
void clear(); void clear();
<%0.upto(GENERATION_LIMIT) {|i|%> <%0.upto(GENERATION_LIMIT) {|i|%>
@ -94,6 +98,15 @@ inline void zone::push_finalizer(void (*func)(void*), void* data)
} }
} }
template <typename T>
inline void zone::push_finalizer(std::auto_ptr<T> obj)
{
if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, obj.get())) {
throw std::bad_alloc();
}
obj.release();
}
inline void zone::clear() inline void zone::clear()
{ {
msgpack_zone_clear(this); msgpack_zone_clear(this);

View File

@ -0,0 +1,37 @@
import java.nio.ByteBuffer;
import java.io.InputStream;
import java.io.IOException;
public class MessagePack {
static public Object unpack(InputStream source)
{
// FIXME not implemented yet
return null;
}
static public Object unpack(byte[] source, int len) throws IOException
{
// FIXME not implemented yet
return null;
}
static public Object unpack(ByteBuffer source) throws IOException
{
// FIXME not implemented yet
return null;
}
static public Object unpack(ByteBuffer[] source) throws IOException
{
// FIXME not implemented yet
return null;
}
}
/*
public interface MessagePackable {
public void toMessagePack(Packer pk);
}
*/

266
java-plan1/Packer.java Normal file
View File

@ -0,0 +1,266 @@
import java.io.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.math.BigInteger;
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;
}
//public Packer pack(Object o) throws IOException
}

401
java-plan1/Unpacker.java Normal file
View File

@ -0,0 +1,401 @@
import java.io.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.math.BigInteger;
public class Unpacker {
protected static final int CS_HEADER = 0x00;
protected static final int CS_FLOAT = 0x0a;
protected static final int CS_DOUBLE = 0x0b;
protected static final int CS_UINT_8 = 0x0c;
protected static final int CS_UINT_16 = 0x0d;
protected static final int CS_UINT_32 = 0x0e;
protected static final int CS_UINT_64 = 0x0f;
protected static final int CS_INT_8 = 0x10;
protected static final int CS_INT_16 = 0x11;
protected static final int CS_INT_32 = 0x12;
protected static final int CS_INT_64 = 0x13;
protected static final int CS_RAW_16 = 0x1a;
protected static final int CS_RAW_32 = 0x1b;
protected static final int CS_ARRAY_16 = 0x1c;
protected static final int CS_ARRAY_32 = 0x1d;
protected static final int CS_MAP_16 = 0x1e;
protected static final int CS_MAP_32 = 0x1f;
protected static final int ACS_RAW_VALUE = 0x20;
protected static final int CT_ARRAY_ITEM = 0x00;
protected static final int CT_MAP_KEY = 0x01;
protected static final int CT_MAP_VALUE = 0x02;
protected 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 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 Object[] stack_map_key = new Object[MAX_STACK_SIZE];
//protected Object user;
protected ByteBuffer castBuffer = ByteBuffer.allocate(8);
public Object getData()
{
return stack_obj[0];
}
public boolean isFinished()
{
return finished;
}
public void reset()
{
for(int i=0; i <= top; ++top) {
stack_ct[top] = 0;
stack_count[top] = 0;
stack_obj[top] = null;
stack_map_key[top] = null;
}
cs = CS_HEADER;
trail = 0;
top = -1;
finished = false;
}
@SuppressWarnings("unchecked")
public int execute(byte[] src, int off, int length) throws IOException
{
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 = b;
break _push;
}
if((b & 0xe0) == 0xe0) { // Negative Fixnum
//System.out.println("negative fixnum "+b);
obj = b;
break _push;
}
if((b & 0xe0) == 0xa0) { // FixRaw
trail = b & 0x1f;
if(trail == 0) {
obj = new byte[0];
break _push;
}
cs = ACS_RAW_VALUE;
break _fixed_trail_again;
}
if((b & 0xf0) == 0x90) { // FixArray
if(top >= MAX_STACK_SIZE) {
throw new IOException("parse error");
}
count = b & 0x0f;
++top;
stack_obj[top] = new ArrayList(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 IOException("parse error");
}
count = b & 0x0f;
++top;
stack_obj[top] = new HashMap(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 = null;
break _push;
case 0xc2: // false
obj = false;
break _push;
case 0xc3: // true
obj = 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 IOException("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 = castBuffer.getFloat(0);
//System.out.println("float "+obj);
break _push;
case CS_DOUBLE:
castBuffer.rewind();
castBuffer.put(src, n, 8);
obj = 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 = ((int)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 = ((int)castBuffer.getShort(0)) & 0xffff;
//System.out.println("uint 16 "+obj);
break _push;
case CS_UINT_32:
castBuffer.rewind();
castBuffer.put(src, n, 4);
{
// FIXME always long?
int o = castBuffer.getInt(0);
if(o < 0) {
obj = ((long)o) & 0xffffffffL;
} else {
obj = o;
}
}
//System.out.println("uint 32 "+obj);
break _push;
case CS_UINT_64:
castBuffer.rewind();
castBuffer.put(src, n, 8);
{
// FIXME always BigInteger?
long o = castBuffer.getLong(0);
if(o < 0) {
obj = BigInteger.valueOf(o & 0x7fffffffL).setBit(31);
} else {
obj = o;
}
}
throw new IOException("uint 64 is not supported");
case CS_INT_8:
obj = (int)src[n];
break _push;
case CS_INT_16:
castBuffer.rewind();
castBuffer.put(src, n, 2);
obj = (int)castBuffer.getShort(0);
break _push;
case CS_INT_32:
castBuffer.rewind();
castBuffer.put(src, n, 4);
obj = (int)castBuffer.getInt(0);
break _push;
case CS_INT_64:
castBuffer.rewind();
castBuffer.put(src, n, 8);
{
// FIXME always long?
long o = castBuffer.getLong(0);
if(o <= 0x7fffffffL && o > -0x80000000L) {
obj = (int)o;
} else {
obj = o;
}
}
//System.out.println("long "+obj);
break _push;
case CS_RAW_16:
castBuffer.rewind();
castBuffer.put(src, n, 2);
trail = ((int)castBuffer.getShort(0)) & 0xffff;
if(trail == 0) {
obj = new byte[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 = new byte[0];
break _push;
}
cs = ACS_RAW_VALUE;
case ACS_RAW_VALUE:
obj = ByteBuffer.wrap(src, n, trail); // FIXME プール? コピー
break _push;
case CS_ARRAY_16:
if(top >= MAX_STACK_SIZE) {
throw new IOException("parse error");
}
castBuffer.rewind();
castBuffer.put(src, n, 2);
count = ((int)castBuffer.getShort(0)) & 0xffff;
++top;
stack_obj[top] = new ArrayList(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 IOException("parse error");
}
castBuffer.rewind();
castBuffer.put(src, n, 4);
// FIXME overflow check
count = castBuffer.getInt(0) & 0x7fffffff;
++top;
stack_obj[top] = new ArrayList(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 IOException("parse error");
}
castBuffer.rewind();
castBuffer.put(src, n, 2);
count = ((int)castBuffer.getShort(0)) & 0xffff;
++top;
stack_obj[top] = new HashMap(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 IOException("parse error");
}
castBuffer.rewind();
castBuffer.put(src, n, 4);
// FIXME overflow check
count = castBuffer.getInt(0) & 0x7fffffff;
++top;
stack_obj[top] = new HashMap(count);
stack_ct[top] = CT_MAP_KEY;
stack_count[top] = count;
//System.out.println("fixmap count:"+count);
break _header_again;
default:
throw new IOException("parse error");
}
} // _fixed_trail_again
} while(true);
} // _push
do {
_push: {
//System.out.println("push top:"+top);
if(top == -1) {
stack_obj[0] = obj;
finished = true;
break _out;
}
switch(stack_ct[top]) {
case CT_ARRAY_ITEM:
//System.out.println("array item "+obj);
((ArrayList)(stack_obj[top])).add(obj);
if(--stack_count[top] == 0) {
obj = stack_obj[top];
stack_obj[top] = null;
--top;
break _push;
}
break _header_again;
case CT_MAP_KEY:
//System.out.println("map key:"+top+" "+obj);
stack_map_key[top] = obj;
stack_ct[top] = CT_MAP_VALUE;
break _header_again;
case CT_MAP_VALUE:
//System.out.println("map value:"+top+" "+obj);
((HashMap)(stack_obj[top])).put(stack_map_key[top], obj);
if(--stack_count[top] == 0) {
obj = stack_obj[top];
stack_map_key[top] = null;
stack_obj[top] = null;
--top;
break _push;
}
stack_ct[top] = CT_MAP_KEY;
break _header_again;
default:
throw new IOException("parse error");
}
} // _push
} while(true);
} // _header_again
cs = CS_HEADER;
++i;
} while(i < limit); // _out
return i;
}
}

3
java-plan1/run.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
javac MessagePack.java Packer.java Unpacker.java test.java
java test

94
java-plan1/test.java Normal file
View File

@ -0,0 +1,94 @@
import java.util.*;
import java.io.*;
class OpenByteArrayOutputStream extends ByteArrayOutputStream {
int getCount() { return count; }
byte[] getBuffer() { return buf; }
}
public class test {
public static void main(String[] args) throws IOException
{
testSimple();
testStreaming();
}
public static void testSimple() throws IOException
{
OpenByteArrayOutputStream out = new OpenByteArrayOutputStream();
Packer pk = new Packer(out);
pk.packArray(3)
.packInt(1)
.packByte((byte)2)
.packDouble(0.3);
Unpacker pac = new Unpacker();
int nlen = pac.execute(out.getBuffer(), 0, out.getCount());
if(pac.isFinished()) {
System.out.println("testSimple: "+pac.getData());
}
}
public static void testStreaming() throws IOException
{
OpenByteArrayOutputStream out = new OpenByteArrayOutputStream();
////
// sender
//
// initialize the streaming serializer
Packer pk = new Packer(out);
// serialize 2 objects
pk.packArray(3)
.packInt(0)
.packByte((byte)1)
.packDouble(0.2);
pk.packArray(3)
.packInt(3)
.packByte((byte)4)
.packDouble(0.5);
// send it through the network
InputStream sock = new ByteArrayInputStream(out.getBuffer(), 0, out.getCount());
////
// receiver
//
// initialize the streaming deserializer
Unpacker pac = new Unpacker();
int parsed = 0;
byte[] buf = new byte[1024];
int buflen = 0;
while(true) {
// receive data from the network
int c = sock.read();
if(c < 0) { return; }
buf[buflen++] = (byte)c;
// deserialize
parsed = pac.execute(buf, parsed, buflen);
if(pac.isFinished()) {
// get an object
Object msg = pac.getData();
System.out.println("testStreaming: "+msg);
// reset the streaming deserializer
pac.reset();
buflen = 0;
parsed = 0;
}
}
}
}

15
java-plan2/build.xml Normal file
View 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>

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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");
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -0,0 +1,7 @@
package org.msgpack;
public interface MessageConvertable
{
public void messageConvert(GenericObject obj);
}

View File

@ -0,0 +1,7 @@
package org.msgpack;
public interface MessageMergeable {
public void setField(int index, Object value);
public Object getField(int index);
}

View File

@ -0,0 +1,10 @@
package org.msgpack;
public class MessagePackException extends RuntimeException
{
public MessagePackException(String message)
{
super(message);
}
}

View File

@ -0,0 +1,9 @@
package org.msgpack;
import java.io.IOException;
public interface MessagePackable
{
public void messagePack(Packer pk) throws IOException;
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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();
}
}

View 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;
}
*/
}

View File

@ -0,0 +1,7 @@
package org.msgpack.impl;
public interface ArrayBuilder {
public void add(Object element);
public Object finish();
}

View 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;
}
}

View File

@ -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);
}
}

View 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();
}

View 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);
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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();
}

View 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);
}

View 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());
}
}

View 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);
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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);
}
}
}

View 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");
}
}

View 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;
}
}

View 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());
}
}

View 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) {
// }
//}
}

View 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());
}
}
}

View 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 s2 = 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);
}
}

View File

@ -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;
}
}

View File

@ -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)))
)

View File

@ -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();
}
}

15
java-plan3/build.xml Normal file
View 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" source="1.5" target="1.5">
<compilerarg value="-Xlint:unchecked" />
</javac>
</target>
</project>

View File

@ -0,0 +1,23 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
public interface MessageMergeable {
public void messageMerge(Object obj) throws MessageTypeException;
}

View File

@ -0,0 +1,25 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
public interface MessagePackable {
public void messagePack(Packer pk) throws IOException;
}

View File

@ -0,0 +1,39 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
public class MessageTypeException extends IOException {
public MessageTypeException() { }
public MessageTypeException(String s) {
super(s);
}
public static MessageTypeException invalidConvert(Object from, Schema to) {
return new MessageTypeException(from.getClass().getName()+" cannot be convert to "+to.getExpression());
}
/* FIXME
public static MessageTypeException schemaMismatch(Schema to) {
return new MessageTypeException("schema mismatch "+to.getExpression());
}
*/
}

View File

@ -0,0 +1,409 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.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;
}
public Packer packWithSchema(Object o, Schema s) throws IOException {
s.pack(this, o);
return this;
}
public Packer packString(String s) throws IOException {
byte[] b = ((String)s).getBytes("UTF-8");
packRaw(b.length);
return packRawBody(b);
}
public Packer pack(String o) throws IOException {
if(o == null) { return packNil(); }
return packString(o);
}
public Packer pack(MessagePackable o) throws IOException {
if(o == null) { return packNil(); }
o.messagePack(this);
return this;
}
public Packer pack(byte[] o) throws IOException {
if(o == null) { return packNil(); }
packRaw(o.length);
return packRawBody(o);
}
public Packer pack(List o) throws IOException {
if(o == null) { return packNil(); }
packArray(o.size());
for(Object i : o) { pack(i); }
return this;
}
@SuppressWarnings("unchecked")
public Packer pack(Map o) throws IOException {
if(o == null) { return packNil(); }
packMap(o.size());
for(Map.Entry e : ((Map<Object,Object>)o).entrySet()) {
pack(e.getKey());
pack(e.getValue());
}
return this;
}
public Packer pack(Boolean o) throws IOException {
if(o == null) { return packNil(); }
if(o) {
return packTrue();
} else {
return packFalse();
}
}
public Packer pack(Byte o) throws IOException {
if(o == null) { return packNil(); }
return packByte(o);
}
public Packer pack(Short o) throws IOException {
if(o == null) { return packNil(); }
return packShort(o);
}
public Packer pack(Integer o) throws IOException {
if(o == null) { return packNil(); }
return packInt(o);
}
public Packer pack(Long o) throws IOException {
if(o == null) { return packNil(); }
return packLong(o);
}
public Packer pack(Float o) throws IOException {
if(o == null) { return packNil(); }
return packFloat(o);
}
public Packer pack(Double o) throws IOException {
if(o == null) { return packNil(); }
return packDouble(o);
}
@SuppressWarnings("unchecked")
public Packer pack(Object o) throws IOException {
if(o == null) {
return packNil();
} else if(o instanceof String) {
byte[] b = ((String)o).getBytes("UTF-8");
packRaw(b.length);
return packRawBody(b);
} else if(o instanceof MessagePackable) {
((MessagePackable)o).messagePack(this);
return this;
} else if(o instanceof byte[]) {
byte[] b = (byte[])o;
packRaw(b.length);
return packRawBody(b);
} else if(o instanceof List) {
List<Object> l = (List<Object>)o;
packArray(l.size());
for(Object i : l) { pack(i); }
return this;
} 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());
}
return this;
} else if(o instanceof Boolean) {
if((Boolean)o) {
return packTrue();
} else {
return packFalse();
}
} else if(o instanceof Integer) {
return packInt((Integer)o);
} else if(o instanceof Long) {
return packLong((Long)o);
} else if(o instanceof Short) {
return packShort((Short)o);
} else if(o instanceof Byte) {
return packByte((Byte)o);
} else if(o instanceof Float) {
return packFloat((Float)o);
} else if(o instanceof Double) {
return packDouble((Double)o);
} else {
throw new IOException("unknown object "+o+" ("+o.getClass()+")");
}
}
}

View File

@ -0,0 +1,133 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.Writer;
import java.io.IOException;
import org.msgpack.schema.SSchemaParser;
import org.msgpack.schema.ClassGenerator;
public abstract class Schema {
private String expression;
private String name;
public Schema(String name) {
this.expression = expression;
this.name = name;
}
public String getName() {
return name;
}
public String getFullName() {
return name;
}
public String getExpression() {
return name;
}
public static Schema parse(String source) {
return SSchemaParser.parse(source);
}
public static Schema load(String source) {
return SSchemaParser.load(source);
}
public void write(Writer output) throws IOException {
ClassGenerator.write(this, output);
}
public abstract void pack(Packer pk, Object obj) throws IOException;
public abstract Object convert(Object obj) throws MessageTypeException;
public Object createFromNil() {
return null;
}
public Object createFromBoolean(boolean v) {
throw new RuntimeException("type error");
}
public Object createFromByte(byte v) {
throw new RuntimeException("type error");
}
public Object createFromShort(short v) {
throw new RuntimeException("type error");
}
public Object createFromInt(int v) {
throw new RuntimeException("type error");
}
public Object createFromLong(long v) {
throw new RuntimeException("type error");
}
public Object createFromFloat(float v) {
throw new RuntimeException("type error");
}
public Object createFromDouble(double v) {
throw new RuntimeException("type error");
}
public Object createFromRaw(byte[] b, int offset, int length) {
throw new RuntimeException("type error");
}
/* FIXME
public Object createFromBoolean(boolean v) {
throw MessageTypeException.schemaMismatch(this);
}
public Object createFromByte(byte v) {
throw MessageTypeException.schemaMismatch(this);
}
public Object createFromShort(short v) {
throw MessageTypeException.schemaMismatch(this);
}
public Object createFromInt(int v) {
throw MessageTypeException.schemaMismatch(this);
}
public Object createFromLong(long v) {
throw MessageTypeException.schemaMismatch(this);
}
public Object createFromFloat(float v) {
throw MessageTypeException.schemaMismatch(this);
}
public Object createFromDouble(double v) {
throw MessageTypeException.schemaMismatch(this);
}
public Object createFromRaw(byte[] b, int offset, int length) {
throw MessageTypeException.schemaMismatch(this);
}
*/
}

View File

@ -0,0 +1,82 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.lang.Iterable;
import java.io.InputStream;
import java.io.IOException;
import java.util.Iterator;
import org.msgpack.impl.UnpackerImpl;
public class UnbufferedUnpacker extends UnpackerImpl {
private int offset;
private boolean finished;
private Object data;
public UnbufferedUnpacker() {
super();
this.offset = 0;
this.finished = false;
}
public UnbufferedUnpacker useSchema(Schema s) {
super.setSchema(s);
return this;
}
public Object getData() {
return data;
}
public boolean isFinished() {
return finished;
}
public void reset() {
super.reset();
this.offset = 0;
}
int getOffset() {
return offset;
}
void setOffset(int offset) {
this.offset = offset;
}
public int execute(byte[] buffer) throws UnpackException {
return execute(buffer, 0, buffer.length);
}
// FIXME
public int execute(byte[] buffer, int offset, int length) throws UnpackException
{
int noffset = super.execute(buffer, offset + this.offset, length);
this.offset = noffset - offset;
if(super.isFinished()) {
this.data = super.getData();
this.finished = true;
super.reset();
} else {
this.finished = false;
}
return noffset;
}
}

View File

@ -0,0 +1,29 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
public class UnpackException extends IOException {
public UnpackException() { }
public UnpackException(String s) {
super(s);
}
}

View File

@ -0,0 +1,66 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
import java.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 && !hasNext()) {
throw new NoSuchElementException();
}
have = false;
return data;
}
public void remove() {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,245 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.lang.Iterable;
import java.io.InputStream;
import java.io.IOException;
import java.util.Iterator;
import org.msgpack.impl.UnpackerImpl;
public class 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() {
this(DEFAULT_BUFFER_SIZE);
}
public Unpacker(int bufferReserveSize) {
this(null, bufferReserveSize);
}
public Unpacker(InputStream stream) {
this(stream, DEFAULT_BUFFER_SIZE);
}
public Unpacker(InputStream stream, int bufferReserveSize) {
super();
this.used = 0;
this.offset = 0;
this.parsed = 0;
this.buffer = new byte[bufferReserveSize];
this.bufferReserveSize = bufferReserveSize/2;
this.stream = stream;
}
public Unpacker useSchema(Schema s) {
super.setSchema(s);
return this;
}
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;
}
*/
}

View File

@ -0,0 +1,483 @@
package org.msgpack.impl;
import java.nio.ByteBuffer;
//import java.math.BigInteger;
import org.msgpack.*;
import org.msgpack.schema.GenericSchema;
import org.msgpack.schema.IMapSchema;
import org.msgpack.schema.IArraySchema;
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;
private int cs;
private int trail;
private int top;
private int[] stack_ct = new int[MAX_STACK_SIZE];
private int[] stack_count = new int[MAX_STACK_SIZE];
private Object[] stack_obj = new Object[MAX_STACK_SIZE];
private Schema[] stack_schema = new Schema[MAX_STACK_SIZE];
private int top_ct;
private int top_count;
private Object top_obj;
private Schema top_schema;
private ByteBuffer castBuffer = ByteBuffer.allocate(8);
private boolean finished = false;
private Object data = null;
private static final Schema GENERIC_SCHEMA = new GenericSchema();
private Schema rootSchema;
protected UnpackerImpl()
{
setSchema(GENERIC_SCHEMA);
}
protected void setSchema(Schema schema)
{
this.rootSchema = schema;
reset();
}
protected Object getData()
{
return data;
}
protected boolean isFinished()
{
return finished;
}
protected void reset()
{
cs = CS_HEADER;
top = -1;
finished = false;
data = null;
top_ct = 0;
top_count = 0;
top_obj = null;
top_schema = rootSchema;
}
@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 = top_schema.createFromByte((byte)b);
break _push;
}
if((b & 0xe0) == 0xe0) { // Negative Fixnum
//System.out.println("negative fixnum "+b);
obj = top_schema.createFromByte((byte)b);
break _push;
}
if((b & 0xe0) == 0xa0) { // FixRaw
trail = b & 0x1f;
if(trail == 0) {
obj = top_schema.createFromRaw(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");
}
if(!(top_schema instanceof IArraySchema)) {
throw new RuntimeException("type error");
}
count = b & 0x0f;
//System.out.println("fixarray count:"+count);
obj = new Object[count];
if(count == 0) { break _push; } // FIXME check IArraySchema
++top;
stack_obj[top] = top_obj;
stack_ct[top] = top_ct;
stack_count[top] = top_count;
stack_schema[top] = top_schema;
top_obj = obj;
top_ct = CT_ARRAY_ITEM;
top_count = count;
top_schema = ((IArraySchema)top_schema).getElementSchema(0);
break _header_again;
}
if((b & 0xf0) == 0x80) { // FixMap
if(top >= MAX_STACK_SIZE) {
throw new UnpackException("parse error");
}
if(!(top_schema instanceof IMapSchema)) {
throw new RuntimeException("type error");
}
count = b & 0x0f;
obj = new Object[count*2];
if(count == 0) { break _push; } // FIXME check IMapSchema
//System.out.println("fixmap count:"+count);
++top;
stack_obj[top] = top_obj;
stack_ct[top] = top_ct;
stack_count[top] = top_count;
stack_schema[top] = top_schema;
top_obj = obj;
top_ct = CT_MAP_KEY;
top_count = count;
top_schema = ((IMapSchema)top_schema).getKeySchema();
break _header_again;
}
switch(b & 0xff) { // FIXME
case 0xc0: // nil
obj = top_schema.createFromNil();
break _push;
case 0xc2: // false
obj = top_schema.createFromBoolean(false);
break _push;
case 0xc3: // true
obj = top_schema.createFromBoolean(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");
}
} // _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 = top_schema.createFromFloat( castBuffer.getFloat(0) );
//System.out.println("float "+obj);
break _push;
case CS_DOUBLE:
castBuffer.rewind();
castBuffer.put(src, n, 8);
obj = top_schema.createFromDouble( castBuffer.getDouble(0) );
//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 = top_schema.createFromShort( (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 = top_schema.createFromInt( ((int)castBuffer.getShort(0)) & 0xffff );
//System.out.println("uint 16 "+obj);
break _push;
case CS_UINT_32:
castBuffer.rewind();
castBuffer.put(src, n, 4);
obj = top_schema.createFromLong( ((long)castBuffer.getInt(0)) & 0xffffffffL );
//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);
throw new UnpackException("uint 64 bigger than 0x7fffffff is not supported");
} else {
obj = top_schema.createFromLong( o );
}
}
break _push;
case CS_INT_8:
obj = top_schema.createFromByte( src[n] );
break _push;
case CS_INT_16:
castBuffer.rewind();
castBuffer.put(src, n, 2);
obj = top_schema.createFromShort( castBuffer.getShort(0) );
break _push;
case CS_INT_32:
castBuffer.rewind();
castBuffer.put(src, n, 4);
obj = top_schema.createFromInt( castBuffer.getInt(0) );
break _push;
case CS_INT_64:
castBuffer.rewind();
castBuffer.put(src, n, 8);
obj = top_schema.createFromLong( castBuffer.getLong(0) );
break _push;
case CS_RAW_16:
castBuffer.rewind();
castBuffer.put(src, n, 2);
trail = ((int)castBuffer.getShort(0)) & 0xffff;
if(trail == 0) {
obj = top_schema.createFromRaw(new byte[0], 0, 0);
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 = top_schema.createFromRaw(new byte[0], 0, 0);
break _push;
}
cs = ACS_RAW_VALUE;
case ACS_RAW_VALUE:
obj = top_schema.createFromRaw(src, n, trail);
break _push;
case CS_ARRAY_16:
if(top >= MAX_STACK_SIZE) {
throw new UnpackException("parse error");
}
if(!(top_schema instanceof IArraySchema)) {
throw new RuntimeException("type error");
}
castBuffer.rewind();
castBuffer.put(src, n, 2);
count = ((int)castBuffer.getShort(0)) & 0xffff;
obj = new Object[count];
if(count == 0) { break _push; } // FIXME check IArraySchema
++top;
stack_obj[top] = top_obj;
stack_ct[top] = top_ct;
stack_count[top] = top_count;
stack_schema[top] = top_schema;
top_obj = obj;
top_ct = CT_ARRAY_ITEM;
top_count = count;
top_schema = ((IArraySchema)top_schema).getElementSchema(0);
break _header_again;
case CS_ARRAY_32:
if(top >= MAX_STACK_SIZE) {
throw new UnpackException("parse error");
}
if(!(top_schema instanceof IArraySchema)) {
throw new RuntimeException("type error");
}
castBuffer.rewind();
castBuffer.put(src, n, 4);
// FIXME overflow check
count = castBuffer.getInt(0) & 0x7fffffff;
obj = new Object[count];
if(count == 0) { break _push; } // FIXME check IArraySchema
++top;
stack_obj[top] = top_obj;
stack_ct[top] = top_ct;
stack_count[top] = top_count;
stack_schema[top] = top_schema;
top_obj = obj;
top_ct = CT_ARRAY_ITEM;
top_count = count;
top_schema = ((IArraySchema)top_schema).getElementSchema(0);
break _header_again;
case CS_MAP_16:
if(top >= MAX_STACK_SIZE) {
throw new UnpackException("parse error");
}
if(!(top_schema instanceof IMapSchema)) {
throw new RuntimeException("type error");
}
castBuffer.rewind();
castBuffer.put(src, n, 2);
count = ((int)castBuffer.getShort(0)) & 0xffff;
obj = new Object[count*2];
if(count == 0) { break _push; } // FIXME check IMapSchema
//System.out.println("fixmap count:"+count);
stack_obj[top] = top_obj;
stack_ct[top] = top_ct;
stack_count[top] = top_count;
stack_schema[top] = top_schema;
++top;
top_obj = obj;
top_ct = CT_MAP_KEY;
top_count = count;
top_schema = ((IMapSchema)top_schema).getKeySchema();
break _header_again;
case CS_MAP_32:
if(top >= MAX_STACK_SIZE) {
throw new UnpackException("parse error");
}
if(!(top_schema instanceof IMapSchema)) {
throw new RuntimeException("type error");
}
castBuffer.rewind();
castBuffer.put(src, n, 4);
// FIXME overflow check
count = castBuffer.getInt(0) & 0x7fffffff;
obj = new Object[count*2];
if(count == 0) { break _push; } // FIXME check IMapSchema
//System.out.println("fixmap count:"+count);
++top;
stack_obj[top] = top_obj;
stack_ct[top] = top_ct;
stack_count[top] = top_count;
stack_schema[top] = top_schema;
top_obj = obj;
top_ct = CT_MAP_KEY;
top_count = count;
top_schema = ((IMapSchema)top_schema).getKeySchema();
break _header_again;
default:
throw new UnpackException("parse error");
}
} // _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(top_ct) {
case CT_ARRAY_ITEM: {
//System.out.println("array item "+obj);
Object[] ar = (Object[])top_obj;
ar[ar.length - top_count] = obj;
if(--top_count == 0) {
top_obj = stack_obj[top];
top_ct = stack_ct[top];
top_count = stack_count[top];
top_schema = stack_schema[top];
obj = ((IArraySchema)top_schema).createFromArray(ar);
stack_obj[top] = null;
stack_schema[top] = null;
--top;
break _push;
} else {
top_schema = ((IArraySchema)stack_schema[top]).getElementSchema(ar.length - top_count);
}
break _header_again;
}
case CT_MAP_KEY: {
//System.out.println("map key:"+top+" "+obj);
Object[] mp = (Object[])top_obj;
mp[mp.length - top_count*2] = obj;
top_ct = CT_MAP_VALUE;
top_schema = ((IMapSchema)stack_schema[top]).getValueSchema();
break _header_again;
}
case CT_MAP_VALUE: {
//System.out.println("map value:"+top+" "+obj);
Object[] mp = (Object[])top_obj;
mp[mp.length - top_count*2 + 1] = obj;
if(--top_count == 0) {
top_obj = stack_obj[top];
top_ct = stack_ct[top];
top_count = stack_count[top];
top_schema = stack_schema[top];
obj = ((IMapSchema)top_schema).createFromMap(mp);
stack_obj[top] = null;
stack_schema[top] = null;
--top;
break _push;
}
top_ct = CT_MAP_KEY;
break _header_again;
}
default:
throw new UnpackException("parse error");
}
} // _push
} while(true);
} // _header_again
cs = CS_HEADER;
++i;
} while(i < limit); // _out
return i;
}
}

View File

@ -0,0 +1,125 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.RandomAccess;
import java.io.IOException;
import org.msgpack.*;
public class ArraySchema extends Schema implements IArraySchema {
private Schema elementSchema;
public ArraySchema(Schema elementSchema)
{
super("array");
this.elementSchema = elementSchema;
}
@Override
public String getFullName()
{
return "List<"+elementSchema.getFullName()+">";
}
@Override
public String getExpression()
{
return "(array "+elementSchema.getExpression()+")";
}
@Override
@SuppressWarnings("unchecked")
public void pack(Packer pk, Object obj) throws IOException
{
if(obj instanceof List) {
ArrayList<Object> d = (ArrayList<Object>)obj;
pk.packArray(d.size());
if(obj instanceof RandomAccess) {
for(int i=0; i < d.size(); ++i) {
elementSchema.pack(pk, d.get(i));
}
} else {
for(Object e : d) {
elementSchema.pack(pk, e);
}
}
} else if(obj instanceof Set) {
Set<Object> d = (Set<Object>)obj;
pk.packArray(d.size());
for(Object e : d) {
elementSchema.pack(pk, e);
}
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
@SuppressWarnings("unchecked")
public Object convert(Object obj) throws MessageTypeException
{
if(obj instanceof List) {
List d = (List)obj;
ArrayList ar = new ArrayList(d.size());
if(obj instanceof RandomAccess) {
for(int i=0; i < d.size(); ++i) {
ar.add( elementSchema.convert(d.get(i)) );
}
} else {
for(Object e : d) {
ar.add( elementSchema.convert(e) );
}
}
return ar;
} else if(obj instanceof Collection) {
Collection d = (Collection)obj;
ArrayList ar = new ArrayList(d.size());
for(Object e : (Collection)obj) {
ar.add( elementSchema.convert(e) );
}
return ar;
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Schema getElementSchema(int index)
{
return elementSchema;
}
@Override
public Object createFromArray(Object[] obj)
{
return Arrays.asList(obj);
}
}

View File

@ -0,0 +1,89 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.io.IOException;
import org.msgpack.*;
public class ByteSchema extends Schema {
public ByteSchema() {
super("Byte");
}
@Override
public String getExpression() {
return "byte";
}
@Override
public void pack(Packer pk, Object obj) throws IOException {
if(obj instanceof Number) {
pk.packByte( ((Number)obj).byteValue() );
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
if(obj instanceof Byte) {
return obj;
} else if(obj instanceof Number) {
return ((Number)obj).byteValue();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object createFromByte(byte v) {
return (byte)v;
}
@Override
public Object createFromShort(short v) {
return (byte)v;
}
@Override
public Object createFromInt(int v) {
return (byte)v;
}
@Override
public Object createFromLong(long v) {
return (byte)v;
}
@Override
public Object createFromFloat(float v) {
return (byte)v;
}
@Override
public Object createFromDouble(double v) {
return (byte)v;
}
}

View File

@ -0,0 +1,241 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
import java.io.File;
import java.io.Writer;
import org.msgpack.*;
public class ClassGenerator {
private ClassSchema schema;
private Writer writer;
private int indent;
private ClassGenerator(Writer writer) {
this.writer = writer;
this.indent = 0;
}
public static void write(Schema schema, Writer dest) throws IOException {
if(!(schema instanceof ClassSchema)) {
throw new RuntimeException("schema is not class schema");
}
ClassSchema cs = (ClassSchema)schema;
new ClassGenerator(dest).run(cs);
}
private void run(ClassSchema cs) throws IOException {
List<ClassSchema> subclasses = new ArrayList<ClassSchema>();
for(FieldSchema f : cs.getFields()) {
findSubclassSchema(subclasses, f.getSchema());
}
for(ClassSchema sub : subclasses) {
sub.setNamespace(cs.getNamespace());
sub.setImports(cs.getImports());
}
this.schema = cs;
writeHeader();
writeClass();
for(ClassSchema sub : subclasses) {
this.schema = sub;
writeSubclass();
}
writeFooter();
this.schema = null;
writer.flush();
}
private void findSubclassSchema(List<ClassSchema> dst, Schema s) {
if(s instanceof ClassSchema) {
ClassSchema cs = (ClassSchema)s;
if(!dst.contains(cs)) { dst.add(cs); }
for(FieldSchema f : cs.getFields()) {
findSubclassSchema(dst, f.getSchema());
}
} else if(s instanceof ArraySchema) {
ArraySchema as = (ArraySchema)s;
findSubclassSchema(dst, as.getElementSchema(0));
} else if(s instanceof MapSchema) {
MapSchema as = (MapSchema)s;
findSubclassSchema(dst, as.getKeySchema());
findSubclassSchema(dst, as.getValueSchema());
}
}
private void writeHeader() throws IOException {
if(schema.getNamespace() != null) {
line("package "+schema.getNamespace()+";");
line();
}
line("import java.util.*;");
line("import java.io.*;");
line("import org.msgpack.*;");
line("import org.msgpack.schema.ClassSchema;");
line("import org.msgpack.schema.FieldSchema;");
}
private void writeFooter() throws IOException {
line();
}
private void writeClass() throws IOException {
line();
line("public final class "+schema.getName()+" implements MessagePackable, MessageMergeable");
line("{");
pushIndent();
writeSchema();
writeMemberVariables();
writeMemberFunctions();
popIndent();
line("}");
}
private void writeSubclass() throws IOException {
line();
line("final class "+schema.getName()+" implements MessagePackable, MessageMergeable");
line("{");
pushIndent();
writeSchema();
writeMemberVariables();
writeMemberFunctions();
popIndent();
line("}");
}
private void writeSchema() throws IOException {
line("private static final ClassSchema _SCHEMA = (ClassSchema)Schema.load(\""+schema.getExpression()+"\");");
line("public static ClassSchema getSchema() { return _SCHEMA; }");
}
private void writeMemberVariables() throws IOException {
line();
for(FieldSchema f : schema.getFields()) {
line("public "+f.getSchema().getFullName()+" "+f.getName()+";");
}
}
private void writeMemberFunctions() throws IOException {
// void messagePack(Packer pk)
// boolean equals(Object obj)
// int hashCode()
// void set(int _index, Object _value)
// Object get(int _index);
// getXxx()
// setXxx(Xxx xxx)
writeConstructors();
writeAccessors();
writePackFunction();
writeMergeFunction();
writeFactoryFunction();
}
private void writeConstructors() throws IOException {
line();
line("public "+schema.getName()+"() { }");
}
private void writeAccessors() throws IOException {
// FIXME
//line();
//for(FieldSchema f : schema.getFields()) {
// line("");
//}
}
private void writePackFunction() throws IOException {
line();
line("@Override");
line("public void messagePack(Packer _pk) throws IOException");
line("{");
pushIndent();
line("_pk.packArray("+schema.getFields().length+");");
line("FieldSchema[] _fields = _SCHEMA.getFields();");
int i = 0;
for(FieldSchema f : schema.getFields()) {
line("_fields["+i+"].getSchema().pack(_pk, "+f.getName()+");");
++i;
}
popIndent();
line("}");
}
private void writeMergeFunction() throws IOException {
line();
line("@Override");
line("@SuppressWarnings(\"unchecked\")");
line("public void messageMerge(Object obj) throws MessageTypeException");
line("{");
pushIndent();
line("Object[] _source = ((List)obj).toArray();");
line("FieldSchema[] _fields = _SCHEMA.getFields();");
int i = 0;
for(FieldSchema f : schema.getFields()) {
line("if(_source.length <= "+i+") { return; } this."+f.getName()+" = ("+f.getSchema().getFullName()+")_fields["+i+"].getSchema().convert(_source["+i+"]);");
++i;
}
popIndent();
line("}");
}
private void writeFactoryFunction() throws IOException {
line();
line("@SuppressWarnings(\"unchecked\")");
line("public static "+schema.getName()+" createFromMessage(Object[] _message)");
line("{");
pushIndent();
line(schema.getName()+" _self = new "+schema.getName()+"();");
int i = 0;
for(FieldSchema f : schema.getFields()) {
line("if(_message.length <= "+i+") { return _self; } _self."+f.getName()+" = ("+f.getSchema().getFullName()+")_message["+i+"];");
++i;
}
line("return _self;");
popIndent();
line("}");
}
private void line(String str) throws IOException {
for(int i=0; i < indent; ++i) {
writer.write("\t");
}
writer.write(str+"\n");
}
private void line() throws IOException {
writer.write("\n");
}
private void pushIndent() {
indent += 1;
}
private void popIndent() {
indent -= 1;
}
}

View File

@ -0,0 +1,95 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.util.Arrays;
import java.util.List;
import org.msgpack.*;
public abstract class ClassSchema extends Schema implements IArraySchema {
protected FieldSchema[] fields;
protected List<String> imports;
protected String namespace;
protected String fqdn;
public ClassSchema(
String name, String namespace,
List<String> imports, List<FieldSchema> fields) {
super(name);
this.namespace = namespace;
this.imports = imports; // FIXME clone?
this.fields = new FieldSchema[fields.size()];
System.arraycopy(fields.toArray(), 0, this.fields, 0, fields.size());
if(namespace == null) {
this.fqdn = name;
} else {
this.fqdn = namespace+"."+name;
}
}
public final FieldSchema[] getFields() {
return fields;
}
String getNamespace() {
return namespace;
}
List<String> getImports() {
return imports;
}
void setNamespace(String namespace) {
this.namespace = namespace;
}
void setImports(List<String> imports) {
this.imports = imports; // FIXME clone?
}
//@Override
//public String getFullName()
//{
// if(namespace == null) {
// return getName();
// } else {
// return namespace+"."+getName();
// }
//}
@Override
public String getExpression() {
StringBuffer b = new StringBuffer();
b.append("(class ");
b.append(getName());
if(namespace != null) {
b.append(" (package "+namespace+")");
}
for(FieldSchema f : fields) {
b.append(" "+f.getExpression());
}
b.append(")");
return b.toString();
}
public boolean equals(SpecificClassSchema o) {
return (namespace != null ? namespace.equals(o.getNamespace()) : o.getNamespace() == null) &&
getName().equals(o.getName());
}
}

View File

@ -0,0 +1,84 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.io.IOException;
import org.msgpack.*;
public class DoubleSchema extends Schema {
public DoubleSchema() {
super("Double");
}
@Override
public String getExpression() {
return "double";
}
@Override
public void pack(Packer pk, Object obj) throws IOException {
if(obj instanceof Number) {
pk.packDouble( ((Number)obj).doubleValue() );
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
if(obj instanceof Double) {
return obj;
} else if(obj instanceof Number) {
return ((Number)obj).doubleValue();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object createFromByte(byte v) {
return (double)v;
}
@Override
public Object createFromShort(short v) {
return (double)v;
}
@Override
public Object createFromInt(int v) {
return (double)v;
}
@Override
public Object createFromFloat(float v) {
return (double)v;
}
@Override
public Object createFromDouble(double v) {
return (double)v;
}
}

View File

@ -0,0 +1,43 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import org.msgpack.Schema;
public class FieldSchema {
private String name;
private Schema schema;
public FieldSchema(String name, Schema schema) {
this.name = name;
this.schema = schema;
}
public final String getName() {
return name;
}
public final Schema getSchema() {
return schema;
}
public String getExpression() {
return "(field "+name+" "+schema.getExpression()+")";
}
}

View File

@ -0,0 +1,84 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.io.IOException;
import org.msgpack.*;
public class FloatSchema extends Schema {
public FloatSchema() {
super("Float");
}
@Override
public String getExpression() {
return "float";
}
@Override
public void pack(Packer pk, Object obj) throws IOException {
if(obj instanceof Number) {
pk.packFloat( ((Number)obj).floatValue() );
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
if(obj instanceof Float) {
return obj;
} else if(obj instanceof Number) {
return ((Number)obj).floatValue();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object createFromByte(byte v) {
return (float)v;
}
@Override
public Object createFromShort(short v) {
return (float)v;
}
@Override
public Object createFromInt(int v) {
return (float)v;
}
@Override
public Object createFromFloat(float v) {
return (float)v;
}
@Override
public Object createFromDouble(double v) {
return (float)v;
}
}

View File

@ -0,0 +1,91 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import org.msgpack.*;
public class GenericClassSchema extends ClassSchema {
public GenericClassSchema(
String name, String namespace,
List<String> imports, List<FieldSchema> fields) {
super(name, namespace, imports, fields);
}
@Override
@SuppressWarnings("unchecked")
public void pack(Packer pk, Object obj) throws IOException {
if(obj instanceof Map) {
Map d = (Map)obj;
pk.packArray(fields.length);
for(int i=0; i < fields.length; ++i) {
FieldSchema f = fields[i];
f.getSchema().pack(pk, d.get(f.getName()));
}
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
if(obj instanceof Collection) {
// FIXME optimize
return createFromArray( ((Collection)obj).toArray() );
} else if(obj instanceof Map) {
HashMap<String,Object> m = new HashMap<String,Object>(fields.length);
Map d = (Map)obj;
for(int i=0; i < fields.length; ++i) {
FieldSchema f = fields[i];
String fieldName = f.getName();
m.put(fieldName, f.getSchema().convert(d.get(fieldName)));
}
return m;
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
public Schema getElementSchema(int index) {
// FIXME check index < fields.length
return fields[index].getSchema();
}
public Object createFromArray(Object[] obj) {
HashMap<String,Object> m = new HashMap<String,Object>(fields.length);
int i=0;
for(; i < obj.length; ++i) {
m.put(fields[i].getName(), obj[i]);
}
for(; i < fields.length; ++i) {
m.put(fields[i].getName(), null);
}
return m;
}
}

View File

@ -0,0 +1,192 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.util.Arrays;
import java.util.List;
import java.util.HashMap;
import java.io.IOException;
import org.msgpack.*;
//import org.msgpack.generic.*;
public class GenericSchema extends Schema implements IArraySchema, IMapSchema {
public GenericSchema() {
super("Object");
}
@Override
public String getExpression() {
return "object";
}
@Override
public void pack(Packer pk, Object obj) throws IOException {
pk.pack(obj);
}
@Override
public Object convert(Object obj) throws MessageTypeException {
return obj;
}
@Override
public Schema getElementSchema(int index) {
return this;
}
@Override
public Schema getKeySchema() {
return this;
}
@Override
public Schema getValueSchema() {
return this;
}
@Override
public Object createFromNil() {
return null;
}
@Override
public Object createFromBoolean(boolean v) {
return v;
}
@Override
public Object createFromByte(byte v) {
return v;
}
@Override
public Object createFromShort(short v) {
return v;
}
@Override
public Object createFromInt(int v) {
return v;
}
@Override
public Object createFromLong(long v) {
return v;
}
@Override
public Object createFromFloat(float v) {
return v;
}
@Override
public Object createFromDouble(double v) {
return v;
}
@Override
public Object createFromRaw(byte[] b, int offset, int length) {
byte[] bytes = new byte[length];
System.arraycopy(b, offset, bytes, 0, length);
return bytes;
}
@Override
public Object createFromArray(Object[] obj) {
return Arrays.asList(obj);
}
@Override
@SuppressWarnings("unchecked")
public Object createFromMap(Object[] obj) {
HashMap m = new HashMap(obj.length / 2);
int i = 0;
while(i < obj.length) {
Object k = obj[i++];
Object v = obj[i++];
m.put(k, v);
}
return m;
}
/*
@Override
public Object createFromNil() {
return null;
}
@Override
public Object createFromBoolean(boolean v) {
return new GenericBoolean(v);
}
@Override
public Object createFromFromByte(byte v) {
return new GenericByte(v);
}
@Override
public Object createFromShort(short v) {
return new GenericShort(v);
}
@Override
public Object createFromInt(int v) {
return new GenericInt(v);
}
@Override
public Object createFromLong(long v) {
return new GenericLong(v);
}
@Override
public Object createFromFloat(float v) {
return new GenericFloat(v);
}
@Override
public Object createFromDouble(double v) {
return new GenericDouble(v);
}
@Override
public Object createFromRaw(byte[] b, int offset, int length) {
return new GenericRaw(b, offset, length);
}
@Override
public Object createFromArray(Object[] obj) {
// FIXME GenericArray
return Arrays.asList(obj);
}
@Override
public Object createFromMap(Object[] obj) {
GenericMap m = new GenericMap(obj.length / 2);
int i = 0;
while(i < obj.length) {
Object k = obj[i++];
Object v = obj[i++];
m.put(k, v);
}
return m;
}
*/
}

View File

@ -0,0 +1,26 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import org.msgpack.Schema;
public interface IArraySchema {
public Schema getElementSchema(int index);
public Object createFromArray(Object[] obj);
}

View File

@ -0,0 +1,27 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import org.msgpack.Schema;
public interface IMapSchema {
public Schema getKeySchema();
public Schema getValueSchema();
public Object createFromMap(Object[] obj);
}

View File

@ -0,0 +1,89 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.io.IOException;
import org.msgpack.*;
public class IntSchema extends Schema {
public IntSchema() {
super("Integer");
}
@Override
public String getExpression() {
return "int";
}
@Override
public void pack(Packer pk, Object obj) throws IOException {
if(obj instanceof Number) {
pk.packInt( ((Number)obj).intValue() );
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
if(obj instanceof Integer) {
return obj;
} else if(obj instanceof Number) {
return ((Number)obj).intValue();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object createFromByte(byte v) {
return (int)v;
}
@Override
public Object createFromShort(short v) {
return (int)v;
}
@Override
public Object createFromInt(int v) {
return (int)v;
}
@Override
public Object createFromLong(long v) {
return (int)v;
}
@Override
public Object createFromFloat(float v) {
return (int)v;
}
@Override
public Object createFromDouble(double v) {
return (int)v;
}
}

View File

@ -0,0 +1,89 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.io.IOException;
import org.msgpack.*;
public class LongSchema extends Schema {
public LongSchema() {
super("Long");
}
@Override
public String getExpression() {
return "long";
}
@Override
public void pack(Packer pk, Object obj) throws IOException {
if(obj instanceof Number) {
pk.packLong( ((Number)obj).longValue() );
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
if(obj instanceof Long) {
return obj;
} else if(obj instanceof Number) {
return ((Number)obj).longValue();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object createFromByte(byte v) {
return (long)v;
}
@Override
public Object createFromShort(short v) {
return (long)v;
}
@Override
public Object createFromInt(int v) {
return (long)v;
}
@Override
public Object createFromLong(long v) {
return (long)v;
}
@Override
public Object createFromFloat(float v) {
return (long)v;
}
@Override
public Object createFromDouble(double v) {
return (long)v;
}
}

View File

@ -0,0 +1,102 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import org.msgpack.*;
public class MapSchema extends Schema implements IMapSchema {
private Schema keySchema;
private Schema valueSchema;
public MapSchema(Schema keySchema, Schema valueSchema) {
super("map");
this.keySchema = keySchema;
this.valueSchema = valueSchema;
}
@Override
public String getFullName() {
return "HashList<"+keySchema.getFullName()+", "+valueSchema.getFullName()+">";
}
@Override
public String getExpression() {
return "(map "+keySchema.getExpression()+" "+valueSchema.getExpression()+")";
}
@Override
@SuppressWarnings("unchecked")
public void pack(Packer pk, Object obj) throws IOException {
if(obj instanceof Map) {
Map<Object,Object> d = (Map<Object,Object>)obj;
pk.packMap(d.size());
for(Map.Entry<Object,Object> e : d.entrySet()) {
keySchema.pack(pk, e.getKey());
valueSchema.pack(pk, e.getValue());
}
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
@SuppressWarnings("unchecked")
public Object convert(Object obj) throws MessageTypeException {
if(obj instanceof Map) {
Map<Object,Object> d = (Map<Object,Object>)obj;
Map<Object,Object> m = new HashMap<Object,Object>();
for(Map.Entry<Object,Object> e : d.entrySet()) {
m.put(keySchema.convert(e.getKey()), valueSchema.convert(e.getValue()));
}
return m;
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Schema getKeySchema() {
return keySchema;
}
@Override
public Schema getValueSchema() {
return valueSchema;
}
@Override
public Object createFromMap(Object[] obj) {
HashMap m = new HashMap(obj.length / 2);
int i = 0;
while(i < obj.length) {
Object k = obj[i++];
Object v = obj[i++];
m.put(k, v);
}
return m;
}
}

View File

@ -0,0 +1,105 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.nio.ByteBuffer;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.msgpack.*;
public class RawSchema extends Schema {
public RawSchema() {
super("raw");
}
public String getFullName() {
return "byte[]";
}
@Override
public void pack(Packer pk, Object obj) throws IOException {
// FIXME instanceof GenericObject
if(obj instanceof byte[]) {
byte[] d = (byte[])obj;
pk.packRaw(d.length);
pk.packRawBody(d);
} else if(obj instanceof ByteBuffer) {
ByteBuffer d = (ByteBuffer)obj;
if(!d.hasArray()) {
throw MessageTypeException.invalidConvert(obj, this);
}
pk.packRaw(d.capacity());
pk.packRawBody(d.array(), d.position(), d.capacity());
} else if(obj instanceof String) {
try {
byte[] d = ((String)obj).getBytes("UTF-8");
pk.packRaw(d.length);
pk.packRawBody(d);
} catch (UnsupportedEncodingException e) {
throw MessageTypeException.invalidConvert(obj, this);
}
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
// FIXME instanceof GenericObject
if(obj instanceof byte[]) {
// FIXME copy?
//byte[] d = (byte[])obj;
//byte[] v = new byte[d.length];
//System.arraycopy(d, 0, v, 0, d.length);
//return v;
return obj;
} else if(obj instanceof ByteBuffer) {
ByteBuffer d = (ByteBuffer)obj;
byte[] v = new byte[d.capacity()];
int pos = d.position();
d.get(v);
d.position(pos);
return v;
} else if(obj instanceof String) {
try {
return ((String)obj).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw MessageTypeException.invalidConvert(obj, this);
}
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object createFromRaw(byte[] b, int offset, int length) {
byte[] d = new byte[length];
System.arraycopy(b, offset, d, 0, length);
return d;
}
}

View File

@ -0,0 +1,64 @@
package org.msgpack.schema;
import java.util.Arrays;
import java.util.List;
import java.lang.reflect.*;
import org.msgpack.*;
// FIXME
public abstract class ReflectionClassSchema extends ClassSchema {
private Constructor constructorCache;
public ReflectionClassSchema(String name, List<FieldSchema> fields, String namespace, List<String> imports) {
super(name, namespace, imports, fields);
}
/*
Schema getElementSchema(int index)
{
// FIXME check index < fields.length
fields[index].getSchema();
}
Object createFromArray(Object[] obj)
{
Object o = newInstance();
((MessageConvertable)o).messageConvert(obj);
return o;
}
Object newInstance()
{
if(constructorCache == null) {
cacheConstructor();
}
try {
return constructorCache.newInstance((Object[])null);
} catch (InvocationTargetException e) {
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
} catch (InstantiationException e) {
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
} catch (IllegalAccessException e) {
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
}
}
private void cacheConstructor()
{
try {
Class c = Class.forName(fqdn);
int index = 0;
for(SpecificFieldSchema f : fields) {
f.cacheField(c, index++);
}
constructorCache = c.getDeclaredConstructor((Class[])null);
constructorCache.setAccessible(true);
} catch(ClassNotFoundException e) {
throw new RuntimeException("class not found: "+fqdn);
} catch (NoSuchMethodException e) {
throw new RuntimeException("class not found: "+fqdn+": "+e.getMessage());
}
}
*/
}

View File

@ -0,0 +1,254 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import org.msgpack.*;
// FIXME exception class
public class SSchemaParser {
public static Schema parse(String source) {
return new SSchemaParser(false).run(source);
}
public static Schema load(String source) {
return new SSchemaParser(true).run(source);
}
private static abstract class SExp {
boolean isAtom() { return false; }
public String getAtom() { return null; }
boolean isTuple() { return false; }
public SExp getTuple(int i) { return null; }
public int size() { return 0; }
public boolean empty() { return size() == 0; }
Iterator<SExp> iterator(int offset) { return null; }
}
private static class SAtom extends SExp {
private String atom;
SAtom(String atom) { this.atom = atom; }
boolean isAtom() { return true; }
public String getAtom() { return atom; }
public String toString() { return atom; }
}
private static class STuple extends SExp {
private List<SExp> tuple;
STuple() { this.tuple = new ArrayList<SExp>(); }
public void add(SExp e) { tuple.add(e); }
boolean isTuple() { return true; }
public SExp getTuple(int i) { return tuple.get(i); }
public int size() { return tuple.size(); }
Iterator<SExp> iterator(int skip) {
Iterator<SExp> i = tuple.iterator();
for(int s=0; s < skip; ++s) { i.next(); }
return i;
}
public String toString() {
if(tuple.isEmpty()) { return "()"; }
Iterator<SExp> i = tuple.iterator();
StringBuffer o = new StringBuffer();
o.append("(").append(i.next());
while(i.hasNext()) { o.append(" ").append(i.next()); }
o.append(")");
return o.toString();
}
}
boolean specificClass;
private SSchemaParser(boolean specificClass) {
this.specificClass = specificClass;
}
private static Pattern pattern = Pattern.compile(
"(?:\\s+)|([\\(\\)]|[\\d\\w\\.]+)");
private Schema run(String source) {
Matcher m = pattern.matcher(source);
Stack<STuple> stack = new Stack<STuple>();
String token;
while(true) {
while(true) {
if(!m.find()) { throw new RuntimeException("unexpected end of file"); }
token = m.group(1);
if(token != null) { break; }
}
if(token.equals("(")) {
stack.push(new STuple());
} else if(token.equals(")")) {
STuple top = stack.pop();
if(stack.empty()) {
stack.push(top);
break;
}
stack.peek().add(top);
} else {
if(stack.empty()) {
throw new RuntimeException("unexpected token '"+token+"'");
}
stack.peek().add(new SAtom(token));
}
}
while(true) {
if(!m.find()) { break; }
token = m.group(1);
if(token != null) { throw new RuntimeException("unexpected token '"+token+"'"); }
}
return readType( stack.pop() );
}
private Schema readType(SExp exp) {
if(exp.isAtom()) {
String type = exp.getAtom();
if(type.equals("string")) {
return new StringSchema();
} else if(type.equals("raw")) {
return new RawSchema();
} else if(type.equals("byte")) {
return new ByteSchema();
} else if(type.equals("short")) {
return new ShortSchema();
} else if(type.equals("int")) {
return new IntSchema();
} else if(type.equals("long")) {
return new LongSchema();
} else if(type.equals("float")) {
return new FloatSchema();
} else if(type.equals("double")) {
return new DoubleSchema();
} else if(type.equals("object")) {
return new GenericSchema();
} else {
throw new RuntimeException("byte, short, int, long, float, double, raw, string or object is expected but got '"+type+"': "+exp);
}
} else {
String type = exp.getTuple(0).getAtom();
if(type.equals("class")) {
return parseClass(exp);
} else if(type.equals("array")) {
return parseArray(exp);
} else if(type.equals("map")) {
return parseMap(exp);
} else {
throw new RuntimeException("class, array or map is expected but got '"+type+"': "+exp);
}
}
}
private ClassSchema parseClass(SExp exp) {
if(exp.size() < 3 || !exp.getTuple(1).isAtom()) {
throw new RuntimeException("class is (class NAME CLASS_BODY): "+exp);
}
String namespace = null;
List<String> imports = new ArrayList<String>();
String name = exp.getTuple(1).getAtom();
List<FieldSchema> fields = new ArrayList<FieldSchema>();
for(Iterator<SExp> i=exp.iterator(2); i.hasNext();) {
SExp subexp = i.next();
if(!subexp.isTuple() || subexp.empty() || !subexp.getTuple(0).isAtom()) {
throw new RuntimeException("field, package or import is expected: "+subexp);
}
String type = subexp.getTuple(0).getAtom();
if(type.equals("field")) {
fields.add( parseField(subexp) );
} else if(type.equals("package")) {
if(namespace != null) {
throw new RuntimeException("duplicated package definition: "+subexp);
}
namespace = parseNamespace(subexp);
} else if(type.equals("import")) {
imports.add( parseImport(subexp) );
} else {
throw new RuntimeException("field, package or import is expected but got '"+type+"': "+subexp);
}
}
if(specificClass) {
return new SpecificClassSchema(name, namespace, imports, fields);
} else {
return new GenericClassSchema(name, namespace, imports, fields);
}
}
private ArraySchema parseArray(SExp exp) {
if(exp.size() != 2) {
throw new RuntimeException("array is (array ELEMENT_TYPE): "+exp);
}
Schema elementType = readType(exp.getTuple(1));
return new ArraySchema(elementType);
}
private MapSchema parseMap(SExp exp) {
if(exp.size() != 3 || !exp.getTuple(1).isAtom()) {
throw new RuntimeException("map is (map KEY_TYPE VALUE_TYPE): "+exp);
}
Schema keyType = readType(exp.getTuple(1));
Schema valueType = readType(exp.getTuple(2));
return new MapSchema(keyType, valueType);
}
private String parseNamespace(SExp exp) {
if(exp.size() != 2 || !exp.getTuple(1).isAtom()) {
throw new RuntimeException("package is (package NAME): "+exp);
}
String name = exp.getTuple(1).getAtom();
return name;
}
private String parseImport(SExp exp) {
if(exp.size() != 2 || !exp.getTuple(1).isAtom()) {
throw new RuntimeException("import is (import NAME): "+exp);
}
String name = exp.getTuple(1).getAtom();
return name;
}
private FieldSchema parseField(SExp exp) {
if(exp.size() != 3 || !exp.getTuple(1).isAtom()) {
throw new RuntimeException("field is (field NAME TYPE): "+exp);
}
String name = exp.getTuple(1).getAtom();
Schema type = readType(exp.getTuple(2));
return new FieldSchema(name, type);
}
}

View File

@ -0,0 +1,89 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.io.IOException;
import org.msgpack.*;
public class ShortSchema extends Schema {
public ShortSchema() {
super("Short");
}
@Override
public String getExpression() {
return "short";
}
@Override
public void pack(Packer pk, Object obj) throws IOException {
if(obj instanceof Number) {
pk.packShort( ((Number)obj).shortValue() );
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
if(obj instanceof Short) {
return obj;
} else if(obj instanceof Number) {
return ((Number)obj).shortValue();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object createFromByte(byte v) {
return (short)v;
}
@Override
public Object createFromShort(short v) {
return (short)v;
}
@Override
public Object createFromInt(int v) {
return (short)v;
}
@Override
public Object createFromLong(long v) {
return (short)v;
}
@Override
public Object createFromFloat(float v) {
return (short)v;
}
@Override
public Object createFromDouble(double v) {
return (short)v;
}
}

View File

@ -0,0 +1,122 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.util.Collection;
import java.util.List;
import java.lang.reflect.*;
import java.io.IOException;
import org.msgpack.*;
public class SpecificClassSchema extends ClassSchema {
private Class classCache;
private Method factoryCache;
private Constructor constructorCache;
public SpecificClassSchema(
String name, String namespace,
List<String> imports, List<FieldSchema> fields) {
super(name, namespace, imports, fields);
}
@Override
@SuppressWarnings("unchecked")
public void pack(Packer pk, Object obj) throws IOException {
if(obj == null) {
pk.packNil();
return;
}
if(classCache == null) {
cacheFactory();
}
if(classCache.isInstance(obj)) {
((MessagePackable)obj).messagePack(pk);
} else {
// FIXME Map<String,Object>
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
if(obj instanceof Collection) {
if(constructorCache == null) {
cacheConstructor();
}
try {
MessageMergeable o = (MessageMergeable)constructorCache.newInstance((Object[])null);
o.messageMerge(obj);
return o;
} catch (InvocationTargetException e) {
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
} catch (InstantiationException e) {
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
} catch (IllegalAccessException e) {
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
}
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
public Schema getElementSchema(int index) {
// FIXME check index < fields.length
return fields[index].getSchema();
}
public Object createFromArray(Object[] obj) {
if(factoryCache == null) {
cacheFactory();
}
try {
return factoryCache.invoke(null, new Object[]{obj});
} catch (InvocationTargetException e) {
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getCause());
} catch (IllegalAccessException e) {
throw new RuntimeException("can't instantiate "+fqdn+": "+e.getMessage());
}
}
@SuppressWarnings("unchecked")
private void cacheFactory() {
try {
classCache = Class.forName(fqdn);
factoryCache = classCache.getDeclaredMethod("createFromMessage", new Class[]{Object[].class});
factoryCache.setAccessible(true);
} catch(ClassNotFoundException e) {
throw new RuntimeException("class not found: "+fqdn);
} catch (NoSuchMethodException e) {
throw new RuntimeException("class not found: "+fqdn+": "+e.getMessage());
}
}
@SuppressWarnings("unchecked")
private void cacheConstructor() {
try {
classCache = Class.forName(fqdn);
constructorCache = classCache.getDeclaredConstructor((Class[])null);
constructorCache.setAccessible(true);
} catch(ClassNotFoundException e) {
throw new RuntimeException("class not found: "+fqdn);
} catch (NoSuchMethodException e) {
throw new RuntimeException("class not found: "+fqdn+": "+e.getMessage());
}
}
}

View File

@ -0,0 +1,111 @@
//
// MessagePack for Java
//
// Copyright (C) 2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.schema;
import java.nio.ByteBuffer;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.msgpack.*;
public class StringSchema extends Schema {
public StringSchema() {
super("string");
}
@Override
public String getFullName() {
return "String";
}
@Override
public void pack(Packer pk, Object obj) throws IOException {
// FIXME instanceof GenericObject
if(obj instanceof String) {
try {
byte[] d = ((String)obj).getBytes("UTF-8");
pk.packRaw(d.length);
pk.packRawBody(d);
} catch (UnsupportedEncodingException e) {
throw MessageTypeException.invalidConvert(obj, this);
}
} else if(obj instanceof byte[]) {
byte[] d = (byte[])obj;
pk.packRaw(d.length);
pk.packRawBody(d);
} else if(obj instanceof ByteBuffer) {
ByteBuffer d = (ByteBuffer)obj;
if(!d.hasArray()) {
throw MessageTypeException.invalidConvert(obj, this);
}
pk.packRaw(d.capacity());
pk.packRawBody(d.array(), d.position(), d.capacity());
} else if(obj == null) {
pk.packNil();
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object convert(Object obj) throws MessageTypeException {
// FIXME instanceof GenericObject
if(obj instanceof String) {
return obj;
} else if(obj instanceof byte[]) {
try {
return new String((byte[])obj, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw MessageTypeException.invalidConvert(obj, this);
}
} else if(obj instanceof ByteBuffer) {
ByteBuffer d = (ByteBuffer)obj;
try {
if(d.hasArray()) {
return new String(d.array(), d.position(), d.capacity(), "UTF-8");
} else {
byte[] v = new byte[d.capacity()];
int pos = d.position();
d.get(v);
d.position(pos);
return new String(v, "UTF-8");
}
} catch (UnsupportedEncodingException e) {
throw MessageTypeException.invalidConvert(obj, this);
}
} else {
throw MessageTypeException.invalidConvert(obj, this);
}
}
@Override
public Object createFromRaw(byte[] b, int offset, int length) {
try {
return new String(b, offset, length, "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
}

View File

@ -0,0 +1,38 @@
import java.io.*;
import java.util.*;
import org.msgpack.*;
import org.msgpack.schema.*;
public class Generate {
public static void main(String[] args) throws IOException
{
String source =
"(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)))"+
" )";
Schema schema = Schema.parse(source);
Writer output = new OutputStreamWriter(System.out);
ClassGenerator.write(schema, output);
}
}

View File

@ -0,0 +1,173 @@
package serializers.msgpack;
import java.util.*;
import java.io.*;
import org.msgpack.*;
import org.msgpack.schema.ClassSchema;
import org.msgpack.schema.FieldSchema;
public final class MediaContent implements MessagePackable, 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 List<Image> image;
public Media media;
public MediaContent() { }
@Override
public void messagePack(Packer _pk) throws IOException
{
_pk.packArray(2);
FieldSchema[] _fields = _SCHEMA.getFields();
_fields[0].getSchema().pack(_pk, image);
_fields[1].getSchema().pack(_pk, media);
}
@Override
@SuppressWarnings("unchecked")
public void messageMerge(Object obj) throws MessageTypeException
{
Object[] _source = ((List)obj).toArray();
FieldSchema[] _fields = _SCHEMA.getFields();
if(_source.length <= 0) { return; } this.image = (List<Image>)_fields[0].getSchema().convert(_source[0]);
if(_source.length <= 1) { return; } this.media = (Media)_fields[1].getSchema().convert(_source[1]);
}
@SuppressWarnings("unchecked")
public static MediaContent createFromMessage(Object[] _message)
{
MediaContent _self = new MediaContent();
if(_message.length <= 0) { return _self; } _self.image = (List<Image>)_message[0];
if(_message.length <= 1) { return _self; } _self.media = (Media)_message[1];
return _self;
}
}
final class Image implements MessagePackable, 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
{
_pk.packArray(5);
FieldSchema[] _fields = _SCHEMA.getFields();
_fields[0].getSchema().pack(_pk, uri);
_fields[1].getSchema().pack(_pk, title);
_fields[2].getSchema().pack(_pk, width);
_fields[3].getSchema().pack(_pk, height);
_fields[4].getSchema().pack(_pk, size);
}
@Override
@SuppressWarnings("unchecked")
public void messageMerge(Object obj) throws MessageTypeException
{
Object[] _source = ((List)obj).toArray();
FieldSchema[] _fields = _SCHEMA.getFields();
if(_source.length <= 0) { return; } this.uri = (String)_fields[0].getSchema().convert(_source[0]);
if(_source.length <= 1) { return; } this.title = (String)_fields[1].getSchema().convert(_source[1]);
if(_source.length <= 2) { return; } this.width = (Integer)_fields[2].getSchema().convert(_source[2]);
if(_source.length <= 3) { return; } this.height = (Integer)_fields[3].getSchema().convert(_source[3]);
if(_source.length <= 4) { return; } this.size = (Integer)_fields[4].getSchema().convert(_source[4]);
}
@SuppressWarnings("unchecked")
public static Image createFromMessage(Object[] _message)
{
Image _self = new Image();
if(_message.length <= 0) { return _self; } _self.uri = (String)_message[0];
if(_message.length <= 1) { return _self; } _self.title = (String)_message[1];
if(_message.length <= 2) { return _self; } _self.width = (Integer)_message[2];
if(_message.length <= 3) { return _self; } _self.height = (Integer)_message[3];
if(_message.length <= 4) { return _self; } _self.size = (Integer)_message[4];
return _self;
}
}
final class Media implements MessagePackable, 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 List<String> person;
public Integer player;
public String copyright;
public Media() { }
@Override
public void messagePack(Packer _pk) throws IOException
{
_pk.packArray(11);
FieldSchema[] _fields = _SCHEMA.getFields();
_fields[0].getSchema().pack(_pk, uri);
_fields[1].getSchema().pack(_pk, title);
_fields[2].getSchema().pack(_pk, width);
_fields[3].getSchema().pack(_pk, height);
_fields[4].getSchema().pack(_pk, format);
_fields[5].getSchema().pack(_pk, duration);
_fields[6].getSchema().pack(_pk, size);
_fields[7].getSchema().pack(_pk, bitrate);
_fields[8].getSchema().pack(_pk, person);
_fields[9].getSchema().pack(_pk, player);
_fields[10].getSchema().pack(_pk, copyright);
}
@Override
@SuppressWarnings("unchecked")
public void messageMerge(Object obj) throws MessageTypeException
{
Object[] _source = ((List)obj).toArray();
FieldSchema[] _fields = _SCHEMA.getFields();
if(_source.length <= 0) { return; } this.uri = (String)_fields[0].getSchema().convert(_source[0]);
if(_source.length <= 1) { return; } this.title = (String)_fields[1].getSchema().convert(_source[1]);
if(_source.length <= 2) { return; } this.width = (Integer)_fields[2].getSchema().convert(_source[2]);
if(_source.length <= 3) { return; } this.height = (Integer)_fields[3].getSchema().convert(_source[3]);
if(_source.length <= 4) { return; } this.format = (String)_fields[4].getSchema().convert(_source[4]);
if(_source.length <= 5) { return; } this.duration = (Long)_fields[5].getSchema().convert(_source[5]);
if(_source.length <= 6) { return; } this.size = (Long)_fields[6].getSchema().convert(_source[6]);
if(_source.length <= 7) { return; } this.bitrate = (Integer)_fields[7].getSchema().convert(_source[7]);
if(_source.length <= 8) { return; } this.person = (List<String>)_fields[8].getSchema().convert(_source[8]);
if(_source.length <= 9) { return; } this.player = (Integer)_fields[9].getSchema().convert(_source[9]);
if(_source.length <= 10) { return; } this.copyright = (String)_fields[10].getSchema().convert(_source[10]);
}
@SuppressWarnings("unchecked")
public static Media createFromMessage(Object[] _message)
{
Media _self = new Media();
if(_message.length <= 0) { return _self; } _self.uri = (String)_message[0];
if(_message.length <= 1) { return _self; } _self.title = (String)_message[1];
if(_message.length <= 2) { return _self; } _self.width = (Integer)_message[2];
if(_message.length <= 3) { return _self; } _self.height = (Integer)_message[3];
if(_message.length <= 4) { return _self; } _self.format = (String)_message[4];
if(_message.length <= 5) { return _self; } _self.duration = (Long)_message[5];
if(_message.length <= 6) { return _self; } _self.size = (Long)_message[6];
if(_message.length <= 7) { return _self; } _self.bitrate = (Integer)_message[7];
if(_message.length <= 8) { return _self; } _self.person = (List<String>)_message[8];
if(_message.length <= 9) { return _self; } _self.player = (Integer)_message[9];
if(_message.length <= 10) { return _self; } _self.copyright = (String)_message[10];
return _self;
}
}

View File

@ -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)))
)

View File

@ -0,0 +1,68 @@
package serializers.msgpack;
import java.io.*;
import java.util.*;
import org.msgpack.*;
import serializers.ObjectSerializer;
public class MessagePackDynamicSerializer implements ObjectSerializer<Object>
{
public String getName() {
return "msgpack-dynamic";
}
public Object create() throws Exception {
ArrayList media = new ArrayList(11);
media.add("http://javaone.com/keynote.mpg");
media.add("video/mpg4");
media.add("Javaone Keynote");
media.add(1234567L);
media.add(0);
ArrayList<String> person = new ArrayList<String>(2);
person.add("Bill Gates");
person.add("Steve Jobs");
media.add(person);
media.add(0);
media.add(0);
media.add(0);
media.add(123L);
media.add("");
ArrayList image1 = new ArrayList(5);
image1.add("http://javaone.com/keynote_large.jpg");
image1.add(0);
image1.add(0);
image1.add(2);
image1.add("Javaone Keynote");
ArrayList image2 = new ArrayList(5);
image2.add("http://javaone.com/keynote_thumbnail.jpg");
image2.add(0);
image2.add(0);
image2.add(1);
image2.add("Javaone Keynote");
ArrayList content = new ArrayList(2);
content.add(media);
ArrayList<Object> images = new ArrayList<Object>(2);
images.add(image1);
images.add(image2);
content.add(images);
return content;
}
public byte[] serialize(Object content) throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
Packer pk = new Packer(os);
pk.pack(content);
return os.toByteArray();
}
public Object deserialize(byte[] array) throws Exception {
UnbufferedUnpacker pac = new UnbufferedUnpacker();
pac.execute(array);
return (Object)pac.getData();
}
}

Some files were not shown because too many files have changed in this diff Show More