diff --git a/src/zutil/parser/binary/BinaryFieldSerializer.java b/src/zutil/parser/binary/BinaryFieldSerializer.java index e504e65..43988fc 100755 --- a/src/zutil/parser/binary/BinaryFieldSerializer.java +++ b/src/zutil/parser/binary/BinaryFieldSerializer.java @@ -31,8 +31,9 @@ import java.io.OutputStream; /** * An Interface defining a custom field parser and writer. *

- * A new instance of the serializer will be instantiated for every time serialization is required. - * {@link BinaryStructInputStream} and {@link BinaryStructOutputStream} objects. + * One singleton instance of the serializer will be cached for the lifetime of the + * {@link BinaryStructInputStream} and {@link BinaryStructOutputStream} objects, + * this can be disabled by calling the {@link BinaryStructInputStream#enableSerializerCache(boolean)}. *

* NOTE: Partial octet serializing not supported. */ diff --git a/src/zutil/parser/binary/BinaryStructInputStream.java b/src/zutil/parser/binary/BinaryStructInputStream.java index 3961265..14c0eb4 100755 --- a/src/zutil/parser/binary/BinaryStructInputStream.java +++ b/src/zutil/parser/binary/BinaryStructInputStream.java @@ -30,7 +30,9 @@ import zutil.io.PositionalInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * A stream class that parses a byte stream into binary struct objects. @@ -46,9 +48,13 @@ public class BinaryStructInputStream extends InputStream{ private byte data; private int dataBitIndex = -1; + private Map serializerCache; + public BinaryStructInputStream(InputStream in) { this.in = in; + + enableSerializerCache(true); } @@ -78,11 +84,22 @@ public class BinaryStructInputStream extends InputStream{ */ public int read(BinaryStruct struct) throws IOException { List structDataList = BinaryFieldData.getStructFieldList(struct.getClass()); - PositionalInputStream positionalInputStream = new PositionalInputStream(in); + PositionalInputStream positionalInputStream = (in instanceof PositionalInputStream ? (PositionalInputStream) in : new PositionalInputStream(in)); + long startPos = positionalInputStream.getPosition(); for (BinaryFieldData field : structDataList) { if (field.hasSerializer()) { - BinaryFieldSerializer serializer = field.getSerializer(); + // Handle serializer cache + + BinaryFieldSerializer serializer = (serializerCache != null ? serializerCache.get(field.getSerializerClass()) : null); + if (serializer == null) { + serializer = field.getSerializer(); + + if (serializerCache != null) + serializerCache.put(serializer.getClass(), serializer); + } + + // Read in field through serializer Object value = serializer.read(positionalInputStream, field, struct); field.setValue(struct, value); @@ -108,7 +125,7 @@ public class BinaryStructInputStream extends InputStream{ } } - return (int) positionalInputStream.getPosition(); + return (int) (positionalInputStream.getPosition() - startPos); } @Override @@ -150,6 +167,31 @@ public class BinaryStructInputStream extends InputStream{ } + /** + * Enable or disable the caching of serializer objects. If disabled then + * a new instance of the serializer will be created every time it is needed. + *

+ * By default, caching is enabled. + * + * @param enabled set true to enable caching or false to disable. + */ + public void enableSerializerCache(boolean enabled) { + if (enabled) { + serializerCache = new HashMap<>(); + } else { + serializerCache = null; + } + } + + /** + * Method will clear all cached instances of serializer objects. + */ + public void clearSerializerCache() { + if (serializerCache != null) { + serializerCache.clear(); + } + } + protected static int shiftLeftBy(int bitIndex, int bitLength) { return (8 - ((7-bitIndex) + bitLength) % 8) % 8; } diff --git a/test/zutil/net/dns/DnsPacketTest.java b/test/zutil/net/dns/DnsPacketTest.java index 7279c80..309a418 100755 --- a/test/zutil/net/dns/DnsPacketTest.java +++ b/test/zutil/net/dns/DnsPacketTest.java @@ -437,7 +437,7 @@ Multicast Domain Name System (query) DnsPacketQuestion question2 = packet.getQuestions().get(1); assertEquals("qNAME", "_homekit._tcp.local", question2.name); - //assertEquals("qNAME", "_homekit.<28>", question2.name); // TODO: Fix support for string pointers + //assertEquals("qNAME", "_homekit.<28>", question2.name); assertEquals("type", DnsConstants.TYPE.PTR, question2.type); assertEquals("clazz", DnsConstants.CLASS.IN, question2.clazz);