diff --git a/src/main/java/org/redkale/convert/pb/ProtobufByteBufferWriter.java b/src/main/java/org/redkale/convert/pb/ProtobufByteBufferWriter.java index 1ad4be233..2005ed064 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufByteBufferWriter.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufByteBufferWriter.java @@ -21,7 +21,7 @@ public class ProtobufByteBufferWriter extends ProtobufWriter { private int currBufIndex; public ProtobufByteBufferWriter(int features, boolean enumtostring, Supplier supplier) { - super((byte[]) null); + super(); this.features = features; this.enumtostring = enumtostring; this.supplier = supplier; @@ -37,30 +37,31 @@ public class ProtobufByteBufferWriter extends ProtobufWriter { @Override public final ProtobufWriter pollChild() { - ProtobufWriter rs = super.pollChild(); - this.delegate = null; - this.child = null; - rs.parent = null; - return rs; + ProtobufBytesWriter result = new ProtobufBytesWriter(); + return result.configFieldFunc(this); } @Override public final void offerChild(ProtobufWriter child) { - int total = child.length(); - ProtobufWriter next = child; + ProtobufBytesWriter bw = (ProtobufBytesWriter) child; + int total = bw.length(); + ProtobufBytesWriter next = bw; while ((next = next.child) != null) { total += next.length(); } writeLength(total); - writeTo(child.content(), 0, child.length()); - next = child; + writeTo(bw.content(), 0, bw.length()); + next = bw; while ((next = next.child) != null) { writeTo(next.content(), 0, next.length()); } - offerPool(child); } @Override + protected final void writeSelfLength(int value) { + this.writeLength(value); + } + public ByteBuffer[] toBuffers() { if (buffers == null) { return new ByteBuffer[0]; @@ -183,19 +184,4 @@ public class ProtobufByteBufferWriter extends ProtobufWriter { public String toString() { return Objects.toString(this); } - - @Override - public final ProtobufWriter clear() { - throw new UnsupportedOperationException("Not supported yet."); // 无需实现 - } - - @Override - public final byte[] toArray() { - return toByteArray().getBytes(); - } - - @Override - public final byte[] content() { - throw new UnsupportedOperationException("Not supported yet."); // 无需实现 - } } diff --git a/src/main/java/org/redkale/convert/pb/ProtobufBytesWriter.java b/src/main/java/org/redkale/convert/pb/ProtobufBytesWriter.java new file mode 100644 index 000000000..7ec6f314b --- /dev/null +++ b/src/main/java/org/redkale/convert/pb/ProtobufBytesWriter.java @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2016-2116 Redkale + * All rights reserved. + */ +package org.redkale.convert.pb; + +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.function.Consumer; +import org.redkale.convert.ConvertBytesHandler; +import static org.redkale.convert.pb.ProtobufWriter.CHILD_SIZE; +import org.redkale.util.ByteArray; +import org.redkale.util.ByteTuple; + +/** + * + * @author zhangjx + */ +public class ProtobufBytesWriter extends ProtobufWriter implements ByteTuple { + + private byte[] content; + + // 链表结构 + private ProtobufBytesWriter delegate; + + private ArrayDeque pool; + + protected ProtobufBytesWriter(byte[] bs) { + this.content = bs; + } + + ProtobufBytesWriter(byte[] bs, int count) { + this.content = bs; + this.count = count; + } + + public ProtobufBytesWriter() { + this(DEFAULT_SIZE); + } + + public ProtobufBytesWriter(int size) { + this.content = new byte[Math.max(size, DEFAULT_SIZE)]; + } + + public ProtobufBytesWriter(ByteTuple tuple) { + this.content = tuple.content(); + this.count = tuple.length(); + } + + @Override + protected boolean recycle() { + super.recycle(); + if (this.delegate != null && this.pool != null) { + ProtobufWriter s; + ProtobufWriter p = this.delegate; + do { + s = p; + p = p.parent; + offerPool(s); + } while (p != this); + } + this.delegate = null; + if (this.content.length > DEFAULT_SIZE) { + this.content = new byte[DEFAULT_SIZE]; + } + return true; + } + + private void offerPool(ProtobufWriter item) { + if (this.pool != null && this.pool.size() < CHILD_SIZE) { + item.recycle(); + this.pool.offer((ProtobufBytesWriter) item); + } + } + + @Override + public ProtobufWriter pollChild() { + Queue queue = this.pool; + if (queue == null) { + this.pool = new ArrayDeque<>(CHILD_SIZE); + queue = this.pool; + } + ProtobufBytesWriter result = queue.poll(); + if (result == null) { + result = new ProtobufBytesWriter(new byte[256], 0); + } + if (delegate == null) { + result.parent = this; + this.child = result; + delegate = result; + } else { + result.parent = delegate; + delegate.child = result; + delegate = result; + } + result.configFieldFunc(result.parent); + return result; + } + + @Override + public void offerChild(ProtobufWriter child) { + if (child != null) { + int len = child.length(); + ProtobufWriter next = child; + while ((next = next.child) != null) { + len += next.length(); + } + child.parent.writeSelfLength(len); + } + } + + @Override + protected final void writeSelfLength(int value) { + ProtobufBytesWriter old = this.delegate; + this.delegate = null; + if (value < 128) { + writeTo((byte) value); + } else { + writeUInt32(value); + } + this.delegate = old; + } + + /** + * 将本对象的内容引用复制给array + * + * @param array ByteArray + */ + public void directTo(ByteArray array) { + array.directFrom(content, count); + } + + public void completed(ConvertBytesHandler handler, Consumer callback) { + handler.completed(content, 0, count, callback, this); + } + + @Override + public byte[] toArray() { + if (delegate == null) { + byte[] copy = new byte[count]; + System.arraycopy(content, 0, copy, 0, count); + return copy; + } else { + int total = count; + ProtobufBytesWriter next = this; + while ((next = next.child) != null) { + total += next.length(); + } + byte[] data = new byte[total]; + System.arraycopy(content, 0, data, 0, count); + next = this; + int pos = count; + while ((next = next.child) != null) { + System.arraycopy(next.content(), 0, data, pos, next.length()); + pos += next.length(); + } + return data; + } + } + + @Override + protected int expand(int len) { + int newcount = count + len; + if (newcount > content.length) { + byte[] newdata = new byte[Math.max(content.length * 2, newcount)]; + System.arraycopy(content, 0, newdata, 0, count); + this.content = newdata; + } + return 0; + } + + @Override + public void writeTo(final byte ch) { + if (delegate == null) { + expand(1); + content[count++] = ch; + } else { + delegate.writeTo(ch); + } + } + + @Override + public void writeTo(final byte[] chs, final int start, final int len) { + if (delegate == null) { + expand(len); + System.arraycopy(chs, start, content, count, len); + count += len; + } else { + delegate.writeTo(chs, start, len); + } + } + + @Override + protected void writeUInt32(int value) { + if (value >= 0 && value < TENTHOUSAND_MAX) { + writeTo(TENTHOUSAND_UINT_BYTES[value]); + return; + } else if (value < 0 && value > TENTHOUSAND_MAX) { + writeTo(TENTHOUSAND_UINT_BYTES2[-value]); + return; + } + if (delegate == null) { + expand(5); + int curr = this.count; + byte[] data = this.content; + while (true) { + if ((value & ~0x7F) == 0) { + data[curr++] = (byte) value; + this.count = curr; + return; + } else { + data[curr++] = (byte) ((value & 0x7F) | 0x80); + value >>>= 7; + } + } + } else { + delegate.writeUInt32(value); + } + } + + @Override + protected void writeUInt64(long value) { + if (value >= 0 && value < TENTHOUSAND_MAX) { + writeTo(TENTHOUSAND_UINT_BYTES[(int) value]); + return; + } else if (value < 0 && value > TENTHOUSAND_MAX) { + writeTo(TENTHOUSAND_UINT_BYTES2[(int) -value]); + return; + } + if (delegate == null) { + expand(10); + int curr = this.count; + byte[] data = this.content; + while (true) { + if ((value & ~0x7FL) == 0) { + data[curr++] = (byte) value; + this.count = curr; + return; + } else { + data[curr++] = (byte) (((int) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } else { + delegate.writeUInt64(value); + } + } + + @Override + public byte[] content() { + return content; + } + + @Override + public int offset() { + return 0; + } +} diff --git a/src/main/java/org/redkale/convert/pb/ProtobufConvert.java b/src/main/java/org/redkale/convert/pb/ProtobufConvert.java index 3ae1d8d99..a1bd68ba1 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufConvert.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufConvert.java @@ -27,7 +27,8 @@ import org.redkale.util.*; */ public class ProtobufConvert extends BinaryConvert { - private final ThreadLocal writerPool = Utility.withInitialThreadLocal(ProtobufWriter::new); + private final ThreadLocal writerPool = + Utility.withInitialThreadLocal(ProtobufBytesWriter::new); private final Consumer writerConsumer = this::offerWriter; @@ -105,7 +106,8 @@ public class ProtobufConvert extends BinaryConvert S configWrite(S writer) { - return (S) writer.configWrite(); + writer.withFeatures(features).enumtostring(((ProtobufFactory) factory).enumtostring); + return writer; } public ProtobufByteBufferWriter pollProtobufWriter(final Supplier supplier) { @@ -117,21 +119,21 @@ public class ProtobufConvert extends BinaryConvert pool; - - protected ProtobufWriter(byte[] bs) { - this.content = bs; - } - - private ProtobufWriter(byte[] bs, int count) { - this.content = bs; - this.count = count; - } - - public ProtobufWriter() { - this(DEFAULT_SIZE); - } - - public ProtobufWriter(int size) { - this.content = new byte[Math.max(size, DEFAULT_SIZE)]; - } - - public ProtobufWriter(ByteTuple tuple) { - this.content = tuple.content(); - this.count = tuple.length(); - } + protected ProtobufWriter() {} @Override public final ProtobufWriter withFeatures(int features) { @@ -105,10 +78,6 @@ public class ProtobufWriter extends Writer implements ByteTuple { return this; } - protected final ProtobufWriter configWrite() { - return this; - } - protected final ProtobufWriter configFieldFunc(ProtobufWriter out) { this.mapFieldFunc = out.mapFieldFunc; this.objFieldFunc = out.objFieldFunc; @@ -126,172 +95,47 @@ public class ProtobufWriter extends Writer implements ByteTuple { return objExtFunc; } + public ProtobufWriter enumtostring(boolean enumtostring) { + this.enumtostring = enumtostring; + return this; + } + @Override protected boolean recycle() { super.recycle(); - if (this.delegate != null && this.pool != null) { - ProtobufWriter s; - ProtobufWriter p = this.delegate; - do { - s = p; - p = p.parent; - offerPool(s); - } while (p != this); - } - this.parent = null; this.child = null; - this.delegate = null; + this.parent = null; this.mapFieldFunc = null; this.objFieldFunc = null; this.objExtFunc = null; this.features = 0; this.enumtostring = false; this.count = 0; - if (this.content.length > DEFAULT_SIZE) { - this.content = new byte[DEFAULT_SIZE]; - } return true; } - protected final void offerPool(ProtobufWriter item) { - if (this.pool != null && this.pool.size() < CHILD_SIZE) { - item.recycle(); - this.pool.offer(item); - } - } + public abstract ProtobufWriter pollChild(); - public ProtobufWriter pollChild() { - Queue queue = this.pool; - if (queue == null) { - this.pool = new ArrayDeque<>(CHILD_SIZE); - queue = this.pool; - } - ProtobufWriter result = queue.poll(); - if (result == null) { - result = new ProtobufWriter(new byte[256], 0); - } - if (delegate == null) { - result.parent = this; - this.child = result; - delegate = result; - } else { - result.parent = delegate; - delegate.child = result; - delegate = result; - } - result.configFieldFunc(result.parent); - return result; - } + public abstract void offerChild(ProtobufWriter child); - public void offerChild(ProtobufWriter child) { - if (child != null) { - int len = child.length(); - ProtobufWriter next = child; - while ((next = next.child) != null) { - len += next.length(); - } - child.parent.writeSelfLength(len); - } - } + protected abstract int expand(int len); - @Override - public final int length() { - return count; - } + public abstract void writeTo(final byte ch); - @Override - public byte[] content() { - return content; - } + public abstract void writeTo(final byte[] chs, final int start, final int len); - @Override - public final int offset() { - return 0; - } + protected abstract void writeSelfLength(int value); - /** - * 将本对象的内容引用复制给array - * - * @param array ByteArray - */ - public void directTo(ByteArray array) { - array.directFrom(content, count); - } + protected abstract void writeUInt32(int value); - public ByteBuffer[] toBuffers() { - return new ByteBuffer[] {ByteBuffer.wrap(content, 0, count)}; - } - - public void completed(ConvertBytesHandler handler, Consumer callback) { - handler.completed(content, 0, count, callback, this); - } - - @Override - public byte[] toArray() { - if (delegate == null) { - byte[] copy = new byte[count]; - System.arraycopy(content, 0, copy, 0, count); - return copy; - } else { - int total = count; - ProtobufWriter next = this; - while ((next = next.child) != null) { - total += next.length(); - } - byte[] data = new byte[total]; - System.arraycopy(content, 0, data, 0, count); - next = this; - int pos = count; - while ((next = next.child) != null) { - System.arraycopy(next.content(), 0, data, pos, next.length()); - pos += next.length(); - } - return data; - } - } - - public ProtobufWriter enumtostring(boolean enumtostring) { - this.enumtostring = enumtostring; - return this; - } - - protected int expand(int len) { - int newcount = count + len; - if (newcount > content.length) { - byte[] newdata = new byte[Math.max(content.length * 2, newcount)]; - System.arraycopy(content, 0, newdata, 0, count); - this.content = newdata; - } - return 0; - } - - public void writeTo(final byte ch) { - if (delegate == null) { - expand(1); - content[count++] = ch; - } else { - delegate.writeTo(ch); - } - } + protected abstract void writeUInt64(long value); public final void writeTo(final byte... chs) { writeTo(chs, 0, chs.length); } - public void writeTo(final byte[] chs, final int start, final int len) { - if (delegate == null) { - expand(len); - System.arraycopy(chs, start, content, count, len); - count += len; - } else { - delegate.writeTo(chs, start, len); - } - } - - public ProtobufWriter clear() { - this.count = 0; - this.delegate = null; - return this; + public final int length() { + return count; } @Override @@ -1212,71 +1056,6 @@ public class ProtobufWriter extends Writer implements ByteTuple { } } - protected final void writeSelfLength(int value) { - ProtobufWriter old = this.delegate; - this.delegate = null; - if (value < 128) { - writeTo((byte) value); - } else { - writeUInt32(value); - } - this.delegate = old; - } - - protected void writeUInt32(int value) { - if (value >= 0 && value < TENTHOUSAND_MAX) { - writeTo(TENTHOUSAND_UINT_BYTES[value]); - return; - } else if (value < 0 && value > TENTHOUSAND_MAX) { - writeTo(TENTHOUSAND_UINT_BYTES2[-value]); - return; - } - if (delegate == null) { - expand(5); - int curr = this.count; - byte[] data = this.content; - while (true) { - if ((value & ~0x7F) == 0) { - data[curr++] = (byte) value; - this.count = curr; - return; - } else { - data[curr++] = (byte) ((value & 0x7F) | 0x80); - value >>>= 7; - } - } - } else { - delegate.writeUInt32(value); - } - } - - protected void writeUInt64(long value) { - if (value >= 0 && value < TENTHOUSAND_MAX) { - writeTo(TENTHOUSAND_UINT_BYTES[(int) value]); - return; - } else if (value < 0 && value > TENTHOUSAND_MAX) { - writeTo(TENTHOUSAND_UINT_BYTES2[(int) -value]); - return; - } - if (delegate == null) { - expand(10); - int curr = this.count; - byte[] data = this.content; - while (true) { - if ((value & ~0x7FL) == 0) { - data[curr++] = (byte) value; - this.count = curr; - return; - } else { - data[curr++] = (byte) (((int) value & 0x7F) | 0x80); - value >>>= 7; - } - } - } else { - delegate.writeUInt64(value); - } - } - protected final void writeFixed32(int value) { if (value >= 0 && value < TENTHOUSAND_MAX) { writeTo(TENTHOUSAND_FIXED32_BYTES[value]);