Changed BinaryFieldSerializer instance to be between read sessions
This commit is contained in:
parent
decf114f49
commit
e42d25fa99
5 changed files with 63 additions and 23 deletions
|
|
@ -33,6 +33,7 @@ import zutil.parser.binary.BinaryStruct.CustomBinaryField;
|
|||
import zutil.parser.binary.BinaryStruct.VariableLengthBinaryField;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
|
|
@ -49,7 +50,7 @@ public class BinaryFieldData {
|
|||
private BinaryFieldData lengthField;
|
||||
private int lengthMultiplier;
|
||||
/* @CustomBinaryField */
|
||||
private BinaryFieldSerializer serializer;
|
||||
private Class<? extends BinaryFieldSerializer> serializerClass;
|
||||
|
||||
|
||||
protected static List<BinaryFieldData> getStructFieldList(Class<? extends BinaryStruct> clazz) {
|
||||
|
|
@ -80,16 +81,17 @@ public class BinaryFieldData {
|
|||
}
|
||||
|
||||
|
||||
private BinaryFieldData(Field f) throws IllegalAccessException, InstantiationException, NoSuchFieldException {
|
||||
private BinaryFieldData(Field f) throws NoSuchFieldException {
|
||||
field = f;
|
||||
this.length = -1;
|
||||
this.lengthField = null;
|
||||
this.lengthMultiplier = 1;
|
||||
this.serializer = null;
|
||||
this.serializerClass = null;
|
||||
|
||||
if (field.isAnnotationPresent(CustomBinaryField.class)) {
|
||||
CustomBinaryField fieldData = field.getAnnotation(CustomBinaryField.class);
|
||||
this.index = fieldData.index();
|
||||
this.serializer = fieldData.serializer().newInstance();
|
||||
this.serializerClass = fieldData.serializer();
|
||||
}
|
||||
else if (field.isAnnotationPresent(VariableLengthBinaryField.class)) {
|
||||
VariableLengthBinaryField fieldData = field.getAnnotation(VariableLengthBinaryField.class);
|
||||
|
|
@ -185,8 +187,21 @@ public class BinaryFieldData {
|
|||
return length;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasSerializer() {
|
||||
return serializerClass != null;
|
||||
}
|
||||
|
||||
public Class<? extends BinaryFieldSerializer> getSerializerClass() {
|
||||
return serializerClass;
|
||||
}
|
||||
|
||||
public BinaryFieldSerializer getSerializer() {
|
||||
return serializer;
|
||||
try {
|
||||
return serializerClass.getDeclaredConstructor().newInstance();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Unable to instantiate class: " + serializerClass, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -197,8 +212,8 @@ public class BinaryFieldData {
|
|||
(lengthField != null ?
|
||||
"LengthField: " + lengthField + ", LengthMultiplier: " + lengthMultiplier :
|
||||
length + " bits") +
|
||||
(serializer != null ?
|
||||
", Serializer: " + serializer.getClass().getName() : "") +
|
||||
(serializerClass != null ?
|
||||
", Serializer: " + serializerClass.getClass().getName() : "") +
|
||||
")";
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@ import java.io.OutputStream;
|
|||
|
||||
/**
|
||||
* An Interface where custom field parser and writer can be implemented.
|
||||
* <p></p>
|
||||
* One instance of the serializer and will have the scope of the methods
|
||||
* {@link BinaryStructInputStream#read(BinaryStruct)} and {@link BinaryStructOutputStream#write(BinaryStruct)}
|
||||
* where as it will be deallocated after the methods have returned.
|
||||
* <p></p>
|
||||
* NOTE: Partial octet serializing not supported.
|
||||
*
|
||||
* Created by Ziver on 2016-04-11.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public interface BinaryStruct {
|
|||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@interface BinaryField{
|
||||
@interface BinaryField {
|
||||
/** @return a number indicating the order the fields are read. Lowest index number field will be read first. */
|
||||
int index();
|
||||
/** @return the bit length of the data */
|
||||
|
|
@ -56,7 +56,7 @@ public interface BinaryStruct {
|
|||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@interface VariableLengthBinaryField{
|
||||
@interface VariableLengthBinaryField {
|
||||
/** @return a number indicating the order the fields are read. Lowest index number field will be read first. */
|
||||
int index();
|
||||
/** @return a String name of the field that contains the length of the data to be read. */
|
||||
|
|
@ -71,7 +71,7 @@ public interface BinaryStruct {
|
|||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@interface CustomBinaryField{
|
||||
@interface CustomBinaryField {
|
||||
/** @return a number indicating the order the fields are read. Lowest index number field will be read first. */
|
||||
int index();
|
||||
/** @return the serializer class name that will be used. Class needs to be publicly visible. */
|
||||
|
|
|
|||
|
|
@ -29,11 +29,15 @@ import zutil.ByteUtil;
|
|||
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.
|
||||
* A stream class that parses a byte stream into binary struct objects.
|
||||
* <p><p/>
|
||||
* Limitations:<br>
|
||||
* - Does not support sub binary objects.<br>
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
|
|
@ -74,14 +78,20 @@ public class BinaryStructInputStream {
|
|||
*/
|
||||
public int read(BinaryStruct struct) throws IOException {
|
||||
List<BinaryFieldData> structDataList = BinaryFieldData.getStructFieldList(struct.getClass());
|
||||
Map<Class, BinaryFieldSerializer> serializerCache = new HashMap<>();
|
||||
|
||||
int totalReadLength = 0;
|
||||
for (BinaryFieldData field : structDataList) {
|
||||
if (field.getSerializer() != null) {
|
||||
Object value = field.getSerializer().read(in, field);
|
||||
if (field.hasSerializer()) {
|
||||
BinaryFieldSerializer serializer = serializerCache.get(field.getSerializerClass());
|
||||
if (serializer == null) {
|
||||
serializer = field.getSerializer();
|
||||
serializerCache.put(serializer.getClass(), serializer);
|
||||
}
|
||||
|
||||
Object value = serializer.read(in, field);
|
||||
field.setValue(struct, value);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
byte[] valueData = new byte[(int) Math.ceil(field.getBitLength(struct) / 8.0)];
|
||||
int fieldReadLength = 0; // How much we have read so far
|
||||
int shiftBy = shiftLeftBy(dataBitIndex, field.getBitLength(struct));
|
||||
|
|
|
|||
|
|
@ -29,12 +29,16 @@ import zutil.ByteUtil;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* A stream class that generates a byte stream from
|
||||
* binary struct objects.
|
||||
* A stream class that generates a byte stream from a binary struct objects.
|
||||
* <p><p/>
|
||||
* Limitations:<br>
|
||||
* - Does not support sub binary objects.<br>
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
|
|
@ -84,13 +88,19 @@ public class BinaryStructOutputStream {
|
|||
*/
|
||||
public void write(BinaryStruct struct) throws IOException {
|
||||
List<BinaryFieldData> structDataList = BinaryFieldData.getStructFieldList(struct.getClass());
|
||||
Map<Class, BinaryFieldSerializer> serializerCache = new HashMap<>();
|
||||
|
||||
for (BinaryFieldData field : structDataList) {
|
||||
if (field.getSerializer() != null) {
|
||||
if (field.hasSerializer()) {
|
||||
BinaryFieldSerializer serializer = serializerCache.get(field.getSerializerClass());
|
||||
if (serializer == null) {
|
||||
serializer = field.getSerializer();
|
||||
serializerCache.put(serializer.getClass(), serializer);
|
||||
}
|
||||
|
||||
localFlush();
|
||||
field.getSerializer().write(out, field.getValue(struct), field);
|
||||
}
|
||||
else {
|
||||
serializer.write(out, field.getValue(struct), field);
|
||||
} else {
|
||||
int fieldBitLength = field.getBitLength(struct);
|
||||
byte[] data = field.getByteValue(struct);
|
||||
data = ByteUtil.shiftRight(data, ((8 - fieldBitLength % 8) % 8));
|
||||
|
|
@ -100,7 +110,7 @@ public class BinaryStructOutputStream {
|
|||
if (restBitLength == 0 && fieldBitLength >= 8)
|
||||
out.write(0xFF & b);
|
||||
else {
|
||||
b = (byte)((b&0xFF) >> restBitLength);
|
||||
b = (byte) ((b & 0xFF) >> restBitLength);
|
||||
b &= ByteUtil.getBitMask(7 - restBitLength, fieldBitLength);
|
||||
rest |= b;
|
||||
restBitLength += fieldBitLength;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue