ProtobufBytesWriter
This commit is contained in:
@@ -21,7 +21,7 @@ public class ProtobufByteBufferWriter extends ProtobufWriter {
|
|||||||
private int currBufIndex;
|
private int currBufIndex;
|
||||||
|
|
||||||
public ProtobufByteBufferWriter(int features, boolean enumtostring, Supplier<ByteBuffer> supplier) {
|
public ProtobufByteBufferWriter(int features, boolean enumtostring, Supplier<ByteBuffer> supplier) {
|
||||||
super((byte[]) null);
|
super();
|
||||||
this.features = features;
|
this.features = features;
|
||||||
this.enumtostring = enumtostring;
|
this.enumtostring = enumtostring;
|
||||||
this.supplier = supplier;
|
this.supplier = supplier;
|
||||||
@@ -37,30 +37,31 @@ public class ProtobufByteBufferWriter extends ProtobufWriter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final ProtobufWriter pollChild() {
|
public final ProtobufWriter pollChild() {
|
||||||
ProtobufWriter rs = super.pollChild();
|
ProtobufBytesWriter result = new ProtobufBytesWriter();
|
||||||
this.delegate = null;
|
return result.configFieldFunc(this);
|
||||||
this.child = null;
|
|
||||||
rs.parent = null;
|
|
||||||
return rs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void offerChild(ProtobufWriter child) {
|
public final void offerChild(ProtobufWriter child) {
|
||||||
int total = child.length();
|
ProtobufBytesWriter bw = (ProtobufBytesWriter) child;
|
||||||
ProtobufWriter next = child;
|
int total = bw.length();
|
||||||
|
ProtobufBytesWriter next = bw;
|
||||||
while ((next = next.child) != null) {
|
while ((next = next.child) != null) {
|
||||||
total += next.length();
|
total += next.length();
|
||||||
}
|
}
|
||||||
writeLength(total);
|
writeLength(total);
|
||||||
writeTo(child.content(), 0, child.length());
|
writeTo(bw.content(), 0, bw.length());
|
||||||
next = child;
|
next = bw;
|
||||||
while ((next = next.child) != null) {
|
while ((next = next.child) != null) {
|
||||||
writeTo(next.content(), 0, next.length());
|
writeTo(next.content(), 0, next.length());
|
||||||
}
|
}
|
||||||
offerPool(child);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
protected final void writeSelfLength(int value) {
|
||||||
|
this.writeLength(value);
|
||||||
|
}
|
||||||
|
|
||||||
public ByteBuffer[] toBuffers() {
|
public ByteBuffer[] toBuffers() {
|
||||||
if (buffers == null) {
|
if (buffers == null) {
|
||||||
return new ByteBuffer[0];
|
return new ByteBuffer[0];
|
||||||
@@ -183,19 +184,4 @@ public class ProtobufByteBufferWriter extends ProtobufWriter {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return Objects.toString(this);
|
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."); // 无需实现
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
258
src/main/java/org/redkale/convert/pb/ProtobufBytesWriter.java
Normal file
258
src/main/java/org/redkale/convert/pb/ProtobufBytesWriter.java
Normal file
@@ -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<ProtobufBytesWriter> 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<ProtobufBytesWriter> 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<ProtobufWriter> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,8 @@ import org.redkale.util.*;
|
|||||||
*/
|
*/
|
||||||
public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWriter> {
|
public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWriter> {
|
||||||
|
|
||||||
private final ThreadLocal<ProtobufWriter> writerPool = Utility.withInitialThreadLocal(ProtobufWriter::new);
|
private final ThreadLocal<ProtobufBytesWriter> writerPool =
|
||||||
|
Utility.withInitialThreadLocal(ProtobufBytesWriter::new);
|
||||||
|
|
||||||
private final Consumer<ProtobufWriter> writerConsumer = this::offerWriter;
|
private final Consumer<ProtobufWriter> writerConsumer = this::offerWriter;
|
||||||
|
|
||||||
@@ -105,7 +106,8 @@ public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWrite
|
|||||||
// ------------------------------ writer -----------------------------------------------------------
|
// ------------------------------ writer -----------------------------------------------------------
|
||||||
@Override
|
@Override
|
||||||
protected <S extends ProtobufWriter> S configWrite(S writer) {
|
protected <S extends ProtobufWriter> S configWrite(S writer) {
|
||||||
return (S) writer.configWrite();
|
writer.withFeatures(features).enumtostring(((ProtobufFactory) factory).enumtostring);
|
||||||
|
return writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProtobufByteBufferWriter pollProtobufWriter(final Supplier<ByteBuffer> supplier) {
|
public ProtobufByteBufferWriter pollProtobufWriter(final Supplier<ByteBuffer> supplier) {
|
||||||
@@ -117,21 +119,21 @@ public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWrite
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProtobufWriter pollWriter() {
|
public ProtobufBytesWriter pollWriter() {
|
||||||
ProtobufWriter writer = writerPool.get();
|
ProtobufBytesWriter writer = writerPool.get();
|
||||||
if (writer == null) {
|
if (writer == null) {
|
||||||
writer = new ProtobufWriter();
|
writer = new ProtobufBytesWriter();
|
||||||
} else {
|
} else {
|
||||||
writerPool.set(null);
|
writerPool.set(null);
|
||||||
}
|
}
|
||||||
return configWrite(writer.withFeatures(features).enumtostring(((ProtobufFactory) factory).enumtostring));
|
return configWrite(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void offerWriter(final ProtobufWriter out) {
|
public void offerWriter(final ProtobufWriter out) {
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
out.recycle();
|
out.recycle();
|
||||||
writerPool.set(out);
|
writerPool.set((ProtobufBytesWriter) out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,14 +668,14 @@ public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWrite
|
|||||||
@Override
|
@Override
|
||||||
public byte[] convertTo(final Type type, final Object value) {
|
public byte[] convertTo(final Type type, final Object value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
final ProtobufWriter writer = pollWriter();
|
final ProtobufBytesWriter writer = pollWriter();
|
||||||
writer.writeNull();
|
writer.writeNull();
|
||||||
byte[] result = writer.toArray();
|
byte[] result = writer.toArray();
|
||||||
offerWriter(writer);
|
offerWriter(writer);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
final Type t = type == null ? value.getClass() : type;
|
final Type t = type == null ? value.getClass() : type;
|
||||||
final ProtobufWriter writer = pollWriter();
|
final ProtobufBytesWriter writer = pollWriter();
|
||||||
Encodeable encoder = this.lastEncodeable;
|
Encodeable encoder = this.lastEncodeable;
|
||||||
if (encoder == null || encoder.getType() != t) {
|
if (encoder == null || encoder.getType() != t) {
|
||||||
encoder = factory.loadEncoder(t);
|
encoder = factory.loadEncoder(t);
|
||||||
@@ -699,7 +701,7 @@ public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWrite
|
|||||||
if (type == null) {
|
if (type == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final ProtobufWriter writer = pollWriter();
|
final ProtobufBytesWriter writer = pollWriter();
|
||||||
Encodeable encoder = this.lastEncodeable;
|
Encodeable encoder = this.lastEncodeable;
|
||||||
if (encoder == null || encoder.getType() != type) {
|
if (encoder == null || encoder.getType() != type) {
|
||||||
encoder = factory.loadEncoder(type);
|
encoder = factory.loadEncoder(type);
|
||||||
@@ -727,7 +729,7 @@ public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWrite
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler) {
|
public void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler) {
|
||||||
final ProtobufWriter writer = pollWriter();
|
final ProtobufBytesWriter writer = pollWriter();
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
writer.writeNull();
|
writer.writeNull();
|
||||||
} else {
|
} else {
|
||||||
@@ -751,9 +753,7 @@ public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWrite
|
|||||||
@Override
|
@Override
|
||||||
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
|
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
|
||||||
Objects.requireNonNull(array);
|
Objects.requireNonNull(array);
|
||||||
final ProtobufWriter writer = configWrite(new ProtobufWriter(array)
|
final ProtobufBytesWriter writer = configWrite(new ProtobufBytesWriter(array));
|
||||||
.withFeatures(features)
|
|
||||||
.enumtostring(((ProtobufFactory) factory).enumtostring));
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
writer.writeNull();
|
writer.writeNull();
|
||||||
} else {
|
} else {
|
||||||
@@ -825,7 +825,7 @@ public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWrite
|
|||||||
writer.writeNull();
|
writer.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
writer.configWrite();
|
configWrite(writer);
|
||||||
final Type t = type == null ? value.getClass() : type;
|
final Type t = type == null ? value.getClass() : type;
|
||||||
Encodeable encoder = this.lastEncodeable;
|
Encodeable encoder = this.lastEncodeable;
|
||||||
if (encoder == null || encoder.getType() != t) {
|
if (encoder == null || encoder.getType() != t) {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package org.redkale.convert.pb;
|
package org.redkale.convert.pb;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
@@ -17,13 +16,14 @@ import org.redkale.convert.*;
|
|||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/** @author zhangjx */
|
/** @author zhangjx */
|
||||||
public class ProtobufWriter extends Writer implements ByteTuple {
|
public abstract class ProtobufWriter extends Writer {
|
||||||
|
|
||||||
private static final int DEFAULT_SIZE = Integer.getInteger(
|
protected static final int DEFAULT_SIZE = Integer.getInteger(
|
||||||
"redkale.convert.protobuf.writer.buffer.defsize",
|
"redkale.convert.protobuf.writer.buffer.defsize",
|
||||||
Integer.getInteger("redkale.convert.writer.buffer.defsize", 1024));
|
Integer.getInteger("redkale.convert.writer.buffer.defsize", 1024));
|
||||||
|
|
||||||
private static final int CHILD_SIZE = 32;
|
protected static final int CHILD_SIZE = 32;
|
||||||
|
|
||||||
protected static final byte[] EMPTY_BYTES = new byte[0];
|
protected static final byte[] EMPTY_BYTES = new byte[0];
|
||||||
|
|
||||||
protected static final int TENTHOUSAND_MAX = 10001;
|
protected static final int TENTHOUSAND_MAX = 10001;
|
||||||
@@ -68,36 +68,9 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
|||||||
|
|
||||||
protected ProtobufWriter parent;
|
protected ProtobufWriter parent;
|
||||||
|
|
||||||
protected ProtobufWriter child;
|
protected ProtobufBytesWriter child;
|
||||||
|
|
||||||
// 链表结构
|
protected ProtobufWriter() {}
|
||||||
protected ProtobufWriter delegate;
|
|
||||||
|
|
||||||
private byte[] content;
|
|
||||||
|
|
||||||
private ArrayDeque<ProtobufWriter> 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final ProtobufWriter withFeatures(int features) {
|
public final ProtobufWriter withFeatures(int features) {
|
||||||
@@ -105,10 +78,6 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final ProtobufWriter configWrite() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final ProtobufWriter configFieldFunc(ProtobufWriter out) {
|
protected final ProtobufWriter configFieldFunc(ProtobufWriter out) {
|
||||||
this.mapFieldFunc = out.mapFieldFunc;
|
this.mapFieldFunc = out.mapFieldFunc;
|
||||||
this.objFieldFunc = out.objFieldFunc;
|
this.objFieldFunc = out.objFieldFunc;
|
||||||
@@ -126,172 +95,47 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
|||||||
return objExtFunc;
|
return objExtFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProtobufWriter enumtostring(boolean enumtostring) {
|
||||||
|
this.enumtostring = enumtostring;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean recycle() {
|
protected boolean recycle() {
|
||||||
super.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.child = null;
|
||||||
this.delegate = null;
|
this.parent = null;
|
||||||
this.mapFieldFunc = null;
|
this.mapFieldFunc = null;
|
||||||
this.objFieldFunc = null;
|
this.objFieldFunc = null;
|
||||||
this.objExtFunc = null;
|
this.objExtFunc = null;
|
||||||
this.features = 0;
|
this.features = 0;
|
||||||
this.enumtostring = false;
|
this.enumtostring = false;
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
if (this.content.length > DEFAULT_SIZE) {
|
|
||||||
this.content = new byte[DEFAULT_SIZE];
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void offerPool(ProtobufWriter item) {
|
public abstract ProtobufWriter pollChild();
|
||||||
if (this.pool != null && this.pool.size() < CHILD_SIZE) {
|
|
||||||
item.recycle();
|
|
||||||
this.pool.offer(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProtobufWriter pollChild() {
|
public abstract void offerChild(ProtobufWriter child);
|
||||||
Queue<ProtobufWriter> 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 void offerChild(ProtobufWriter child) {
|
protected abstract int expand(int len);
|
||||||
if (child != null) {
|
|
||||||
int len = child.length();
|
|
||||||
ProtobufWriter next = child;
|
|
||||||
while ((next = next.child) != null) {
|
|
||||||
len += next.length();
|
|
||||||
}
|
|
||||||
child.parent.writeSelfLength(len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public abstract void writeTo(final byte ch);
|
||||||
public final int length() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public abstract void writeTo(final byte[] chs, final int start, final int len);
|
||||||
public byte[] content() {
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
protected abstract void writeSelfLength(int value);
|
||||||
public final int offset() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
protected abstract void writeUInt32(int value);
|
||||||
* 将本对象的内容引用复制给array
|
|
||||||
*
|
|
||||||
* @param array ByteArray
|
|
||||||
*/
|
|
||||||
public void directTo(ByteArray array) {
|
|
||||||
array.directFrom(content, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer[] toBuffers() {
|
protected abstract void writeUInt64(long value);
|
||||||
return new ByteBuffer[] {ByteBuffer.wrap(content, 0, count)};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void completed(ConvertBytesHandler handler, Consumer<ProtobufWriter> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void writeTo(final byte... chs) {
|
public final void writeTo(final byte... chs) {
|
||||||
writeTo(chs, 0, chs.length);
|
writeTo(chs, 0, chs.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
public final int length() {
|
||||||
if (delegate == null) {
|
return count;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
protected final void writeFixed32(int value) {
|
||||||
if (value >= 0 && value < TENTHOUSAND_MAX) {
|
if (value >= 0 && value < TENTHOUSAND_MAX) {
|
||||||
writeTo(TENTHOUSAND_FIXED32_BYTES[value]);
|
writeTo(TENTHOUSAND_FIXED32_BYTES[value]);
|
||||||
|
|||||||
Reference in New Issue
Block a user