java: redesign

This commit is contained in:
frsyuki 2010-05-20 03:49:26 +09:00
parent 6cde9f3a9d
commit 979ff80982
14 changed files with 864 additions and 258 deletions

View File

@ -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 */

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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

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

View File

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

View File

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

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

View File

@ -237,5 +237,5 @@ public class TestPackUnpack {
System.out.println("Got unexpected class: " + obj.getClass());
assertTrue(false);
}
}
}
};