This commit is contained in:
185
src/com/wentch/redkale/convert/bson/BsonByteBufferWriter.java
Normal file
185
src/com/wentch/redkale/convert/bson/BsonByteBufferWriter.java
Normal file
@@ -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<ByteBuffer> supplier;
|
||||||
|
|
||||||
|
private ByteBuffer[] buffers;
|
||||||
|
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
public BsonByteBufferWriter(Supplier<ByteBuffer> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.wentch.redkale.convert.*;
|
|||||||
import com.wentch.redkale.util.*;
|
import com.wentch.redkale.util.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BSON协议格式:
|
* BSON协议格式:
|
||||||
@@ -95,6 +96,28 @@ public final class BsonConvert extends Convert<BsonReader, BsonWriter> {
|
|||||||
factory.loadEncoder(type).convertTo(out, value);
|
factory.loadEncoder(type).convertTo(out, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> 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<ByteBuffer> 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) {
|
public void convertTo(final BsonWriter out, Object value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ import java.nio.*;
|
|||||||
*
|
*
|
||||||
* @author zhangjx
|
* @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);
|
private static final int defaultSize = Integer.getInteger("convert.bson.writer.buffer.defsize", 1024);
|
||||||
|
|
||||||
protected int count;
|
|
||||||
|
|
||||||
private byte[] content;
|
private byte[] content;
|
||||||
|
|
||||||
|
protected int count;
|
||||||
|
|
||||||
protected boolean tiny;
|
protected boolean tiny;
|
||||||
|
|
||||||
public static ObjectPool<BsonWriter> createPool(int max) {
|
public static ObjectPool<BsonWriter> createPool(int max) {
|
||||||
@@ -58,7 +58,7 @@ public final class BsonWriter implements Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTiny() {
|
public final boolean isTiny() {
|
||||||
return tiny;
|
return tiny;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ public final class BsonWriter implements Writer {
|
|||||||
* @param len
|
* @param len
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public byte[] expand(int len) {
|
private byte[] expand(int len) {
|
||||||
int newcount = count + len;
|
int newcount = count + len;
|
||||||
if (newcount <= content.length) return content;
|
if (newcount <= content.length) return content;
|
||||||
byte[] newdata = new byte[Math.max(content.length * 3 / 2, newcount)];
|
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;
|
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);
|
rewriteTo(position, (byte) (value >> 8), (byte) value);
|
||||||
return position + 2;
|
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));
|
rewriteTo(position, (byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
|
||||||
return position + 2;
|
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);
|
rewriteTo(position, (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
||||||
return position + 4;
|
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),
|
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);
|
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
||||||
return position + 8;
|
return position + 8;
|
||||||
@@ -128,15 +128,11 @@ public final class BsonWriter implements Writer {
|
|||||||
content[count++] = ch;
|
content[count++] = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(final byte... chs) {
|
public final void writeTo(final byte... chs) {
|
||||||
int len = chs.length;
|
writeTo(chs, 0, chs.length);
|
||||||
expand(len);
|
|
||||||
System.arraycopy(chs, 0, content, count, len);
|
|
||||||
count += len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(final byte[] chs, final int start, final int end) {
|
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||||
int len = end - start;
|
|
||||||
expand(len);
|
expand(len);
|
||||||
System.arraycopy(chs, start, content, count, len);
|
System.arraycopy(chs, start, content, count, len);
|
||||||
count += len;
|
count += len;
|
||||||
@@ -150,68 +146,59 @@ public final class BsonWriter implements Writer {
|
|||||||
return true;
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new String(content, 0, count);
|
return new String(content, 0, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
public final int count() {
|
||||||
|
return this.count;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeBoolean(boolean value) {
|
public final void writeBoolean(boolean value) {
|
||||||
writeTo(value ? (byte) 1 : (byte) 0);
|
writeTo(value ? (byte) 1 : (byte) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeByte(byte value) {
|
public final void writeByte(byte value) {
|
||||||
writeTo(value);
|
writeTo(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeChar(final char value) {
|
public final void writeChar(final char value) {
|
||||||
writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
|
writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeShort(short value) {
|
public final void writeShort(short value) {
|
||||||
writeTo((byte) (value >> 8), (byte) value);
|
writeTo((byte) (value >> 8), (byte) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeInt(int value) {
|
public final void writeInt(int value) {
|
||||||
writeTo((byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
writeTo((byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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),
|
writeTo((byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
|
||||||
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeFloat(float value) {
|
public final void writeFloat(float value) {
|
||||||
writeInt(Float.floatToIntBits(value));
|
writeInt(Float.floatToIntBits(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeDouble(double value) {
|
public final void writeDouble(double value) {
|
||||||
writeLong(Double.doubleToLongBits(value));
|
writeLong(Double.doubleToLongBits(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void wirteClassName(String clazz) {
|
public final void wirteClassName(String clazz) {
|
||||||
writeSmallString(clazz == null ? "" : clazz);
|
writeSmallString(clazz == null ? "" : clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +266,7 @@ public final class BsonWriter implements Writer {
|
|||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void writeSmallString(String value) {
|
public final void writeSmallString(String value) {
|
||||||
if (value.isEmpty()) {
|
if (value.isEmpty()) {
|
||||||
writeTo((byte) 0);
|
writeTo((byte) 0);
|
||||||
return;
|
return;
|
||||||
@@ -296,7 +283,7 @@ public final class BsonWriter implements Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeString(String value) {
|
public final void writeString(String value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
writeInt(Reader.SIGN_NULL);
|
writeInt(Reader.SIGN_NULL);
|
||||||
return;
|
return;
|
||||||
@@ -315,16 +302,16 @@ public final class BsonWriter implements Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeArrayB(int size) {
|
public final void writeArrayB(int size) {
|
||||||
writeInt(size);
|
writeInt(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeArrayMark() {
|
public final void writeArrayMark() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeArrayE() {
|
public final void writeArrayE() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -333,11 +320,11 @@ public final class BsonWriter implements Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeMapMark() {
|
public final void writeMapMark() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeMapE() {
|
public final void writeMapE() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,13 +40,14 @@ public final class JsonByteBufferWriter extends JsonWriter {
|
|||||||
protected boolean recycle() {
|
protected boolean recycle() {
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
this.buffers = null;
|
this.buffers = null;
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer[] toBuffers() {
|
public ByteBuffer[] toBuffers() {
|
||||||
if (buffers == null) return new ByteBuffer[0];
|
if (buffers == null) return new ByteBuffer[0];
|
||||||
for (int i = index; i < this.buffers.length; i++) {
|
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;
|
return this.buffers;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user