Skip to content

Commit 531e0f1

Browse files
committed
started 1.2.0 version, improved compilation and parsing to support fields of custom types
1 parent 654412a commit 531e0f1

14 files changed

+655
-44
lines changed

changelog.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
Change log
22
--------------------------
33

4-
1.1.1
4+
1.2.0
55
- Refactoring
66
- Improved tree of JBBP exceptions
77
- Fixed NPE in JBBPTextWriter for String field mapped to byte array
8+
- Added support of custom field types through JBBPCustomFieldTypeProcessor
9+
- Added JBBPCustomFieldTypeProcessorAggregator, auxiliary class to join several JBBPCustomFieldTypeProcessors
810

911
1.1.0
1012
- Added support to write mapped classes into JBBPOut

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.igormaznitsa</groupId>
66
<artifactId>jbbp</artifactId>
7-
<version>1.1.1-SNAPSHOT</version>
7+
<version>1.2.0-SNAPSHOT</version>
88
<packaging>jar</packaging>
99

1010
<name>jbbp</name>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2015 Igor Maznitsa.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.igormaznitsa.jbbp;
17+
18+
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
19+
import com.igormaznitsa.jbbp.compiler.tokenizer.JBBPFieldTypeParameterContainer;
20+
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
21+
import com.igormaznitsa.jbbp.io.JBBPBitOrder;
22+
import com.igormaznitsa.jbbp.model.JBBPAbstractField;
23+
import java.io.IOException;
24+
25+
/**
26+
* Allows to define and process own custom field types during parsing.
27+
*
28+
* @since 1.2.0
29+
*/
30+
public interface JBBPCustomFieldTypeProcessor {
31+
/**
32+
* Get custom types of fields supported by the custom type field processor.
33+
* @return array of strings where every string is custom field type in lower-case.
34+
*/
35+
String [] getCustomFieldTypes();
36+
37+
/**
38+
* Called by compiler to check parameters for custom field.
39+
* @param fieldType field type info, it must not be null
40+
* @param fieldName name of the field, it can be null for anonymous fields
41+
* @param extraData number placed as extra value for field, followed by ':' if not presented then zero
42+
* @param isArray flag shows that the field describes an array
43+
* @return true if such configuration allowed, false otherwise
44+
*/
45+
boolean isAllowed(JBBPFieldTypeParameterContainer fieldType, String fieldName, int extraData, boolean isArray);
46+
47+
/**
48+
* Read custom field from stream and return the data as a JBBP field.
49+
* @param in the data source stream, must not be null
50+
* @param bitOrder the bit order defined for parsing, must not be null
51+
* @param parserFlags the flags defined for parsing
52+
* @param customTypeFieldInfo the current field type info, must not be null
53+
* @param fieldName the field name info, it can be null if the field is anonymous one
54+
* @param extraData extra numeric value for the field, followed by ':', if not presented then 0
55+
* @param readWholeStream if true then the field is array which should contain parse data for whole stream till the end
56+
* @param arrayLength -1 if it is not array else length of the array to be read.
57+
* @return parsed data as JBBP field, must not be null
58+
* @throws IOException it can be thrown for transport errors
59+
*/
60+
JBBPAbstractField readCustomFieldType(JBBPBitInputStream in, JBBPBitOrder bitOrder, int parserFlags, JBBPFieldTypeParameterContainer customTypeFieldInfo, JBBPNamedFieldInfo fieldName, int extraData, boolean readWholeStream, int arrayLength) throws IOException;
61+
}

src/main/java/com/igormaznitsa/jbbp/JBBPParser.java

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.igormaznitsa.jbbp;
1717

