Skip to content

Commit ebb1750

Browse files
committed
#28 added JBBPOut#BinForceByteOrder to override byte order defined in @bin annotations of written object.
1 parent 8442f25 commit ebb1750

File tree

8 files changed

+273
-8
lines changed

8 files changed

+273
-8
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ Java has some embedded features to parse binary data (for instance ByteBuffer),
1212
![Use cases](https://github.com/raydac/java-binary-block-parser/blob/master/docs/jbbp_mm.png)
1313

1414
# Change log
15+
- **2.0.2 (SNAPSHOT)**
16+
- [#28](https://github.com/raydac/java-binary-block-parser/issues/28) added `JBBPOut#BinForceByteOrder` to override byte order defined in `@Bin` annotations of written object.
17+
1518
- **2.0.1 (04-feb-2020)**
1619
- [#26](https://github.com/raydac/java-binary-block-parser/issues/26) fixed bug in array write with MSB0
1720

changelog.txt

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2.0.2 (SNAPSHOT)
2+
- [#28](https://github.com/raydac/java-binary-block-parser/issues/28) added `JBBPOut#BinForceByteOrder` to override byte order defined in `@Bin` annotations of written object.
3+
14
2.0.1
25
- [#26](https://github.com/raydac/java-binary-block-parser/issues/26) fixed bug in array write with MSB0
36

jbbp/src/main/java/com/igormaznitsa/jbbp/io/AbstractMappedClassFieldObserver.java

+21-5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.igormaznitsa.jbbp.model.JBBPFieldLong;
2727
import com.igormaznitsa.jbbp.model.JBBPFieldShort;
2828
import com.igormaznitsa.jbbp.model.JBBPFieldString;
29+
import com.igormaznitsa.jbbp.utils.BinAnnotationWrapper;
2930
import com.igormaznitsa.jbbp.utils.JBBPUtils;
3031
import java.lang.reflect.Array;
3132
import java.lang.reflect.Field;
@@ -75,10 +76,12 @@ private static void assertFieldArray(final Field field) {
7576
*
7677
* @param obj an object which is an instance of a mapped class, must not be null
7778
* @param field a field where the object has been found, it can be null for first call
79+
* @param forceByteOrder value to replace all byte order values in processing oject, can be null
7880
* @param customFieldProcessor a processor for custom fields, it can be null
7981
* @see Bin
82+
* @since 2.0.2
8083
*/
81-
protected void processObject(final Object obj, Field field, final Object customFieldProcessor) {
84+
protected void processObject(final Object obj, Field field, final JBBPByteOrder forceByteOrder, final Object customFieldProcessor) {
8285
JBBPUtils.assertNotNull(obj, "Object must not be null");
8386

8487
final List<MappedFieldRecord> orderedFields = JBBPMapper.findAffectedFields(obj);
@@ -95,7 +98,7 @@ protected void processObject(final Object obj, Field field, final Object customF
9598
throw new JBBPIllegalArgumentException("Class '" + obj.getClass().getName() + "' contains field '" + rec.mappingField.getName() + "\' which is custom one, you must provide JBBPCustomFieldWriter instance to save it.");
9699
}
97100

98-
processObjectField(obj, rec, binAnno, customFieldProcessor);
101+
processObjectField(obj, rec, forceByteOrder, binAnno, customFieldProcessor);
99102
}
100103

101104
this.onStructEnd(obj, field, clazzAnno == null ? fieldAnno : clazzAnno);
@@ -106,13 +109,26 @@ protected void processObject(final Object obj, Field field, final Object customF
106109
*
107110
* @param obj the object which field under processing, must not be null
108111
* @param fieldRecord internal record about the field, must not be null
112+
* @param forceByteOrder byte order to replace byte order defined for field, can be null
109113
* @param annotation the annotation to be used as data source about the field,
110114
* must not be null
111115
* @param customFieldProcessor an object which will be provided for processing
112116
* of custom fields, must not be null if object contains custom fields
117+
* @since 2.0.2
113118
*/
114-
protected void processObjectField(final Object obj, final MappedFieldRecord fieldRecord, final Bin annotation, final Object customFieldProcessor) {
119+
protected void processObjectField(
120+
final Object obj,
121+
final MappedFieldRecord fieldRecord,
122+
final JBBPByteOrder forceByteOrder,
123+
Bin annotation,
124+
final Object customFieldProcessor
125+
) {
115126
final Field field = fieldRecord.mappingField;
127+
128+
if (forceByteOrder != null) {
129+
annotation = new BinAnnotationWrapper(annotation).setByteOrder(forceByteOrder);
130+
}
131+
116132
if (annotation.custom()) {
117133
this.onFieldCustom(obj, field, annotation, customFieldProcessor, readFieldValue(obj, fieldRecord));
118134
} else {
@@ -233,7 +249,7 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
233249
}
234250
break;
235251
case STRUCT: {
236-
processObject(readFieldValue(obj, fieldRecord), field, customFieldProcessor);
252+
processObject(readFieldValue(obj, fieldRecord), field, forceByteOrder, customFieldProcessor);
237253
}
238254
break;
239255
default: {
@@ -428,7 +444,7 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
428444
final int len = Array.getLength(array);
429445
this.onArrayStart(obj, field, annotation, len);
430446
for (int i = 0; i < len; i++) {
431-
this.processObject(Array.get(array, i), field, customFieldProcessor);
447+
this.processObject(Array.get(array, i), field, forceByteOrder, customFieldProcessor);
432448
}
433449
this.onArrayEnd(obj, field, annotation);
434450
}

jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOut.java

+32-1
Original file line numberDiff line numberDiff line change
@@ -1026,9 +1026,40 @@ public JBBPOut Bin(final Object object) throws IOException {
10261026
*/
10271027
public JBBPOut Bin(final Object object, final JBBPCustomFieldWriter customFieldWriter) {
10281028
if (this.processCommands) {
1029-
this.processObject(object, null, customFieldWriter);
1029+
this.processObject(object, null, null, customFieldWriter);
10301030
}
1031+
return this;
1032+
}
10311033

1034+
/**
1035+
* Works like {@link #Bin(Object)} but forcing override of all annotation byte order values by the JBBPOut byte order.
1036+
*
1037+
* @param object an object to be saved into stream, must not be null
1038+
* @return the context
1039+
* @throws IOException it will be thrown for any transport error
1040+
* @see JBBPMapper#clearFieldCache()
1041+
* @see Bin
1042+
* @see Bin#byteOrder()
1043+
* @since 2.0.2
1044+
*/
1045+
public JBBPOut BinForceByteOrder(final Object object) throws IOException {
1046+
return this.BinForceByteOrder(object, null);
1047+
}
1048+
1049+
/**
1050+
* Works like {@link #Bin(Object, JBBPCustomFieldWriter)} but forcing override of all annotation byte order values by the JBBPOut byte order.
1051+
*
1052+
* @param object an object to be saved into stream, must not be null
1053+
* @param customFieldWriter a custom field writer to be used for saving of
1054+
* custom fields of the object, it can be null
1055+
* @return the context
1056+
* @see Bin#byteOrder()
1057+
* @since 2.0.2
1058+
*/
1059+
public JBBPOut BinForceByteOrder(final Object object, final JBBPCustomFieldWriter customFieldWriter) {
1060+
if (this.processCommands) {
1061+
this.processObject(object, null, this.byteOrder, customFieldWriter);
1062+
}
10321063
return this;
10331064
}
10341065

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package com.igormaznitsa.jbbp.utils;
2+
3+
import com.igormaznitsa.jbbp.io.JBBPBitNumber;
4+
import com.igormaznitsa.jbbp.io.JBBPBitOrder;
5+
import com.igormaznitsa.jbbp.io.JBBPByteOrder;
6+
import com.igormaznitsa.jbbp.mapper.Bin;
7+
import com.igormaznitsa.jbbp.mapper.BinType;
8+
import java.lang.annotation.Annotation;
9+
10+
/**
11+
* Auxiliary class to replace Bin annotation fields during internal processing
12+
*
13+
* @since 2.0.
14+
*/
15+
public class BinAnnotationWrapper implements Bin {
16+
private final Bin bin;
17+
private String name;
18+
private String path;
19+
private String customType;
20+
private String arraySizeExpr;
21+
private BinType type;
22+
private JBBPBitOrder bitOrder;
23+
private Boolean custom;
24+
private String paramExpr;
25+
private JBBPBitNumber bitNumber;
26+
private JBBPByteOrder byteOrder;
27+
private Integer order;
28+
private String comment;
29+
30+
public BinAnnotationWrapper(final Bin bin) {
31+
this.bin = bin;
32+
}
33+
34+
public BinAnnotationWrapper setName(final String value) {
35+
this.name = value;
36+
return this;
37+
}
38+
39+
@Override
40+
public String name() {
41+
return this.name == null ? this.bin.name() : this.name;
42+
}
43+
44+
public BinAnnotationWrapper setPath(final String value) {
45+
this.path = value;
46+
return this;
47+
}
48+
49+
@Override
50+
public String path() {
51+
return this.path == null ? this.bin.path() : this.path;
52+
}
53+
54+
public BinAnnotationWrapper setCustomType(final String value) {
55+
this.customType = value;
56+
return this;
57+
}
58+
59+
@Override
60+
public String customType() {
61+
return this.customType == null ? this.bin.customType() : this.customType;
62+
}
63+
64+
public BinAnnotationWrapper setArraySizeExpr(final String value) {
65+
this.arraySizeExpr = value;
66+
return this;
67+
}
68+
69+
@Override
70+
public String arraySizeExpr() {
71+
return this.arraySizeExpr == null ? this.bin.arraySizeExpr() : this.arraySizeExpr;
72+
}
73+
74+
public BinAnnotationWrapper setType(final BinType value) {
75+
this.type = value;
76+
return this;
77+
}
78+
79+
@Override
80+
public BinType type() {
81+
return this.type == null ? this.bin.type() : this.type;
82+
}
83+
84+
public BinAnnotationWrapper setBitOrder(final JBBPBitOrder value) {
85+
this.bitOrder = value;
86+
return this;
87+
}
88+
89+
@Override
90+
public JBBPBitOrder bitOrder() {
91+
return this.bitOrder == null ? this.bin.bitOrder() : this.bitOrder;
92+
}
93+
94+
public BinAnnotationWrapper setCustom(final Boolean value) {
95+
this.custom = value;
96+
return this;
97+
}
98+
99+
@Override
100+
public boolean custom() {
101+
return this.custom == null ? this.bin.custom() : this.custom;
102+
}
103+
104+
public BinAnnotationWrapper setParamExpr(final String value) {
105+
this.paramExpr = value;
106+
return this;
107+
}
108+
109+
@Override
110+
public String paramExpr() {
111+
return this.paramExpr == null ? this.bin.paramExpr() : this.paramExpr;
112+
}
113+
114+
public BinAnnotationWrapper setBitNumber(final JBBPBitNumber value) {
115+
this.bitNumber = value;
116+
return this;
117+
}
118+
119+
@Override
120+
public JBBPBitNumber bitNumber() {
121+
return this.bitNumber == null ? this.bin.bitNumber() : this.bitNumber;
122+
}
123+
124+
public BinAnnotationWrapper setByteOrder(final JBBPByteOrder value) {
125+
this.byteOrder = value;
126+
return this;
127+
}
128+
129+
@Override
130+
public JBBPByteOrder byteOrder() {
131+
return this.byteOrder == null ? this.bin.byteOrder() : this.byteOrder;
132+
}
133+
134+
public BinAnnotationWrapper setOrder(final Integer value) {
135+
this.order = value;
136+
return this;
137+
}
138+
139+
@Override
140+
public int order() {
141+
return this.order == null ? this.bin.order() : this.order;
142+
}
143+
144+
public BinAnnotationWrapper setComment(final String value) {
145+
this.comment = value;
146+
return this;
147+
}
148+
149+
@Override
150+
public String comment() {
151+
return this.comment == null ? this.bin.comment() : this.comment;
152+
}
153+
154+
@Override
155+
public Class<? extends Annotation> annotationType() {
156+
return this.bin.getClass();
157+
}
158+
}

jbbp/src/main/java/com/igormaznitsa/jbbp/utils/JBBPTextWriter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -2004,7 +2004,7 @@ protected void onFieldCustom(final Object obj, final Field field, final Bin anno
20042004
}
20052005

20062006
public void processObject(final Object obj) {
2007-
super.processObject(obj, null, this);
2007+
super.processObject(obj, null, null, this);
20082008
}
20092009
}
20102010

jbbp/src/test/java/com/igormaznitsa/jbbp/io/JBBPOutTest.java

+49
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,55 @@ class Test {
773773
assertArrayEquals(new byte[] {1, (byte) 0x80, 0}, BeginBin().Bin(new Test(true, true, false)).End().toByteArray());
774774
}
775775

776+
@Test
777+
public void testBin_ForceByteOrder() throws Exception {
778+
class DefaultByteOrder {
779+
@Bin
780+
int value = 0x01020304;
781+
}
782+
783+
class BigEndianByteOrder {
784+
@Bin(byteOrder = JBBPByteOrder.BIG_ENDIAN)
785+
int value = 0x01020304;
786+
}
787+
788+
class LittleEndianByteOrder {
789+
@Bin(byteOrder = JBBPByteOrder.LITTLE_ENDIAN)
790+
int value = 0x01020304;
791+
}
792+
793+
class LittleEndianByteOrderWithStructure {
794+
795+
@Bin(byteOrder = JBBPByteOrder.LITTLE_ENDIAN, order = 1)
796+
int value = 0x01020304;
797+
@Bin(order = 2)
798+
Internal internal = new Internal();
799+
800+
class Internal {
801+
@Bin(byteOrder = JBBPByteOrder.BIG_ENDIAN)
802+
int value = 0x05060708;
803+
}
804+
}
805+
806+
final byte[] defaultOrder = JBBPOut.BeginBin().ByteOrder(JBBPByteOrder.LITTLE_ENDIAN).BinForceByteOrder(new DefaultByteOrder()).End().toByteArray();
807+
assertArrayEquals(new byte[] {4, 3, 2, 1}, defaultOrder);
808+
809+
final byte[] bigEndianOrder = JBBPOut.BeginBin().ByteOrder(JBBPByteOrder.LITTLE_ENDIAN).BinForceByteOrder(new BigEndianByteOrder()).End().toByteArray();
810+
assertArrayEquals(new byte[] {4, 3, 2, 1}, bigEndianOrder);
811+
812+
final byte[] littleEndianOrder = JBBPOut.BeginBin().ByteOrder(JBBPByteOrder.BIG_ENDIAN).BinForceByteOrder(new LittleEndianByteOrder()).End().toByteArray();
813+
assertArrayEquals(new byte[] {1, 2, 3, 4}, littleEndianOrder);
814+
815+
final byte[] littleEndianOrderWithStruct = JBBPOut.BeginBin().ByteOrder(JBBPByteOrder.BIG_ENDIAN).BinForceByteOrder(new LittleEndianByteOrderWithStructure()).End().toByteArray();
816+
assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8}, littleEndianOrderWithStruct);
817+
818+
final byte[] littleEndianOrderWithStructBin = JBBPOut.BeginBin().ByteOrder(JBBPByteOrder.LITTLE_ENDIAN).Bin(new LittleEndianByteOrderWithStructure()).End().toByteArray();
819+
assertArrayEquals(new byte[] {4, 3, 2, 1, 5, 6, 7, 8}, littleEndianOrderWithStructBin);
820+
821+
final byte[] littleEndianOrderWithStructLe = JBBPOut.BeginBin().ByteOrder(JBBPByteOrder.LITTLE_ENDIAN).BinForceByteOrder(new LittleEndianByteOrderWithStructure()).End().toByteArray();
822+
assertArrayEquals(new byte[] {4, 3, 2, 1, 8, 7, 6, 5}, littleEndianOrderWithStructLe);
823+
}
824+
776825
@Test
777826
public void testBin_BitType_Bits() throws Exception {
778827
class Test {

pom.xml

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
<modules>
1111
<module>jbbp</module>
12-
<module>jbbp-plugins</module>
1312
</modules>
1413

1514
<url>https://github.com/raydac/java-binary-block-parser</url>
@@ -116,6 +115,12 @@
116115
</dependencies>
117116

118117
<profiles>
118+
<profile>
119+
<id>plugins</id>
120+
<modules>
121+
<module>jbbp-plugins</module>
122+
</modules>
123+
</profile>
119124
<profile>
120125
<id>bundle</id>
121126
<activation>

0 commit comments

Comments
 (0)