From 1cfc17766a1a536f84fc649ccd54bbde45c4b274 Mon Sep 17 00:00:00 2001 From: redkale Date: Tue, 17 Sep 2024 08:57:39 +0800 Subject: [PATCH] DeMemberNode --- .../java/org/redkale/convert/DeMember.java | 1 + .../org/redkale/convert/DeMemberNode.java | 67 +++++++++++++++++++ .../org/redkale/convert/ObjectDecoder.java | 30 ++++++--- .../org/redkale/convert/ObjectEncoder.java | 10 ++- src/main/java/org/redkale/convert/Reader.java | 4 +- .../org/redkale/convert/bson/BsonReader.java | 23 +------ .../convert/ext/PatternSimpledCoder.java | 11 +-- .../convert/json/JsonByteBufferReader.java | 39 ++++++++++- .../org/redkale/convert/json/JsonReader.java | 59 ++++++++++------ .../redkale/convert/pb/ProtobufReader.java | 9 ++- .../test/convert/CustMessage2Test.java | 4 +- .../redkale/test/convert/CustMessageTest.java | 4 +- .../test/convert/InnerCoderEntity.java | 5 +- .../test/convert/pb/PBCustMessage2Test.java | 4 +- .../test/convert/pb/PBCustMessageTest.java | 4 +- 15 files changed, 192 insertions(+), 82 deletions(-) create mode 100644 src/main/java/org/redkale/convert/DeMemberNode.java diff --git a/src/main/java/org/redkale/convert/DeMember.java b/src/main/java/org/redkale/convert/DeMember.java index 216ca1115..39389bebf 100644 --- a/src/main/java/org/redkale/convert/DeMember.java +++ b/src/main/java/org/redkale/convert/DeMember.java @@ -183,4 +183,5 @@ public final class DeMember { return "DeMember{" + "attribute=" + attribute.field() + ", position=" + position + ", tag=" + tag + ", decoder=" + (decoder == null ? null : decoder.getClass().getName()) + '}'; } + } diff --git a/src/main/java/org/redkale/convert/DeMemberNode.java b/src/main/java/org/redkale/convert/DeMemberNode.java new file mode 100644 index 000000000..7a6518d7f --- /dev/null +++ b/src/main/java/org/redkale/convert/DeMemberNode.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016-2116 Redkale + * All rights reserved. + */ +package org.redkale.convert; + +/** + * 字段的反序列化操作类 + * + *

详情见: https://redkale.org + * + * @author zhangjx + * @since 2.8.0 + */ +public class DeMemberNode { + + protected static final int MIN_INDEX = 32; + + protected DeMember value; + + protected DeMemberNode[] nodes = new DeMemberNode[127 - MIN_INDEX]; + + public DeMemberNode getNode(char ch) { + if (ch <= MIN_INDEX || ch > 127) { + return null; + } + return nodes[ch - MIN_INDEX]; + } + + public DeMember getMember(String field) { + char[] chs = field.toCharArray(); + DeMemberNode n = this; + for (int i = 0; i < chs.length; i++) { + n = n.nodes[chs[i] - MIN_INDEX]; + if (n == null) { + break; + } + } + return n == null ? null : n.value; + } + + public DeMember getValue() { + return value; + } + + private void add(DeMember member) { + char[] chs = member.attribute.field().toCharArray(); + DeMemberNode n = this; + for (int i = 0; i < chs.length; i++) { + DeMemberNode s = n.nodes[chs[i] - MIN_INDEX]; + if (s == null) { + s = new DeMemberNode(); + n.nodes[chs[i] - MIN_INDEX] = s; + } + n = s; + } + n.value = member; + } + + public static DeMemberNode create(DeMember... members) { + DeMemberNode root = new DeMemberNode(); + for (DeMember member : members) { + root.add(member); + } + return root; + } +} diff --git a/src/main/java/org/redkale/convert/ObjectDecoder.java b/src/main/java/org/redkale/convert/ObjectDecoder.java index 87dd36bf2..dba3fd835 100644 --- a/src/main/java/org/redkale/convert/ObjectDecoder.java +++ b/src/main/java/org/redkale/convert/ObjectDecoder.java @@ -34,6 +34,8 @@ public class ObjectDecoder implements Decodeable { protected DeMember[] members; + protected DeMemberNode memberNode; + protected Map memberFieldMap; protected Map memberTagMap; @@ -69,6 +71,7 @@ public class ObjectDecoder implements Decodeable { this.factory = factory; try { if (type == Object.class) { + this.memberNode = DeMemberNode.create(); this.creatorConstructorMembers = null; return; } @@ -304,15 +307,9 @@ public class ObjectDecoder implements Decodeable { } initForEachDeMember(factory, member); } - - this.members = list.toArray(new DeMember[list.size()]); + DeMember[] deMembers = list.toArray(new DeMember[list.size()]); Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b)); - this.memberFieldMap = new HashMap<>(this.members.length); - this.memberTagMap = new HashMap<>(this.members.length); - for (DeMember member : this.members) { - this.memberFieldMap.put(member.getAttribute().field(), member); - this.memberTagMap.put(member.getTag(), member); - } + this.initFieldMember(deMembers); if (cps != null) { final String[] fields = cps; @@ -343,6 +340,17 @@ public class ObjectDecoder implements Decodeable { } } + protected void initFieldMember(DeMember[] deMembers) { + this.members = deMembers; + this.memberFieldMap = new HashMap<>(this.members.length); + this.memberTagMap = new HashMap<>(this.members.length); + for (DeMember member : this.members) { + this.memberFieldMap.put(member.getAttribute().field(), member); + this.memberTagMap.put(member.getTag(), member); + } + this.memberNode = DeMemberNode.create(this.members); + } + /** * 对象格式: [0x1][short字段个数][字段名][字段值]...[0x2] * @@ -376,14 +384,14 @@ public class ObjectDecoder implements Decodeable { } } - DeMember[] memberArray = this.members; + DeMemberNode fieldNode = this.memberNode; Map fieldMap = this.memberFieldMap; Map tagMap = this.memberTagMap; if (this.creatorConstructorMembers == null) { // 空构造函数 final T result = this.creator == null ? null : this.creator.create(); boolean first = true; while (objin.hasNext()) { - DeMember member = objin.readFieldName(memberArray, fieldMap, tagMap); + DeMember member = objin.readFieldName(fieldNode, fieldMap, tagMap); objin.readBlank(); if (member == null) { objin.skipValue(); // 跳过不存在的属性的值 @@ -401,7 +409,7 @@ public class ObjectDecoder implements Decodeable { int oc = 0; boolean first = true; while (objin.hasNext()) { - DeMember member = objin.readFieldName(memberArray, fieldMap, tagMap); + DeMember member = objin.readFieldName(fieldNode, fieldMap, tagMap); objin.readBlank(); if (member == null) { objin.skipValue(); // 跳过不存在的属性的值 diff --git a/src/main/java/org/redkale/convert/ObjectEncoder.java b/src/main/java/org/redkale/convert/ObjectEncoder.java index 4f05ccd9c..1a898b324 100644 --- a/src/main/java/org/redkale/convert/ObjectEncoder.java +++ b/src/main/java/org/redkale/convert/ObjectEncoder.java @@ -287,9 +287,9 @@ public class ObjectEncoder implements Encodeable { } initForEachEnMember(factory, member); } - - this.members = list.toArray(new EnMember[list.size()]); - Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b)); + EnMember[] enMembers = list.toArray(new EnMember[list.size()]); + Arrays.sort(enMembers, (a, b) -> a.compareTo(factory.isFieldSort(), b)); + this.initFieldMember(enMembers); afterInitEnMember(factory); } catch (Exception ex) { throw new ConvertException("ObjectEncoder init type=" + this.type + " error", ex); @@ -305,6 +305,10 @@ public class ObjectEncoder implements Encodeable { } } + protected void initFieldMember(EnMember[] enMembers) { + this.members = enMembers; + } + @Override public void convertTo(W out, T value) { if (value == null) { diff --git a/src/main/java/org/redkale/convert/Reader.java b/src/main/java/org/redkale/convert/Reader.java index 75288a35c..988e47d88 100644 --- a/src/main/java/org/redkale/convert/Reader.java +++ b/src/main/java/org/redkale/convert/Reader.java @@ -136,13 +136,13 @@ public abstract class Reader { /** * 根据字段读取字段对应的DeMember * - * @param members DeMember的全量集合 + * @param fieldNode DeMember的全量集合 * @param memberFieldMap DeMember的字段名map * @param memberTagMap DeMember的tag map * @return 匹配的DeMember */ public abstract DeMember readFieldName( - final DeMember[] members, Map memberFieldMap, Map memberTagMap); + final DeMemberNode fieldNode, Map memberFieldMap, Map memberTagMap); /** * 读取一个boolean值 diff --git a/src/main/java/org/redkale/convert/bson/BsonReader.java b/src/main/java/org/redkale/convert/bson/BsonReader.java index b01cfc356..aaf03a2bf 100644 --- a/src/main/java/org/redkale/convert/bson/BsonReader.java +++ b/src/main/java/org/redkale/convert/bson/BsonReader.java @@ -5,11 +5,10 @@ */ package org.redkale.convert.bson; -import static org.redkale.convert.Reader.SIGN_NULL; - import java.nio.charset.StandardCharsets; import java.util.Map; import org.redkale.convert.*; +import static org.redkale.convert.Reader.SIGN_NULL; import org.redkale.convert.ext.ByteSimpledCoder; import org.redkale.util.ObjectPool; @@ -253,26 +252,10 @@ public class BsonReader extends Reader { @Override public final DeMember readFieldName( - final DeMember[] members, Map memberFieldMap, Map memberTagMap) { + final DeMemberNode fieldNode, Map memberFieldMap, Map memberTagMap) { final String exceptedField = readSmallString(); this.typeval = readByte(); - final int len = members.length; - if (this.fieldIndex >= len) { - this.fieldIndex = 0; - } - for (int k = this.fieldIndex; k < len; k++) { - if (exceptedField.equals(members[k].getAttribute().field())) { - this.fieldIndex = k; - return members[k]; - } - } - for (int k = 0; k < this.fieldIndex; k++) { - if (exceptedField.equals(members[k].getAttribute().field())) { - this.fieldIndex = k; - return members[k]; - } - } - return null; + return fieldNode.getMember(exceptedField); } // ------------------------------------------------------------ diff --git a/src/main/java/org/redkale/convert/ext/PatternSimpledCoder.java b/src/main/java/org/redkale/convert/ext/PatternSimpledCoder.java index bfc257ab5..ed6cf0a04 100644 --- a/src/main/java/org/redkale/convert/ext/PatternSimpledCoder.java +++ b/src/main/java/org/redkale/convert/ext/PatternSimpledCoder.java @@ -5,7 +5,6 @@ */ package org.redkale.convert.ext; -import java.util.HashMap; import java.util.regex.Pattern; import org.redkale.convert.*; import org.redkale.util.Attribute; @@ -48,7 +47,7 @@ public class PatternSimpledCoder extends Sim Attribute.create(Pattern.class, "pattern", String.class, t -> t.pattern(), null), 2, StringSimpledCoder.instance); - this.members = new EnMember[] {flagsMember, patternMember}; + this.initFieldMember(new EnMember[] {flagsMember, patternMember}); this.inited = true; } } @@ -65,14 +64,8 @@ public class PatternSimpledCoder extends Sim 2, StringSimpledCoder.instance); this.creator = args -> Pattern.compile((String) args[1], (Integer) args[0]); - this.members = new DeMember[] {flagsMember, patternMember}; + this.initFieldMember(new DeMember[] {flagsMember, patternMember}); this.creatorConstructorMembers = this.members; - this.memberFieldMap = new HashMap<>(this.members.length); - this.memberTagMap = new HashMap<>(this.members.length); - for (DeMember member : this.members) { - this.memberFieldMap.put(member.getAttribute().field(), member); - this.memberTagMap.put(member.getTag(), member); - } this.inited = true; } } diff --git a/src/main/java/org/redkale/convert/json/JsonByteBufferReader.java b/src/main/java/org/redkale/convert/json/JsonByteBufferReader.java index 689454cea..7037e8f14 100644 --- a/src/main/java/org/redkale/convert/json/JsonByteBufferReader.java +++ b/src/main/java/org/redkale/convert/json/JsonByteBufferReader.java @@ -5,11 +5,11 @@ */ package org.redkale.convert.json; -import static org.redkale.convert.Reader.*; - import java.nio.ByteBuffer; import java.nio.charset.UnmappableCharacterException; +import java.util.Map; import org.redkale.convert.*; +import static org.redkale.convert.Reader.*; /** * 以ByteBuffer为数据载体的JsonReader
@@ -313,4 +313,39 @@ public class JsonByteBufferReader extends JsonReader { return "null".equalsIgnoreCase(rs) ? null : rs; } } + + @Override + public DeMember readFieldName( + final DeMemberNode fieldNode, Map memberFieldMap, Map memberTagMap) { + char ch = nextGoodChar(true); + if (ch == 0) { + return null; + } + DeMemberNode node = fieldNode; + StringBuilder sb = new StringBuilder(); + if (ch == '"' || ch == '\'') { + final char quote = ch; + for (; ; ) { + ch = nextChar(sb); + if (ch == quote || ch == 0) { + break; + } else { + node = node == null ? null : node.getNode(ch); + } + } + return node == null ? null : node.getValue(); + } else { + node = node == null ? null : node.getNode(ch); + for (; ; ) { + ch = nextChar(sb); + if (ch == ',' || ch == ']' || ch == '}' || ch <= ' ' || ch == ':') { // ch <= ' ' 包含 0 + backChar(ch); + break; + } else { + node = node == null ? null : node.getNode(ch); + } + } + return node == null ? null : node.getValue(); + } + } } diff --git a/src/main/java/org/redkale/convert/json/JsonReader.java b/src/main/java/org/redkale/convert/json/JsonReader.java index ade4bad73..085664b02 100644 --- a/src/main/java/org/redkale/convert/json/JsonReader.java +++ b/src/main/java/org/redkale/convert/json/JsonReader.java @@ -5,11 +5,10 @@ */ package org.redkale.convert.json; -import static org.redkale.convert.Reader.*; - import java.nio.charset.StandardCharsets; import java.util.Map; import org.redkale.convert.*; +import static org.redkale.convert.Reader.*; import org.redkale.convert.Reader.ValueType; import org.redkale.util.Utility; @@ -696,30 +695,48 @@ public class JsonReader extends Reader { } @Override - public final DeMember readFieldName( - final DeMember[] members, Map memberFieldMap, Map memberTagMap) { - final String exceptedField = this.readSmallString(); - if (exceptedField == null) { + public DeMember readFieldName( + final DeMemberNode fieldNode, Map memberFieldMap, Map memberTagMap) { + + final int eof = this.limit; + if (this.position == eof) { return null; } - final int len = members.length; - if (this.fieldIndex >= len) { - this.fieldIndex = 0; - } - for (int k = this.fieldIndex; k < len; k++) { - if (exceptedField.equals(members[k].getAttribute().field())) { - this.fieldIndex = k; - return members[k]; + DeMemberNode node = fieldNode; + char ch = nextGoodChar(true); // 需要跳过注释 + final char[] text0 = this.text; + int currpos = this.position; + if (ch == '"' || ch == '\'') { + final char quote = ch; + for (; ; ) { + ch = text0[++currpos]; + if (ch == quote) { + break; + } + node = node == null ? null : node.getNode(ch); } - } - for (int k = 0; k < this.fieldIndex; k++) { - if (exceptedField.equals(members[k].getAttribute().field())) { - this.fieldIndex = k; - return members[k]; + this.position = currpos; + return node == null ? null : node.getValue(); + } else { + int start = currpos; + for (; ; ) { + if (currpos == eof) { + break; + } + ch = text0[++currpos]; + if (ch == ',' || ch == ']' || ch == '}' || ch <= ' ' || ch == ':') { + break; + } + node = node == null ? null : node.getNode(ch); } + int len = currpos - start; + if (len < 1) { + this.position = currpos; + } else { + this.position = currpos - 1; + } + return node == null ? null : node.getValue(); } - return null; - // if (result == null && len == 1 && text0[start] == '@') return REFER; } // ------------------------------------------------------------ diff --git a/src/main/java/org/redkale/convert/pb/ProtobufReader.java b/src/main/java/org/redkale/convert/pb/ProtobufReader.java index dcb49bf6d..332ee3e1f 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufReader.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufReader.java @@ -211,12 +211,11 @@ public class ProtobufReader extends Reader { @Override public final DeMember readFieldName( - final DeMember[] members, Map memberFieldMap, Map memberTagMap) { + final DeMemberNode fieldNode, Map memberFieldMap, Map memberTagMap) { int tag = readTag(); - for (DeMember member : members) { - if (member.getTag() == tag) { - return member; - } + DeMember member = memberTagMap.get(tag); + if (member != null) { + return member; } backTag(tag); return null; diff --git a/src/test/java/org/redkale/test/convert/CustMessage2Test.java b/src/test/java/org/redkale/test/convert/CustMessage2Test.java index d59d0fe0a..8e8cfff16 100644 --- a/src/test/java/org/redkale/test/convert/CustMessage2Test.java +++ b/src/test/java/org/redkale/test/convert/CustMessage2Test.java @@ -88,7 +88,7 @@ public class CustMessage2Test { setIndex(member2, 2); setPosition(member2, 2); initForEachEnMember(factory, member2); - this.members = new EnMember[] {member1, member2}; + this.initFieldMember(new EnMember[] {member1, member2}); } }; encoder.init(factory); @@ -117,7 +117,7 @@ public class CustMessage2Test { setIndex(member2, 2); setPosition(member2, 2); initForEachDeMember(factory, member2); - this.members = new DeMember[] {member1, member2}; + this.initFieldMember(new DeMember[] {member1, member2}); } @Override diff --git a/src/test/java/org/redkale/test/convert/CustMessageTest.java b/src/test/java/org/redkale/test/convert/CustMessageTest.java index 161e3a0e9..741e454ae 100644 --- a/src/test/java/org/redkale/test/convert/CustMessageTest.java +++ b/src/test/java/org/redkale/test/convert/CustMessageTest.java @@ -76,7 +76,7 @@ public class CustMessageTest { setIndex(member, 1); setPosition(member, 1); initForEachEnMember(factory, member); - this.members = new EnMember[] {member}; + this.initFieldMember(new EnMember[] {member}); } }; encoder.init(factory); @@ -96,7 +96,7 @@ public class CustMessageTest { setIndex(member, 1); setPosition(member, 1); initForEachDeMember(factory, member); - this.members = new DeMember[] {member}; + this.initFieldMember(new DeMember[] {member}); } @Override diff --git a/src/test/java/org/redkale/test/convert/InnerCoderEntity.java b/src/test/java/org/redkale/test/convert/InnerCoderEntity.java index ccc2a02f5..e86248dc2 100644 --- a/src/test/java/org/redkale/test/convert/InnerCoderEntity.java +++ b/src/test/java/org/redkale/test/convert/InnerCoderEntity.java @@ -41,6 +41,8 @@ public class InnerCoderEntity { final org.redkale.convert.ConvertFactory factory) { return new SimpledCoder() { + private DeMemberNode memberNode; + private Map deMemberFieldMap; private Map deMemberTagMap; @@ -64,6 +66,7 @@ public class InnerCoderEntity { this.deMemberFieldMap.put(member.getAttribute().field(), member); this.deMemberTagMap.put(member.getTag(), member); } + this.memberNode = DeMemberNode.create(deMembers); } @Override @@ -85,7 +88,7 @@ public class InnerCoderEntity { int index = 0; final Object[] params = new Object[deMembers.length]; while (in.hasNext()) { - DeMember member = in.readFieldName(deMembers, deMemberFieldMap, deMemberTagMap); // 读取字段名 + DeMember member = in.readFieldName(memberNode, deMemberFieldMap, deMemberTagMap); // 读取字段名 in.readBlank(); // 读取字段名与字段值之间的间隔符,JSON则是跳过冒号: if (member == null) { in.skipValue(); // 跳过不存在的字段的值, 一般不会发生 diff --git a/src/test/java/org/redkale/test/convert/pb/PBCustMessage2Test.java b/src/test/java/org/redkale/test/convert/pb/PBCustMessage2Test.java index 6b81e1b65..97a2d1be4 100644 --- a/src/test/java/org/redkale/test/convert/pb/PBCustMessage2Test.java +++ b/src/test/java/org/redkale/test/convert/pb/PBCustMessage2Test.java @@ -108,7 +108,7 @@ public class PBCustMessage2Test { setIndex(member2, 2); setPosition(member2, 2); initForEachEnMember(factory, member2); - this.members = new EnMember[] {member1, member2}; + this.initFieldMember(new EnMember[] {member1, member2}); } }; encoder.init(factory); @@ -137,7 +137,7 @@ public class PBCustMessage2Test { setIndex(member2, 2); setPosition(member2, 2); initForEachDeMember(factory, member2); - this.members = new DeMember[] {member1, member2}; + this.initFieldMember(new DeMember[] {member1, member2}); } @Override diff --git a/src/test/java/org/redkale/test/convert/pb/PBCustMessageTest.java b/src/test/java/org/redkale/test/convert/pb/PBCustMessageTest.java index 9e608ec94..e0cf02246 100644 --- a/src/test/java/org/redkale/test/convert/pb/PBCustMessageTest.java +++ b/src/test/java/org/redkale/test/convert/pb/PBCustMessageTest.java @@ -87,7 +87,7 @@ public class PBCustMessageTest { setIndex(member, 1); setPosition(member, 1); initForEachEnMember(factory, member); - this.members = new EnMember[] {member}; + this.initFieldMember(new EnMember[] {member}); } }; encoder.init(factory); @@ -107,7 +107,7 @@ public class PBCustMessageTest { setIndex(member, 1); setPosition(member, 1); initForEachDeMember(factory, member); - this.members = new DeMember[] {member}; + this.initFieldMember(new DeMember[] {member}); } @Override