DataType添加类型HEX(十六进制字符串),删除BCD实现,改用Netty中StringUtil
parent
a2f5abb6f4
commit
7c1f0bce6c
2
pom.xml
2
pom.xml
|
@ -62,7 +62,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.netty</groupId>
|
<groupId>io.netty</groupId>
|
||||||
<artifactId>netty-buffer</artifactId>
|
<artifactId>netty-buffer</artifactId>
|
||||||
<version>4.1.65.Final</version>
|
<version>4.1.66.Final</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
|
@ -19,6 +19,8 @@ public enum DataType {
|
||||||
BYTES(-1),
|
BYTES(-1),
|
||||||
/** BCD8421码 */
|
/** BCD8421码 */
|
||||||
BCD8421(-1),
|
BCD8421(-1),
|
||||||
|
/** 十六进制字符串 */
|
||||||
|
HEX(-1),
|
||||||
/** 字符串 */
|
/** 字符串 */
|
||||||
STRING(-1),
|
STRING(-1),
|
||||||
/** 对象 */
|
/** 对象 */
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class DefaultLoadStrategy extends LoadStrategy {
|
public class DefaultLoadStrategy extends LoadStrategy {
|
||||||
|
|
||||||
private Map<String, Map<Integer, RuntimeSchema<?>>> typeClassMapping = new HashMap(140);
|
private Map<String, Map<Integer, RuntimeSchema<?>>> typeClassMapping = new HashMap(256);
|
||||||
|
|
||||||
public DefaultLoadStrategy() {
|
public DefaultLoadStrategy() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,9 @@ public abstract class FieldFactory {
|
||||||
else
|
else
|
||||||
fieldSchema = ArraySchema.ByteArraySchema.INSTANCE;
|
fieldSchema = ArraySchema.ByteArraySchema.INSTANCE;
|
||||||
break;
|
break;
|
||||||
|
case HEX:
|
||||||
|
fieldSchema = StringSchema.HEX.INSTANCE;
|
||||||
|
break;
|
||||||
case STRING:
|
case STRING:
|
||||||
fieldSchema = StringSchema.Chars.getInstance(field.pad(), field.charset());
|
fieldSchema = StringSchema.Chars.getInstance(field.pad(), field.charset());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package io.github.yezhihao.protostar;
|
package io.github.yezhihao.protostar;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 消息结构
|
* 消息结构
|
||||||
|
@ -11,8 +9,6 @@ import org.slf4j.LoggerFactory;
|
||||||
*/
|
*/
|
||||||
public interface Schema<T> {
|
public interface Schema<T> {
|
||||||
|
|
||||||
Logger log = LoggerFactory.getLogger(Schema.class.getSimpleName());
|
|
||||||
|
|
||||||
T readFrom(ByteBuf input);
|
T readFrom(ByteBuf input);
|
||||||
|
|
||||||
void writeTo(ByteBuf output, T message);
|
void writeTo(ByteBuf output, T message);
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
package io.github.yezhihao.protostar.schema;
|
package io.github.yezhihao.protostar.schema;
|
||||||
|
|
||||||
import io.github.yezhihao.protostar.Schema;
|
import io.github.yezhihao.protostar.Schema;
|
||||||
import io.github.yezhihao.protostar.util.Bcd;
|
|
||||||
import io.github.yezhihao.protostar.util.Cache;
|
import io.github.yezhihao.protostar.util.Cache;
|
||||||
|
import io.github.yezhihao.protostar.util.CharsBuilder;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.util.internal.StringUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class StringSchema {
|
public class StringSchema {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(StringSchema.class.getSimpleName());
|
||||||
|
|
||||||
public static class Chars implements Schema<String> {
|
public static class Chars implements Schema<String> {
|
||||||
private static final Cache<String, Chars> cache = new Cache<>();
|
private static final Cache<String, Chars> cache = new Cache<>();
|
||||||
|
|
||||||
|
@ -65,7 +70,7 @@ public class StringSchema {
|
||||||
output.writeBytes(bytes);
|
output.writeBytes(bytes);
|
||||||
} else if (srcPos < 0) {
|
} else if (srcPos < 0) {
|
||||||
output.writeBytes(bytes, -srcPos, length);
|
output.writeBytes(bytes, -srcPos, length);
|
||||||
log.error("字符长度超出限制: 长度[{}],数据长度[{}],{}", length, bytes.length, value);
|
log.info("字符长度超出限制: 长度[{}],数据长度[{}],{}", length, bytes.length, value);
|
||||||
} else {
|
} else {
|
||||||
output.writeBytes(bytes);
|
output.writeBytes(bytes);
|
||||||
}
|
}
|
||||||
|
@ -75,7 +80,6 @@ public class StringSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class BCD implements Schema<String> {
|
public static class BCD implements Schema<String> {
|
||||||
public static final Schema INSTANCE = new BCD();
|
public static final Schema INSTANCE = new BCD();
|
||||||
|
|
||||||
|
@ -91,12 +95,10 @@ public class StringSchema {
|
||||||
public String readFrom(ByteBuf input, int length) {
|
public String readFrom(ByteBuf input, int length) {
|
||||||
byte[] bytes = new byte[length];
|
byte[] bytes = new byte[length];
|
||||||
input.readBytes(bytes);
|
input.readBytes(bytes);
|
||||||
char[] chars = Bcd.toChars(bytes);
|
|
||||||
|
|
||||||
int i = Bcd.indexOf(chars, '0');
|
CharsBuilder cb = new CharsBuilder(length << 1);
|
||||||
if (i == 0)
|
StringUtil.toHexStringPadded(cb, bytes);
|
||||||
return new String(chars);
|
return cb.leftStrip('0');
|
||||||
return new String(chars, i, chars.length - i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,9 +117,53 @@ public class StringSchema {
|
||||||
chars[--i] = '0';
|
chars[--i] = '0';
|
||||||
} else {
|
} else {
|
||||||
value.getChars(-i, charLength - i, chars, 0);
|
value.getChars(-i, charLength - i, chars, 0);
|
||||||
log.warn("字符长度超出限制: 长度[{}],[{}]", charLength, value);
|
log.info("字符长度超出限制: 长度[{}],[{}]", charLength, value);
|
||||||
}
|
}
|
||||||
byte[] src = Bcd.from(chars);
|
byte[] src = StringUtil.decodeHexDump(new CharsBuilder(chars));
|
||||||
|
output.writeBytes(src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HEX implements Schema<String> {
|
||||||
|
public static final Schema INSTANCE = new HEX();
|
||||||
|
|
||||||
|
private HEX() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readFrom(ByteBuf input) {
|
||||||
|
return readFrom(input, input.readableBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readFrom(ByteBuf input, int length) {
|
||||||
|
byte[] bytes = new byte[length];
|
||||||
|
input.readBytes(bytes);
|
||||||
|
|
||||||
|
CharsBuilder cb = new CharsBuilder(length << 1);
|
||||||
|
StringUtil.toHexStringPadded(cb, bytes);
|
||||||
|
return cb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(ByteBuf output, String value) {
|
||||||
|
writeTo(output, value.length() >> 1, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(ByteBuf output, int length, String value) {
|
||||||
|
int charLength = length << 1;
|
||||||
|
char[] chars = new char[charLength];
|
||||||
|
int i = charLength - value.length();
|
||||||
|
if (i >= 0) {
|
||||||
|
value.getChars(0, charLength - i, chars, i);
|
||||||
|
while (i > 0)
|
||||||
|
chars[--i] = '0';
|
||||||
|
} else {
|
||||||
|
value.getChars(-i, charLength - i, chars, 0);
|
||||||
|
log.info("字符长度超出限制: 长度[{}],[{}]", charLength, value);
|
||||||
|
}
|
||||||
|
byte[] src = StringUtil.decodeHexDump(new CharsBuilder(chars));
|
||||||
output.writeBytes(src);
|
output.writeBytes(src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,35 +17,6 @@ public class Bcd {
|
||||||
public static final int YEAR_RANGE = YEAR - 30;
|
public static final int YEAR_RANGE = YEAR - 30;
|
||||||
public static final int HUNDRED_YEAR = YEAR_RANGE / 100 * 100;
|
public static final int HUNDRED_YEAR = YEAR_RANGE / 100 * 100;
|
||||||
|
|
||||||
/** BCD转String */
|
|
||||||
public static String toString(byte[] bcd) {
|
|
||||||
return new String(toChars(bcd));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** BCD转char[] */
|
|
||||||
public static char[] toChars(byte[] bcd) {
|
|
||||||
char[] chars = new char[bcd.length * 2];
|
|
||||||
for (int i = 0, j = 0; i < bcd.length; i++) {
|
|
||||||
chars[j++] = (char) (48 + (bcd[i] >> 4 & 0xf));
|
|
||||||
chars[j++] = (char) (48 + (bcd[i] & 0xf));
|
|
||||||
}
|
|
||||||
return chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** String转BCD */
|
|
||||||
public static byte[] from(String str) {
|
|
||||||
return from(str.toCharArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** char[]转BCD */
|
|
||||||
public static byte[] from(char[] chars) {
|
|
||||||
byte[] bcd = new byte[chars.length / 2];
|
|
||||||
for (int i = 0, j = 0; i < bcd.length; i++) {
|
|
||||||
bcd[i] = (byte) ((chars[j++] - 48 << 4) | ((chars[j++] - 48 & 0xf)));
|
|
||||||
}
|
|
||||||
return bcd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 时间转BCD (yyMMddHHmmss) */
|
/** 时间转BCD (yyMMddHHmmss) */
|
||||||
public static byte[] from(LocalDateTime dateTime) {
|
public static byte[] from(LocalDateTime dateTime) {
|
||||||
byte[] bcd = new byte[6];
|
byte[] bcd = new byte[6];
|
||||||
|
@ -113,10 +84,4 @@ public class Bcd {
|
||||||
public static int num(byte bcd) {
|
public static int num(byte bcd) {
|
||||||
return (bcd >> 4 & 0xf) * 10 + (bcd & 0xf);
|
return (bcd >> 4 & 0xf) * 10 + (bcd & 0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int indexOf(char[] chars, char pad) {
|
|
||||||
int i = 0, len = chars.length;
|
|
||||||
while (i < len && chars[i] == pad) i++;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package io.github.yezhihao.protostar.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class CharsBuilder implements CharSequence, Appendable {
|
||||||
|
|
||||||
|
private char[] value;
|
||||||
|
private int pos;
|
||||||
|
|
||||||
|
public CharsBuilder(int length) {
|
||||||
|
this.value = new char[length];
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharsBuilder(char[] chars) {
|
||||||
|
this.value = chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Appendable append(CharSequence s) {
|
||||||
|
return append(s, 0, s.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Appendable append(CharSequence s, int start, int end) {
|
||||||
|
int len = end - start;
|
||||||
|
for (int i = start, j = pos; i < end; i++, j++)
|
||||||
|
value[j] = s.charAt(i);
|
||||||
|
pos += len;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Appendable append(char c) {
|
||||||
|
value[pos++] = c;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char charAt(int index) {
|
||||||
|
return value[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence subSequence(int start, int end) {
|
||||||
|
if (start == end) {
|
||||||
|
return new CharsBuilder(Math.min(16, value.length));
|
||||||
|
}
|
||||||
|
return new CharsBuilder(Arrays.copyOfRange(value, start, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int length() {
|
||||||
|
return value.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String leftStrip(char c) {
|
||||||
|
int i = leftOf(value, c);
|
||||||
|
return new String(value, i, value.length - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String rightStrip(char c) {
|
||||||
|
int i = rightOf(value, c);
|
||||||
|
return new String(value, 0, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int leftOf(char[] chars, char pad) {
|
||||||
|
int i = 0, len = chars.length;
|
||||||
|
while (i < len && chars[i] == pad) i++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int rightOf(char[] chars, char pad) {
|
||||||
|
int i = 0, len = chars.length;
|
||||||
|
while ((i < len) && (chars[len - 1] <= pad)) len--;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package io.github.yezhihao.protostar.convert;
|
||||||
|
|
||||||
|
import io.github.yezhihao.protostar.PrepareLoadStrategy;
|
||||||
|
import io.github.yezhihao.protostar.converter.MapConverter;
|
||||||
|
import io.github.yezhihao.protostar.schema.NumberSchema;
|
||||||
|
import io.github.yezhihao.protostar.schema.StringSchema;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
public class AttributeConverterV2 extends MapConverter<Integer, Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSchemas(PrepareLoadStrategy schemaRegistry) {
|
||||||
|
schemaRegistry
|
||||||
|
.addSchema(1, NumberSchema.Int32.INSTANCE)
|
||||||
|
.addSchema(2, StringSchema.Chars.getInstance((byte) 0, "UTF-8"))
|
||||||
|
|
||||||
|
.addSchema(3, Attr1.class)
|
||||||
|
.addSchema(4, Attr2.Schema.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer readKey(ByteBuf input) {
|
||||||
|
return (int) input.readUnsignedByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeKey(ByteBuf output, Integer key) {
|
||||||
|
output.writeByte(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int valueSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue