diff --git a/src/com/wentch/redkale/convert/bson/BsonByteBufferWriter.java b/src/com/wentch/redkale/convert/bson/BsonByteBufferWriter.java new file mode 100644 index 000000000..ac2356717 --- /dev/null +++ b/src/com/wentch/redkale/convert/bson/BsonByteBufferWriter.java @@ -0,0 +1,185 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.convert.bson; + +import java.nio.*; +import java.nio.charset.*; +import java.util.function.*; + +/** + * + * @author zhangjx + */ +public final class BsonByteBufferWriter extends BsonWriter { + + private static final Charset UTF8 = Charset.forName("UTF-8"); + + private final Supplier supplier; + + private ByteBuffer[] buffers; + + private int index; + + public BsonByteBufferWriter(Supplier supplier) { + this.supplier = supplier; + } + + public ByteBuffer[] toBuffers() { + if (buffers == null) return new ByteBuffer[0]; + for (int i = index; i < this.buffers.length; i++) { + ByteBuffer buf = this.buffers[i]; + if (buf.position() != 0) buf.flip(); + } + return this.buffers; + } + + @Override + public byte[] toArray() { + if (buffers == null) return new byte[0]; + int pos = 0; + byte[] bytes = new byte[this.count]; + for (ByteBuffer buf : toBuffers()) { + int r = buf.remaining(); + buf.get(bytes, pos, r); + buf.flip(); + pos += r; + } + return bytes; + } + + @Override + public ByteBuffer toBuffer() { + if (buffers == null) return null; + if (buffers.length == 1) return buffers[0]; + final ByteBuffer rs = ByteBuffer.allocate(count); + for (ByteBuffer buf : toBuffers()) { + rs.put(buf); + buf.flip(); + } + rs.flip(); + return rs; + } + + @Override + public void toBuffer(ByteBuffer buffer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public int toBuffer(int offset, ByteBuffer buffer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String toString() { + return "bytes[" + count() + "]"; + } + + @Override + public BsonByteBufferWriter setTiny(boolean tiny) { + this.tiny = tiny; + return this; + } + + @Override + public BsonByteBufferWriter fillRange(final int len) { + ByteBuffer buffer = this.buffers[index]; + if (expand(len) == 0) { + buffer.position(buffer.position() + len); + } else { + int remain = len; //还剩多少没有写 + while (remain > 0) { + final int br = buffer.remaining(); + if (remain > br) { //一个buffer写不完 + buffer.position(buffer.position() + br); + buffer = nextByteBuffer(); + remain -= br; + } else { + buffer.position(buffer.position() + remain); + remain = 0; + } + } + } + this.count += len; + return this; + } + + private int expand(final int byteLength) { + if (this.buffers == null) { + this.index = 0; + this.buffers = new ByteBuffer[]{supplier.get()}; + } + ByteBuffer buffer = this.buffers[index]; + if (!buffer.hasRemaining()) { + buffer.flip(); + buffer = supplier.get(); + ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1]; + System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length); + bufs[this.buffers.length] = buffer; + this.buffers = bufs; + this.index++; + } + int len = buffer.remaining(); + int size = 0; + while (len < byteLength) { + buffer = supplier.get(); + ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1]; + System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length); + bufs[this.buffers.length] = buffer; + this.buffers = bufs; + len += buffer.remaining(); + size++; + } + return size; + } + + @Override + public int rewriteTo(int position, byte... chs) { + return position += chs.length; + } + + @Override + public void writeTo(final byte[] chs, final int start, final int len) { + if (expand(len) == 0) { + this.buffers[index].put(chs, start, len); + } else { + ByteBuffer buffer = this.buffers[index]; + final int end = start + len; + int remain = len; //还剩多少没有写 + while (remain > 0) { + final int br = buffer.remaining(); + if (remain > br) { //一个buffer写不完 + buffer.put(chs, end - remain, br); + buffer = nextByteBuffer(); + remain -= br; + } else { + buffer.put(chs, end - remain, remain); + remain = 0; + } + } + } + this.count += len; + } + + private ByteBuffer nextByteBuffer() { + this.buffers[this.index].flip(); + return this.buffers[++this.index]; + } + + @Override + public void writeTo(final byte ch) { + expand(1); + this.buffers[index].put(ch); + count++; + } + + @Override + protected boolean recycle() { + this.index = 0; + this.buffers = null; + return false; + } +} diff --git a/src/com/wentch/redkale/convert/bson/BsonConvert.java b/src/com/wentch/redkale/convert/bson/BsonConvert.java index e69a90034..939a20231 100644 --- a/src/com/wentch/redkale/convert/bson/BsonConvert.java +++ b/src/com/wentch/redkale/convert/bson/BsonConvert.java @@ -9,6 +9,7 @@ import com.wentch.redkale.convert.*; import com.wentch.redkale.util.*; import java.lang.reflect.*; import java.nio.*; +import java.util.function.*; /** * BSON协议格式: @@ -95,6 +96,28 @@ public final class BsonConvert extends Convert { factory.loadEncoder(type).convertTo(out, value); } + public ByteBuffer[] convertTo(final Supplier supplier, final Type type, Object value) { + if (supplier == null || type == null) return null; + BsonByteBufferWriter out = new BsonByteBufferWriter(supplier); + if (value == null) { + out.writeNull(); + } else { + factory.loadEncoder(type).convertTo(out, value); + } + return out.toBuffers(); + } + + public ByteBuffer[] convertTo(final Supplier supplier, Object value) { + if (supplier == null) return null; + BsonByteBufferWriter out = new BsonByteBufferWriter(supplier); + if (value == null) { + out.writeNull(); + } else { + factory.loadEncoder(value.getClass()).convertTo(out, value); + } + return out.toBuffers(); + } + public void convertTo(final BsonWriter out, Object value) { if (value == null) { out.writeNull(); diff --git a/src/com/wentch/redkale/convert/bson/BsonWriter.java b/src/com/wentch/redkale/convert/bson/BsonWriter.java index eeb22efcd..16b86e3da 100644 --- a/src/com/wentch/redkale/convert/bson/BsonWriter.java +++ b/src/com/wentch/redkale/convert/bson/BsonWriter.java @@ -13,14 +13,14 @@ import java.nio.*; * * @author zhangjx */ -public final class BsonWriter implements Writer { +public class BsonWriter implements Writer { private static final int defaultSize = Integer.getInteger("convert.bson.writer.buffer.defsize", 1024); - protected int count; - private byte[] content; + protected int count; + protected boolean tiny; public static ObjectPool createPool(int max) { @@ -58,7 +58,7 @@ public final class BsonWriter implements Writer { } @Override - public boolean isTiny() { + public final boolean isTiny() { return tiny; } @@ -75,7 +75,7 @@ public final class BsonWriter implements Writer { * @param len * @return */ - public byte[] expand(int len) { + private byte[] expand(int len) { int newcount = count + len; if (newcount <= content.length) return content; byte[] newdata = new byte[Math.max(content.length * 3 / 2, newcount)]; @@ -96,22 +96,22 @@ public final class BsonWriter implements Writer { return position + chs.length; } - public int rewriteTo(int position, short value) { + public final int rewriteTo(int position, short value) { rewriteTo(position, (byte) (value >> 8), (byte) value); return position + 2; } - public int rewriteTo(int position, char value) { + public final int rewriteTo(int position, char value) { rewriteTo(position, (byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF)); return position + 2; } - public int rewriteTo(int position, int value) { + public final int rewriteTo(int position, int value) { rewriteTo(position, (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value); return position + 4; } - public int rewriteTo(int position, long value) { + public final int rewriteTo(int position, long value) { rewriteTo(position, (byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32), (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value); return position + 8; @@ -128,15 +128,11 @@ public final class BsonWriter implements Writer { content[count++] = ch; } - public void writeTo(final byte... chs) { - int len = chs.length; - expand(len); - System.arraycopy(chs, 0, content, count, len); - count += len; + public final void writeTo(final byte... chs) { + writeTo(chs, 0, chs.length); } - public void writeTo(final byte[] chs, final int start, final int end) { - int len = end - start; + public void writeTo(final byte[] chs, final int start, final int len) { expand(len); System.arraycopy(chs, start, content, count, len); count += len; @@ -150,68 +146,59 @@ public final class BsonWriter implements Writer { return true; } - //------------------------------------------------------------------------ - public int position() { - return this.count; - } - - public final int count() { - return this.count; - } - - public final void count(int count) { - if (count >= 0) this.count = count; - } - - //----------------------------------------------------------------------- @Override public String toString() { return new String(content, 0, count); } + //------------------------------------------------------------------------ + public final int count() { + return this.count; + } + @Override - public void writeBoolean(boolean value) { + public final void writeBoolean(boolean value) { writeTo(value ? (byte) 1 : (byte) 0); } @Override - public void writeByte(byte value) { + public final void writeByte(byte value) { writeTo(value); } @Override - public void writeChar(final char value) { + public final void writeChar(final char value) { writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF)); } @Override - public void writeShort(short value) { + public final void writeShort(short value) { writeTo((byte) (value >> 8), (byte) value); } @Override - public void writeInt(int value) { + public final void writeInt(int value) { writeTo((byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value); } @Override - public void writeLong(long value) { + public final void writeLong(long value) { writeTo((byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32), (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value); } @Override - public void writeFloat(float value) { + public final void writeFloat(float value) { writeInt(Float.floatToIntBits(value)); } @Override - public void writeDouble(double value) { + public final void writeDouble(double value) { writeLong(Double.doubleToLongBits(value)); } @Override - public void wirteClassName(String clazz) { + public final void wirteClassName(String clazz) { writeSmallString(clazz == null ? "" : clazz); } @@ -279,7 +266,7 @@ public final class BsonWriter implements Writer { * @param value */ @Override - public void writeSmallString(String value) { + public final void writeSmallString(String value) { if (value.isEmpty()) { writeTo((byte) 0); return; @@ -296,7 +283,7 @@ public final class BsonWriter implements Writer { } @Override - public void writeString(String value) { + public final void writeString(String value) { if (value == null) { writeInt(Reader.SIGN_NULL); return; @@ -315,16 +302,16 @@ public final class BsonWriter implements Writer { } @Override - public void writeArrayB(int size) { + public final void writeArrayB(int size) { writeInt(size); } @Override - public void writeArrayMark() { + public final void writeArrayMark() { } @Override - public void writeArrayE() { + public final void writeArrayE() { } @Override @@ -333,11 +320,11 @@ public final class BsonWriter implements Writer { } @Override - public void writeMapMark() { + public final void writeMapMark() { } @Override - public void writeMapE() { + public final void writeMapE() { } } diff --git a/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java b/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java index 864a28101..54a604956 100644 --- a/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java +++ b/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java @@ -40,13 +40,14 @@ public final class JsonByteBufferWriter extends JsonWriter { protected boolean recycle() { this.index = 0; this.buffers = null; - return true; + return false; } public ByteBuffer[] toBuffers() { if (buffers == null) return new ByteBuffer[0]; for (int i = index; i < this.buffers.length; i++) { - this.buffers[i].flip(); + ByteBuffer buf = this.buffers[i]; + if (buf.position() != 0) buf.flip(); } return this.buffers; }