mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-24 17:49:45 +01:00
java: redesign
This commit is contained in:
parent
6cde9f3a9d
commit
979ff80982
@ -51,6 +51,14 @@ inline void operator<< (object::with_zone& o, type::nil v)
|
||||
{ static_cast<object&>(o) << v; }
|
||||
|
||||
|
||||
template <>
|
||||
inline void object::as<void>() const
|
||||
{
|
||||
msgpack::type::nil v;
|
||||
convert(&v);
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/type/nil.hpp */
|
||||
|
384
java/src/main/java/org/msgpack/BufferedUnpackerImpl.java
Normal file
384
java/src/main/java/org/msgpack/BufferedUnpackerImpl.java
Normal file
@ -0,0 +1,384 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
//import java.math.BigInteger;
|
||||
|
||||
abstract class BufferedUnpackerImpl extends UnpackerImpl {
|
||||
int filled = 0;
|
||||
byte[] buffer = null;
|
||||
private ByteBuffer castBuffer = ByteBuffer.allocate(8);
|
||||
|
||||
abstract boolean fill() throws IOException;
|
||||
|
||||
final int next(int offset, UnpackResult result) throws IOException, UnpackException {
|
||||
if(filled == 0) {
|
||||
if(!fill()) {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
int noffset = super.execute(buffer, offset, filled);
|
||||
if(noffset <= offset) {
|
||||
if(!fill()) {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
offset = noffset;
|
||||
} while(!super.isFinished());
|
||||
|
||||
Object obj = super.getData();
|
||||
super.reset();
|
||||
result.done(obj);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
private final void more(int offset, int require) throws IOException, UnpackException {
|
||||
while(filled - offset < require) {
|
||||
if(!fill()) {
|
||||
// FIXME
|
||||
throw new UnpackException("insufficient buffer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final byte unpackByte(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
int o = unpackInt(c, offset);
|
||||
if(0x7f < o || o < -0x80) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
return (byte)o;
|
||||
}
|
||||
|
||||
final short unpackShort(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
int o = unpackInt(c, offset);
|
||||
if(0x7fff < o || o < -0x8000) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
return (short)o;
|
||||
}
|
||||
|
||||
final int unpackInt(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
more(offset, 1);
|
||||
int b = buffer[offset];
|
||||
if((b & 0x80) == 0 || (b & 0xe0) == 0xe0) { // Fixnum
|
||||
return (int)b;
|
||||
}
|
||||
switch(b & 0xff) {
|
||||
case 0xcc: // unsigned int 8
|
||||
more(offset, 2);
|
||||
c.advance(2);
|
||||
return (int)((short)buffer[offset+1] & 0xff);
|
||||
case 0xcd: // unsigned int 16
|
||||
more(offset, 3);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 2);
|
||||
c.advance(3);
|
||||
return (int)((int)castBuffer.getShort(0) & 0xffff);
|
||||
case 0xce: // unsigned int 32
|
||||
more(offset, 5);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
{
|
||||
int o = castBuffer.getInt(0);
|
||||
if(o < 0) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
c.advance(5);
|
||||
return o;
|
||||
}
|
||||
case 0xcf: // unsigned int 64
|
||||
more(offset, 9);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 8);
|
||||
{
|
||||
long o = castBuffer.getLong(0);
|
||||
if(o < 0 || o > 0x7fffffffL) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
c.advance(9);
|
||||
return (int)o;
|
||||
}
|
||||
case 0xd0: // signed int 8
|
||||
more(offset, 2);
|
||||
c.advance(2);
|
||||
return (int)buffer[offset+1];
|
||||
case 0xd1: // signed int 16
|
||||
more(offset, 3);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 2);
|
||||
c.advance(3);
|
||||
return (int)castBuffer.getShort(0);
|
||||
case 0xd2: // signed int 32
|
||||
more(offset, 4);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
c.advance(4);
|
||||
return (int)castBuffer.getInt(0);
|
||||
case 0xd3: // signed int 64
|
||||
more(offset, 9);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 8);
|
||||
{
|
||||
long o = castBuffer.getLong(0);
|
||||
if(0x7fffffffL < o || o < -0x80000000L) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
c.advance(9);
|
||||
return (int)o;
|
||||
}
|
||||
default:
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
}
|
||||
|
||||
final long unpackLong(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
more(offset, 1);
|
||||
int b = buffer[offset];
|
||||
if((b & 0x80) == 0 || (b & 0xe0) == 0xe0) { // Fixnum
|
||||
return (long)b;
|
||||
}
|
||||
switch(b & 0xff) {
|
||||
case 0xcc: // unsigned int 8
|
||||
more(offset, 2);
|
||||
c.advance(2);
|
||||
return (long)((short)buffer[offset+1] & 0xff);
|
||||
case 0xcd: // unsigned int 16
|
||||
more(offset, 3);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 2);
|
||||
c.advance(3);
|
||||
return (long)((int)castBuffer.getShort(0) & 0xffff);
|
||||
case 0xce: // unsigned int 32
|
||||
more(offset, 5);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
c.advance(5);
|
||||
return ((long)castBuffer.getInt(0) & 0xffffffffL);
|
||||
case 0xcf: // unsigned int 64
|
||||
more(offset, 9);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 8);
|
||||
{
|
||||
long o = castBuffer.getLong(0);
|
||||
if(o < 0) {
|
||||
// FIXME
|
||||
throw new MessageTypeException("uint 64 bigger than 0x7fffffff is not supported");
|
||||
}
|
||||
c.advance(9);
|
||||
return o;
|
||||
}
|
||||
case 0xd0: // signed int 8
|
||||
more(offset, 2);
|
||||
c.advance(2);
|
||||
return (long)buffer[offset+1];
|
||||
case 0xd1: // signed int 16
|
||||
more(offset, 3);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 2);
|
||||
c.advance(3);
|
||||
return (long)castBuffer.getShort(0);
|
||||
case 0xd2: // signed int 32
|
||||
more(offset, 4);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
c.advance(4);
|
||||
return (long)castBuffer.getInt(0);
|
||||
case 0xd3: // signed int 64
|
||||
more(offset, 9);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 8);
|
||||
c.advance(9);
|
||||
return (long)castBuffer.getLong(0);
|
||||
default:
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
}
|
||||
|
||||
final float unpackFloat(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
more(offset, 1);
|
||||
int b = buffer[offset];
|
||||
switch(b & 0xff) {
|
||||
case 0xca: // float
|
||||
more(offset, 5);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
c.advance(5);
|
||||
return castBuffer.getFloat(0);
|
||||
case 0xcb: // double
|
||||
more(offset, 9);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 8);
|
||||
c.advance(9);
|
||||
// FIXME overflow check
|
||||
return (float)castBuffer.getDouble(0);
|
||||
default:
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
}
|
||||
|
||||
final double unpackDouble(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
more(offset, 1);
|
||||
int b = buffer[offset];
|
||||
switch(b & 0xff) {
|
||||
case 0xca: // float
|
||||
more(offset, 5);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
c.advance(5);
|
||||
return (double)castBuffer.getFloat(0);
|
||||
case 0xcb: // double
|
||||
more(offset, 9);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 8);
|
||||
c.advance(9);
|
||||
return castBuffer.getDouble(0);
|
||||
default:
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
}
|
||||
|
||||
final Object unpackNull(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
more(offset, 1);
|
||||
int b = buffer[offset] & 0xff;
|
||||
if(b != 0xc0) { // nil
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
c.advance(1);
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean unpackBoolean(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
more(offset, 1);
|
||||
int b = buffer[offset] & 0xff;
|
||||
if(b == 0xc2) { // false
|
||||
c.advance(1);
|
||||
return false;
|
||||
} else if(b == 0xc3) { // true
|
||||
c.advance(1);
|
||||
return true;
|
||||
} else {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
}
|
||||
|
||||
final int unpackArray(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
more(offset, 1);
|
||||
int b = buffer[offset];
|
||||
if((b & 0xf0) == 0x90) { // FixArray
|
||||
c.advance(1);
|
||||
return (int)(b & 0x0f);
|
||||
}
|
||||
switch(b & 0xff) {
|
||||
case 0xdc: // array 16
|
||||
more(offset, 3);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 2);
|
||||
c.advance(3);
|
||||
return (int)castBuffer.getShort(0) & 0xffff;
|
||||
case 0xdd: // array 32
|
||||
more(offset, 5);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
c.advance(5);
|
||||
// FIXME overflow check
|
||||
return castBuffer.getInt(0) & 0x7fffffff;
|
||||
default:
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
}
|
||||
|
||||
final int unpackMap(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
more(offset, 1);
|
||||
int b = buffer[offset];
|
||||
if((b & 0xf0) == 0x80) { // FixMap
|
||||
c.advance(1);
|
||||
return (int)(b & 0x0f);
|
||||
}
|
||||
switch(b & 0xff) {
|
||||
case 0xde: // map 16
|
||||
more(offset, 3);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 2);
|
||||
c.advance(3);
|
||||
return (int)castBuffer.getShort(0) & 0xffff;
|
||||
case 0xdf: // map 32
|
||||
more(offset, 5);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
c.advance(5);
|
||||
// FIXME overflow check
|
||||
return castBuffer.getInt(0) & 0x7fffffff;
|
||||
default:
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
}
|
||||
|
||||
final int unpackRaw(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
more(offset, 1);
|
||||
int b = buffer[offset];
|
||||
if((b & 0xe0) == 0xa0) { // FixRaw
|
||||
c.advance(1);
|
||||
return (int)(b & 0x0f);
|
||||
}
|
||||
switch(b & 0xff) {
|
||||
case 0xda: // raw 16
|
||||
more(offset, 3);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 2);
|
||||
c.advance(3);
|
||||
return (int)castBuffer.getShort(0) & 0xffff;
|
||||
case 0xdb: // raw 32
|
||||
more(offset, 5);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
c.advance(5);
|
||||
// FIXME overflow check
|
||||
return castBuffer.getInt(0) & 0x7fffffff;
|
||||
default:
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
}
|
||||
|
||||
final byte[] unpackRawBody(UnpackCursor c, int offset, int length) throws IOException, MessageTypeException {
|
||||
more(offset, length);
|
||||
byte[] bytes = new byte[length];
|
||||
System.arraycopy(buffer, offset, bytes, 0, length);
|
||||
c.advance(length);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
final String unpackString(UnpackCursor c, int offset) throws IOException, MessageTypeException {
|
||||
int length = unpackRaw(c, offset);
|
||||
offset = c.getOffset();
|
||||
more(offset, length);
|
||||
String s;
|
||||
try {
|
||||
s = new String(buffer, offset, length, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
c.advance(length);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
public interface MessageMergeable {
|
||||
public void messageMerge(Object obj) throws MessageTypeException;
|
||||
public interface MessageConvertable {
|
||||
public void messageConvert(Object obj) throws MessageTypeException;
|
||||
}
|
||||
|
@ -17,9 +17,7 @@
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class MessageTypeException extends IOException {
|
||||
public class MessageTypeException extends RuntimeException {
|
||||
public MessageTypeException() { }
|
||||
|
||||
public MessageTypeException(String s) {
|
||||
|
25
java/src/main/java/org/msgpack/MessageUnpackable.java
Normal file
25
java/src/main/java/org/msgpack/MessageUnpackable.java
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface MessageUnpackable {
|
||||
public void messageUnpack(Unpacker pk) throws IOException, MessageTypeException;
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ public class Packer {
|
||||
} else if(o instanceof Double) {
|
||||
return packDouble((Double)o);
|
||||
} else {
|
||||
throw new IOException("unknown object "+o+" ("+o.getClass()+")");
|
||||
throw new MessageTypeException("unknown object "+o+" ("+o.getClass()+")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,82 +0,0 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
96
java/src/main/java/org/msgpack/UnpackCursor.java
Normal file
96
java/src/main/java/org/msgpack/UnpackCursor.java
Normal file
@ -0,0 +1,96 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class UnpackCursor {
|
||||
private Unpacker pac;
|
||||
private int offset;
|
||||
|
||||
UnpackCursor(Unpacker pac, int offset)
|
||||
{
|
||||
this.pac = pac;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
final void advance(int length) {
|
||||
offset += length;
|
||||
}
|
||||
|
||||
final int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public byte unpackByte() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackByte(this, offset);
|
||||
}
|
||||
|
||||
public short unpackShort() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackShort(this, offset);
|
||||
}
|
||||
|
||||
public int unpackInt() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackInt(this, offset);
|
||||
}
|
||||
|
||||
public long unpackLong() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackLong(this, offset);
|
||||
}
|
||||
|
||||
public float unpackFloat() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackFloat(this, offset);
|
||||
}
|
||||
|
||||
public double unpackDouble() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackDouble(this, offset);
|
||||
}
|
||||
|
||||
public Object unpackNull() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackNull(this, offset);
|
||||
}
|
||||
|
||||
public boolean unpackBoolean() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackBoolean(this, offset);
|
||||
}
|
||||
|
||||
public int unpackArray() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackArray(this, offset);
|
||||
}
|
||||
|
||||
public int unpackMap() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackMap(this, offset);
|
||||
}
|
||||
|
||||
public int unpackRaw() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackRaw(this, offset);
|
||||
}
|
||||
|
||||
public byte[] unpackRawBody(int length) throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackRawBody(this, offset, length);
|
||||
}
|
||||
|
||||
public String unpackString() throws IOException, MessageTypeException {
|
||||
return pac.impl.unpackString(this, offset);
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
pac.setOffset(offset);
|
||||
}
|
||||
}
|
||||
|
@ -21,41 +21,27 @@ import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class UnpackIterator implements Iterator<Object> {
|
||||
public class UnpackIterator extends UnpackResult implements Iterator<Object> {
|
||||
private Unpacker pac;
|
||||
private boolean have;
|
||||
private Object data;
|
||||
|
||||
UnpackIterator(Unpacker pac) {
|
||||
super();
|
||||
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;
|
||||
}
|
||||
}
|
||||
return pac.next(this);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
if(!have && !hasNext()) {
|
||||
if(!finished && !hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
have = false;
|
||||
finished = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
42
java/src/main/java/org/msgpack/UnpackResult.java
Normal file
42
java/src/main/java/org/msgpack/UnpackResult.java
Normal file
@ -0,0 +1,42 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
public class UnpackResult {
|
||||
protected boolean finished = false;
|
||||
protected Object data = null;
|
||||
|
||||
public boolean isFinished() {
|
||||
return finished;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
finished = false;
|
||||
data = null;
|
||||
}
|
||||
|
||||
void done(Object obj) {
|
||||
finished = true;
|
||||
data = obj;
|
||||
}
|
||||
}
|
||||
|
@ -22,18 +22,43 @@ import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.nio.ByteBuffer;
|
||||
import org.msgpack.impl.UnpackerImpl;
|
||||
|
||||
public class Unpacker extends UnpackerImpl implements Iterable<Object> {
|
||||
public class Unpacker implements Iterable<Object> {
|
||||
|
||||
public static final int DEFAULT_BUFFER_SIZE = 32*1024;
|
||||
// buffer:
|
||||
// +---------------------------------------------+
|
||||
// | [object] | [obje| unparsed ... | unused ...|
|
||||
// +---------------------------------------------+
|
||||
// ^ parsed
|
||||
// ^ offset
|
||||
// ^ filled
|
||||
// ^ buffer.length
|
||||
|
||||
private static final int DEFAULT_BUFFER_SIZE = 32*1024;
|
||||
|
||||
protected int offset;
|
||||
protected int parsed;
|
||||
protected int bufferReserveSize;
|
||||
protected InputStream stream;
|
||||
|
||||
class BufferedUnpackerMixin extends BufferedUnpackerImpl {
|
||||
boolean fill() throws IOException {
|
||||
if(stream == null) {
|
||||
return false;
|
||||
}
|
||||
reserveBuffer(bufferReserveSize);
|
||||
int rl = stream.read(buffer, filled, buffer.length - filled);
|
||||
// equals: stream.read(getBuffer(), getBufferOffset(), getBufferCapacity());
|
||||
if(rl <= 0) {
|
||||
return false;
|
||||
}
|
||||
bufferConsumed(rl);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
final BufferedUnpackerMixin impl = new BufferedUnpackerMixin();
|
||||
|
||||
private int used;
|
||||
private int offset;
|
||||
private int parsed;
|
||||
private byte[] buffer;
|
||||
private int bufferReserveSize;
|
||||
private InputStream stream;
|
||||
|
||||
public Unpacker() {
|
||||
this(DEFAULT_BUFFER_SIZE);
|
||||
@ -48,67 +73,31 @@ public class Unpacker extends UnpackerImpl implements Iterable<Object> {
|
||||
}
|
||||
|
||||
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);
|
||||
impl.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 InputStream getStream() {
|
||||
return this.stream;
|
||||
}
|
||||
|
||||
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 setStream(InputStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public void feed(ByteBuffer buffer) {
|
||||
int length = buffer.remaining();
|
||||
if (length == 0) return;
|
||||
reserveBuffer(length);
|
||||
buffer.get(this.buffer, this.offset, length);
|
||||
buffer.get(impl.buffer, this.offset, length);
|
||||
bufferConsumed(length);
|
||||
}
|
||||
|
||||
@ -118,48 +107,116 @@ public class Unpacker extends UnpackerImpl implements Iterable<Object> {
|
||||
|
||||
public void feed(byte[] buffer, int offset, int length) {
|
||||
reserveBuffer(length);
|
||||
System.arraycopy(buffer, offset, this.buffer, this.offset, length);
|
||||
System.arraycopy(buffer, offset, impl.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;
|
||||
return impl.fill();
|
||||
}
|
||||
|
||||
public Iterator<Object> iterator() {
|
||||
return new UnpackIterator(this);
|
||||
}
|
||||
|
||||
public UnpackResult next() throws IOException, UnpackException {
|
||||
UnpackResult result = new UnpackResult();
|
||||
this.offset = impl.next(this.offset, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean next(UnpackResult result) throws IOException, UnpackException {
|
||||
this.offset = impl.next(this.offset, result);
|
||||
return result.isFinished();
|
||||
}
|
||||
|
||||
|
||||
public void reserveBuffer(int require) {
|
||||
if(impl.buffer == null) {
|
||||
int nextSize = (bufferReserveSize < require) ? require : bufferReserveSize;
|
||||
impl.buffer = new byte[nextSize];
|
||||
return;
|
||||
}
|
||||
|
||||
if(impl.buffer.length - impl.filled >= require) {
|
||||
return;
|
||||
}
|
||||
|
||||
int nextSize = impl.buffer.length * 2;
|
||||
int notParsed = impl.filled - this.offset;
|
||||
while(nextSize < require + notParsed) {
|
||||
nextSize *= 2;
|
||||
}
|
||||
|
||||
byte[] tmp = new byte[nextSize];
|
||||
System.arraycopy(impl.buffer, this.offset, tmp, 0, impl.filled - this.offset);
|
||||
|
||||
impl.buffer = tmp;
|
||||
impl.filled = notParsed;
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
public byte[] getBuffer() {
|
||||
return impl.buffer;
|
||||
}
|
||||
|
||||
public int getBufferOffset() {
|
||||
return impl.filled;
|
||||
}
|
||||
|
||||
public int getBufferCapacity() {
|
||||
return impl.buffer.length - impl.filled;
|
||||
}
|
||||
|
||||
public void bufferConsumed(int size) {
|
||||
impl.filled += size;
|
||||
}
|
||||
|
||||
public boolean execute() throws UnpackException {
|
||||
int noffset = super.execute(buffer, offset, used);
|
||||
int noffset = impl.execute(impl.buffer, offset, impl.filled);
|
||||
if(noffset <= offset) {
|
||||
return false;
|
||||
}
|
||||
parsed += noffset - offset;
|
||||
offset = noffset;
|
||||
return super.isFinished();
|
||||
return impl.isFinished();
|
||||
}
|
||||
|
||||
|
||||
public int execute(byte[] buffer) throws UnpackException {
|
||||
return execute(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
public int execute(byte[] buffer, int offset, int length) throws UnpackException {
|
||||
int noffset = impl.execute(buffer, offset + this.offset, length);
|
||||
this.offset = noffset - offset;
|
||||
if(impl.isFinished()) {
|
||||
impl.resetState();
|
||||
}
|
||||
return noffset;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return impl.isFinished();
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return super.getData();
|
||||
return impl.getData();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
parsed = 0;
|
||||
impl.reset();
|
||||
}
|
||||
|
||||
|
||||
public UnpackCursor begin()
|
||||
{
|
||||
return new UnpackCursor(this, offset);
|
||||
}
|
||||
|
||||
|
||||
public int getMessageSize() {
|
||||
return parsed - offset + used;
|
||||
return parsed - offset + impl.filled;
|
||||
}
|
||||
|
||||
public int getParsedSize() {
|
||||
@ -167,7 +224,7 @@ public class Unpacker extends UnpackerImpl implements Iterable<Object> {
|
||||
}
|
||||
|
||||
public int getNonParsedSize() {
|
||||
return used - offset;
|
||||
return impl.filled - offset;
|
||||
}
|
||||
|
||||
public void skipNonparsedBuffer(int size) {
|
||||
@ -175,80 +232,14 @@ public class Unpacker extends UnpackerImpl implements Iterable<Object> {
|
||||
}
|
||||
|
||||
public void removeNonparsedBuffer() {
|
||||
used = offset;
|
||||
impl.filled = 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
|
||||
void setOffset(int offset)
|
||||
{
|
||||
return unpack(ctx, buffer, 0, buffer.length);
|
||||
parsed += offset - this.offset;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.impl;
|
||||
package org.msgpack;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
//import java.math.BigInteger;
|
||||
@ -47,7 +47,7 @@ public class UnpackerImpl {
|
||||
static final int CT_MAP_KEY = 0x01;
|
||||
static final int CT_MAP_VALUE = 0x02;
|
||||
|
||||
static final int MAX_STACK_SIZE = 16;
|
||||
static final int MAX_STACK_SIZE = 32;
|
||||
|
||||
private int cs;
|
||||
private int trail;
|
||||
@ -67,41 +67,45 @@ public class UnpackerImpl {
|
||||
private static final Schema GENERIC_SCHEMA = new GenericSchema();
|
||||
private Schema rootSchema;
|
||||
|
||||
protected UnpackerImpl()
|
||||
public UnpackerImpl()
|
||||
{
|
||||
setSchema(GENERIC_SCHEMA);
|
||||
}
|
||||
|
||||
protected void setSchema(Schema schema)
|
||||
public void setSchema(Schema schema)
|
||||
{
|
||||
this.rootSchema = schema;
|
||||
reset();
|
||||
}
|
||||
|
||||
protected Object getData()
|
||||
public final Object getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
protected boolean isFinished()
|
||||
public final boolean isFinished()
|
||||
{
|
||||
return finished;
|
||||
}
|
||||
|
||||
protected void reset()
|
||||
{
|
||||
public final void resetState() {
|
||||
cs = CS_HEADER;
|
||||
top = -1;
|
||||
finished = false;
|
||||
data = null;
|
||||
top_ct = 0;
|
||||
top_count = 0;
|
||||
top_obj = null;
|
||||
top_schema = rootSchema;
|
||||
}
|
||||
|
||||
public final void reset()
|
||||
{
|
||||
resetState();
|
||||
finished = false;
|
||||
data = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected int execute(byte[] src, int off, int length) throws UnpackException
|
||||
public final int execute(byte[] src, int off, int length) throws UnpackException
|
||||
{
|
||||
if(off >= length) { return off; }
|
||||
|
154
java/src/test/java/org/msgpack/TestDirectConversion.java
Normal file
154
java/src/test/java/org/msgpack/TestDirectConversion.java
Normal file
@ -0,0 +1,154 @@
|
||||
package org.msgpack;
|
||||
|
||||
import org.msgpack.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class TestDirectConversion {
|
||||
private UnpackCursor prepareCursor(ByteArrayOutputStream out) {
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
Unpacker upk = new Unpacker(in);
|
||||
return upk.begin();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt() throws Exception {
|
||||
testInt(0);
|
||||
testInt(-1);
|
||||
testInt(1);
|
||||
testInt(Integer.MIN_VALUE);
|
||||
testInt(Integer.MAX_VALUE);
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < 1000; i++)
|
||||
testInt(rand.nextInt());
|
||||
}
|
||||
public void testInt(int val) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
new Packer(out).pack(val);
|
||||
UnpackCursor c = prepareCursor(out);
|
||||
assertEquals(val, c.unpackInt());
|
||||
c.commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFloat() throws Exception {
|
||||
testFloat((float)0.0);
|
||||
testFloat((float)-0.0);
|
||||
testFloat((float)1.0);
|
||||
testFloat((float)-1.0);
|
||||
testFloat((float)Float.MAX_VALUE);
|
||||
testFloat((float)Float.MIN_VALUE);
|
||||
testFloat((float)Float.NaN);
|
||||
testFloat((float)Float.NEGATIVE_INFINITY);
|
||||
testFloat((float)Float.POSITIVE_INFINITY);
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < 1000; i++)
|
||||
testFloat(rand.nextFloat());
|
||||
}
|
||||
public void testFloat(float val) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
new Packer(out).pack(val);
|
||||
UnpackCursor c = prepareCursor(out);
|
||||
float f = c.unpackFloat();
|
||||
if(Float.isNaN(val)) {
|
||||
assertTrue(Float.isNaN(f));
|
||||
} else {
|
||||
assertEquals(val, f, 10e-10);
|
||||
}
|
||||
c.commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDouble() throws Exception {
|
||||
testDouble((double)0.0);
|
||||
testDouble((double)-0.0);
|
||||
testDouble((double)1.0);
|
||||
testDouble((double)-1.0);
|
||||
testDouble((double)Double.MAX_VALUE);
|
||||
testDouble((double)Double.MIN_VALUE);
|
||||
testDouble((double)Double.NaN);
|
||||
testDouble((double)Double.NEGATIVE_INFINITY);
|
||||
testDouble((double)Double.POSITIVE_INFINITY);
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < 1000; i++)
|
||||
testDouble(rand.nextDouble());
|
||||
}
|
||||
public void testDouble(double val) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
new Packer(out).pack(val);
|
||||
UnpackCursor c = prepareCursor(out);
|
||||
double f = c.unpackDouble();
|
||||
if(Double.isNaN(val)) {
|
||||
assertTrue(Double.isNaN(f));
|
||||
} else {
|
||||
assertEquals(val, f, 10e-10);
|
||||
}
|
||||
c.commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNil() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
new Packer(out).packNil();
|
||||
UnpackCursor c = prepareCursor(out);
|
||||
assertEquals(null, c.unpackNull());
|
||||
c.commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoolean() throws Exception {
|
||||
testBoolean(false);
|
||||
testBoolean(true);
|
||||
}
|
||||
public void testBoolean(boolean val) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
new Packer(out).pack(val);
|
||||
UnpackCursor c = prepareCursor(out);
|
||||
assertEquals(val, c.unpackBoolean());
|
||||
c.commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString() throws Exception {
|
||||
testString("");
|
||||
testString("a");
|
||||
testString("ab");
|
||||
testString("abc");
|
||||
// small size string
|
||||
for (int i = 0; i < 100; i++) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int len = (int)Math.random() % 31 + 1;
|
||||
for (int j = 0; j < len; j++)
|
||||
sb.append('a' + ((int)Math.random()) & 26);
|
||||
testString(sb.toString());
|
||||
}
|
||||
// medium size string
|
||||
for (int i = 0; i < 100; i++) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int len = (int)Math.random() % 100 + (1 << 15);
|
||||
for (int j = 0; j < len; j++)
|
||||
sb.append('a' + ((int)Math.random()) & 26);
|
||||
testString(sb.toString());
|
||||
}
|
||||
// large size string
|
||||
for (int i = 0; i < 10; i++) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int len = (int)Math.random() % 100 + (1 << 31);
|
||||
for (int j = 0; j < len; j++)
|
||||
sb.append('a' + ((int)Math.random()) & 26);
|
||||
testString(sb.toString());
|
||||
}
|
||||
}
|
||||
public void testString(String val) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
new Packer(out).pack(val);
|
||||
UnpackCursor c = prepareCursor(out);
|
||||
assertEquals(val, c.unpackString());
|
||||
c.commit();
|
||||
}
|
||||
|
||||
// FIXME container types
|
||||
};
|
@ -237,5 +237,5 @@ public class TestPackUnpack {
|
||||
System.out.println("Got unexpected class: " + obj.getClass());
|
||||
assertTrue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user