1818
import com.igormaznitsa.jbbp.compiler.*;
19+
import com.igormaznitsa.jbbp.compiler.tokenizer.JBBPFieldTypeParameterContainer;
1920
import com.igormaznitsa.jbbp.compiler.varlen.JBBPIntegerValueEvaluator;
2021
import com.igormaznitsa.jbbp.exceptions.JBBPParsingException;
2122
import com.igormaznitsa.jbbp.io.*;
@@ -61,21 +62,28 @@ public final class JBBPParser {
6162
private final int flags;
6263

6364
/**
64-
* The Constructor.
65+
* Custom field type processor for the parser, it can be null.
66+
*/
67+
private final JBBPCustomFieldTypeProcessor customFieldTypeProcessor;
68+
69+
/**
70+
* Constructor.
6571
*
6672
* @param source the source script to parse binary blocks and streams, must
6773
* not be null
6874
* @param bitOrder the bit order for bit reading operations, must not be null
75+
* @param customFieldTypeProcessor custom field type processor for the parser instance, it can be null
6976
* @param flags special flags for parsing process
7077
* @see #FLAG_SKIP_REMAINING_FIELDS_IF_EOF
7178
*/
72-
private JBBPParser(final String source, final JBBPBitOrder bitOrder, final int flags) {
79+
private JBBPParser(final String source, final JBBPBitOrder bitOrder, final JBBPCustomFieldTypeProcessor customFieldTypeProcessor, final int flags) {
7380
JBBPUtils.assertNotNull(source, "Script is null");
7481
JBBPUtils.assertNotNull(bitOrder, "Bit order is null");
82+
this.customFieldTypeProcessor = customFieldTypeProcessor;
7583
this.bitOrder = bitOrder;
7684
this.flags = flags;
7785
try {
78-
this.compiledBlock = JBBPCompiler.compile(source);
86+
this.compiledBlock = JBBPCompiler.compile(source, customFieldTypeProcessor);
7987
}
8088
catch (IOException ex) {
8189
throw new RuntimeException("Can't compile script for unexpected IOException", ex);
@@ -231,6 +239,15 @@ private List<JBBPAbstractField> parseStruct(final JBBPBitInputStream inStream, f
231239
}
232240
}
233241
break;
242+
case JBBPCompiler.CODE_CUSTOMTYPE: {
243+
if (resultNotIgnored){
244+
final int extraData = JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
245+
final JBBPFieldTypeParameterContainer fieldTypeInfo = this.compiledBlock.getCustomTypeFields()[JBBPUtils.unpackInt(compiled, positionAtCompiledBlock)];
246+
final JBBPAbstractField field = this.customFieldTypeProcessor.readCustomFieldType(inStream, this.bitOrder, this.flags, fieldTypeInfo, name, extraData, wholeStreamArray, arrayLength);
247+
JBBPUtils.assertNotNull(field, "Must not return null as read result");
248+
structureFields.add(field);
249+
}
250+
}break;
234251
case JBBPCompiler.CODE_BOOL: {
235252
if (resultNotIgnored) {
236253
if (arrayLength < 0) {
@@ -511,7 +528,7 @@ public JBBPFieldStruct parse(final byte[] array, final JBBPVarFieldProcessor var
511528
* @see JBBPBitOrder#MSB0
512529
*/
513530
public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrder) {
514-
return new JBBPParser(script, bitOrder, 0);
531+
return new JBBPParser(script, bitOrder, null, 0);
515532
}
516533

517534
/**
@@ -529,9 +546,27 @@ public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrde
529546
* @since 1.1
530547
*/
531548
public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrder, final int flags) {
532-
return new JBBPParser(script, bitOrder, flags);
549+
return new JBBPParser(script, bitOrder, null, flags);
533550
}
534551

552+
/**
553+
* Prepare a parser for a script with defined bit order and special flags.
554+
*
555+
* @param script a text script contains field order and types reference, it
556+
* must not be null
557+
* @param bitOrder the bit order for reading operations, it must not be null
558+
* @param customFieldTypeProcessor custom field type processor, it can be null
559+
* @param flags special flags for parsing
560+
* @return the prepared parser for the script
561+
* @see JBBPBitOrder#LSB0
562+
* @see JBBPBitOrder#MSB0
563+
* @see #FLAG_SKIP_REMAINING_FIELDS_IF_EOF
564+
*
565+
* @since 1.1.1
566+
*/
567+
public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrder, final JBBPCustomFieldTypeProcessor customFieldTypeProcessor, final int flags) {
568+
return new JBBPParser(script, bitOrder, customFieldTypeProcessor, flags);
569+
}
535570

536571
/**
537572
* Prepare a parser for a script with default bit order (LSB0) use.

src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiledBlock.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.igormaznitsa.jbbp.compiler;
1717

18+
import com.igormaznitsa.jbbp.compiler.tokenizer.JBBPFieldTypeParameterContainer;
1819
import com.igormaznitsa.jbbp.compiler.varlen.JBBPIntegerValueEvaluator;
1920
import com.igormaznitsa.jbbp.exceptions.JBBPException;
2021
import com.igormaznitsa.jbbp.exceptions.JBBPIllegalArgumentException;
@@ -40,11 +41,17 @@ public final class JBBPCompiledBlock {
4041
* The Compiled script data.
4142
*/
4243
private final byte[] compiledArray;
44+
4345
/**
4446
* The Array of variable size array evaluators.
4547
*/
4648
private final JBBPIntegerValueEvaluator[] arraySizeEvaluators;
4749

50+
/**
51+
* The Array of variable size array evaluators.
52+
*/
53+
private final JBBPFieldTypeParameterContainer[] customTypeFields;
54+
4855
/**
4956
* The Flag shows that the compiled block contains var fields.
5057
*/
@@ -60,6 +67,7 @@ public final static class Builder {
6067
private byte[] compiledData;
6168
private boolean hasVarFields;
6269
private final List<JBBPIntegerValueEvaluator> varLenProcessors = new ArrayList<JBBPIntegerValueEvaluator>();
70+
private final List<JBBPFieldTypeParameterContainer> customTypeFields = new ArrayList<JBBPFieldTypeParameterContainer>();
6371

6472
/**
6573
* Build a compiled block based on the data and check that all needed data
@@ -72,7 +80,7 @@ public JBBPCompiledBlock build() {
7280
JBBPUtils.assertNotNull(source, "Source is not defined");
7381
JBBPUtils.assertNotNull(compiledData, "Compiled data is not defined");
7482

75-
return new JBBPCompiledBlock(this.source, this.namedFields.toArray(new JBBPNamedFieldInfo[this.namedFields.size()]), this.varLenProcessors.isEmpty() ? null : this.varLenProcessors.toArray(new JBBPIntegerValueEvaluator[this.varLenProcessors.size()]), this.compiledData, this.hasVarFields);
83+
return new JBBPCompiledBlock(this.source, this.namedFields.toArray(new JBBPNamedFieldInfo[this.namedFields.size()]), this.varLenProcessors.isEmpty() ? null : this.varLenProcessors.toArray(new JBBPIntegerValueEvaluator[this.varLenProcessors.size()]), this.compiledData, this.hasVarFields, this.customTypeFields.toArray(new JBBPFieldTypeParameterContainer[this.customTypeFields.size()]));
7684
}
7785

7886
/**
@@ -136,6 +144,19 @@ public Builder setArraySizeEvaluators(final List<JBBPIntegerValueEvaluator> eval
136144
}
137145
return this;
138146
}
147+
148+
/**
149+
* Set list of fields processed by custom type field processor.
150+
* @param list list of field token info, it can be null
151+
* @return this object
152+
*/
153+
public Builder setCustomTypeFields(final List<JBBPFieldTypeParameterContainer> list){
154+
this.customTypeFields.clear();
155+
if (list != null) {
156+
this.customTypeFields.addAll(list);
157+
}
158+
return this;
159+
}
139160
}
140161

141162
/**
@@ -156,12 +177,13 @@ public static Builder prepare() {
156177
* @param compiledData compiled data block
157178
* @param hasVarFields the flag shows that te block contains var fields
158179
*/
159-
private JBBPCompiledBlock(final String source, final JBBPNamedFieldInfo[] namedFields, final JBBPIntegerValueEvaluator[] arraySizeEvaluators, final byte[] compiledData, final boolean hasVarFields) {
180+
private JBBPCompiledBlock(final String source, final JBBPNamedFieldInfo[] namedFields, final JBBPIntegerValueEvaluator[] arraySizeEvaluators, final byte[] compiledData, final boolean hasVarFields, final JBBPFieldTypeParameterContainer [] customTypeFields) {
160181
this.source = source;
161182
this.namedFieldData = namedFields;
162183
this.hasVarFields = hasVarFields;
163184
this.compiledArray = compiledData;
164185
this.arraySizeEvaluators = arraySizeEvaluators;
186+
this.customTypeFields = customTypeFields;
165187
}
166188

167189
/**
@@ -210,6 +232,14 @@ public JBBPNamedFieldInfo[] getNamedFields() {
210232
return this.namedFieldData;
211233
}
212234

235+
/**
236+
* Get array contains parameter info of detected custom type fields.
237+
* @return the array contains the info for every registered custom type field.
238+
*/
239+
public JBBPFieldTypeParameterContainer[] getCustomTypeFields(){
240+
return this.customTypeFields;
241+
}
242+
213243
/**
214244
* Get the array size evaluators
215245
*

0 commit comments

Comments
 (0)