diff --git a/.gitignore b/.gitignore
index 7e65dc8e..cb2f51b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,42 +1,30 @@
/**/target/
/target/
/nbproject/
-/.idea/
+/**/.idea/
*.iml
/jbbp-plugins/jbbp-gradle/.gradle/
/jbbp-plugins/jbbp-gradle/build/
/jbbp/BenchmarkList
/jbbp/CompilerHints
/jbbp/nb-configuration.xml
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/common/converters/Java16Converter.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/common/converters/JBBPScriptTranslator$Parameters.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/common/converters/JBBPScriptTranslator.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/common/converters/ParserFlags.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/common/converters/Target.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/common/utils/CommonUtils.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/mvn/AbstractJBBPMojo.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/mvn/HelpMojo.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/mvn/JBBPCleanMojo.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojo$1.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojo.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/META-INF/maven/com.igormaznitsa/jbbp-maven-plugin/plugin-help.xml
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/classes/META-INF/maven/plugin.xml
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/generated-sources/plugin/com/igormaznitsa/jbbp/plugin/mvn/HelpMojo.java
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/maven-archiver/pom.properties
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/surefire-reports/TEST-com.igormaznitsa.jbbp.plugin.mvn.JBBPGenerateMojoTest.xml
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/test-classes/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojoTest.class
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/test-classes/com/igormaznitsa/jbbp/plugin/mvn/mojoConfig.xml
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/jbbp-maven-plugin-2.0.0-SNAPSHOT.jar
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/jbbp-maven-plugin-2.0.0-SNAPSHOT-bundle.jar
-/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/target/maven-plugin-help.properties
+/jbbp-plugins/**/target/
/jbbp/jmh-out.txt
/jbbp/jmh-result.json
/jbbp-plugins/jbbp-gradle/.settings/
/jbbp-plugins/jbbp-gradle/bin/
/jbbp-plugins/jbbp-gradle/.classpath
/jbbp-plugins/jbbp-gradle/.project
-/.vscode/
+/**/.vscode/
+/jbbp-plugins/jbbp-gradle/gradle/wrapper/
+/jbbp-plugins/jbbp-gradle/gradlew
+/jbbp-plugins/jbbp-gradle/gradlew.bat
+/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/build/
+/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/.gradle/
+/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/.gradle/
+/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/build/
+/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/.gradle/
+/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/build/
+/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/.gradle/
+/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/build/
+/jbbp/uber-pom.xml
diff --git a/.projectKnowledge/JBBP.mmd b/.projectKnowledge/JBBP.mmd
index 2aa92079..4f9496d7 100644
--- a/.projectKnowledge/JBBP.mmd
+++ b/.projectKnowledge/JBBP.mmd
@@ -1,8 +1,8 @@
-Mind Map generated by NB MindMap plugin
+[Scia Reto](https://sciareto.org) mind map
> __version__=`1.1`,showJumps=`true`
---
-# Java Binary Block Parser v 2\.0\.1
+# Java Binary Block Parser v 3\.0\.1
## License
> fillColor=`#33CC00`,leftSide=`true`
@@ -16,11 +16,11 @@ Mind Map generated by NB MindMap plugin
> fillColor=`#CCCCFF`,leftSide=`true`
-### Java 1\.8\+
+### Java 11\+
> fillColor=`#3399FF`,textColor=`#FFFFCC`
-### Android 3\.0\+
+### Android 12\+
> fillColor=`#3399FF`,textColor=`#FFFFCC`
diff --git a/.projectKnowledge/JBBP_Types.mmd b/.projectKnowledge/JBBP_Types.mmd
index 1cfc8826..1fa5bdc4 100644
--- a/.projectKnowledge/JBBP_Types.mmd
+++ b/.projectKnowledge/JBBP_Types.mmd
@@ -82,6 +82,22 @@ Mind Map generated by NB MindMap plugin
> fillColor=`#99FFFF`
+#### uint
+> fillColor=`#9999FF`
+
+
+##### 32 bit unsigned field
+> fillColor=`#99FFFF`
+
+
+###### requires long representation
+> fillColor=`#FF6666`,mmd.emoticon=`error`
+
+
+###### can throw error in expression if value can\\t be represented as zero or positive int
+> fillColor=`#FF6666`,mmd.emoticon=`error`
+
+
#### long
> fillColor=`#9999FF`
diff --git a/README.md b/README.md
index 05b8329b..8523e1c2 100644
--- a/README.md
+++ b/README.md
@@ -1,128 +1,183 @@
+
+
[](http://www.apache.org/licenses/LICENSE-2.0)
-[](http://search.maven.org/#artifactdetails|com.igormaznitsa|jbbp|2.0.1|jar)
-[](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
-[](http://developer.android.com/sdk/index.html)
-[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=AHWJHJFBAWGL2)
-[](http://yasobe.ru/na/iamoss)
+[](http://search.maven.org/#artifactdetails|com.igormaznitsa|jbbp|3.0.1|jar)
+[](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
+[](http://developer.android.com/sdk/index.html)
+[](https://www.arthursacresanimalsanctuary.org/donate)
-
# Introduction
-Java has some embedded features to parse binary data (for instance ByteBuffer), but sometime it is needed to work on bit level and describe binary structures through some DSL(domain specific language). I was impressed by the [the Python Struct package](https://docs.python.org/2/library/struct.html) package and wanted to get something like that for Java. So I developed the JBBP library.
+
+Java has some embedded features to parse binary data (for instance ByteBuffer), but sometime it is needed to work on bit
+level and describe binary structures through some DSL(domain specific language). I was impressed by
+the [the Python Struct package](https://docs.python.org/2/library/struct.html) package and wanted to get something like
+that for Java. So I developed the JBBP library.

# Change log
-- **2.0.1 (04-feb-2020)**
- - [#26](https://github.com/raydac/java-binary-block-parser/issues/26) fixed bug in array write with MSB0
-
-- **2.0.0 (20-nov-2019)**
- - __removed DslBinCustom annotation, use @Bin annotation instead__
- - __renamed attributes of @Bin annotation to their correct form__
- - __reworked object mapping system, removed hacks to instantiate classes, now only mapping to objects allowed, support of private fields mapping is removed__
- - __minimal JDK version now 1.8+__
- - __minimal Android API now 3.0+__
- - added support of getters and setters into mapping
- - added `Object newInstance(Class)` method support of mapped classes to generate local class member instances
- - added generating of `makeFIELD()` method for structure types in Java class converter
- - refactoring
-
-- **1.4.1 (20-aug-2018)**
- - fixed incompatibility in tokenizer regex syntax for Android SDK [#23](https://github.com/raydac/java-binary-block-parser/issues/23)
- - added DslBinCustom annotation to provide way to mark custom type fields for JBBPDslBuilder
- - fixed NPE in JBBPDslBuilder for not-provided outBitNumber attribute in annotated field marked as type BIT or BIT_ARRAY [#20](https://github.com/raydac/java-binary-block-parser/issues/20)
- - naming of fields has been made more tolerant, now it is allowed to have field names with names similar to data types
- - improved check of field names in JBBPDslBuilder [#21](https://github.com/raydac/java-binary-block-parser/issues/21)
-
-[Full changelog](https://github.com/raydac/java-binary-block-parser/blob/master/changelog.txt)
+
+- __3.0.1 (24-dec-2024)__
+ - added `MSB0_DIRECT` bit order mode, MSB0 without data
+ revers [#46](https://github.com/raydac/java-binary-block-parser/issues/46)
+ - added `JBBPBitInputStream#isDetectedPartlyReadBitField` to check that only part of bit field read during last
+ operation
+ - added flag into constructors for JBBPBitInputStream to force return -1 instead of partly accumulated bits data if
+ end of field
+
+- __3.0.0 (16-nov-2024)__
+ - __Minimum JDK Version: Updated to 11.0.__
+ - __Minimum Supported Android: Updated to 12 (API 32).__
+ - __API Changes:__ Modifications made to the CompiledBlockVisitor API.
+ - __New Feature:__ Added `JBBPUtils#findMaxStaticArraySize` for calculating the largest static array size defined in a
+ JBBP script.
+ - __Internal API:__ Certain internal APIs have been opened.
+ - __Codebase Improvements:__ General refactoring performed.
+
+- __2.1.0 (05-nov-2024)__
+ - minor changes in API for `JBBPVarFieldProcessor` and `JBBPCustomFieldTypeProcessor`
+ - provided way to control size of arrays read as stream
+ rest [#44](https://github.com/raydac/java-binary-block-parser/issues/44)
+ - provided way to control size of arrays which size calculated through
+ expressions [#45](https://github.com/raydac/java-binary-block-parser/issues/45)
+ - improved tests
+
+[Full changelog](https://github.com/raydac/java-binary-block-parser/blob/master/changelog.txt)
# Maven dependency
+
The Framework has been published in the Maven Central and can be easily added as a dependency
+
```
com.igormaznitsajbbp
- 2.0.1
+ 3.0.1
```
-the precompiled library jar, javadoc and sources also can be downloaded directly from [the Maven central.](https://search.maven.org/artifact/com.igormaznitsa/jbbp/2.0.1/jar)
+
+the precompiled library jar, javadoc and sources also can be downloaded directly
+from [the Maven central.](https://search.maven.org/artifact/com.igormaznitsa/jbbp/3.0.1/jar)
# Hello world
-The library is very easy in use because in many cases only two its classes are needed - com.igormaznitsa.jbbp.JBBPParser (for data parsing) and com.igormaznitsa.jbbp.io.JBBPOut (for binary block writing). Both these classes work over low-level IO classes - com.igormaznitsa.jbbp.io.JBBPBitInputStream and com.igormaznitsa.jbbp.io.JBBPBitOutputStream, those bit stream classes are the core of the library.
-The easiet use case shows parsing of whole byte array to bits.
+The library is very easy in use because in many cases only two its classes are needed -
+com.igormaznitsa.jbbp.JBBPParser (for data parsing) and com.igormaznitsa.jbbp.io.JBBPOut (for binary block writing).
+Both these classes work over low-level IO classes - com.igormaznitsa.jbbp.io.JBBPBitInputStream and
+com.igormaznitsa.jbbp.io.JBBPBitOutputStream, those bit stream classes are the core of the library.
+
+The easiet use case shows parsing of whole byte array to bits.
+
```Java
- byte [] parsedBits = JBBPParser.prepare("bit:1 [_];").parse(new byte[]{1,2,3,4,5}).
- findFieldForType(JBBPFieldArrayBit.class).getArray();
+ byte[]parsedBits=JBBPParser.prepare("bit:1 [_];").parse(new byte[]{1,2,3,4,5}).
+ findFieldForType(JBBPFieldArrayBit.class).getArray();
```
-On start it was the only functionality but then I found that it is no so comfort way to get result, so that added some mapping of parsed result to pre-instantiated object. It works slower, because uses a lot of Java reflection but much easy in some cases.
+
+On start it was the only functionality but then I found that it is no so comfort way to get result, so that added some
+mapping of parsed result to pre-instantiated object. It works slower, because uses a lot of Java reflection but much
+easy in some cases.
+
```Java
-class Parsed {@Bin(type = BinType.BIT_ARRAY)byte[] parsed;}
-Parsed parsedBits = JBBPParser.prepare("bit:1 [_] parsed;").parse(new byte[]{1,2,3,4,5}).mapTo(new Parsed());
+class Parsed {
+ @Bin(type = BinType.BIT_ARRAY)
+ byte[] parsed;
+}
+ Parsed parsedBits = JBBPParser.prepare("bit:1 [_] parsed;").parse(new byte[] {1, 2, 3, 4, 5}).mapTo(new Parsed());
```
# Relative speed of different approaches in parsing
-Mainly I developed the library to help in my development of ZX-Spectrum emulator where I needed to work with data snapshots containing data on bit level. It didn't need much productivity in work. But since 1.3.0 version I added way to generate Java classes from JBBP scripts, such classes work in about five times faster than dynamic parsing and mapping approaches.
+
+Mainly I developed the library to help in my development of ZX-Spectrum emulator where I needed to work with data
+snapshots containing data on bit level. It didn't need much productivity in work. But since 1.3.0 version I added way to
+generate Java classes from JBBP scripts, such classes work in about five times faster than dynamic parsing and mapping
+approaches.

Chart below compares speed of three provided ways to parse data with JBBP:
-* __Dynamic__ - the basic parsing through interpretation of prepared JBBP DSL script. It is no so fast, but provide way to generate parsers on fly from text description.
-* __Dynamic + map to class__ - parsing through interpretation of parsed JBBP script and mapping of parsed data to pre-instantiated class instance. It provides compfortable way to work with data and get result but uses a lot of Java reflection features and so fast.
-* __Static class__ - the fastest way of JBBP use, some JBBP script is translated into Java class. There is no any interpretation or reflection operators so that it is very fast. [You can take a look at auxiliary class which I use in tests](https://github.com/raydac/java-binary-block-parser/blob/master/jbbp/src/test/java/com/igormaznitsa/jbbp/testaux/AbstractJBBPToJavaConverterTest.java).
+* __Dynamic__ - the basic parsing through interpretation of prepared JBBP DSL script. It is no so fast, but provide way
+ to generate parsers on fly from text description.
+* __Dynamic + map to class__ - parsing through interpretation of parsed JBBP script and mapping of parsed data to
+ pre-instantiated class instance. It provides compfortable way to work with data and get result but uses a lot of Java
+ reflection features and so fast.
+* __Static class__ - the fastest way of JBBP use, some JBBP script is translated into Java class. There is no any
+ interpretation or reflection operators so that it is very
+ fast. [You can take a look at auxiliary class which I use in tests](https://github.com/raydac/java-binary-block-parser/blob/master/jbbp/src/test/java/com/igormaznitsa/jbbp/testaux/AbstractJBBPToJavaConverterTest.java)
+ .
# Generate sources from JBBP scripts
-Since 1.3.0 version, the library provides Java source generator for JBBP scripts, __(keep in mind that generated sources anyway depends on JBBP library and it is needed for their work)__.
-For instance such snippet can be used to generate Java classes from a JBBP script. It also can generate multiple classes.
+
+Since 1.3.0 version, the library provides Java source generator for JBBP scripts, __(keep in mind that generated sources
+anyway depends on JBBP library and it is needed for their work)__. For instance such snippet can be used to generate
+Java classes from a JBBP script. It also can generate multiple classes.
+
```Java
- JBBPParser parser = JBBPParser.prepare("byte a; byte b; byte c;");
- List generated = parser.convertToSrc(TargetSources.JAVA,"com.test.jbbp.gen.SomeClazz");
- for(ResultSrcItem i : generated) {
- for(Map.Entry j :i.getResult().entrySet()) {
- System.out.println("Class file name "+j.getKey());
- System.out.println("Class file content "+j.getValue());
- }
+ JBBPParser parser=JBBPParser.prepare("byte a; byte b; byte c;");
+ List generated=parser.convertToSrc(TargetSources.JAVA,"com.test.jbbp.gen.SomeClazz");
+ for(ResultSrcItem i:generated){
+ for(Map.Entry j:i.getResult().entrySet()) {
+ System.out.println("Class file name "+j.getKey());
+ System.out.println("Class file content "+j.getValue());
+ }
}
```
-also there are developed plug-ins for both Maven and Gradle to generate sources from JBBP scripts during source generate phase.
+
+also there are developed plug-ins for both Maven and Gradle to generate sources from JBBP scripts during source generate
+phase.
in Maven it can be used through snippet:
+
```xml
-
- com.igormaznitsa
- jbbp-maven-plugin
- 2.0.1
-
-
- gen-jbbp-src
-
- generate
-
-
-
+
+
+ com.igormaznitsa
+ jbbp-maven-plugin
+ 3.0.1
+
+
+ gen-jbbp-src
+
+ generate
+
+
+
```
-By default the maven plug-in looks for files with `jbbp` extension in `src/jbbp` folder of the project (it can be changed through plug-in configuration) and produces resulting java classes into `target/generated-sources/jbbp` folder. [For instance, I use such approach in my ZX-Poly emulator](https://github.com/raydac/zxpoly/tree/master/zxpoly-emul/src/jbbp).
+
+By default the maven plug-in looks for files with `jbbp` extension in `src/jbbp` folder of the project (it can be
+changed through plug-in configuration) and produces resulting java classes into `target/generated-sources/jbbp`
+folder. [For instance, I use such approach in my ZX-Poly emulator](https://github.com/raydac/zxpoly/tree/master/zxpoly-emul/src/jbbp)
+.
# More complex example with features added as of 1.1.0
-Example below shows how to parse a byte stream written in non-standard MSB0 order (Java has LSB0 bit order) into bit fields, then print its values and pack fields back:
+
+Example below shows how to parse a byte stream written in non-standard MSB0 order (Java has LSB0 bit order) into bit
+fields, then print its values and pack fields back:
+
```Java
class Flags {
- @Bin(order = 1, name = "f1", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_1, comment = "It's flag one") byte flag1;
- @Bin(order = 2, name = "f2", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_2, comment = "It's second flag") byte flag2;
- @Bin(order = 3, name = "f3", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_1, comment = "It's 3th flag") byte flag3;
- @Bin(order = 4, name = "f4", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_4, comment = "It's 4th flag") byte flag4;
- }
-
- final int data = 0b10101010;
+ @Bin(order = 1, name = "f1", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_1, comment = "It's flag one")
+ byte flag1;
+ @Bin(order = 2, name = "f2", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_2, comment = "It's second flag")
+ byte flag2;
+ @Bin(order = 3, name = "f3", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_1, comment = "It's 3th flag")
+ byte flag3;
+ @Bin(order = 4, name = "f4", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_4, comment = "It's 4th flag")
+ byte flag4;
+}
+
+ final int data = 0b10101010;
Flags parsed = JBBPParser.prepare("bit:1 f1; bit:2 f2; bit:1 f3; bit:4 f4;", JBBPBitOrder.MSB0).parse(new byte[]{(byte)data}).mapTo(new Flags());
- assertEquals(1,parsed.flag1);
- assertEquals(2,parsed.flag2);
- assertEquals(0,parsed.flag3);
- assertEquals(5,parsed.flag4);
+ assertEquals(1, parsed.flag1);
+ assertEquals(2, parsed.flag2);
+ assertEquals(0, parsed.flag3);
+ assertEquals(5, parsed.flag4);
System.out.println(new JBBPTextWriter().Bin(parsed).Close().toString());
assertEquals(data, JBBPOut.BeginBin(JBBPBitOrder.MSB0).Bin(parsed).End().toByteArray()[0] & 0xFF);
```
+
The Example will print in console the text below
+
```
;--------------------------------------------------------------------------------
; START : Flags
@@ -135,32 +190,51 @@ The Example will print in console the text below
; END : Flags
;--------------------------------------------------------------------------------
```
+
# Fields
-Each field can have case insensitive name which must not contain '.' (because dot is reserved for links to structure field values) and '#'(because it is also reserved for internal library use).
-A field name must not be started with either number or chars '$' and '_'. *Keep in mind that field names are case insensitive!*
+
+Each field can have case insensitive name which must not contain '.' (because dot is reserved for links to structure
+field values) and '#'(because it is also reserved for internal library use). A field name must not be started with
+either number or chars '$' and '_'. *Keep in mind that field names are case insensitive!*
+
```
int someNamedField;
byte field1;
byte field2;
byte field3;
```
+

## Primitive types
+
JBBP supports full set of Java numeric primitives with some extra types like ubyte and bit.

+
## Complex types
-JBBP provides support both arrays and structures. __In expressions you can use links only to field values which already read!__
+
+JBBP provides support both arrays and structures. __In expressions you can use links only to field values which already
+read!__

## Custom types
-It is possible to define processors for custom data types. For instance you can take a look at [case processing three byte unsigned integer types](https://github.com/raydac/java-binary-block-parser/blob/master/jbbp/src/test/java/com/igormaznitsa/jbbp/it/CustomThreeByteIntegerTypeTest.java).
+
+It is possible to define processors for custom data types. For instance you can take a look
+at [case processing three byte unsigned integer types](https://github.com/raydac/java-binary-block-parser/blob/master/jbbp/src/test/java/com/igormaznitsa/jbbp/it/CustomThreeByteIntegerTypeTest.java)
+.
### Support of float, double and String types
-Since 1.4.0 in JBBP was added support of Java float, double and String values. Because they have specific format, they are named as `doublej`, `floatj` and `stringj`.
+
+Since 1.4.0 in JBBP was added support of Java float, double and String values. Because they have specific format, they
+are named as `doublej`, `floatj` and `stringj`.
## Variable fields
-If you have some data which internal structure is undefined and variable then you can use the `var` type to mark such field and provide custom processor to read data of such value. Processor should implement interface [JBBPVarFieldProcessor](https://github.com/raydac/java-binary-block-parser/blob/master/src/main/java/com/igormaznitsa/jbbp/JBBPVarFieldProcessor.java) instance.
+
+If you have some data which internal structure is undefined and variable then you can use the `var` type to mark such
+field and provide custom processor to read data of such value. Processor should implement
+interface [JBBPVarFieldProcessor](https://github.com/raydac/java-binary-block-parser/blob/master/src/main/java/com/igormaznitsa/jbbp/JBBPVarFieldProcessor.java)
+instance.
+
```
final JBBPParser parser = JBBPParser.prepare("short k; var; int;");
final JBBPIntCounter counter = new JBBPIntCounter();
@@ -177,24 +251,35 @@ If you have some data which internal structure is undefined and variable then yo
}
}, null);
```
-*NB! Some programmers trying to use only parser for complex data, it is a mistake. In the case it is much better to have several easy parsers working with the same [JBBPBitInputStream](https://github.com/raydac/java-binary-block-parser/blob/master/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java) instance, it allows to keep decision points on Java level and make solution easier.*
+
+*NB! Some programmers trying to use only parser for complex data, it is a mistake. In the case it is much better to have
+several easy parsers working with the
+same [JBBPBitInputStream](https://github.com/raydac/java-binary-block-parser/blob/master/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java)
+instance, it allows to keep decision points on Java level and make solution easier.*
## Special types
+
Special types makes some actions to skip data in input stream

## Byte order
+
Multi-byte types can be read with different byte order.

# Expressions
-Expressions are used for calculation of length of arrays and allow brackets and integer operators which work similar to Java operators:
+
+Expressions are used for calculation of length of arrays and allow brackets and integer operators which work similar to
+Java operators:
+
- Arithmetic operators: +,-,%,*,/,%
- Bit operators: &,|,^,~
- Shift operators: <<,>>,>>>
- Brackets: (, )
-Inside expression you can use integer numbers and named field values through their names (if you use fields from the same structure) or paths. Keep in your mind that you can't use array fields or fields placed inside structure arrays.
+Inside expression you can use integer numbers and named field values through their names (if you use fields from the
+same structure) or paths. Keep in your mind that you can't use array fields or fields placed inside structure arrays.
+
```
int field1;
struct1 {
@@ -204,7 +289,10 @@ int field1;
```
# Commentaries
-You can use commentaries inside a parser script, the parser supports the only comment format and recognizes as commentaries all text after '//' till the end of line.
+
+You can use commentaries inside a parser script, the parser supports the only comment format and recognizes as
+commentaries all text after '//' till the end of line.
+
```
int;
// hello commentaries
@@ -212,13 +300,23 @@ You can use commentaries inside a parser script, the parser supports the only co
```
# Expression macroses
-Inside expression you can use field names and field paths, also you can use the special macros '$$' which represents the current input stream byte counter, all fields started with '$' will be recognized by the parser as special user defined variables and it will be requesting them from special user defined provider. If the array size contains the only '_' symbol then the field or structure will not have defined size and whole stream will be read.
+
+Inside expression you can use field names and field paths, also you can use the special macros '$$' which represents the
+current input stream byte counter, all fields started with '$' will be recognized by the parser as special user defined
+variables and it will be requesting them from special user defined provider. If the array size contains the only '_'
+symbol then the field or structure will not have defined size and whole stream will be read.
# How to get result of parsing
-The Result of parsing is an instance of com.igormaznitsa.jbbp.model.JBBPFieldStruct class which represents the root invisible structure for the parsed data and you can use its inside methods to find desired fields for their names, paths or classes. All Fields are successors of com.igormaznitsa.jbbp.model.JBBPAbstractField class. To increase comfort, it is easier to use mapping to classes when the mapper automatically places values to fields of a Java class.
+
+The Result of parsing is an instance of com.igormaznitsa.jbbp.model.JBBPFieldStruct class which represents the root
+invisible structure for the parsed data and you can use its inside methods to find desired fields for their names, paths
+or classes. All Fields are successors of com.igormaznitsa.jbbp.model.JBBPAbstractField class. To increase comfort, it is
+easier to use mapping to classes when the mapper automatically places values to fields of a Java class.
# Example
+
Example below shows how to parse a PNG file through JBBP parser:
+
```Java
final InputStream pngStream = getResourceAsInputStream("picture.png");
try {
@@ -253,7 +351,9 @@ final InputStream pngStream = getResourceAsInputStream("picture.png");
closeResource(pngStream);
}
```
+
Also it is possible to map parsed packet to class fields
+
```Java
final JBBPParser pngParser = JBBPParser.prepare(
"long header;"
@@ -286,6 +386,7 @@ final JBBPParser pngParser = JBBPParser.prepare(
```
Example shows how to parse TCP frame:
+
```Java
final JBBPParser tcpParser = JBBPParser.prepare(
"skip:34; // skip bytes till the frame\n"
@@ -318,17 +419,30 @@ final JBBPParser tcpParser = JBBPParser.prepare(
```
# F.A.Q.
+
## Is it possible to use `@Bin` annotations for parsing and not only mapping?
-`@Bin` annotations is used only for mapping and data writing, but there is special class [JBBPDslBuilder](/jbbp/src/main/java/com/igormaznitsa/jbbp/utils/JBBPDslBuilder.java) which can convert `@Bin` marked class into JBBP script, for instance:
+
+`@Bin` annotations is used only for mapping and data writing, but there is special
+class [JBBPDslBuilder](/jbbp/src/main/java/com/igormaznitsa/jbbp/utils/JBBPDslBuilder.java) which can convert `@Bin`
+marked class into JBBP script, for instance:
+
```java
JBBPDslBuilder.Begin().AnnotatedClass(SomeBinAnnotatetClass.class).End(true);
```
## My Binary data format is too complex one to be decoded by a JBBP script
-No problems! JBBP parser works over [com.igormaznitsa.jbbp.io.JBBPBitInputStream](/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java) class which can be used directly and allows read bits, bytes, count bytes and align data. For writing there is similar class [JBBPBitOutputStream](https://github.com/raydac/java-binary-block-parser/blob/master/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOutputStream.java).
+
+No problems! JBBP parser works
+over [com.igormaznitsa.jbbp.io.JBBPBitInputStream](/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java)
+class which can be used directly and allows read bits, bytes, count bytes and align data. For writing there is similar
+class [JBBPBitOutputStream](https://github.com/raydac/java-binary-block-parser/blob/master/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOutputStream.java)
+.
## I want to make a binary data block instead of parsing!
-Library provides special helper [JBBPOut](/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOut.java). The helper allows to generate binary blocks and provides some kind of DSL
+
+Library provides special helper [JBBPOut](/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOut.java). The helper allows
+to generate binary blocks and provides some kind of DSL
+
```Java
import static com.igormaznitsa.jbbp.io.JBBPOut.*;
...
diff --git a/changelog.txt b/changelog.txt
index 14a540e9..143fa08b 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,42 @@
+3.0.1 (24-dec-2024)
+ - added `MSB0_DIRECT` bit order mode, MSB0 without data revers [#46](https://github.com/raydac/java-binary-block-parser/issues/46)
+ - added `JBBPBitInputStream#isDetectedPartlyReadBitField` to check that only part of bit field read during last operation
+ - added flag into constructors for JBBPBitInputStream to force return -1 instead of partly accumulated bits data if end of field
+
+3.0.0 (16-nov-2024)
+ - Minimum JDK Version: Updated to 11.0.
+ - Minimum Supported Android: Updated to 12 (API 32).
+ - API Changes: Modifications made to the CompiledBlockVisitor API.
+ - New Feature: Added `JBBPUtils#findMaxStaticArraySize` for calculating the largest static array size defined in a JBBP script.
+ - Internal API: Certain internal APIs have been opened.
+ - Codebase Improvements: General refactoring performed.
+
+2.1.0 (05-nov-2024)
+ - minor changes in API for JBBPVarFieldProcessor and JBBPCustomFieldTypeProcessor
+ - provided way to control size of arrays read as stream rest [#44](https://github.com/raydac/java-binary-block-parser/issues/44)
+ - provided way to control size of arrays which size calculated through expressions [#45](https://github.com/raydac/java-binary-block-parser/issues/45)
+ - improved tests
+
+2.0.6 (01-jul-2023)
+ - [#42](https://github.com/raydac/java-binary-block-parser/issues/42) unexpected exception during JBBPDslBuilder.AnnotatedClass method call
+ - improved tests
+
+2.0.5 (17-jun-2023)
+ - [#41](https://github.com/raydac/java-binary-block-parser/issues/41) fix for Gradle plug-in
+ - improved tests
+
+2.0.4 (01-aug-2022)
+ - added unsigned 32 bit integer type __uint__ [#37](https://github.com/raydac/java-binary-block-parser/issues/37)
+ - provided way to filter fields for mapping operations and write object operations [#36](https://github.com/raydac/java-binary-block-parser/issues/36)
+
+2.0.3 (03-jan-2021)
+ - added service methods `JBBPUtils.traceData` to print dump of an input stream into a PrintStream
+ - improved `JBBPTokenizerException` to show marked error position [#30](https://github.com/raydac/java-binary-block-parser/issues/30)
+
+2.0.2 (22-aug-2020)
+ - added `JBBPOut#Bin` variant to override `@Bin` annotation fields in written objects.
+ - [#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.
+
2.0.1
- [#26](https://github.com/raydac/java-binary-block-parser/issues/26) fixed bug in array write with MSB0
@@ -38,7 +77,7 @@
- added converter of compiled parser data into Java class sources (1.6+)
- added method to read unsigned short values as char [] into JBBPBitInputStream
- Class version target has been changed to Java 1.6
- - fixed compatibiity of tests with Java 1.6
+ - fixed compatibility of tests with Java 1.6
- Minor refactoring
1.2.0
diff --git a/docs/arthur_sanctuary_banner.png b/docs/arthur_sanctuary_banner.png
new file mode 100644
index 00000000..566b7bd5
Binary files /dev/null and b/docs/arthur_sanctuary_banner.png differ
diff --git a/docs/jbbp_fields.png b/docs/jbbp_fields.png
index 404f36ba..79351c92 100644
Binary files a/docs/jbbp_fields.png and b/docs/jbbp_fields.png differ
diff --git a/docs/jbbp_mm.png b/docs/jbbp_mm.png
index d5886f54..b4765040 100644
Binary files a/docs/jbbp_mm.png and b/docs/jbbp_mm.png differ
diff --git a/docs/jbbp_primitives.png b/docs/jbbp_primitives.png
index 70297aaf..32bf5efe 100644
Binary files a/docs/jbbp_primitives.png and b/docs/jbbp_primitives.png differ
diff --git a/docs/jmh_results.ods b/docs/jmh_results.ods
index 137a1c8d..96dbd502 100644
Binary files a/docs/jmh_results.ods and b/docs/jmh_results.ods differ
diff --git a/docs/jmh_results.png b/docs/jmh_results.png
index a29ede56..df72ec02 100644
Binary files a/docs/jmh_results.png and b/docs/jmh_results.png differ
diff --git a/docs/white_properties.properties b/docs/white_properties.properties
new file mode 100644
index 00000000..8144b61c
--- /dev/null
+++ b/docs/white_properties.properties
@@ -0,0 +1,69 @@
+#SciaReto editor settings
+#Sat Jun 17 11:11:33 EEST 2023
+MindMapPanelConfig.birdseyeBackground=-1869559553
+MindMapPanelConfig.birdseyeFront=-1879029100
+MindMapPanelConfig.birdseyeMouseButton=BUTTON_2
+MindMapPanelConfig.collapsatorBackgroundColor=-526635
+MindMapPanelConfig.collapsatorBorderColor=-12566464
+MindMapPanelConfig.collapsatorBorderWidth=1.0
+MindMapPanelConfig.collapsatorSize=16
+MindMapPanelConfig.connectorColor=-15592942
+MindMapPanelConfig.connectorWidth=1.5
+MindMapPanelConfig.drawBackground=true
+MindMapPanelConfig.dropShadow=true
+MindMapPanelConfig.elementBorderColor=-16777216
+MindMapPanelConfig.elementBorderWidth=1.0
+MindMapPanelConfig.firstLevelBackgroundColor=-5128244
+MindMapPanelConfig.firstLevelHorizontalInset=48
+MindMapPanelConfig.firstLevelTextColor=-16777216
+MindMapPanelConfig.firstLevelVerticalInset=32
+MindMapPanelConfig.font.name=Arial
+MindMapPanelConfig.font.size=16
+MindMapPanelConfig.font.style=1
+MindMapPanelConfig.gridColor=-12364185
+MindMapPanelConfig.gridStep=32
+MindMapPanelConfig.horizontalBlockGap=5
+MindMapPanelConfig.jumpLinkColor=-15597313
+MindMapPanelConfig.jumpLinkWidth=1.5
+MindMapPanelConfig.otherLevelBackgroundColor=-131587
+MindMapPanelConfig.otherLevelHorizontalInset=32
+MindMapPanelConfig.otherLevelTextColor=-16777216
+MindMapPanelConfig.otherLevelVerticalInset=16
+MindMapPanelConfig.paperColor=-1
+MindMapPanelConfig.paperMargins=20
+MindMapPanelConfig.renderQuality=QUALITY
+MindMapPanelConfig.rootBackgroundColor=-16573903
+MindMapPanelConfig.rootTextColor=-1
+MindMapPanelConfig.scale=1.0
+MindMapPanelConfig.scaleModifiers=2
+MindMapPanelConfig.selectLineColor=-14336
+MindMapPanelConfig.selectLineGap=5
+MindMapPanelConfig.selectLineWidth=3.0
+MindMapPanelConfig.shadowColor=805306368
+MindMapPanelConfig.shadowOffset=5.0
+MindMapPanelConfig.showGrid=false
+MindMapPanelConfig.smartTextPaste=false
+MindMapPanelConfig.textMargins=10
+mapShortCut.addChildAndStartEdit=addChildAndStartEdit*900000000
+mapShortCut.addSiblingAndStartEdit=addSiblingAndStartEdit*A00000000
+mapShortCut.birdsEyeModifiers=birdsEyeModifiers*7FFFFFFF00000000
+mapShortCut.cancelEdit=cancelEdit*1B00000000
+mapShortCut.deleteSelectedTopic=deleteSelectedTopic*7F00000000
+mapShortCut.focusToRootOrStartEdit=focusToRootOrStartEdit*2000000002
+mapShortCut.moveFocusDown=moveFocusDown*2800000000
+mapShortCut.moveFocusDownAddFocused=moveFocusDownAddFocused*2800000001
+mapShortCut.moveFocusLeft=moveFocusLeft*2500000000
+mapShortCut.moveFocusLeftAddFocused=moveFocusLeftAddFocused*2500000001
+mapShortCut.moveFocusRight=moveFocusRight*2700000000
+mapShortCut.moveFocusRightAddFocused=moveFocusRightAddFocused*2700000001
+mapShortCut.moveFocusUp=moveFocusUp*2600000000
+mapShortCut.moveFocusUpAddFocused=moveFocusUpAddFocused*2600000001
+mapShortCut.nextLineInTopicText=nextLineInTopicText*A00000001
+mapShortCut.showPopupMenu=showPopupMenu*200000000A
+mapShortCut.topicFold=topicFold*2D00000000
+mapShortCut.topicFoldAll=topicFoldAll*2D00000008
+mapShortCut.topicUnfold=topicUnfold*3D00000000
+mapShortCut.topicUnfoldAll=topicUnfoldAll*3D00000008
+mapShortCut.zoomIn=zoomIn*3D00000002
+mapShortCut.zoomOut=zoomOut*2D00000002
+mapShortCut.zoomReset=zoomReset*3000000002
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/build.gradle b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/build.gradle
new file mode 100644
index 00000000..9d314477
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/build.gradle
@@ -0,0 +1,36 @@
+plugins {
+ id 'java'
+ id 'com.igormaznitsa.gradle.jbbp' version "${jbbp_plugin_version}"
+}
+
+group = 'com.igormaznitsa.jbbp.gradle.test'
+version = '0.0.0-SNAPSHOT'
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+}
+
+dependencies {
+ implementation "com.igormaznitsa:jbbp:${jbbp_plugin_version}"
+ testImplementation platform("org.junit:junit-bom:${junit_version}")
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+}
+
+test {
+ useJUnitPlatform()
+}
+
+import com.igormaznitsa.jbbp.plugin.common.converters.ParserFlags
+
+jbbp {
+ headComment = 'Free license'
+ addBinAnnotations = true
+ addGettersSetters = true
+ customTypes = ['some']
+ interfaces = ['java.lang.Runnable']
+ customText = 'public void run () {}'
+ parserFlags = [ParserFlags.SKIP_REMAINING_FIELDS_IF_EOF]
+}
+
+compileJava.dependsOn(jbbpGenerate)
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/pom.xml b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/pom.xml
new file mode 100644
index 00000000..09e1c195
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/pom.xml
@@ -0,0 +1,80 @@
+
+
+ 4.0.0
+
+
+ com.igormaznitsa
+ jbbp-gradle-tests
+ 0.0.0-SNAPSHOT
+
+
+ jbbp-gradle5-plugin-test
+ pom
+
+
+ gradle5
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}/gradle
+ false
+
+
+ ${project.basedir}
+
+ gradlew
+ gradlew.bat
+
+ false
+
+
+ ${project.basedir}/downloaded
+ false
+
+
+ ${project.basedir}/build
+ false
+
+
+ ${project.basedir}/out
+ false
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+
+ gradle
+ compile
+
+ ${gradle.executable}
+
+ clean
+ test
+ --info
+ --scan
+ --no-daemon
+ -Pjbbp_plugin_version=${jbbp.test.version}
+ -Pjunit_version=${junit5.version}
+
+
+
+ exec
+
+
+
+
+
+
+
+
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/settings.gradle b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/settings.gradle
new file mode 100644
index 00000000..a21b7724
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/settings.gradle
@@ -0,0 +1,9 @@
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenLocal()
+ }
+}
+
+rootProject.name = 'jbbp-gradle5-plugin-test'
+
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
new file mode 100644
index 00000000..b1f6c18f
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
@@ -0,0 +1,10 @@
+ubyte len;
+uint uintField;
+uint [1] uintArr;
+some1 {
+ bit:4 [len] someField;
+ ubyte len;
+ some2 {
+ byte [len] field;
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp
new file mode 100644
index 00000000..58f5edc9
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp
@@ -0,0 +1,8 @@
+ubyte len;
+some1 {
+ bit:4 [len] someField;
+ ubyte len;
+ some2 {
+ byte [len] field;
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp
new file mode 100644
index 00000000..39d99c87
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp
@@ -0,0 +1,11 @@
+// custom and var fields
+byte bytea;
+some field1;
+ readVarArray(Object sourceStruct,
+ JBBPBitInputStream inStream,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo,
+ int extraValue,
+ boolean readWholeStream,
+ int arraySize)
+ throws IOException {
+ if (readWholeStream) {
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo, inStream.readLongArray(-1, byteOrder));
+ } else {
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo,
+ inStream.readLongArray(arraySize, byteOrder));
+ }
+ }
+
+ @Override
+ public void run() {
+ }
+
+ @Override
+ public void writeVarField(Object sourceStruct, JBBPAbstractField value,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue)
+ throws IOException {
+ outStream.writeLong(((JBBPFieldLong) value).getAsLong(), byteOrder);
+ }
+
+ @Override
+ public void writeVarArray(Object sourceStruct,
+ JBBPAbstractArrayField extends JBBPAbstractField> array,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue,
+ int arraySizeToWrite) throws IOException {
+ final JBBPFieldArrayLong a = (JBBPFieldArrayLong) array;
+ if (arraySizeToWrite < 0) {
+ for (final long l : a.getArray()) {
+ outStream.writeLong(l, byteOrder);
+ }
+ } else {
+ final long[] larr = a.getArray();
+ for (int i = 0; i < arraySizeToWrite; i++) {
+ outStream.writeLong(larr[i], byteOrder);
+ }
+ }
+ }
+
+}
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/main/java/org/example/Main.java b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/main/java/org/example/Main.java
new file mode 100644
index 00000000..407f157b
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/main/java/org/example/Main.java
@@ -0,0 +1,7 @@
+package org.example;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello world!");
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/test/java/org/example/MainTest.java b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/test/java/org/example/MainTest.java
new file mode 100644
index 00000000..f98a9f30
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle5-plugin-test/src/test/java/org/example/MainTest.java
@@ -0,0 +1,124 @@
+package org.example;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.igormaznitsa.jbbp.JBBPParser;
+import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
+import com.igormaznitsa.jbbp.io.JBBPBitOutputStream;
+import com.igormaznitsa.mvn.tst.VarCustomImpl;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Random;
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+
+import com.igormaznitsa.mvn.test.jbbp.*;
+
+public class MainTest {
+
+ @Test
+ void testReadWrite_Annotations_Static() throws IOException {
+ final byte[] testData = new byte[] {
+ 4,
+ (byte)0xFF, (byte)0x1A, (byte)0x1B, (byte)0x1C,
+ (byte)0xFF, (byte)0x2A, (byte)0x2B, (byte)0x2C,
+ (byte) 0x12, (byte) 0x34, 3, 5, 6, 7
+ };
+
+ final GenAnnotations result =
+ new GenAnnotations().read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ assertEquals(4, result.getLEN());
+ assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
+
+ final String script = "ubyte len;"
+ + " uint uintField;"
+ + " uint [1] uintArr;"
+ + "some1 {"
+ + " bit:4 [len] someField;"
+ + " ubyte len;"
+ + " some2 {"
+ + " byte [len] field;"
+ + " }"
+ + "}";
+
+ final GenAnnotations instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotations());
+
+ assertEquals(result.getUINTFIELD(), instance.getUINTFIELD());
+ assertArrayEquals(result.getUINTARR(), instance.getUINTARR());
+ assertEquals(result.getLEN(), instance.getLEN());
+ assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
+ assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
+ }
+
+ @Test
+ void testReadWrite_Annotations_NonStatic() throws IOException {
+ final byte[] testData = new byte[] {4, (byte) 0x12, (byte) 0x34, 3, 5, 6, 7};
+
+ final GenAnnotationsNonStatic result = new GenAnnotationsNonStatic()
+ .read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ assertEquals(4, result.getLEN());
+ assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
+
+ final String script = "ubyte len;"
+ + "some1 {"
+ + " bit:4 [len] someField;"
+ + " ubyte len;"
+ + " some2 {"
+ + " byte [len] field;"
+ + " }"
+ + "}";
+
+ final GenAnnotationsNonStatic instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotationsNonStatic());
+ assertEquals(result.getLEN(), instance.getLEN());
+ assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
+ assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
+ }
+
+ private static final Random RND = new Random(12345);
+
+ @Test
+ public void testReadWrite_VarCustom() throws Exception {
+ final VarCustomImpl impl = new VarCustomImpl();
+
+ final byte[] etalonArray = new byte[319044];
+ RND.nextBytes(etalonArray);
+ etalonArray[0] = 1;
+
+ impl.read(new JBBPBitInputStream(new ByteArrayInputStream(etalonArray)));
+
+ assertEquals(1, impl.getBYTEA());
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final JBBPBitOutputStream bios = new JBBPBitOutputStream(bos);
+
+ impl.write(bios);
+ bios.close();
+
+ assertArrayEquals(etalonArray, bos.toByteArray());
+ }
+
+ @Test
+ public void testRead_DefaultBitOrder() throws IOException {
+ final WholeStreamByteArray struct = new WholeStreamByteArray().read(new JBBPBitInputStream(
+ new ByteArrayInputStream(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})));
+ assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, struct.getARRAY());
+ }
+
+ @Test
+ public void testWrite_DefaultBitOrder() throws IOException {
+ final WholeStreamByteArray struct = new WholeStreamByteArray();
+ struct.setARRAY(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final JBBPBitOutputStream bitOut = new JBBPBitOutputStream(out);
+ struct.write(bitOut);
+ bitOut.close();
+ assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, out.toByteArray());
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/build.gradle b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/build.gradle
new file mode 100644
index 00000000..9d314477
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/build.gradle
@@ -0,0 +1,36 @@
+plugins {
+ id 'java'
+ id 'com.igormaznitsa.gradle.jbbp' version "${jbbp_plugin_version}"
+}
+
+group = 'com.igormaznitsa.jbbp.gradle.test'
+version = '0.0.0-SNAPSHOT'
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+}
+
+dependencies {
+ implementation "com.igormaznitsa:jbbp:${jbbp_plugin_version}"
+ testImplementation platform("org.junit:junit-bom:${junit_version}")
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+}
+
+test {
+ useJUnitPlatform()
+}
+
+import com.igormaznitsa.jbbp.plugin.common.converters.ParserFlags
+
+jbbp {
+ headComment = 'Free license'
+ addBinAnnotations = true
+ addGettersSetters = true
+ customTypes = ['some']
+ interfaces = ['java.lang.Runnable']
+ customText = 'public void run () {}'
+ parserFlags = [ParserFlags.SKIP_REMAINING_FIELDS_IF_EOF]
+}
+
+compileJava.dependsOn(jbbpGenerate)
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/pom.xml b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/pom.xml
new file mode 100644
index 00000000..9f3903b1
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/pom.xml
@@ -0,0 +1,80 @@
+
+
+ 4.0.0
+
+
+ com.igormaznitsa
+ jbbp-gradle-tests
+ 0.0.0-SNAPSHOT
+
+
+ jbbp-gradle6-plugin-test
+ pom
+
+
+ gradle6
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}/gradle
+ false
+
+
+ ${project.basedir}
+
+ gradlew
+ gradlew.bat
+
+ false
+
+
+ ${project.basedir}/downloaded
+ false
+
+
+ ${project.basedir}/build
+ false
+
+
+ ${project.basedir}/out
+ false
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+
+ gradle
+ compile
+
+ ${gradle.executable}
+
+ clean
+ test
+ --info
+ --scan
+ --no-daemon
+ -Pjbbp_plugin_version=${jbbp.test.version}
+ -Pjunit_version=${junit5.version}
+
+
+
+ exec
+
+
+
+
+
+
+
+
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/settings.gradle b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/settings.gradle
new file mode 100644
index 00000000..713e1502
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/settings.gradle
@@ -0,0 +1,9 @@
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenLocal()
+ }
+}
+
+rootProject.name = 'jbbp-gradle6-plugin-test'
+
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
new file mode 100644
index 00000000..b1f6c18f
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
@@ -0,0 +1,10 @@
+ubyte len;
+uint uintField;
+uint [1] uintArr;
+some1 {
+ bit:4 [len] someField;
+ ubyte len;
+ some2 {
+ byte [len] field;
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp
new file mode 100644
index 00000000..58f5edc9
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp
@@ -0,0 +1,8 @@
+ubyte len;
+some1 {
+ bit:4 [len] someField;
+ ubyte len;
+ some2 {
+ byte [len] field;
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp
new file mode 100644
index 00000000..39d99c87
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp
@@ -0,0 +1,11 @@
+// custom and var fields
+byte bytea;
+some field1;
+ readVarArray(Object sourceStruct,
+ JBBPBitInputStream inStream,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo,
+ int extraValue,
+ boolean readWholeStream,
+ int arraySize)
+ throws IOException {
+ if (readWholeStream) {
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo, inStream.readLongArray(-1, byteOrder));
+ } else {
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo,
+ inStream.readLongArray(arraySize, byteOrder));
+ }
+ }
+
+ @Override
+ public void run() {
+ }
+
+ @Override
+ public void writeVarField(Object sourceStruct, JBBPAbstractField value,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue)
+ throws IOException {
+ outStream.writeLong(((JBBPFieldLong) value).getAsLong(), byteOrder);
+ }
+
+ @Override
+ public void writeVarArray(Object sourceStruct,
+ JBBPAbstractArrayField extends JBBPAbstractField> array,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue,
+ int arraySizeToWrite) throws IOException {
+ final JBBPFieldArrayLong a = (JBBPFieldArrayLong) array;
+ if (arraySizeToWrite < 0) {
+ for (final long l : a.getArray()) {
+ outStream.writeLong(l, byteOrder);
+ }
+ } else {
+ final long[] larr = a.getArray();
+ for (int i = 0; i < arraySizeToWrite; i++) {
+ outStream.writeLong(larr[i], byteOrder);
+ }
+ }
+ }
+
+}
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/main/java/org/example/Main.java b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/main/java/org/example/Main.java
new file mode 100644
index 00000000..407f157b
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/main/java/org/example/Main.java
@@ -0,0 +1,7 @@
+package org.example;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello world!");
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/test/java/org/example/MainTest.java b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/test/java/org/example/MainTest.java
new file mode 100644
index 00000000..f98a9f30
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle6-plugin-test/src/test/java/org/example/MainTest.java
@@ -0,0 +1,124 @@
+package org.example;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.igormaznitsa.jbbp.JBBPParser;
+import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
+import com.igormaznitsa.jbbp.io.JBBPBitOutputStream;
+import com.igormaznitsa.mvn.tst.VarCustomImpl;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Random;
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+
+import com.igormaznitsa.mvn.test.jbbp.*;
+
+public class MainTest {
+
+ @Test
+ void testReadWrite_Annotations_Static() throws IOException {
+ final byte[] testData = new byte[] {
+ 4,
+ (byte)0xFF, (byte)0x1A, (byte)0x1B, (byte)0x1C,
+ (byte)0xFF, (byte)0x2A, (byte)0x2B, (byte)0x2C,
+ (byte) 0x12, (byte) 0x34, 3, 5, 6, 7
+ };
+
+ final GenAnnotations result =
+ new GenAnnotations().read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ assertEquals(4, result.getLEN());
+ assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
+
+ final String script = "ubyte len;"
+ + " uint uintField;"
+ + " uint [1] uintArr;"
+ + "some1 {"
+ + " bit:4 [len] someField;"
+ + " ubyte len;"
+ + " some2 {"
+ + " byte [len] field;"
+ + " }"
+ + "}";
+
+ final GenAnnotations instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotations());
+
+ assertEquals(result.getUINTFIELD(), instance.getUINTFIELD());
+ assertArrayEquals(result.getUINTARR(), instance.getUINTARR());
+ assertEquals(result.getLEN(), instance.getLEN());
+ assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
+ assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
+ }
+
+ @Test
+ void testReadWrite_Annotations_NonStatic() throws IOException {
+ final byte[] testData = new byte[] {4, (byte) 0x12, (byte) 0x34, 3, 5, 6, 7};
+
+ final GenAnnotationsNonStatic result = new GenAnnotationsNonStatic()
+ .read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ assertEquals(4, result.getLEN());
+ assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
+
+ final String script = "ubyte len;"
+ + "some1 {"
+ + " bit:4 [len] someField;"
+ + " ubyte len;"
+ + " some2 {"
+ + " byte [len] field;"
+ + " }"
+ + "}";
+
+ final GenAnnotationsNonStatic instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotationsNonStatic());
+ assertEquals(result.getLEN(), instance.getLEN());
+ assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
+ assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
+ }
+
+ private static final Random RND = new Random(12345);
+
+ @Test
+ public void testReadWrite_VarCustom() throws Exception {
+ final VarCustomImpl impl = new VarCustomImpl();
+
+ final byte[] etalonArray = new byte[319044];
+ RND.nextBytes(etalonArray);
+ etalonArray[0] = 1;
+
+ impl.read(new JBBPBitInputStream(new ByteArrayInputStream(etalonArray)));
+
+ assertEquals(1, impl.getBYTEA());
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final JBBPBitOutputStream bios = new JBBPBitOutputStream(bos);
+
+ impl.write(bios);
+ bios.close();
+
+ assertArrayEquals(etalonArray, bos.toByteArray());
+ }
+
+ @Test
+ public void testRead_DefaultBitOrder() throws IOException {
+ final WholeStreamByteArray struct = new WholeStreamByteArray().read(new JBBPBitInputStream(
+ new ByteArrayInputStream(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})));
+ assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, struct.getARRAY());
+ }
+
+ @Test
+ public void testWrite_DefaultBitOrder() throws IOException {
+ final WholeStreamByteArray struct = new WholeStreamByteArray();
+ struct.setARRAY(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final JBBPBitOutputStream bitOut = new JBBPBitOutputStream(out);
+ struct.write(bitOut);
+ bitOut.close();
+ assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, out.toByteArray());
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/build.gradle b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/build.gradle
new file mode 100644
index 00000000..9d314477
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/build.gradle
@@ -0,0 +1,36 @@
+plugins {
+ id 'java'
+ id 'com.igormaznitsa.gradle.jbbp' version "${jbbp_plugin_version}"
+}
+
+group = 'com.igormaznitsa.jbbp.gradle.test'
+version = '0.0.0-SNAPSHOT'
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+}
+
+dependencies {
+ implementation "com.igormaznitsa:jbbp:${jbbp_plugin_version}"
+ testImplementation platform("org.junit:junit-bom:${junit_version}")
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+}
+
+test {
+ useJUnitPlatform()
+}
+
+import com.igormaznitsa.jbbp.plugin.common.converters.ParserFlags
+
+jbbp {
+ headComment = 'Free license'
+ addBinAnnotations = true
+ addGettersSetters = true
+ customTypes = ['some']
+ interfaces = ['java.lang.Runnable']
+ customText = 'public void run () {}'
+ parserFlags = [ParserFlags.SKIP_REMAINING_FIELDS_IF_EOF]
+}
+
+compileJava.dependsOn(jbbpGenerate)
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/pom.xml b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/pom.xml
new file mode 100644
index 00000000..397b970d
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/pom.xml
@@ -0,0 +1,80 @@
+
+
+ 4.0.0
+
+
+ com.igormaznitsa
+ jbbp-gradle-tests
+ 0.0.0-SNAPSHOT
+
+
+ jbbp-gradle7-plugin-test
+ pom
+
+
+ gradle7
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}/gradle
+ false
+
+
+ ${project.basedir}
+
+ gradlew
+ gradlew.bat
+
+ false
+
+
+ ${project.basedir}/downloaded
+ false
+
+
+ ${project.basedir}/build
+ false
+
+
+ ${project.basedir}/out
+ false
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+
+ gradle
+ compile
+
+ ${gradle.executable}
+
+ clean
+ test
+ --info
+ --scan
+ --no-daemon
+ -Pjbbp_plugin_version=${jbbp.test.version}
+ -Pjunit_version=${junit5.version}
+
+
+
+ exec
+
+
+
+
+
+
+
+
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/settings.gradle b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/settings.gradle
new file mode 100644
index 00000000..944d2e3c
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/settings.gradle
@@ -0,0 +1,9 @@
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenLocal()
+ }
+}
+
+rootProject.name = 'jbbp-gradle7-plugin-test'
+
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
new file mode 100644
index 00000000..b1f6c18f
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
@@ -0,0 +1,10 @@
+ubyte len;
+uint uintField;
+uint [1] uintArr;
+some1 {
+ bit:4 [len] someField;
+ ubyte len;
+ some2 {
+ byte [len] field;
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp
new file mode 100644
index 00000000..58f5edc9
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp
@@ -0,0 +1,8 @@
+ubyte len;
+some1 {
+ bit:4 [len] someField;
+ ubyte len;
+ some2 {
+ byte [len] field;
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp
new file mode 100644
index 00000000..39d99c87
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp
@@ -0,0 +1,11 @@
+// custom and var fields
+byte bytea;
+some field1;
+ readVarArray(Object sourceStruct,
+ JBBPBitInputStream inStream,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo,
+ int extraValue,
+ boolean readWholeStream,
+ int arraySize)
+ throws IOException {
+ if (readWholeStream) {
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo, inStream.readLongArray(-1, byteOrder));
+ } else {
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo,
+ inStream.readLongArray(arraySize, byteOrder));
+ }
+ }
+
+ @Override
+ public void run() {
+ }
+
+ @Override
+ public void writeVarField(Object sourceStruct, JBBPAbstractField value,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue)
+ throws IOException {
+ outStream.writeLong(((JBBPFieldLong) value).getAsLong(), byteOrder);
+ }
+
+ @Override
+ public void writeVarArray(Object sourceStruct,
+ JBBPAbstractArrayField extends JBBPAbstractField> array,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue,
+ int arraySizeToWrite) throws IOException {
+ final JBBPFieldArrayLong a = (JBBPFieldArrayLong) array;
+ if (arraySizeToWrite < 0) {
+ for (final long l : a.getArray()) {
+ outStream.writeLong(l, byteOrder);
+ }
+ } else {
+ final long[] larr = a.getArray();
+ for (int i = 0; i < arraySizeToWrite; i++) {
+ outStream.writeLong(larr[i], byteOrder);
+ }
+ }
+ }
+
+}
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/main/java/org/example/Main.java b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/main/java/org/example/Main.java
new file mode 100644
index 00000000..407f157b
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/main/java/org/example/Main.java
@@ -0,0 +1,7 @@
+package org.example;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello world!");
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/test/java/org/example/MainTest.java b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/test/java/org/example/MainTest.java
new file mode 100644
index 00000000..f98a9f30
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle7-plugin-test/src/test/java/org/example/MainTest.java
@@ -0,0 +1,124 @@
+package org.example;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.igormaznitsa.jbbp.JBBPParser;
+import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
+import com.igormaznitsa.jbbp.io.JBBPBitOutputStream;
+import com.igormaznitsa.mvn.tst.VarCustomImpl;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Random;
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+
+import com.igormaznitsa.mvn.test.jbbp.*;
+
+public class MainTest {
+
+ @Test
+ void testReadWrite_Annotations_Static() throws IOException {
+ final byte[] testData = new byte[] {
+ 4,
+ (byte)0xFF, (byte)0x1A, (byte)0x1B, (byte)0x1C,
+ (byte)0xFF, (byte)0x2A, (byte)0x2B, (byte)0x2C,
+ (byte) 0x12, (byte) 0x34, 3, 5, 6, 7
+ };
+
+ final GenAnnotations result =
+ new GenAnnotations().read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ assertEquals(4, result.getLEN());
+ assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
+
+ final String script = "ubyte len;"
+ + " uint uintField;"
+ + " uint [1] uintArr;"
+ + "some1 {"
+ + " bit:4 [len] someField;"
+ + " ubyte len;"
+ + " some2 {"
+ + " byte [len] field;"
+ + " }"
+ + "}";
+
+ final GenAnnotations instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotations());
+
+ assertEquals(result.getUINTFIELD(), instance.getUINTFIELD());
+ assertArrayEquals(result.getUINTARR(), instance.getUINTARR());
+ assertEquals(result.getLEN(), instance.getLEN());
+ assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
+ assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
+ }
+
+ @Test
+ void testReadWrite_Annotations_NonStatic() throws IOException {
+ final byte[] testData = new byte[] {4, (byte) 0x12, (byte) 0x34, 3, 5, 6, 7};
+
+ final GenAnnotationsNonStatic result = new GenAnnotationsNonStatic()
+ .read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ assertEquals(4, result.getLEN());
+ assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
+
+ final String script = "ubyte len;"
+ + "some1 {"
+ + " bit:4 [len] someField;"
+ + " ubyte len;"
+ + " some2 {"
+ + " byte [len] field;"
+ + " }"
+ + "}";
+
+ final GenAnnotationsNonStatic instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotationsNonStatic());
+ assertEquals(result.getLEN(), instance.getLEN());
+ assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
+ assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
+ }
+
+ private static final Random RND = new Random(12345);
+
+ @Test
+ public void testReadWrite_VarCustom() throws Exception {
+ final VarCustomImpl impl = new VarCustomImpl();
+
+ final byte[] etalonArray = new byte[319044];
+ RND.nextBytes(etalonArray);
+ etalonArray[0] = 1;
+
+ impl.read(new JBBPBitInputStream(new ByteArrayInputStream(etalonArray)));
+
+ assertEquals(1, impl.getBYTEA());
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final JBBPBitOutputStream bios = new JBBPBitOutputStream(bos);
+
+ impl.write(bios);
+ bios.close();
+
+ assertArrayEquals(etalonArray, bos.toByteArray());
+ }
+
+ @Test
+ public void testRead_DefaultBitOrder() throws IOException {
+ final WholeStreamByteArray struct = new WholeStreamByteArray().read(new JBBPBitInputStream(
+ new ByteArrayInputStream(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})));
+ assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, struct.getARRAY());
+ }
+
+ @Test
+ public void testWrite_DefaultBitOrder() throws IOException {
+ final WholeStreamByteArray struct = new WholeStreamByteArray();
+ struct.setARRAY(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final JBBPBitOutputStream bitOut = new JBBPBitOutputStream(out);
+ struct.write(bitOut);
+ bitOut.close();
+ assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, out.toByteArray());
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/build.gradle b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/build.gradle
new file mode 100644
index 00000000..9d314477
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/build.gradle
@@ -0,0 +1,36 @@
+plugins {
+ id 'java'
+ id 'com.igormaznitsa.gradle.jbbp' version "${jbbp_plugin_version}"
+}
+
+group = 'com.igormaznitsa.jbbp.gradle.test'
+version = '0.0.0-SNAPSHOT'
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+}
+
+dependencies {
+ implementation "com.igormaznitsa:jbbp:${jbbp_plugin_version}"
+ testImplementation platform("org.junit:junit-bom:${junit_version}")
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+}
+
+test {
+ useJUnitPlatform()
+}
+
+import com.igormaznitsa.jbbp.plugin.common.converters.ParserFlags
+
+jbbp {
+ headComment = 'Free license'
+ addBinAnnotations = true
+ addGettersSetters = true
+ customTypes = ['some']
+ interfaces = ['java.lang.Runnable']
+ customText = 'public void run () {}'
+ parserFlags = [ParserFlags.SKIP_REMAINING_FIELDS_IF_EOF]
+}
+
+compileJava.dependsOn(jbbpGenerate)
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/pom.xml b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/pom.xml
new file mode 100644
index 00000000..b7765735
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/pom.xml
@@ -0,0 +1,80 @@
+
+
+ 4.0.0
+
+
+ com.igormaznitsa
+ jbbp-gradle-tests
+ 0.0.0-SNAPSHOT
+
+
+ jbbp-gradle8-plugin-test
+ pom
+
+
+ gradle8
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}/gradle
+ false
+
+
+ ${project.basedir}
+
+ gradlew
+ gradlew.bat
+
+ false
+
+
+ ${project.basedir}/downloaded
+ false
+
+
+ ${project.basedir}/build
+ false
+
+
+ ${project.basedir}/out
+ false
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+
+ gradle
+ compile
+
+ ${gradle.executable}
+
+ clean
+ test
+ --info
+ --scan
+ --no-daemon
+ -Pjbbp_plugin_version=${jbbp.test.version}
+ -Pjunit_version=${junit5.version}
+
+
+
+ exec
+
+
+
+
+
+
+
+
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/settings.gradle b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/settings.gradle
new file mode 100644
index 00000000..2422dece
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/settings.gradle
@@ -0,0 +1,9 @@
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenLocal()
+ }
+}
+
+rootProject.name = 'jbbp-gradle8-plugin-test'
+
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
new file mode 100644
index 00000000..b1f6c18f
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
@@ -0,0 +1,10 @@
+ubyte len;
+uint uintField;
+uint [1] uintArr;
+some1 {
+ bit:4 [len] someField;
+ ubyte len;
+ some2 {
+ byte [len] field;
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp
new file mode 100644
index 00000000..58f5edc9
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotationsNonStatic.jbbp
@@ -0,0 +1,8 @@
+ubyte len;
+some1 {
+ bit:4 [len] someField;
+ ubyte len;
+ some2 {
+ byte [len] field;
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp
new file mode 100644
index 00000000..39d99c87
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/jbbp/com.igormaznitsa.mvn.test.jbbp.VarCustom.jbbp
@@ -0,0 +1,11 @@
+// custom and var fields
+byte bytea;
+some field1;
+ readVarArray(Object sourceStruct,
+ JBBPBitInputStream inStream,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo,
+ int extraValue,
+ boolean readWholeStream,
+ int arraySize)
+ throws IOException {
+ if (readWholeStream) {
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo, inStream.readLongArray(-1, byteOrder));
+ } else {
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo,
+ inStream.readLongArray(arraySize, byteOrder));
+ }
+ }
+
+ @Override
+ public void run() {
+ }
+
+ @Override
+ public void writeVarField(Object sourceStruct, JBBPAbstractField value,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue)
+ throws IOException {
+ outStream.writeLong(((JBBPFieldLong) value).getAsLong(), byteOrder);
+ }
+
+ @Override
+ public void writeVarArray(Object sourceStruct,
+ JBBPAbstractArrayField extends JBBPAbstractField> array,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue,
+ int arraySizeToWrite) throws IOException {
+ final JBBPFieldArrayLong a = (JBBPFieldArrayLong) array;
+ if (arraySizeToWrite < 0) {
+ for (final long l : a.getArray()) {
+ outStream.writeLong(l, byteOrder);
+ }
+ } else {
+ final long[] larr = a.getArray();
+ for (int i = 0; i < arraySizeToWrite; i++) {
+ outStream.writeLong(larr[i], byteOrder);
+ }
+ }
+ }
+
+}
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/main/java/org/example/Main.java b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/main/java/org/example/Main.java
new file mode 100644
index 00000000..407f157b
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/main/java/org/example/Main.java
@@ -0,0 +1,7 @@
+package org.example;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello world!");
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/test/java/org/example/MainTest.java b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/test/java/org/example/MainTest.java
new file mode 100644
index 00000000..f98a9f30
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/jbbp-gradle8-plugin-test/src/test/java/org/example/MainTest.java
@@ -0,0 +1,124 @@
+package org.example;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.igormaznitsa.jbbp.JBBPParser;
+import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
+import com.igormaznitsa.jbbp.io.JBBPBitOutputStream;
+import com.igormaznitsa.mvn.tst.VarCustomImpl;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Random;
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+
+import com.igormaznitsa.mvn.test.jbbp.*;
+
+public class MainTest {
+
+ @Test
+ void testReadWrite_Annotations_Static() throws IOException {
+ final byte[] testData = new byte[] {
+ 4,
+ (byte)0xFF, (byte)0x1A, (byte)0x1B, (byte)0x1C,
+ (byte)0xFF, (byte)0x2A, (byte)0x2B, (byte)0x2C,
+ (byte) 0x12, (byte) 0x34, 3, 5, 6, 7
+ };
+
+ final GenAnnotations result =
+ new GenAnnotations().read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ assertEquals(4, result.getLEN());
+ assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
+
+ final String script = "ubyte len;"
+ + " uint uintField;"
+ + " uint [1] uintArr;"
+ + "some1 {"
+ + " bit:4 [len] someField;"
+ + " ubyte len;"
+ + " some2 {"
+ + " byte [len] field;"
+ + " }"
+ + "}";
+
+ final GenAnnotations instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotations());
+
+ assertEquals(result.getUINTFIELD(), instance.getUINTFIELD());
+ assertArrayEquals(result.getUINTARR(), instance.getUINTARR());
+ assertEquals(result.getLEN(), instance.getLEN());
+ assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
+ assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
+ }
+
+ @Test
+ void testReadWrite_Annotations_NonStatic() throws IOException {
+ final byte[] testData = new byte[] {4, (byte) 0x12, (byte) 0x34, 3, 5, 6, 7};
+
+ final GenAnnotationsNonStatic result = new GenAnnotationsNonStatic()
+ .read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ assertEquals(4, result.getLEN());
+ assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
+
+ final String script = "ubyte len;"
+ + "some1 {"
+ + " bit:4 [len] someField;"
+ + " ubyte len;"
+ + " some2 {"
+ + " byte [len] field;"
+ + " }"
+ + "}";
+
+ final GenAnnotationsNonStatic instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotationsNonStatic());
+ assertEquals(result.getLEN(), instance.getLEN());
+ assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
+ assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
+ }
+
+ private static final Random RND = new Random(12345);
+
+ @Test
+ public void testReadWrite_VarCustom() throws Exception {
+ final VarCustomImpl impl = new VarCustomImpl();
+
+ final byte[] etalonArray = new byte[319044];
+ RND.nextBytes(etalonArray);
+ etalonArray[0] = 1;
+
+ impl.read(new JBBPBitInputStream(new ByteArrayInputStream(etalonArray)));
+
+ assertEquals(1, impl.getBYTEA());
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final JBBPBitOutputStream bios = new JBBPBitOutputStream(bos);
+
+ impl.write(bios);
+ bios.close();
+
+ assertArrayEquals(etalonArray, bos.toByteArray());
+ }
+
+ @Test
+ public void testRead_DefaultBitOrder() throws IOException {
+ final WholeStreamByteArray struct = new WholeStreamByteArray().read(new JBBPBitInputStream(
+ new ByteArrayInputStream(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})));
+ assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, struct.getARRAY());
+ }
+
+ @Test
+ public void testWrite_DefaultBitOrder() throws IOException {
+ final WholeStreamByteArray struct = new WholeStreamByteArray();
+ struct.setARRAY(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final JBBPBitOutputStream bitOut = new JBBPBitOutputStream(out);
+ struct.write(bitOut);
+ bitOut.close();
+ assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, out.toByteArray());
+ }
+}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle-tests/pom.xml b/jbbp-plugins/jbbp-gradle-tests/pom.xml
new file mode 100644
index 00000000..f4e5c5cf
--- /dev/null
+++ b/jbbp-plugins/jbbp-gradle-tests/pom.xml
@@ -0,0 +1,26 @@
+
+ 4.0.0
+
+
+ com.igormaznitsa
+ jbbp-main-plugin-pom
+ 3.0.2-SNAPSHOT
+
+
+ jbbp-gradle-tests
+ 0.0.0-SNAPSHOT
+ pom
+
+
+ ${jbbp.version}
+
+
+
+ jbbp-gradle5-plugin-test
+ jbbp-gradle6-plugin-test
+ jbbp-gradle7-plugin-test
+ jbbp-gradle8-plugin-test
+
+
+
diff --git a/jbbp-plugins/jbbp-gradle/build.gradle b/jbbp-plugins/jbbp-gradle/build.gradle
index 561aeb4b..5e9ef93d 100644
--- a/jbbp-plugins/jbbp-gradle/build.gradle
+++ b/jbbp-plugins/jbbp-gradle/build.gradle
@@ -1,35 +1,36 @@
-def getProp(name, dflt) {
- if (project.hasProperty(name)) {
- return project.getProperty(name)
+def getProp(name) {
+ String found = project.findProperty(name)
+ if (found == null) {
+ GradleException('Property not found: ' + name)
} else {
- logger.warn('Can not find property "' + name + '" is not found')
- return dflt
+ return project.getProperty(name)
}
}
-def jbbpVersion = getProp('jbbp_plugin_version', '2.0.1')
-def metaLibVersion = getProp('meta_lib_version', '1.1.2')
+def jbbpVersion = getProp('jbbp_plugin_version')
+def metaLibVersion = getProp('meta_lib_version')
+def commonsIoVersion = getProp('commons_io_version')
+def junitVersion = getProp('junit_version')
group = 'com.igormaznitsa'
version = jbbpVersion
apply plugin: 'groovy'
-apply plugin: 'maven'
+apply plugin: 'maven-publish'
apply plugin: "com.gradle.plugin-publish"
-sourceCompatibility = 1.8
-targetCompatibility = 1.8
+sourceCompatibility = 11
+targetCompatibility = 11
dependencies {
- compile gradleApi()
- compile localGroovy()
+ implementation gradleApi()
+ implementation localGroovy()
- compile "commons-io:commons-io:2.5"
- compile "com.igormaznitsa:jbbp:" + jbbpVersion
- compile "com.igormaznitsa:meta-annotations:" + metaLibVersion
- compile "com.igormaznitsa:meta-utils:" + metaLibVersion
+ implementation "commons-io:commons-io:" + commonsIoVersion
+ implementation "com.igormaznitsa:meta-annotations:" + metaLibVersion
+ implementation "com.igormaznitsa:meta-utils:" + metaLibVersion
- testCompile 'junit:junit:4.12'
+ testImplementation "junit:junit:" + junitVersion
}
repositories {
@@ -44,29 +45,48 @@ buildscript {
}
}
dependencies {
- classpath "com.gradle.publish:plugin-publish-plugin:0.9.7"
+ classpath "com.gradle.publish:plugin-publish-plugin:1.1.0"
}
}
+tasks.withType(JavaCompile) {
+ options.compilerArgs << "-Xlint:deprecation"
+}
+
+task sourcesJar(type: Jar) {
+ duplicatesStrategy = 'include'
+ archiveClassifier = 'sources'
+ from sourceSets.main.allSource
+}
+
sourceSets {
main {
java {
+ srcDirs '../../jbbp/src/main/java'
srcDirs 'src/main/java'
srcDirs '../jbbp-plugin-common/src/main/java'
}
}
}
-pluginBundle {
+gradlePlugin {
website = 'https://github.com/raydac/java-binary-block-parser'
vcsUrl = 'https://github.com/raydac/java-binary-block-parser'
- description = 'JBBP script translator!'
- tags = ['jbbp', 'converter']
-
plugins {
- JBBPPlugin {
+ jbbpPlugin {
id = 'com.igormaznitsa.gradle.jbbp'
displayName = 'JBBP Sources Generator plugin'
+ implementationClass = 'com.igormaznitsa.jbbp.plugin.gradle.JBBPPlugin'
+ description = 'The plug-in processes JBBP scripts and generate Java classes from them'
+ tags = ['jbbp', 'converter']
+ }
+ }
+}
+
+publishing {
+ publications {
+ maven(MavenPublication) {
+ from components.java
}
}
}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle/pom.xml b/jbbp-plugins/jbbp-gradle/pom.xml
index 33cf6a55..76bc97ea 100644
--- a/jbbp-plugins/jbbp-gradle/pom.xml
+++ b/jbbp-plugins/jbbp-gradle/pom.xml
@@ -6,7 +6,7 @@
com.igormaznitsajbbp-main-plugin-pom
- 2.0.1
+ 3.0.2-SNAPSHOTjbbp-gradle-plugin
@@ -22,9 +22,8 @@
- 1.8
- 1.8
- install
+ gradle8
+ publishToMavenLocal
@@ -93,29 +92,29 @@
- org.fortasoft
- gradle-maven-plugin
- 1.0.8
-
-
- org.gradle
- gradle-tooling-api
- 5.2.1
-
-
-
-
- 5.4
-
- clean
- ${gradleGoal}
-
-
+ org.codehaus.mojo
+ exec-maven-plugin
+ gradlecompile
+
+ ${gradle.executable}
+
+ clean
+ build
+ ${gradleGoal}
+ --info
+ --scan
+ --no-daemon
+ -Pjbbp_plugin_version=${project.version}
+ -Pmeta_lib_version=${meta.version}
+ -Pcommons_io_version=${commonsio.version}
+ -Pjunit_version=${junit4.version}
+
+
- invoke
+ exec
diff --git a/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/AbstractJBBPTask.java b/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/AbstractJBBPTask.java
index 13ae07d9..3dbb749f 100644
--- a/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/AbstractJBBPTask.java
+++ b/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/AbstractJBBPTask.java
@@ -1,6 +1,12 @@
package com.igormaznitsa.jbbp.plugin.gradle;
import com.igormaznitsa.meta.common.utils.GetUtils;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.apache.commons.io.FileUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
@@ -8,13 +14,6 @@
import org.gradle.api.file.FileVisitor;
import org.gradle.api.tasks.TaskAction;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-
public abstract class AbstractJBBPTask extends DefaultTask {
public AbstractJBBPTask() {
@@ -22,13 +21,16 @@ public AbstractJBBPTask() {
}
@Nullable
- public static String getTextOrFileContent(@Nonnull final JBBPExtension extension, @Nullable final String text, @Nullable final File file) {
+ public static String getTextOrFileContent(@Nonnull final JBBPExtension extension,
+ @Nullable final String text,
+ @Nullable final File file) {
String result = null;
if (text != null) {
result = text;
} else if (file != null) {
try {
- result = FileUtils.readFileToString(file, GetUtils.ensureNonNull(extension.inEncoding, "UTF-8"));
+ result =
+ FileUtils.readFileToString(file, GetUtils.ensureNonNull(extension.inEncoding, "UTF-8"));
} catch (IOException ex) {
throw new GradleException("Can't read file " + file, ex);
}
diff --git a/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPCleanTask.java b/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPCleanTask.java
index c451a395..229b8de6 100644
--- a/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPCleanTask.java
+++ b/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPCleanTask.java
@@ -1,11 +1,10 @@
package com.igormaznitsa.jbbp.plugin.gradle;
import com.igormaznitsa.jbbp.plugin.common.converters.JBBPScriptTranslator;
-import org.gradle.api.GradleException;
-
-import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
+import javax.annotation.Nonnull;
+import org.gradle.api.GradleException;
/**
* Task allows to delete generated files.
diff --git a/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPGenerateTask.java b/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPGenerateTask.java
index e71ec128..9c021429 100644
--- a/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPGenerateTask.java
+++ b/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPGenerateTask.java
@@ -2,10 +2,10 @@
import static com.igormaznitsa.jbbp.utils.JBBPUtils.ARRAY_STRING_EMPTY;
-
import com.igormaznitsa.jbbp.JBBPCustomFieldTypeProcessor;
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
import com.igormaznitsa.jbbp.compiler.tokenizer.JBBPFieldTypeParameterContainer;
+import com.igormaznitsa.jbbp.io.JBBPArraySizeLimiter;
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
import com.igormaznitsa.jbbp.io.JBBPBitOrder;
import com.igormaznitsa.jbbp.model.JBBPAbstractField;
@@ -27,7 +27,6 @@
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.Input;
-import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.SourceSet;
/**
@@ -41,9 +40,12 @@ public class JBBPGenerateTask extends AbstractJBBPTask {
* Flag to register the output folder in Java source folders at the end of process.
*/
@Input
- @Optional
protected boolean addSource = true;
+ public boolean isAddSource() {
+ return this.addSource;
+ }
+
@Override
protected void doTaskAction(@Nonnull final JBBPExtension ext) {
final Target target = GetUtils.ensureNonNull(ext.target, Target.JAVA);
@@ -54,7 +56,8 @@ protected void doTaskAction(@Nonnull final JBBPExtension ext) {
final String trimmed = s.trim();
final String normalized = trimmed.toLowerCase(Locale.ENGLISH);
if (!normalized.equals(trimmed)) {
- getLogger().warn(String.format("Custom type name '%s' in JBBP normal form is '%s' ", trimmed, normalized));
+ getLogger().warn(String
+ .format("Custom type name '%s' in JBBP normal form is '%s' ", trimmed, normalized));
}
normalizedCustomTypeNames.add(normalized);
}
@@ -71,7 +74,9 @@ public String[] getCustomFieldTypes() {
}
@Override
- public boolean isAllowed(@Nonnull final JBBPFieldTypeParameterContainer fieldType, @Nullable final String fieldName, final int extraData, final boolean isArray) {
+ public boolean isAllowed(@Nonnull final JBBPFieldTypeParameterContainer fieldType,
+ @Nullable final String fieldName, final int extraData,
+ final boolean isArray) {
final boolean result = normalizedCustomTypeNames.contains(fieldType.getTypeName());
if (!result) {
getLogger().warn("Detected not allowed custom type name : " + fieldType.getTypeName());
@@ -81,7 +86,16 @@ public boolean isAllowed(@Nonnull final JBBPFieldTypeParameterContainer fieldTyp
@Override
@Nonnull
- public JBBPAbstractField readCustomFieldType(@Nonnull final JBBPBitInputStream in, @Nonnull final JBBPBitOrder bitOrder, final int parserFlags, @Nonnull final JBBPFieldTypeParameterContainer customTypeFieldInfo, @Nullable final JBBPNamedFieldInfo fieldName, final int extraData, final boolean readWholeStream, final int arrayLength) throws IOException {
+ public JBBPAbstractField readCustomFieldType(@Nonnull final JBBPBitInputStream in,
+ @Nonnull final JBBPBitOrder bitOrder,
+ final int parserFlags, @Nonnull
+ final JBBPFieldTypeParameterContainer customTypeFieldInfo,
+ @Nullable final JBBPNamedFieldInfo fieldName,
+ final int extraData,
+ final boolean readWholeStream,
+ final int arrayLength,
+ final JBBPArraySizeLimiter arraySizeLimiter)
+ throws IOException {
throw new Error("Must not be called");
}
};
@@ -117,19 +131,25 @@ public JBBPAbstractField readCustomFieldType(@Nonnull final JBBPBitInputStream i
final Set files = target.getTranslator().translate(parameters, false);
getLogger().debug("Converted " + aScript + " into " + files);
for (final File f : files) {
- getLogger().info(String.format("JBBP script '%s' has been converted into '%s'", aScript.getName(), f.getName()));
+ getLogger().info(String
+ .format("JBBP script '%s' has been converted into '%s'", aScript.getName(),
+ f.getName()));
}
} catch (IOException ex) {
- throw new GradleException("Error during JBBP script translation : " + aScript.getAbsolutePath(), ex);
+ throw new GradleException(
+ "Error during JBBP script translation : " + aScript.getAbsolutePath(), ex);
}
}
if (this.addSource) {
- getLogger().debug("Registering path to java sources : " + Assertions.assertNotNull("Output must not be null", ext.output));
+ getLogger().debug("Registering path to java sources : " +
+ Assertions.assertNotNull("Output must not be null", ext.output));
if (getProject().getPlugins().hasPlugin(JavaPlugin.class)) {
- final JavaPluginConvention javaPluginConvention = getProject().getConvention().getPlugin(JavaPluginConvention.class);
- final SourceSet main = javaPluginConvention.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
+ final JavaPluginConvention javaPluginConvention =
+ getProject().getConvention().getPlugin(JavaPluginConvention.class);
+ final SourceSet main =
+ javaPluginConvention.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
main.getJava().srcDir(ext.output);
getLogger().info("Source folder has been added into Java task : " + ext.output);
} else {
diff --git a/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPPlugin.java b/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPPlugin.java
index 44e97439..41c08ba5 100644
--- a/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPPlugin.java
+++ b/jbbp-plugins/jbbp-gradle/src/main/java/com/igormaznitsa/jbbp/plugin/gradle/JBBPPlugin.java
@@ -1,16 +1,20 @@
package com.igormaznitsa.jbbp.plugin.gradle;
+import javax.annotation.Nonnull;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
-import javax.annotation.Nonnull;
-
public class JBBPPlugin implements Plugin {
@Override
public void apply(@Nonnull final Project project) {
- project.getExtensions().create(JBBPExtension.EXT_NAME, JBBPExtension.class, project);
- project.getTasks().create("jbbpGenerate", JBBPGenerateTask.class);
- project.getTasks().create("jbbpClean", JBBPCleanTask.class);
+ JBBPExtension extension = project.getExtensions()
+ .create(JBBPExtension.class, JBBPExtension.EXT_NAME, JBBPExtension.class, project);
+ project.getTasks().register("jbbpGenerate", JBBPGenerateTask.class, task -> {
+ task.setDescription("Generate JBBP stuff.");
+ });
+ project.getTasks().register("jbbpClean", JBBPCleanTask.class, task -> {
+ task.setDescription("Clean all JBBP stuff.");
+ });
}
}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle/src/main/resources/META-INF/gradle-plugins/com.igormaznitsa.gradle.jbbp.properties b/jbbp-plugins/jbbp-gradle/src/main/resources/META-INF/gradle-plugins/com.igormaznitsa.gradle.jbbp.properties
deleted file mode 100644
index 282c28f3..00000000
--- a/jbbp-plugins/jbbp-gradle/src/main/resources/META-INF/gradle-plugins/com.igormaznitsa.gradle.jbbp.properties
+++ /dev/null
@@ -1 +0,0 @@
-implementation-class=com.igormaznitsa.jbbp.plugin.gradle.JBBPPlugin
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-gradle/src/test/groovy/com/igormaznitsa/jbbp/plugin/gradle/JBBPPluginTest.groovy b/jbbp-plugins/jbbp-gradle/src/test/groovy/com/igormaznitsa/jbbp/plugin/gradle/JBBPPluginTest.groovy
index 02a42fbe..714ed009 100644
--- a/jbbp-plugins/jbbp-gradle/src/test/groovy/com/igormaznitsa/jbbp/plugin/gradle/JBBPPluginTest.groovy
+++ b/jbbp-plugins/jbbp-gradle/src/test/groovy/com/igormaznitsa/jbbp/plugin/gradle/JBBPPluginTest.groovy
@@ -2,17 +2,18 @@ import org.gradle.api.Project
import org.gradle.testfixtures.ProjectBuilder
import org.junit.Test
-import static org.junit.Assert.assertTrue
+import static org.junit.Assert.assertNotNull
class JBBPPluginTest {
@Test
void demo_plugin_should_add_task_to_project() {
Project project = ProjectBuilder.builder().build()
- project.getPlugins().apply 'jbbp'
+ project.tasks.create("jbbpGenerate")
+ project.tasks.create("jbbpClean")
- assertTrue(project.tasks.jbbpGenerate instanceof JBBPGenerateTask)
- assertTrue(project.tasks.jbbpClean instanceof JBBPCleanTask)
+ assertNotNull(project.tasks.getByName("jbbpGenerate"))
+ assertNotNull(project.tasks.getByName("jbbpClean"))
}
}
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-customvars/src/main/java/com/igormaznitsa/mvn/tst/VarCustomImpl.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-customvars/src/main/java/com/igormaznitsa/mvn/tst/VarCustomImpl.java
index 69b08c68..1234feb7 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-customvars/src/main/java/com/igormaznitsa/mvn/tst/VarCustomImpl.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-customvars/src/main/java/com/igormaznitsa/mvn/tst/VarCustomImpl.java
@@ -27,42 +27,69 @@
import com.igormaznitsa.jbbp.model.JBBPFieldLong;
import com.igormaznitsa.jbbp.model.JBBPFieldShort;
import com.igormaznitsa.mvn.test.jbbp.VarCustom;
-
import java.io.IOException;
public class VarCustomImpl extends VarCustom {
@Override
- public JBBPAbstractField readCustomFieldType(Object sourceStruct, JBBPBitInputStream inStream, JBBPFieldTypeParameterContainer typeParameterContainer, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean readWholeStream, int arraySize) throws IOException {
- return new JBBPFieldShort(nullableNamedFieldInfo, (short) inStream.readUnsignedShort(typeParameterContainer.getByteOrder()));
+ public JBBPAbstractField readCustomFieldType(Object sourceStruct, JBBPBitInputStream inStream,
+ JBBPFieldTypeParameterContainer typeParameterContainer,
+ JBBPNamedFieldInfo nullableNamedFieldInfo,
+ int extraValue, boolean readWholeStream,
+ int arraySize) throws IOException {
+ return new JBBPFieldShort(nullableNamedFieldInfo,
+ (short) inStream.readUnsignedShort(typeParameterContainer.getByteOrder()));
}
@Override
- public void writeCustomFieldType(Object sourceStruct, JBBPBitOutputStream outStream, JBBPAbstractField fieldValue, JBBPFieldTypeParameterContainer typeParameterContainer, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean wholeArray, int arraySize) throws IOException {
- outStream.writeShort(((JBBPFieldShort) fieldValue).getAsInt(), typeParameterContainer.getByteOrder());
+ public void writeCustomFieldType(Object sourceStruct, JBBPBitOutputStream outStream,
+ JBBPAbstractField fieldValue,
+ JBBPFieldTypeParameterContainer typeParameterContainer,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue,
+ boolean wholeArray, int arraySize) throws IOException {
+ outStream.writeShort(((JBBPFieldShort) fieldValue).getAsInt(),
+ typeParameterContainer.getByteOrder());
}
@Override
- public JBBPAbstractField readVarField(Object sourceStruct, JBBPBitInputStream inStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue) throws IOException {
+ public JBBPAbstractField readVarField(Object sourceStruct, JBBPBitInputStream inStream,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue)
+ throws IOException {
return new JBBPFieldLong(nullableNamedFieldInfo, inStream.readLong(byteOrder));
}
@Override
- public JBBPAbstractArrayField extends JBBPAbstractField> readVarArray(Object sourceStruct, JBBPBitInputStream inStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean readWholeStream, int arraySize) throws IOException {
+ public JBBPAbstractArrayField extends JBBPAbstractField> readVarArray(Object sourceStruct,
+ JBBPBitInputStream inStream,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo,
+ int extraValue,
+ boolean readWholeStream,
+ int arraySize)
+ throws IOException {
if (readWholeStream) {
return new JBBPFieldArrayLong(nullableNamedFieldInfo, inStream.readLongArray(-1, byteOrder));
} else {
- return new JBBPFieldArrayLong(nullableNamedFieldInfo, inStream.readLongArray(arraySize, byteOrder));
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo,
+ inStream.readLongArray(arraySize, byteOrder));
}
}
@Override
- public void writeVarField(Object sourceStruct, JBBPAbstractField value, JBBPBitOutputStream outStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue) throws IOException {
+ public void writeVarField(Object sourceStruct, JBBPAbstractField value,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue)
+ throws IOException {
outStream.writeLong(((JBBPFieldLong) value).getAsLong(), byteOrder);
}
@Override
- public void writeVarArray(Object sourceStruct, JBBPAbstractArrayField extends JBBPAbstractField> array, JBBPBitOutputStream outStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, int arraySizeToWrite) throws IOException {
+ public void writeVarArray(Object sourceStruct,
+ JBBPAbstractArrayField extends JBBPAbstractField> array,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue,
+ int arraySizeToWrite) throws IOException {
final JBBPFieldArrayLong a = (JBBPFieldArrayLong) array;
if (arraySizeToWrite < 0) {
for (final long l : a.getArray()) {
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-customvars/src/test/java/com/igormaznitsa/mvn/test/jbbp/VarCustomTest.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-customvars/src/test/java/com/igormaznitsa/mvn/test/jbbp/VarCustomTest.java
index 58d9134e..85347e24 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-customvars/src/test/java/com/igormaznitsa/mvn/test/jbbp/VarCustomTest.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-customvars/src/test/java/com/igormaznitsa/mvn/test/jbbp/VarCustomTest.java
@@ -16,16 +16,16 @@
package com.igormaznitsa.mvn.test.jbbp;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
import com.igormaznitsa.jbbp.io.JBBPBitOutputStream;
import com.igormaznitsa.mvn.tst.VarCustomImpl;
-import org.junit.jupiter.api.Test;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Random;
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import org.junit.jupiter.api.Test;
public class VarCustomTest {
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations-nonstatic/src/test/java/com/igormaznitsa/mvn/test/jbbp/GenAnnotationsNonStaticTest.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations-nonstatic/src/test/java/com/igormaznitsa/mvn/test/jbbp/GenAnnotationsNonStaticTest.java
index 8d99671e..ed031763 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations-nonstatic/src/test/java/com/igormaznitsa/mvn/test/jbbp/GenAnnotationsNonStaticTest.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations-nonstatic/src/test/java/com/igormaznitsa/mvn/test/jbbp/GenAnnotationsNonStaticTest.java
@@ -32,7 +32,8 @@ class GenAnnotationsNonStaticTest {
void testReadWrite() throws IOException {
final byte[] testData = new byte[] {4, (byte) 0x12, (byte) 0x34, 3, 5, 6, 7};
- final GenAnnotationsNonStatic result = new GenAnnotationsNonStatic().read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ final GenAnnotationsNonStatic result = new GenAnnotationsNonStatic()
+ .read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
assertEquals(4, result.getLEN());
assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
@@ -45,10 +46,12 @@ void testReadWrite() throws IOException {
+ " }"
+ "}";
- final GenAnnotationsNonStatic instance = JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotationsNonStatic());
+ final GenAnnotationsNonStatic instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotationsNonStatic());
assertEquals(result.getLEN(), instance.getLEN());
assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
- assertArrayEquals(result.getSOME1().getSOME2().getFIELD(), instance.getSOME1().getSOME2().getFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
}
}
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
index 58f5edc9..b1f6c18f 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations/src/jbbp/com.igormaznitsa.mvn.test.jbbp.GenAnnotations.jbbp
@@ -1,4 +1,6 @@
ubyte len;
+uint uintField;
+uint [1] uintArr;
some1 {
bit:4 [len] someField;
ubyte len;
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations/src/test/java/com/igormaznitsa/mvn/test/jbbp/GenAnnotationsTest.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations/src/test/java/com/igormaznitsa/mvn/test/jbbp/GenAnnotationsTest.java
index 350e0b64..f137c3a1 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations/src/test/java/com/igormaznitsa/mvn/test/jbbp/GenAnnotationsTest.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-genannotations/src/test/java/com/igormaznitsa/mvn/test/jbbp/GenAnnotationsTest.java
@@ -30,13 +30,20 @@ class GenAnnotationsTest {
@Test
void testReadWrite() throws IOException {
- final byte[] testData = new byte[] {4, (byte) 0x12, (byte) 0x34, 3, 5, 6, 7};
+ final byte[] testData = new byte[] {
+ 4,
+ (byte)0xFF, (byte)0x1A, (byte)0x1B, (byte)0x1C,
+ (byte)0xFF, (byte)0x2A, (byte)0x2B, (byte)0x2C,
+ (byte) 0x12, (byte) 0x34, 3, 5, 6, 7};
- final GenAnnotations result = new GenAnnotations().read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
+ final GenAnnotations result =
+ new GenAnnotations().read(new JBBPBitInputStream(new ByteArrayInputStream(testData)));
assertEquals(4, result.getLEN());
assertEquals(3, result.getSOME1().getSOME2().getFIELD().length);
final String script = "ubyte len;"
+ + " uint uintField;"
+ + " uint [1] uintArr;"
+ "some1 {"
+ " bit:4 [len] someField;"
+ " ubyte len;"
@@ -45,10 +52,14 @@ void testReadWrite() throws IOException {
+ " }"
+ "}";
- final GenAnnotations instance = JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotations());
+ final GenAnnotations instance =
+ JBBPParser.prepare(script).parse(testData).mapTo(new GenAnnotations());
+ assertEquals(result.getUINTFIELD(), instance.getUINTFIELD());
+ assertArrayEquals(result.getUINTARR(), instance.getUINTARR());
assertEquals(result.getLEN(), instance.getLEN());
assertEquals(result.getSOME1().getLEN(), instance.getSOME1().getLEN());
assertArrayEquals(result.getSOME1().getSOMEFIELD(), instance.getSOME1().getSOMEFIELD());
- assertArrayEquals(result.getSOME1().getSOME2().getFIELD(), instance.getSOME1().getSOME2().getFIELD());
+ assertArrayEquals(result.getSOME1().getSOME2().getFIELD(),
+ instance.getSOME1().getSOME2().getFIELD());
}
}
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-getterssetters/src/main/java/com/igormaznitsa/mvn/tst/VarCustomImpl.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-getterssetters/src/main/java/com/igormaznitsa/mvn/tst/VarCustomImpl.java
index ac1430f0..b7c6a973 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-getterssetters/src/main/java/com/igormaznitsa/mvn/tst/VarCustomImpl.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-getterssetters/src/main/java/com/igormaznitsa/mvn/tst/VarCustomImpl.java
@@ -32,26 +32,47 @@
public class VarCustomImpl extends VarCustom {
@Override
- public JBBPAbstractField readCustomFieldType(Object sourceStruct, JBBPBitInputStream inStream, JBBPFieldTypeParameterContainer typeParameterContainer, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean readWholeStream, int arraySize) throws IOException {
- return new JBBPFieldShort(nullableNamedFieldInfo, (short) inStream.readUnsignedShort(typeParameterContainer.getByteOrder()));
+ public JBBPAbstractField readCustomFieldType(Object sourceStruct, JBBPBitInputStream inStream,
+ JBBPFieldTypeParameterContainer typeParameterContainer,
+ JBBPNamedFieldInfo nullableNamedFieldInfo,
+ int extraValue, boolean readWholeStream,
+ int arraySize) throws IOException {
+ return new JBBPFieldShort(nullableNamedFieldInfo,
+ (short) inStream.readUnsignedShort(typeParameterContainer.getByteOrder()));
}
@Override
- public void writeCustomFieldType(Object sourceStruct, JBBPBitOutputStream outStream, JBBPAbstractField fieldValue, JBBPFieldTypeParameterContainer typeParameterContainer, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean wholeArray, int arraySize) throws IOException {
- outStream.writeShort(((JBBPFieldShort) fieldValue).getAsInt(), typeParameterContainer.getByteOrder());
+ public void writeCustomFieldType(Object sourceStruct, JBBPBitOutputStream outStream,
+ JBBPAbstractField fieldValue,
+ JBBPFieldTypeParameterContainer typeParameterContainer,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue,
+ boolean wholeArray, int arraySize) throws IOException {
+ outStream.writeShort(((JBBPFieldShort) fieldValue).getAsInt(),
+ typeParameterContainer.getByteOrder());
}
@Override
- public JBBPAbstractField readVarField(Object sourceStruct, JBBPBitInputStream inStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue) throws IOException {
+ public JBBPAbstractField readVarField(Object sourceStruct, JBBPBitInputStream inStream,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue)
+ throws IOException {
return new JBBPFieldLong(nullableNamedFieldInfo, inStream.readLong(byteOrder));
}
@Override
- public JBBPAbstractArrayField extends JBBPAbstractField> readVarArray(Object sourceStruct, JBBPBitInputStream inStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean readWholeStream, int arraySize) throws IOException {
+ public JBBPAbstractArrayField extends JBBPAbstractField> readVarArray(Object sourceStruct,
+ JBBPBitInputStream inStream,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo,
+ int extraValue,
+ boolean readWholeStream,
+ int arraySize)
+ throws IOException {
if (readWholeStream) {
return new JBBPFieldArrayLong(nullableNamedFieldInfo, inStream.readLongArray(-1, byteOrder));
} else {
- return new JBBPFieldArrayLong(nullableNamedFieldInfo, inStream.readLongArray(arraySize, byteOrder));
+ return new JBBPFieldArrayLong(nullableNamedFieldInfo,
+ inStream.readLongArray(arraySize, byteOrder));
}
}
@@ -60,12 +81,19 @@ public void run() {
}
@Override
- public void writeVarField(Object sourceStruct, JBBPAbstractField value, JBBPBitOutputStream outStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue) throws IOException {
+ public void writeVarField(Object sourceStruct, JBBPAbstractField value,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue)
+ throws IOException {
outStream.writeLong(((JBBPFieldLong) value).getAsLong(), byteOrder);
}
@Override
- public void writeVarArray(Object sourceStruct, JBBPAbstractArrayField extends JBBPAbstractField> array, JBBPBitOutputStream outStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, int arraySizeToWrite) throws IOException {
+ public void writeVarArray(Object sourceStruct,
+ JBBPAbstractArrayField extends JBBPAbstractField> array,
+ JBBPBitOutputStream outStream, JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue,
+ int arraySizeToWrite) throws IOException {
final JBBPFieldArrayLong a = (JBBPFieldArrayLong) array;
if (arraySizeToWrite < 0) {
for (final long l : a.getArray()) {
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-primitives/src/test/java/com/igormaznitsa/mvn/test/jbbp/WholeStreamByteArrayTest.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-primitives/src/test/java/com/igormaznitsa/mvn/test/jbbp/WholeStreamByteArrayTest.java
index 8f69face..3c9a76fc 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-primitives/src/test/java/com/igormaznitsa/mvn/test/jbbp/WholeStreamByteArrayTest.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/jbbp-mvn-test-primitives/src/test/java/com/igormaznitsa/mvn/test/jbbp/WholeStreamByteArrayTest.java
@@ -16,22 +16,23 @@
package com.igormaznitsa.mvn.test.jbbp;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
import com.igormaznitsa.jbbp.io.JBBPBitOutputStream;
-import org.junit.jupiter.api.Test;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import org.junit.jupiter.api.Test;
public class WholeStreamByteArrayTest {
@Test
public void testRead_DefaultBitOrder() throws IOException {
- final WholeStreamByteArray struct = new WholeStreamByteArray().read(new JBBPBitInputStream(new ByteArrayInputStream(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})));
+ final WholeStreamByteArray struct = new WholeStreamByteArray().read(new JBBPBitInputStream(
+ new ByteArrayInputStream(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})));
assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, struct.array);
}
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/pom.xml b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/pom.xml
index a31fd33c..709f4ec2 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/pom.xml
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin-tests/pom.xml
@@ -5,7 +5,7 @@
com.igormaznitsajbbp-maven-plugin-pom
- 2.0.1
+ 3.0.2-SNAPSHOTjbbp-maven-plugin-tests
@@ -31,7 +31,6 @@
org.apache.maven.sharedmaven-verifier
- 1.6test
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/pom.xml b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/pom.xml
index 2f4436d0..f73897be 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/pom.xml
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/pom.xml
@@ -5,7 +5,7 @@
com.igormaznitsajbbp-maven-plugin-pom
- 2.0.1
+ 3.0.2-SNAPSHOTjbbp-maven-plugin
@@ -14,11 +14,6 @@
JBBP Maven pluginGenerator of sources from JBBP scripts
-
- 1.8
- 1.8
-
-
publish
@@ -85,6 +80,33 @@
+
+ net.nicoulaj.maven.plugins
+ checksum-maven-plugin
+
+
+ verify
+
+ files
+
+
+
+
+ ${project.build.directory}
+
+ *.jar
+ *.pom
+
+
+
+
+ SHA-1
+ MD5
+
+
+
+
+
@@ -168,7 +190,7 @@
com.igormaznitsauber-pom
- 1.0.1
+ 1.0.3parent
@@ -185,31 +207,10 @@
-
- org.codehaus.mojo
- animal-sniffer-maven-plugin
- 1.17
-
-
- org.codehaus.mojo.signature
- java16-sun
- 1.10
-
-
-
-
- animal-sniffer
- test
-
- check
-
-
-
- org.apache.maven.pluginsmaven-plugin-plugin
- 3.5
+ 3.8.1truejbbp
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/assemble/bundle.xml b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/assemble/bundle.xml
index 1d3c7e7f..008c1efd 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/assemble/bundle.xml
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/assemble/bundle.xml
@@ -7,17 +7,21 @@
false
- jar
+ tar.gz${project.build.directory}
- /
+ /com/igormaznitsa/${project.artifactId}/${project.version}
- *.jar.asc*.jar
+ *.jar.asc
+ *.jar.sha1
+ *.jar.md5*.pom*.pom.asc
+ *.pom.sha1
+ *.pom.md5original*.*
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/assemble/distribution.xml b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/assemble/distribution.xml
deleted file mode 100644
index 22c183dc..00000000
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/assemble/distribution.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-
- distr
-
- false
- false
-
-
- tar.gz
-
-
-
- ${project.basedir}
- /project
-
- target/
- texts/
- nbactions.xml
- catalog.xml
- **/.*
-
-
-
- /lib
- ${project.basedir}/target
-
- ${project.build.finalName}.jar
-
-
-
- /lib
- ${project.basedir}
-
- pom.xml
-
-
-
- /
- ${basedir}/texts
-
- *.*
-
-
-
-
\ No newline at end of file
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/AbstractJBBPMojo.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/AbstractJBBPMojo.java
index 85650ad3..66d95075 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/AbstractJBBPMojo.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/AbstractJBBPMojo.java
@@ -3,6 +3,11 @@
import com.igormaznitsa.jbbp.plugin.common.converters.Target;
import com.igormaznitsa.meta.annotation.MustNotContainNull;
import com.igormaznitsa.meta.common.utils.Assertions;
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
@@ -13,12 +18,6 @@
import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.io.File;
-import java.util.HashSet;
-import java.util.Set;
-
public abstract class AbstractJBBPMojo extends AbstractMojo {
/**
* Provides an explicit list of all the JBBP scripts that should be included
@@ -170,7 +169,8 @@ protected void registerSourceRoot(@Nonnull final File outputDir) {
@Nonnull
public Set findSources(@Nonnull final File targetDirectory) throws MojoExecutionException {
try {
- final SourceInclusionScanner scanner = new SimpleSourceInclusionScanner(this.includes, this.excludes);
+ final SourceInclusionScanner scanner =
+ new SimpleSourceInclusionScanner(this.includes, this.excludes);
scanner.addSourceMapping(new SuffixMapping("JBBP", "jbbp"));
return scanner.getIncludedSources(this.source, targetDirectory);
} catch (InclusionScanException ex) {
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPCleanMojo.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPCleanMojo.java
index bbfa3b67..3bfc7a9d 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPCleanMojo.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPCleanMojo.java
@@ -2,6 +2,9 @@
import com.igormaznitsa.jbbp.plugin.common.converters.JBBPScriptTranslator;
import com.igormaznitsa.jbbp.plugin.common.converters.Target;
+import java.io.File;
+import java.io.IOException;
+import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
@@ -9,10 +12,6 @@
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
-import java.io.File;
-import java.io.IOException;
-import java.util.Set;
-
/**
* The Mojo looks for all java files generated for JBBP scripts and delete them.
*
@@ -67,12 +66,15 @@ public void executeMojo() throws MojoExecutionException, MojoFailureException {
if (f.isFile()) {
if (f.delete()) {
counter++;
- logInfo("Deleted file '" + f.getAbsolutePath() + "' for script '" + aScript + "'", true);
+ logInfo("Deleted file '" + f.getAbsolutePath() + "' for script '" + aScript + "'",
+ true);
} else {
- getLog().error("Can't delete file '" + f.getAbsolutePath() + "' for script '" + aScript + "'");
+ getLog().error(
+ "Can't delete file '" + f.getAbsolutePath() + "' for script '" + aScript + "'");
}
} else {
- getLog().debug("File '" + f.getAbsolutePath() + "' generated for script '" + aScript + "' is not found");
+ getLog().debug("File '" + f.getAbsolutePath() + "' generated for script '" + aScript +
+ "' is not found");
}
}
}
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojo.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojo.java
index 6171a8c5..ac17f190 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojo.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/main/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojo.java
@@ -19,10 +19,10 @@
import static com.igormaznitsa.jbbp.plugin.common.utils.CommonUtils.ensureEncodingName;
import static com.igormaznitsa.jbbp.utils.JBBPUtils.ARRAY_STRING_EMPTY;
-
import com.igormaznitsa.jbbp.JBBPCustomFieldTypeProcessor;
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
import com.igormaznitsa.jbbp.compiler.tokenizer.JBBPFieldTypeParameterContainer;
+import com.igormaznitsa.jbbp.io.JBBPArraySizeLimiter;
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
import com.igormaznitsa.jbbp.io.JBBPBitOrder;
import com.igormaznitsa.jbbp.mapper.Bin;
@@ -202,14 +202,14 @@ public String getSuperClass() {
return this.superClass;
}
- public void setDoAbstract(final boolean value) {
- this.doAbstract = value;
- }
-
public boolean isDoAbstract() {
return this.doAbstract;
}
+ public void setDoAbstract(final boolean value) {
+ this.doAbstract = value;
+ }
+
@Nonnull
public Map getMapStructToInterfaces() {
return this.mapStructToInterfaces;
@@ -280,14 +280,14 @@ public void setDisableGenerateFields(final boolean value) {
this.disableGenerateFields = value;
}
- public void setDoInnerClassesNonStatic(final boolean value) {
- this.doInnerClassesNonStatic = value;
- }
-
public boolean isDoInnerClassesNonStatic() {
return this.doInnerClassesNonStatic;
}
+ public void setDoInnerClassesNonStatic(final boolean value) {
+ this.doInnerClassesNonStatic = value;
+ }
+
@Nullable
private String makeCapText(@Nonnull final String inEncoding) throws IOException {
String result = null;
@@ -343,7 +343,8 @@ protected void executeMojo() throws MojoExecutionException, MojoFailureException
final String trimmed = s.trim();
final String normalized = trimmed.toLowerCase(Locale.ENGLISH);
if (!normalized.equals(trimmed)) {
- getLog().warn(String.format("Custom type name '%s' in JBBP normal form is '%s' ", trimmed, normalized));
+ getLog().warn(String
+ .format("Custom type name '%s' in JBBP normal form is '%s' ", trimmed, normalized));
}
normalizedCustomTypeNames.add(normalized);
}
@@ -360,7 +361,9 @@ public String[] getCustomFieldTypes() {
}
@Override
- public boolean isAllowed(@Nonnull final JBBPFieldTypeParameterContainer fieldType, @Nullable final String fieldName, final int extraData, final boolean isArray) {
+ public boolean isAllowed(@Nonnull final JBBPFieldTypeParameterContainer fieldType,
+ @Nullable final String fieldName, final int extraData,
+ final boolean isArray) {
final boolean result = normalizedCustomTypeNames.contains(fieldType.getTypeName());
if (!result) {
getLog().warn("Detected not allowed custom type name : " + fieldType.getTypeName());
@@ -370,7 +373,17 @@ public boolean isAllowed(@Nonnull final JBBPFieldTypeParameterContainer fieldTyp
@Override
@Nonnull
- public JBBPAbstractField readCustomFieldType(@Nonnull final JBBPBitInputStream in, @Nonnull final JBBPBitOrder bitOrder, final int parserFlags, @Nonnull final JBBPFieldTypeParameterContainer customTypeFieldInfo, @Nullable final JBBPNamedFieldInfo fieldName, final int extraData, final boolean readWholeStream, final int arrayLength) throws IOException {
+ public JBBPAbstractField readCustomFieldType(@Nonnull final JBBPBitInputStream in,
+ @Nonnull final JBBPBitOrder bitOrder,
+ final int parserFlags, @Nonnull
+ final JBBPFieldTypeParameterContainer customTypeFieldInfo,
+ @Nullable final JBBPNamedFieldInfo fieldName,
+ final int extraData,
+ final boolean readWholeStream,
+ final int arrayLength,
+ @Nonnull
+ final JBBPArraySizeLimiter arraySizeLimiter)
+ throws IOException {
throw new Error("Must not be called");
}
};
@@ -407,20 +420,24 @@ public JBBPAbstractField readCustomFieldType(@Nonnull final JBBPBitInputStream i
final Set files = theTarget.getTranslator().translate(parameters, false);
getLog().debug("Converted " + aScript + " into " + files);
for (final File f : files) {
- logInfo(String.format("JBBP script '%s' has been converted into '%s'", aScript.getName(), f.getName()), false);
+ logInfo(String
+ .format("JBBP script '%s' has been converted into '%s'", aScript.getName(),
+ f.getName()), false);
}
} catch (IOException ex) {
- throw new MojoExecutionException("Error during JBBP script translation : " + aScript.getAbsolutePath(), ex);
+ throw new MojoExecutionException(
+ "Error during JBBP script translation : " + aScript.getAbsolutePath(), ex);
}
}
if (this.isAddToSourceFolders()) {
- getLog().info("Add folder to compile source root: "+ this.getOutput().getAbsolutePath());
+ getLog().info("Add folder to compile source root: " + this.getOutput().getAbsolutePath());
this.project.addCompileSourceRoot(this.getOutput().getAbsolutePath());
}
if (this.isAddToTestSourceFolders()) {
- getLog().info("Add folder to test compile source root: "+ this.getOutput().getAbsolutePath());
+ getLog()
+ .info("Add folder to test compile source root: " + this.getOutput().getAbsolutePath());
this.project.addTestCompileSourceRoot(this.getOutput().getAbsolutePath());
}
}
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/java/com/igormaznitsa/jbbp/plugin/common/converters/JavaConverterTest.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/java/com/igormaznitsa/jbbp/plugin/common/converters/JavaConverterTest.java
index bc8aba43..430d4962 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/java/com/igormaznitsa/jbbp/plugin/common/converters/JavaConverterTest.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/java/com/igormaznitsa/jbbp/plugin/common/converters/JavaConverterTest.java
@@ -32,9 +32,12 @@ void testTranslateParameters() {
assertTrue(parameters.setDoInternalClassesNonStatic(true).isDoInternalClassesNonStatic());
assertFalse(parameters.setDoInternalClassesNonStatic(false).isDoInternalClassesNonStatic());
- assertEquals(new File("some_test"), parameters.setOutputDir(new File("some_test")).getOutputDir());
- assertEquals(new File("some_test.script"), parameters.setScriptFile(new File("some_test.script")).getScriptFile());
- assertEquals("some.test.package", parameters.setPackageName("some.test.package").getPackageName());
+ assertEquals(new File("some_test"),
+ parameters.setOutputDir(new File("some_test")).getOutputDir());
+ assertEquals(new File("some_test.script"),
+ parameters.setScriptFile(new File("some_test.script")).getScriptFile());
+ assertEquals("some.test.package",
+ parameters.setPackageName("some.test.package").getPackageName());
assertEquals("bit a;", parameters.setScriptText("bit a;").getScriptText());
assertEquals("SomeSuperClass", parameters.setSuperClass("SomeSuperClass").getSuperClass());
assertEquals(1234, parameters.setParserFlags(1234).getParserFlags());
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojoTest.java b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojoTest.java
index 35cb965c..8127b70a 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojoTest.java
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/java/com/igormaznitsa/jbbp/plugin/mvn/JBBPGenerateMojoTest.java
@@ -98,9 +98,12 @@ public void testConfig() throws Exception {
assertTrue(mojo.isAddToTestSourceFolders());
assertTrue(mojo.getAddGettersSetters());
assertArrayEquals(new String[] {"abc", "def"}, set2array(mojo.getCustomTypes()));
- assertArrayEquals(new String[] {"com.igormaznitsa.InterfaceA", "com.igormaznitsa.InterfaceB"}, set2array(mojo.getInterfaces()));
- assertArrayEquals(new String[] {"path1/**/*.jbbp", "path2/**/*.jbbp"}, set2array(mojo.getIncludes()));
- assertArrayEquals(new String[] {"path3/**/*.jbbp", "path4/**/*.jbbp"}, set2array(mojo.getExcludes()));
+ assertArrayEquals(new String[] {"com.igormaznitsa.InterfaceA", "com.igormaznitsa.InterfaceB"},
+ set2array(mojo.getInterfaces()));
+ assertArrayEquals(new String[] {"path1/**/*.jbbp", "path2/**/*.jbbp"},
+ set2array(mojo.getIncludes()));
+ assertArrayEquals(new String[] {"path3/**/*.jbbp", "path4/**/*.jbbp"},
+ set2array(mojo.getExcludes()));
assertTrue(mojo.isDoInnerClassesNonStatic());
assertTrue(mojo.isDisableGenerateFields());
diff --git a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/resources/com/igormaznitsa/jbbp/plugin/mvn/mojoConfig.xml b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/resources/com/igormaznitsa/jbbp/plugin/mvn/mojoConfig.xml
index 1f2ee6b0..cf77af0d 100644
--- a/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/resources/com/igormaznitsa/jbbp/plugin/mvn/mojoConfig.xml
+++ b/jbbp-plugins/jbbp-maven/jbbp-maven-plugin/src/test/resources/com/igormaznitsa/jbbp/plugin/mvn/mojoConfig.xml
@@ -14,7 +14,7 @@
com.igormaznitsajbbp-maven-plugin
- 2.0.1
+ 2.0.4-SNAPSHOTgenerate
diff --git a/jbbp-plugins/jbbp-maven/pom.xml b/jbbp-plugins/jbbp-maven/pom.xml
index 53ee3bcb..1da1b5aa 100644
--- a/jbbp-plugins/jbbp-maven/pom.xml
+++ b/jbbp-plugins/jbbp-maven/pom.xml
@@ -5,7 +5,7 @@
com.igormaznitsajbbp-main-plugin-pom
- 2.0.1
+ 3.0.2-SNAPSHOTjbbp-maven-plugin-pom
diff --git a/jbbp-plugins/jbbp-plugin-common/pom.xml b/jbbp-plugins/jbbp-plugin-common/pom.xml
index 5157cb73..c320c4b8 100644
--- a/jbbp-plugins/jbbp-plugin-common/pom.xml
+++ b/jbbp-plugins/jbbp-plugin-common/pom.xml
@@ -6,7 +6,7 @@
com.igormaznitsajbbp-main-plugin-pom
- 2.0.1
+ 3.0.2-SNAPSHOTjbbp-plugin-common
diff --git a/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/JBBPScriptTranslator.java b/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/JBBPScriptTranslator.java
index 94a46b4a..ba7f365c 100644
--- a/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/JBBPScriptTranslator.java
+++ b/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/JBBPScriptTranslator.java
@@ -47,24 +47,27 @@ public final class Parameters {
*/
@Nonnull
private final Map subClassSuperclasses = new HashMap();
-
+ /**
+ * Set of interface names to be implemented by the main class.
+ */
+ @Nonnull
+ private final Set classImplements = new HashSet();
+ /**
+ * Processor for custom types.
+ */
+ @Nullable
+ JBBPCustomFieldTypeProcessor customFieldTypeProcessor = null;
/**
* Flag to not make generated subclasses as static ones.
*
* @since 1.4.0
*/
private boolean doInternalClassesNonStatic;
- /**
- * Set of interface names to be implemented by the main class.
- */
- @Nonnull
- private final Set classImplements = new HashSet();
/**
* Super class for main class.
*/
@Nullable
private String superClass = null;
-
/**
* Destination file name.
*
@@ -72,12 +75,6 @@ public final class Parameters {
*/
@Nullable
private String destFileName = null;
-
- /**
- * Processor for custom types.
- */
- @Nullable
- JBBPCustomFieldTypeProcessor customFieldTypeProcessor = null;
/**
* Disable generate class fields.
*
@@ -161,12 +158,6 @@ public Parameters setPackageName(@Nullable final String value) {
return this;
}
- @Nonnull
- public Parameters setSuperClass(@Nullable final String value) {
- this.superClass = value;
- return this;
- }
-
public boolean isAddGettersSetters() {
return this.addGettersSetters;
}
@@ -215,14 +206,22 @@ public Map getSubClassInterfaces() {
return Collections.unmodifiableMap(this.subClassInterfaces);
}
+ @Nonnull
+ public Parameters setSubClassInterfaces(@Nonnull final Map value) {
+ this.subClassInterfaces.clear();
+ this.subClassInterfaces.putAll(value);
+ return this;
+ }
+
@Nonnull
public Map getSubClassSuperclasses() {
return Collections.unmodifiableMap(this.subClassSuperclasses);
}
@Nonnull
- public Parameters setDoInternalClassesNonStatic(final boolean flag) {
- this.doInternalClassesNonStatic = flag;
+ public Parameters setSubClassSuperclasses(@Nonnull final Map value) {
+ this.subClassSuperclasses.clear();
+ this.subClassSuperclasses.putAll(value);
return this;
}
@@ -230,6 +229,12 @@ public boolean isDoInternalClassesNonStatic() {
return this.doInternalClassesNonStatic;
}
+ @Nonnull
+ public Parameters setDoInternalClassesNonStatic(final boolean flag) {
+ this.doInternalClassesNonStatic = flag;
+ return this;
+ }
+
public boolean isAddNewInstanceMethods() {
return this.addNewInstanceMethods;
}
@@ -250,20 +255,6 @@ public Parameters setAddBinAnnotations(final boolean flag) {
return this;
}
- @Nonnull
- public Parameters setSubClassSuperclasses(@Nonnull final Map value) {
- this.subClassSuperclasses.clear();
- this.subClassSuperclasses.putAll(value);
- return this;
- }
-
- @Nonnull
- public Parameters setSubClassInterfaces(@Nonnull final Map value) {
- this.subClassInterfaces.clear();
- this.subClassInterfaces.putAll(value);
- return this;
- }
-
public int getParserFlags() {
return this.parserFlags;
}
@@ -367,7 +358,8 @@ public JBBPCustomFieldTypeProcessor getCustomFieldTypeProcessor() {
}
@Nonnull
- public Parameters setCustomFieldTypeProcessor(@Nullable final JBBPCustomFieldTypeProcessor customProcessor) {
+ public Parameters setCustomFieldTypeProcessor(
+ @Nullable final JBBPCustomFieldTypeProcessor customProcessor) {
this.customFieldTypeProcessor = customProcessor;
return this;
}
@@ -384,5 +376,11 @@ public Parameters assertAllOk() {
public String getSuperClass() {
return this.superClass;
}
+
+ @Nonnull
+ public Parameters setSuperClass(@Nullable final String value) {
+ this.superClass = value;
+ return this;
+ }
}
}
diff --git a/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/JavaConverter.java b/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/JavaConverter.java
index 4ccb8005..28595c4a 100644
--- a/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/JavaConverter.java
+++ b/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/JavaConverter.java
@@ -20,26 +20,35 @@
public class JavaConverter implements JBBPScriptTranslator {
@Override
@Nonnull
- public Set translate(@Nonnull final Parameters parameters, final boolean dryRun) throws IOException {
+ public Set translate(@Nonnull final Parameters parameters, final boolean dryRun)
+ throws IOException {
final String text;
final String rawFileName;
if (parameters.getScriptFile() == null) {
- rawFileName = parameters.getDestFileName() == null ? "JbbpNoName" : parameters.getDestFileName();
- text = Assertions.assertNotNull("Script file is null, expected script text", parameters.getScriptText());
+ rawFileName =
+ parameters.getDestFileName() == null ? "JbbpNoName" : parameters.getDestFileName();
+ text = Assertions
+ .assertNotNull("Script file is null, expected script text", parameters.getScriptText());
} else {
final File scriptToProcess = parameters.getScriptFile();
rawFileName = FilenameUtils.getBaseName(scriptToProcess.getName());
text = FileUtils.readFileToString(scriptToProcess, parameters.getEncodingIn());
}
final String className = CommonUtils.extractClassName(rawFileName);
- final String packageName = parameters.getPackageName() == null ? CommonUtils.extractPackageName(rawFileName) : parameters.getPackageName();
+ final String packageName =
+ parameters.getPackageName() == null ? CommonUtils.extractPackageName(rawFileName) :
+ parameters.getPackageName();
- final Set resultFiles = Collections.singleton(CommonUtils.scriptFileToJavaFile(parameters.getOutputDir(), parameters.getPackageName(), parameters.getScriptFile()));
+ final Set resultFiles = Collections.singleton(CommonUtils
+ .scriptFileToJavaFile(parameters.getOutputDir(), parameters.getPackageName(),
+ parameters.getScriptFile()));
if (!dryRun) {
final File resultJavaFile = resultFiles.iterator().next();
- final JBBPParser parser = JBBPParser.prepare(text, JBBPBitOrder.LSB0, parameters.customFieldTypeProcessor, parameters.getParserFlags());
+ final JBBPParser parser = JBBPParser
+ .prepare(text, JBBPBitOrder.LSB0, parameters.customFieldTypeProcessor,
+ parameters.getParserFlags());
final String[] implementsSorted = parameters.getClassImplements().toArray(ARRAY_STRING_EMPTY);
Arrays.sort(implementsSorted);
diff --git a/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/ParserFlags.java b/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/ParserFlags.java
index 852afa2e..65f65acd 100644
--- a/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/ParserFlags.java
+++ b/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/converters/ParserFlags.java
@@ -1,9 +1,8 @@
package com.igormaznitsa.jbbp.plugin.common.converters;
import com.igormaznitsa.jbbp.JBBPParser;
-
-import javax.annotation.Nullable;
import java.util.Set;
+import javax.annotation.Nullable;
/**
* Allowed parser flags.
diff --git a/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/utils/CommonUtils.java b/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/utils/CommonUtils.java
index 9986cf6c..e4354afb 100644
--- a/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/utils/CommonUtils.java
+++ b/jbbp-plugins/jbbp-plugin-common/src/main/java/com/igormaznitsa/jbbp/plugin/common/utils/CommonUtils.java
@@ -16,13 +16,12 @@
package com.igormaznitsa.jbbp.plugin.common.utils;
-import org.apache.commons.io.FilenameUtils;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.apache.commons.io.FilenameUtils;
/**
* Misc auxiliary methods.
@@ -44,7 +43,8 @@ private CommonUtils() {
public static String ensureEncodingName(@Nullable final String charsetName) {
final Charset defaultCharset = Charset.defaultCharset();
try {
- return (charsetName == null) ? defaultCharset.name() : Charset.forName(charsetName.trim()).name();
+ return (charsetName == null) ? defaultCharset.name() :
+ Charset.forName(charsetName.trim()).name();
} catch (IllegalCharsetNameException ex) {
throw new IllegalArgumentException("Can't recognize charset for name '" + charsetName + '\'');
}
@@ -89,10 +89,13 @@ public static String extractPackageName(@Nonnull final String fileNameWithoutExt
* @return java source file for the script file
*/
@Nonnull
- public static File scriptFileToJavaFile(@Nullable final File targetDir, @Nullable final String classPackage, @Nonnull final File scriptFile) {
+ public static File scriptFileToJavaFile(@Nullable final File targetDir,
+ @Nullable final String classPackage,
+ @Nonnull final File scriptFile) {
final String rawFileName = FilenameUtils.getBaseName(scriptFile.getName());
final String className = CommonUtils.extractClassName(rawFileName);
- final String packageName = classPackage == null ? CommonUtils.extractPackageName(rawFileName) : classPackage;
+ final String packageName =
+ classPackage == null ? CommonUtils.extractPackageName(rawFileName) : classPackage;
String fullClassName = packageName.isEmpty() ? className : packageName + '.' + className;
fullClassName = fullClassName.replace('.', File.separatorChar) + ".java";
diff --git a/jbbp-plugins/jbbp-plugin-common/src/test/java/com/igormaznitsa/jbbp/plugin/common/utils/CommonUtilsTest.java b/jbbp-plugins/jbbp-plugin-common/src/test/java/com/igormaznitsa/jbbp/plugin/common/utils/CommonUtilsTest.java
index fedb1916..d53ae44b 100644
--- a/jbbp-plugins/jbbp-plugin-common/src/test/java/com/igormaznitsa/jbbp/plugin/common/utils/CommonUtilsTest.java
+++ b/jbbp-plugins/jbbp-plugin-common/src/test/java/com/igormaznitsa/jbbp/plugin/common/utils/CommonUtilsTest.java
@@ -18,6 +18,7 @@
import org.junit.jupiter.api.Test;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CommonUtilsTest {
diff --git a/jbbp-plugins/pom.xml b/jbbp-plugins/pom.xml
index 867b0a49..f1cc9863 100644
--- a/jbbp-plugins/pom.xml
+++ b/jbbp-plugins/pom.xml
@@ -5,7 +5,7 @@
com.igormaznitsajbbp-main-pom
- 2.0.1
+ 3.0.2-SNAPSHOTjbbp-main-plugin-pom
@@ -31,10 +31,18 @@
commons-iocommons-io
- 2.6
+
+
+ gradle-tests
+
+ jbbp-gradle-tests
+
+
+
+
@@ -42,10 +50,8 @@
meta-checker${meta.version}
- 6truetrue
-
risky
diff --git a/jbbp/pom.xml b/jbbp/pom.xml
index a7f40c8e..9f031e0f 100644
--- a/jbbp/pom.xml
+++ b/jbbp/pom.xml
@@ -5,7 +5,7 @@
com.igormaznitsajbbp-main-pom
- 2.0.1
+ 3.0.2-SNAPSHOTjbbp
@@ -37,25 +37,22 @@
org.apache.commonscommons-lang3
- 3.9
+ 3.18.0testnet.minidevjson-smart
- 2.3testcommons-iocommons-io
- 2.6testcommons-codeccommons-codec
- 1.13test
@@ -118,7 +115,7 @@
test
- java
+ java8-classpath
@@ -158,6 +155,7 @@
org.apache.maven.pluginsmaven-javadoc-plugin
+ falsetrueprotectedUTF-8
@@ -170,7 +168,7 @@
jar
- 1.8
+ 8
@@ -188,6 +186,33 @@
+
+ net.nicoulaj.maven.plugins
+ checksum-maven-plugin
+
+
+ verify
+
+ files
+
+
+
+
+ ${project.build.directory}
+
+ *.jar
+ *.pom
+
+
+
+
+ SHA-1
+ MD5
+
+
+
+
+
@@ -230,30 +255,16 @@
animal-sniffer-maven-plugin
- ensure-java-1.8-class-library
- test
-
- check
-
-
-
- org.codehaus.mojo.signature
- java18
- 1.0
-
-
-
-
- ensure-android-3.0_r2-class-library
+ ensure-android-api-32-class-librarytestcheck
- net.sf.androidscents.signature
- android-api-level-11
- 3.0_r2
+ com.toasttab.android
+ gummy-bears-api-32
+ 0.10.0sun.misc.Unsafe
diff --git a/jbbp/src/assemble/bundle.xml b/jbbp/src/assemble/bundle.xml
index 227e64af..008c1efd 100644
--- a/jbbp/src/assemble/bundle.xml
+++ b/jbbp/src/assemble/bundle.xml
@@ -1,19 +1,3 @@
-
-
@@ -23,19 +7,24 @@
false
- jar
+ tar.gz${project.build.directory}
- ${file.separator}
+ /com/igormaznitsa/${project.artifactId}/${project.version}
- *.jar.asc*.jar
+ *.jar.asc
+ *.jar.sha1
+ *.jar.md5*.pom*.pom.asc
+ *.pom.sha1
+ *.pom.md5
+ original*.**.zip
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPCustomFieldTypeProcessor.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPCustomFieldTypeProcessor.java
index 25fb3452..c0453dae 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPCustomFieldTypeProcessor.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPCustomFieldTypeProcessor.java
@@ -18,10 +18,11 @@
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
import com.igormaznitsa.jbbp.compiler.tokenizer.JBBPFieldTypeParameterContainer;
+import com.igormaznitsa.jbbp.exceptions.JBBPReachedArraySizeLimitException;
+import com.igormaznitsa.jbbp.io.JBBPArraySizeLimiter;
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
import com.igormaznitsa.jbbp.io.JBBPBitOrder;
import com.igormaznitsa.jbbp.model.JBBPAbstractField;
-
import java.io.IOException;
/**
@@ -46,7 +47,8 @@ public interface JBBPCustomFieldTypeProcessor {
* @param isArray flag shows that the field describes an array
* @return true if such configuration allowed, false otherwise
*/
- boolean isAllowed(JBBPFieldTypeParameterContainer fieldType, String fieldName, int extraData, boolean isArray);
+ boolean isAllowed(JBBPFieldTypeParameterContainer fieldType, String fieldName, int extraData,
+ boolean isArray);
/**
* Read custom field from stream and return the data as a JBBP field.
@@ -59,8 +61,20 @@ public interface JBBPCustomFieldTypeProcessor {
* @param extraData extra numeric value for the field, followed by ':', if not presented then 0
* @param readWholeStream if true then the field is array which should contain parse data for whole stream till the end
* @param arrayLength -1 if it is not array else length of the array to be read.
+ * @param arraySizeLimiter limiter to check number of elements during whole stream array read, must not be null
* @return parsed data as JBBP field, must not be null
- * @throws IOException it can be thrown for transport errors
+ * @throws IOException it can be thrown for transport errors
+ * @throws JBBPReachedArraySizeLimitException thrown if reached limit for a whole stream array
+ * @since 2.1.0
+ * @see JBBPArraySizeLimiter#isBreakReadWholeStream(int, JBBPArraySizeLimiter)
+ * @see JBBPArraySizeLimiter#NO_LIMIT_FOR_ARRAY_SIZE
*/
- JBBPAbstractField readCustomFieldType(JBBPBitInputStream in, JBBPBitOrder bitOrder, int parserFlags, JBBPFieldTypeParameterContainer customTypeFieldInfo, JBBPNamedFieldInfo fieldName, int extraData, boolean readWholeStream, int arrayLength) throws IOException;
+ JBBPAbstractField readCustomFieldType(JBBPBitInputStream in, JBBPBitOrder bitOrder,
+ int parserFlags,
+ JBBPFieldTypeParameterContainer customTypeFieldInfo,
+ JBBPNamedFieldInfo fieldName, int extraData,
+ boolean readWholeStream,
+ int arrayLength,
+ JBBPArraySizeLimiter arraySizeLimiter) throws IOException;
+
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPExternalValueProvider.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPExternalValueProvider.java
index 1271bb40..360e37fe 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPExternalValueProvider.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPExternalValueProvider.java
@@ -32,5 +32,6 @@ public interface JBBPExternalValueProvider {
* @param compiledBlock the compiled block for the script to provide extra information
* @return the size of an array
*/
- int provideArraySize(final String fieldName, final JBBPNamedNumericFieldMap numericFieldMap, final JBBPCompiledBlock compiledBlock);
+ int provideArraySize(final String fieldName, final JBBPNamedNumericFieldMap numericFieldMap,
+ final JBBPCompiledBlock compiledBlock);
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPNamedNumericFieldMap.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPNamedNumericFieldMap.java
index cfde2d4b..0dac9595 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPNamedNumericFieldMap.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPNamedNumericFieldMap.java
@@ -26,7 +26,6 @@
import com.igormaznitsa.jbbp.model.JBBPNumericField;
import com.igormaznitsa.jbbp.model.finder.JBBPFieldFinder;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
-
import java.util.LinkedHashMap;
import java.util.Map;
@@ -168,14 +167,16 @@ public T findFieldForType(final Class fieldType
}
@Override
- public T findFieldForNameAndType(final String fieldName, final Class fieldType) {
+ public T findFieldForNameAndType(final String fieldName,
+ final Class fieldType) {
final String normalizedName = JBBPUtils.normalizeFieldNameOrPath(fieldName);
JBBPUtils.assertNotNull(fieldType, "Field type must not be null");
T result = null;
for (final Map.Entry f : fieldMap.entrySet()) {
- if (normalizedName.equals(f.getKey().getFieldName()) && fieldType.isAssignableFrom(f.getValue().getClass())) {
+ if (normalizedName.equals(f.getKey().getFieldName()) &&
+ fieldType.isAssignableFrom(f.getValue().getClass())) {
result = fieldType.cast(f.getValue());
break;
}
@@ -184,14 +185,16 @@ public T findFieldForNameAndType(final String fiel
}
@Override
- public T findFieldForPathAndType(final String fieldPath, final Class fieldType) {
+ public T findFieldForPathAndType(final String fieldPath,
+ final Class fieldType) {
final String normalizedPath = JBBPUtils.normalizeFieldNameOrPath(fieldPath);
JBBPUtils.assertNotNull(fieldType, "Field type must not be null");
T result = null;
for (final Map.Entry f : fieldMap.entrySet()) {
- if (normalizedPath.equals(f.getKey().getFieldPath()) && fieldType.isAssignableFrom(f.getValue().getClass())) {
+ if (normalizedPath.equals(f.getKey().getFieldPath()) &&
+ fieldType.isAssignableFrom(f.getValue().getClass())) {
result = fieldType.cast(f.getValue());
break;
}
@@ -293,10 +296,13 @@ public int size() {
* @return integer value for the field
* @throws JBBPException if there is not any external value provider
*/
- public int getExternalFieldValue(final String externalFieldName, final JBBPCompiledBlock compiledBlock, final JBBPIntegerValueEvaluator evaluator) {
+ public int getExternalFieldValue(final String externalFieldName,
+ final JBBPCompiledBlock compiledBlock,
+ final JBBPIntegerValueEvaluator evaluator) {
final String normalizedName = JBBPUtils.normalizeFieldNameOrPath(externalFieldName);
if (this.externalValueProvider == null) {
- throw new JBBPEvalException("Request for '" + externalFieldName + "' but there is not any value provider", evaluator);
+ throw new JBBPEvalException(
+ "Request for '" + externalFieldName + "' but there is not any value provider", evaluator);
} else {
return this.externalValueProvider.provideArraySize(normalizedName, this, compiledBlock);
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPParser.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPParser.java
index 4550802a..da3c2ce9 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPParser.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPParser.java
@@ -16,9 +16,9 @@
package com.igormaznitsa.jbbp;
+import static com.igormaznitsa.jbbp.io.JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE;
import static com.igormaznitsa.jbbp.utils.JBBPUtils.ARRAY_FIELD_EMPTY;
-
import com.igormaznitsa.jbbp.compiler.JBBPCompiledBlock;
import com.igormaznitsa.jbbp.compiler.JBBPCompiler;
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
@@ -26,6 +26,8 @@
import com.igormaznitsa.jbbp.compiler.tokenizer.JBBPFieldTypeParameterContainer;
import com.igormaznitsa.jbbp.compiler.varlen.JBBPIntegerValueEvaluator;
import com.igormaznitsa.jbbp.exceptions.JBBPParsingException;
+import com.igormaznitsa.jbbp.exceptions.JBBPReachedArraySizeLimitException;
+import com.igormaznitsa.jbbp.io.JBBPArraySizeLimiter;
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
import com.igormaznitsa.jbbp.io.JBBPBitNumber;
import com.igormaznitsa.jbbp.io.JBBPBitOrder;
@@ -43,6 +45,7 @@
import com.igormaznitsa.jbbp.model.JBBPFieldArrayString;
import com.igormaznitsa.jbbp.model.JBBPFieldArrayStruct;
import com.igormaznitsa.jbbp.model.JBBPFieldArrayUByte;
+import com.igormaznitsa.jbbp.model.JBBPFieldArrayUInt;
import com.igormaznitsa.jbbp.model.JBBPFieldArrayUShort;
import com.igormaznitsa.jbbp.model.JBBPFieldBit;
import com.igormaznitsa.jbbp.model.JBBPFieldBoolean;
@@ -55,6 +58,7 @@
import com.igormaznitsa.jbbp.model.JBBPFieldString;
import com.igormaznitsa.jbbp.model.JBBPFieldStruct;
import com.igormaznitsa.jbbp.model.JBBPFieldUByte;
+import com.igormaznitsa.jbbp.model.JBBPFieldUInt;
import com.igormaznitsa.jbbp.model.JBBPFieldUShort;
import com.igormaznitsa.jbbp.model.JBBPNumericField;
import com.igormaznitsa.jbbp.utils.JBBPIntCounter;
@@ -76,7 +80,7 @@
*
* @since 1.0
*/
-@SuppressWarnings( {"WeakerAccess"})
+@SuppressWarnings({"WeakerAccess"})
public final class JBBPParser {
/**
@@ -89,6 +93,15 @@ public final class JBBPParser {
* @since 1.4.0
*/
public static final int FLAG_NEGATIVE_EXPRESSION_RESULT_AS_ZERO = 2;
+
+ /**
+ * Default expression array size controller. It is doing nothing.
+ *
+ * @since 2.1.0
+ */
+ public static final JBBPParserExpressionArraySizeController
+ DEFAULT_EXPRESSION_ARRAY_SIZE_CONTROLLER =
+ (parser, expressionEvaluator, fieldName, arraySize) -> arraySize;
/**
* Empty structure array
*/
@@ -109,22 +122,29 @@ public final class JBBPParser {
* Custom field type processor for the parser, it can be null.
*/
private final JBBPCustomFieldTypeProcessor customFieldTypeProcessor;
+ /**
+ * Controller to get and change values calculated by expressions as size for array fields.
+ *
+ * @since 2.1.0
+ */
+ private JBBPParserExpressionArraySizeController expressionArraySizeController =
+ DEFAULT_EXPRESSION_ARRAY_SIZE_CONTROLLER;
/**
* The Variable contains the last parsing counter value.
*/
private long finalStreamByteCounter;
-
/**
* Constructor.
*
* @param source the source script to parse binary blocks and streams, must
* not be null
- * @param bitOrder the bit order for bit reading operations, must not be null
+ * @param bitOrder the bit order for a bit reading operations, must not be null
* @param customFieldTypeProcessor custom field type processor for the parser instance, it can be null
* @param flags special flags for parsing process
* @see #FLAG_SKIP_REMAINING_FIELDS_IF_EOF
*/
- private JBBPParser(final String source, final JBBPBitOrder bitOrder, final JBBPCustomFieldTypeProcessor customFieldTypeProcessor, final int flags) {
+ private JBBPParser(final String source, final JBBPBitOrder bitOrder,
+ final JBBPCustomFieldTypeProcessor customFieldTypeProcessor, final int flags) {
JBBPUtils.assertNotNull(source, "Script is null");
JBBPUtils.assertNotNull(bitOrder, "Bit order is null");
this.customFieldTypeProcessor = customFieldTypeProcessor;
@@ -145,7 +165,9 @@ private JBBPParser(final String source, final JBBPBitOrder bitOrder, final JBBPC
*/
private static void assertArrayLength(final int length, final JBBPNamedFieldInfo name) {
if (length < 0) {
- throw new JBBPParsingException("Detected negative calculated array length for field '" + (name == null ? "" : name.getFieldPath()) + "\' [" + JBBPUtils.int2msg(length) + ']');
+ throw new JBBPParsingException("Detected negative calculated array length for field '" +
+ (name == null ? "" : name.getFieldPath()) + "' [" + JBBPUtils.int2msg(length) +
+ ']');
}
}
@@ -163,7 +185,7 @@ public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrde
}
/**
- * Prepare a parser for a script with defined bit order and special flags.
+ * Prepare a parser for a script with defined a bit order and special flags.
*
* @param script a text script contains field order and types reference, it
* must not be null
@@ -175,12 +197,13 @@ public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrde
* @see #FLAG_SKIP_REMAINING_FIELDS_IF_EOF
* @since 1.1
*/
- public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrder, final int flags) {
+ public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrder,
+ final int flags) {
return new JBBPParser(script, bitOrder, null, flags);
}
/**
- * Prepare a parser for a script with defined bit order and special flags.
+ * Prepare a parser for a script with defined a bit order and special flags.
*
* @param script a text script contains field order and types reference, it
* must not be null
@@ -193,7 +216,9 @@ public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrde
* @see #FLAG_SKIP_REMAINING_FIELDS_IF_EOF
* @since 1.1.1
*/
- public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrder, final JBBPCustomFieldTypeProcessor customFieldTypeProcessor, final int flags) {
+ public static JBBPParser prepare(final String script, final JBBPBitOrder bitOrder,
+ final JBBPCustomFieldTypeProcessor customFieldTypeProcessor,
+ final int flags) {
return new JBBPParser(script, bitOrder, customFieldTypeProcessor, flags);
}
@@ -218,7 +243,8 @@ public static JBBPParser prepare(final String script) {
* @see JBBPBitOrder#LSB0
* @since 1.2.0
*/
- public static JBBPParser prepare(final String script, final JBBPCustomFieldTypeProcessor customFieldTypeProcessor) {
+ public static JBBPParser prepare(final String script,
+ final JBBPCustomFieldTypeProcessor customFieldTypeProcessor) {
return JBBPParser.prepare(script, JBBPBitOrder.LSB0, customFieldTypeProcessor, 0);
}
@@ -237,33 +263,72 @@ public static JBBPParser prepare(final String script, final int flags) {
return JBBPParser.prepare(script, JBBPBitOrder.LSB0, flags);
}
+ /**
+ * Get current registered instance of controller to check array size calculated by expression.
+ *
+ * @return current instance of array size observer, can't be null
+ * @since 2.1.0
+ */
+ public JBBPParserExpressionArraySizeController getExpressionArraySizeController() {
+ return this.expressionArraySizeController;
+ }
+
+ /**
+ * Set current registered instance of controller to check array size calculated by expression.
+ *
+ * @param arraySizeController instance of array size observer, must not be null.
+ * @return instance of the parser.
+ * @throws NullPointerException if argument is null
+ * @see #DEFAULT_EXPRESSION_ARRAY_SIZE_CONTROLLER
+ * @since 2.1.0
+ */
+ public JBBPParser setExpressionArraySizeController(
+ final JBBPParserExpressionArraySizeController arraySizeController) {
+ if (arraySizeController == null) {
+ throw new NullPointerException("Controller value must not be null");
+ }
+ this.expressionArraySizeController = arraySizeController;
+ return this;
+ }
+
/**
* Inside method to parse a structure.
*
* @param inStream the input stream, must not be null
* @param positionAtCompiledBlock the current position in the compiled script
* block
- * @param varFieldProcessor a processor to process var fields, it can be null
+ * @param varFieldProcessor a processor to process var fields, it can be null,
* but it will thrown NPE if a var field is met
* @param namedNumericFieldMap the named numeric field map
* @param positionAtNamedFieldList the current position at the named field
* list
* @param positionAtVarLengthProcessors the current position at the variable
* array length processor list
+ * @param arraySizeLimiter limiter for only whole stream arrays, must not be null
* @param skipStructureFields the flag shows that content of fields must be
* skipped because the structure is skipped
* @return list of read fields for the structure
- * @throws IOException it will be thrown for transport errors
+ * @throws IOException it will be thrown for transport errors
+ * @throws JBBPReachedArraySizeLimitException thrown if reached limit for a whole stream array
*/
- private List parseStruct(final JBBPBitInputStream inStream, final JBBPIntCounter positionAtCompiledBlock, final JBBPVarFieldProcessor varFieldProcessor, final JBBPNamedNumericFieldMap namedNumericFieldMap, final JBBPIntCounter positionAtNamedFieldList, final JBBPIntCounter positionAtVarLengthProcessors, final boolean skipStructureFields) throws IOException {
+ private List parseStruct(final JBBPBitInputStream inStream,
+ final JBBPIntCounter positionAtCompiledBlock,
+ final JBBPVarFieldProcessor varFieldProcessor,
+ final JBBPNamedNumericFieldMap namedNumericFieldMap,
+ final JBBPIntCounter positionAtNamedFieldList,
+ final JBBPIntCounter positionAtVarLengthProcessors,
+ final JBBPArraySizeLimiter arraySizeLimiter,
+ final boolean skipStructureFields)
+ throws IOException {
final List structureFields = skipStructureFields ? null : new ArrayList<>();
final byte[] compiled = this.compiledBlock.getCompiledData();
boolean endStructureNotMet = true;
while (endStructureNotMet && positionAtCompiledBlock.get() < compiled.length) {
- if (!inStream.hasAvailableData() && (flags & FLAG_SKIP_REMAINING_FIELDS_IF_EOF) != 0) {
- // Break reading because the ignore flag for EOF has been set
+ if (inStream.isDetectedArrayLimit() ||
+ (!inStream.hasAvailableData() && (flags & FLAG_SKIP_REMAINING_FIELDS_IF_EOF) != 0)) {
+ // Break reading because the ignore flag for EOF has been set or reached limit for whole stream array read
break;
}
@@ -274,17 +339,24 @@ private List parseStruct(final JBBPBitInputStream inStream, f
final int code = (ec << 8) | c;
final boolean fieldTypeDiff = (ec & JBBPCompiler.EXT_FLAG_EXTRA_DIFF_TYPE) != 0;
- final JBBPNamedFieldInfo name = (code & JBBPCompiler.FLAG_NAMED) == 0 ? null : compiledBlock.getNamedFields()[positionAtNamedFieldList.getAndIncrement()];
- final JBBPByteOrder byteOrder = (code & JBBPCompiler.FLAG_LITTLE_ENDIAN) == 0 ? JBBPByteOrder.BIG_ENDIAN : JBBPByteOrder.LITTLE_ENDIAN;
+ final JBBPNamedFieldInfo name = (code & JBBPCompiler.FLAG_NAMED) == 0 ? null :
+ compiledBlock.getNamedFields()[positionAtNamedFieldList.getAndIncrement()];
+ final JBBPByteOrder byteOrder =
+ (code & JBBPCompiler.FLAG_LITTLE_ENDIAN) == 0 ? JBBPByteOrder.BIG_ENDIAN :
+ JBBPByteOrder.LITTLE_ENDIAN;
final boolean resultNotIgnored = !skipStructureFields;
final int extraFieldNumExprResult;
if (extraFieldNumAsExpr) {
- final JBBPIntegerValueEvaluator evaluator = this.compiledBlock.getArraySizeEvaluators()[positionAtVarLengthProcessors.getAndIncrement()];
+ final JBBPIntegerValueEvaluator evaluator =
+ this.compiledBlock.getArraySizeEvaluators()[positionAtVarLengthProcessors
+ .getAndIncrement()];
int resultOfExpression;
if (resultNotIgnored) {
- resultOfExpression = evaluator.eval(inStream, positionAtCompiledBlock.get(), this.compiledBlock, namedNumericFieldMap);
+ resultOfExpression = evaluator
+ .eval(inStream, positionAtCompiledBlock.get(), this.compiledBlock,
+ namedNumericFieldMap);
if ((this.flags & FLAG_NEGATIVE_EXPRESSION_RESULT_AS_ZERO) != 0) {
resultOfExpression = Math.max(resultOfExpression, 0);
}
@@ -299,7 +371,8 @@ private List parseStruct(final JBBPBitInputStream inStream, f
final boolean wholeStreamArray;
final int arrayLength;
final int packedArraySizeOffset;
- switch (code & (JBBPCompiler.FLAG_ARRAY | (JBBPCompiler.EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8))) {
+ switch (code &
+ (JBBPCompiler.FLAG_ARRAY | (JBBPCompiler.EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8))) {
case JBBPCompiler.FLAG_ARRAY: {
final int pos = positionAtCompiledBlock.get();
arrayLength = JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
@@ -314,13 +387,20 @@ private List parseStruct(final JBBPBitInputStream inStream, f
}
break;
case JBBPCompiler.FLAG_ARRAY | (JBBPCompiler.EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8): {
- final JBBPIntegerValueEvaluator evaluator = this.compiledBlock.getArraySizeEvaluators()[positionAtVarLengthProcessors.getAndIncrement()];
+ final JBBPIntegerValueEvaluator evaluator =
+ this.compiledBlock.getArraySizeEvaluators()[positionAtVarLengthProcessors
+ .getAndIncrement()];
int resultOfExpression;
if (resultNotIgnored) {
- resultOfExpression = evaluator.eval(inStream, positionAtCompiledBlock.get(), this.compiledBlock, namedNumericFieldMap);
+ resultOfExpression = evaluator
+ .eval(inStream, positionAtCompiledBlock.get(), this.compiledBlock,
+ namedNumericFieldMap);
if ((this.flags & FLAG_NEGATIVE_EXPRESSION_RESULT_AS_ZERO) != 0) {
resultOfExpression = Math.max(resultOfExpression, 0);
}
+ resultOfExpression =
+ this.expressionArraySizeController.onCalculatedArraySize(this, evaluator, name,
+ resultOfExpression);
} else {
resultOfExpression = 0;
}
@@ -349,14 +429,16 @@ private List parseStruct(final JBBPBitInputStream inStream, f
}
break;
case JBBPCompiler.CODE_ALIGN: {
- final int alignValue = extraFieldNumAsExpr ? extraFieldNumExprResult : JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
+ final int alignValue = extraFieldNumAsExpr ? extraFieldNumExprResult :
+ JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
if (resultNotIgnored) {
inStream.align(alignValue);
}
}
break;
case JBBPCompiler.CODE_SKIP: {
- final int skipByteNumber = extraFieldNumAsExpr ? extraFieldNumExprResult : JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
+ final int skipByteNumber = extraFieldNumAsExpr ? extraFieldNumExprResult :
+ JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
if (resultNotIgnored) {
if (fieldTypeDiff) {
singleAtomicField = new JBBPFieldInt(name, skipByteNumber);
@@ -364,7 +446,9 @@ private List parseStruct(final JBBPBitInputStream inStream, f
if (skipByteNumber > 0) {
final long skippedBytes = inStream.skip(skipByteNumber);
if (skippedBytes != skipByteNumber) {
- throw new EOFException("Can't skip " + skipByteNumber + " byte(s), skipped only " + skippedBytes + " byte(s)");
+ throw new EOFException(
+ "Can't skip " + skipByteNumber + " byte(s), skipped only " + skippedBytes +
+ " byte(s)");
}
}
}
@@ -372,35 +456,52 @@ private List parseStruct(final JBBPBitInputStream inStream, f
}
break;
case JBBPCompiler.CODE_BIT: {
- final int numberOfBits = extraFieldNumAsExpr ? extraFieldNumExprResult : JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
+ final int numberOfBits = extraFieldNumAsExpr ? extraFieldNumExprResult :
+ JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
if (resultNotIgnored) {
final JBBPBitNumber bitNumber = JBBPBitNumber.decode(numberOfBits);
if (arrayLength < 0) {
final int read = inStream.readBitField(bitNumber);
singleAtomicField = new JBBPFieldBit(name, read & 0xFF, bitNumber);
} else {
- structureFields.add(new JBBPFieldArrayBit(name, inStream.readBitsArray(wholeStreamArray ? -1 : arrayLength, bitNumber), bitNumber));
+ structureFields.add(new JBBPFieldArrayBit(name,
+ inStream.readBitsArray(wholeStreamArray ? -1 : arrayLength, bitNumber,
+ arraySizeLimiter),
+ bitNumber));
}
}
}
break;
case JBBPCompiler.CODE_VAR: {
- final int extraField = extraFieldNumAsExpr ? extraFieldNumExprResult : JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
+ final int extraField = extraFieldNumAsExpr ? extraFieldNumExprResult :
+ JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
if (resultNotIgnored) {
if (arrayLength < 0) {
- singleAtomicField = varFieldProcessor.readVarField(inStream, name, extraField, byteOrder, namedNumericFieldMap);
- JBBPUtils.assertNotNull(singleAtomicField, "A Var processor must not return null as a result of a field reading");
+ singleAtomicField = varFieldProcessor
+ .readVarField(inStream, name, extraField, byteOrder, namedNumericFieldMap);
+ JBBPUtils.assertNotNull(singleAtomicField,
+ "A Var processor must not return null as a result of a field reading");
if (singleAtomicField instanceof JBBPAbstractArrayField) {
- throw new JBBPParsingException("A Var field processor has returned an array value instead of a field value [" + name + ':' + extraField + ']');
+ throw new JBBPParsingException(
+ "A Var field processor has returned an array value instead of a field value [" +
+ name + ':' + extraField + ']');
}
if (singleAtomicField.getNameInfo() != name) {
- throw new JBBPParsingException("Detected wrong name for a read field , must be " + name + " but detected " + singleAtomicField.getNameInfo() + ']');
+ throw new JBBPParsingException(
+ "Detected wrong name for a read field , must be " + name + " but detected " +
+ singleAtomicField.getNameInfo() + ']');
}
} else {
- final JBBPAbstractArrayField extends JBBPAbstractField> array = varFieldProcessor.readVarArray(inStream, wholeStreamArray ? -1 : arrayLength, name, extraField, byteOrder, namedNumericFieldMap);
- JBBPUtils.assertNotNull(array, "A Var processor must not return null as a result of an array field reading [" + name + ':' + extraField + ']');
+ final JBBPAbstractArrayField extends JBBPAbstractField> array = varFieldProcessor
+ .readVarArray(inStream, wholeStreamArray ? -1 : arrayLength, name, extraField,
+ byteOrder, namedNumericFieldMap, arraySizeLimiter);
+ JBBPUtils.assertNotNull(array,
+ "A Var processor must not return null as a result of an array field reading [" +
+ name + ':' + extraField + ']');
if (array.getNameInfo() != name) {
- throw new JBBPParsingException("Detected wrong name for a read field array, must be " + name + " but detected " + array.getNameInfo() + ']');
+ throw new JBBPParsingException(
+ "Detected wrong name for a read field array, must be " + name +
+ " but detected " + array.getNameInfo() + ']');
}
structureFields.add(array);
}
@@ -408,10 +509,15 @@ private List parseStruct(final JBBPBitInputStream inStream, f
}
break;
case JBBPCompiler.CODE_CUSTOMTYPE: {
- final int extraData = extraFieldNumAsExpr ? extraFieldNumExprResult : JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
+ final int extraData = extraFieldNumAsExpr ? extraFieldNumExprResult :
+ JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
if (resultNotIgnored) {
- final JBBPFieldTypeParameterContainer fieldTypeInfo = this.compiledBlock.getCustomTypeFields()[JBBPUtils.unpackInt(compiled, positionAtCompiledBlock)];
- final JBBPAbstractField field = this.customFieldTypeProcessor.readCustomFieldType(inStream, this.bitOrder, this.flags, fieldTypeInfo, name, extraData, wholeStreamArray, arrayLength);
+ final JBBPFieldTypeParameterContainer fieldTypeInfo =
+ this.compiledBlock.getCustomTypeFields()[JBBPUtils
+ .unpackInt(compiled, positionAtCompiledBlock)];
+ final JBBPAbstractField field = this.customFieldTypeProcessor
+ .readCustomFieldType(inStream, this.bitOrder, this.flags, fieldTypeInfo, name,
+ extraData, wholeStreamArray, arrayLength, arraySizeLimiter);
JBBPUtils.assertNotNull(field, "Must not return null as read result");
if (arrayLength < 0) {
@@ -425,9 +531,17 @@ private List parseStruct(final JBBPBitInputStream inStream, f
case JBBPCompiler.CODE_BYTE: {
if (resultNotIgnored) {
if (arrayLength < 0) {
- singleAtomicField = new JBBPFieldByte(name, (byte) inStream.readByte());
+ singleAtomicField = fieldTypeDiff ?
+ new JBBPFieldUInt(name, inStream.readInt(byteOrder) & 0xFFFFFFFFL) :
+ new JBBPFieldByte(name, (byte) inStream.readByte());
} else {
- structureFields.add(new JBBPFieldArrayByte(name, inStream.readByteArray(wholeStreamArray ? -1 : arrayLength, byteOrder)));
+ structureFields.add(fieldTypeDiff ?
+ new JBBPFieldArrayUInt(name,
+ inStream.readIntArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter)) :
+ new JBBPFieldArrayByte(name,
+ inStream.readByteArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter)));
}
}
}
@@ -437,7 +551,9 @@ private List parseStruct(final JBBPBitInputStream inStream, f
if (arrayLength < 0) {
singleAtomicField = new JBBPFieldUByte(name, (byte) inStream.readByte());
} else {
- structureFields.add(new JBBPFieldArrayUByte(name, inStream.readByteArray(wholeStreamArray ? -1 : arrayLength, byteOrder)));
+ structureFields.add(new JBBPFieldArrayUByte(name,
+ inStream.readByteArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter)));
}
}
}
@@ -445,11 +561,17 @@ private List parseStruct(final JBBPBitInputStream inStream, f
case JBBPCompiler.CODE_BOOL: {
if (resultNotIgnored) {
if (arrayLength < 0) {
- singleAtomicField = fieldTypeDiff ? new JBBPFieldString(name, inStream.readString(byteOrder)) : new JBBPFieldBoolean(name, inStream.readBoolean());
+ singleAtomicField =
+ fieldTypeDiff ? new JBBPFieldString(name, inStream.readString(byteOrder)) :
+ new JBBPFieldBoolean(name, inStream.readBoolean());
} else {
structureFields.add(fieldTypeDiff ?
- new JBBPFieldArrayString(name, inStream.readStringArray(wholeStreamArray ? -1 : arrayLength, byteOrder)) :
- new JBBPFieldArrayBoolean(name, inStream.readBoolArray(wholeStreamArray ? -1 : arrayLength))
+ new JBBPFieldArrayString(name,
+ inStream.readStringArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter)) :
+ new JBBPFieldArrayBoolean(name,
+ inStream.readBoolArray(wholeStreamArray ? -1 : arrayLength,
+ arraySizeLimiter))
);
}
}
@@ -458,11 +580,17 @@ private List parseStruct(final JBBPBitInputStream inStream, f
case JBBPCompiler.CODE_INT: {
if (resultNotIgnored) {
if (arrayLength < 0) {
- singleAtomicField = fieldTypeDiff ? new JBBPFieldFloat(name, inStream.readFloat(byteOrder)) : new JBBPFieldInt(name, inStream.readInt(byteOrder));
+ singleAtomicField =
+ fieldTypeDiff ? new JBBPFieldFloat(name, inStream.readFloat(byteOrder)) :
+ new JBBPFieldInt(name, inStream.readInt(byteOrder));
} else {
structureFields.add(fieldTypeDiff ?
- new JBBPFieldArrayFloat(name, inStream.readFloatArray(wholeStreamArray ? -1 : arrayLength, byteOrder)) :
- new JBBPFieldArrayInt(name, inStream.readIntArray(wholeStreamArray ? -1 : arrayLength, byteOrder))
+ new JBBPFieldArrayFloat(name,
+ inStream.readFloatArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter)) :
+ new JBBPFieldArrayInt(name,
+ inStream.readIntArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter))
);
}
}
@@ -471,11 +599,17 @@ private List parseStruct(final JBBPBitInputStream inStream, f
case JBBPCompiler.CODE_LONG: {
if (resultNotIgnored) {
if (arrayLength < 0) {
- singleAtomicField = fieldTypeDiff ? new JBBPFieldDouble(name, inStream.readDouble(byteOrder)) : new JBBPFieldLong(name, inStream.readLong(byteOrder));
+ singleAtomicField =
+ fieldTypeDiff ? new JBBPFieldDouble(name, inStream.readDouble(byteOrder)) :
+ new JBBPFieldLong(name, inStream.readLong(byteOrder));
} else {
structureFields.add(fieldTypeDiff ?
- new JBBPFieldArrayDouble(name, inStream.readDoubleArray(wholeStreamArray ? -1 : arrayLength, byteOrder)) :
- new JBBPFieldArrayLong(name, inStream.readLongArray(wholeStreamArray ? -1 : arrayLength, byteOrder))
+ new JBBPFieldArrayDouble(name,
+ inStream.readDoubleArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter)) :
+ new JBBPFieldArrayLong(name,
+ inStream.readLongArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter))
);
}
}
@@ -487,7 +621,9 @@ private List parseStruct(final JBBPBitInputStream inStream, f
final int value = inStream.readUnsignedShort(byteOrder);
singleAtomicField = new JBBPFieldShort(name, (short) value);
} else {
- structureFields.add(new JBBPFieldArrayShort(name, inStream.readShortArray(wholeStreamArray ? -1 : arrayLength, byteOrder)));
+ structureFields.add(new JBBPFieldArrayShort(name,
+ inStream.readShortArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter)));
}
}
}
@@ -498,18 +634,24 @@ private List parseStruct(final JBBPBitInputStream inStream, f
final int value = inStream.readUnsignedShort(byteOrder);
singleAtomicField = new JBBPFieldUShort(name, (short) value);
} else {
- structureFields.add(new JBBPFieldArrayUShort(name, inStream.readShortArray(wholeStreamArray ? -1 : arrayLength, byteOrder)));
+ structureFields.add(new JBBPFieldArrayUShort(name,
+ inStream.readShortArray(wholeStreamArray ? -1 : arrayLength, byteOrder,
+ arraySizeLimiter)));
}
}
}
break;
case JBBPCompiler.CODE_STRUCT_START: {
if (arrayLength < 0) {
- final List structFields = parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor, namedNumericFieldMap, positionAtNamedFieldList, positionAtVarLengthProcessors, skipStructureFields);
+ final List structFields =
+ parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor,
+ namedNumericFieldMap, positionAtNamedFieldList, positionAtVarLengthProcessors,
+ arraySizeLimiter, skipStructureFields);
// skip offset
JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
if (resultNotIgnored) {
- structureFields.add(new JBBPFieldStruct(name, structFields.toArray(ARRAY_FIELD_EMPTY)));
+ structureFields
+ .add(new JBBPFieldStruct(name, structFields.toArray(ARRAY_FIELD_EMPTY)));
}
} else {
final int nameFieldCurrent = positionAtNamedFieldList.get();
@@ -524,9 +666,18 @@ private List parseStruct(final JBBPBitInputStream inStream, f
positionAtNamedFieldList.set(nameFieldCurrent);
positionAtVarLengthProcessors.set(varLenProcCurrent);
- final List fieldsForStruct = parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor, namedNumericFieldMap, positionAtNamedFieldList, positionAtVarLengthProcessors, skipStructureFields);
+ final List fieldsForStruct =
+ parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor,
+ namedNumericFieldMap, positionAtNamedFieldList,
+ positionAtVarLengthProcessors, arraySizeLimiter, skipStructureFields);
list.add(new JBBPFieldStruct(name, fieldsForStruct));
+ if (JBBPArraySizeLimiter.isBreakReadWholeStream(list.size(),
+ arraySizeLimiter)) {
+ inStream.setDetectedArrayLimit(true);
+ break;
+ }
+
final int structStart = JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
if (inStream.hasAvailableData()) {
@@ -540,14 +691,20 @@ private List parseStruct(final JBBPBitInputStream inStream, f
if (arrayLength == 0) {
// skip the structure
result = EMPTY_STRUCT_ARRAY;
- parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor, namedNumericFieldMap, positionAtNamedFieldList, positionAtVarLengthProcessors, true);
+ parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor,
+ namedNumericFieldMap, positionAtNamedFieldList,
+ positionAtVarLengthProcessors, arraySizeLimiter, true);
JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
} else {
result = new JBBPFieldStruct[arrayLength];
for (int i = 0; i < arrayLength; i++) {
- final List fieldsForStruct = parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor, namedNumericFieldMap, positionAtNamedFieldList, positionAtVarLengthProcessors, skipStructureFields);
- final int structBodyStart = JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
+ final List fieldsForStruct =
+ parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor,
+ namedNumericFieldMap, positionAtNamedFieldList,
+ positionAtVarLengthProcessors, arraySizeLimiter, skipStructureFields);
+ final int structBodyStart =
+ JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
result[i] = new JBBPFieldStruct(name, fieldsForStruct);
@@ -555,7 +712,8 @@ private List parseStruct(final JBBPBitInputStream inStream, f
// not the last
positionAtNamedFieldList.set(nameFieldCurrent);
positionAtVarLengthProcessors.set(varLenProcCurrent);
- positionAtCompiledBlock.set(structBodyStart + packedArraySizeOffset + (wideCode ? 2 : 1));
+ positionAtCompiledBlock
+ .set(structBodyStart + packedArraySizeOffset + (wideCode ? 2 : 1));
}
}
}
@@ -565,7 +723,9 @@ private List parseStruct(final JBBPBitInputStream inStream, f
structureFields.add(new JBBPFieldArrayStruct(name, result));
}
} else {
- parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor, namedNumericFieldMap, positionAtNamedFieldList, positionAtVarLengthProcessors, skipStructureFields);
+ parseStruct(inStream, positionAtCompiledBlock, varFieldProcessor,
+ namedNumericFieldMap, positionAtNamedFieldList, positionAtVarLengthProcessors,
+ arraySizeLimiter, skipStructureFields);
JBBPUtils.unpackInt(compiled, positionAtCompiledBlock);
}
}
@@ -583,13 +743,15 @@ private List parseStruct(final JBBPBitInputStream inStream, f
if (name == null) {
throw ex;
} else {
- throw new JBBPParsingException("Can't parse field '" + name.getFieldPath() + "' for IOException", ex);
+ throw new JBBPParsingException(
+ "Can't parse field '" + name.getFieldPath() + "' for IOException", ex);
}
}
if (singleAtomicField != null) {
structureFields.add(singleAtomicField);
- if (namedNumericFieldMap != null && singleAtomicField instanceof JBBPNumericField && name != null) {
+ if (namedNumericFieldMap != null && singleAtomicField instanceof JBBPNumericField &&
+ name != null) {
namedNumericFieldMap.putField((JBBPNumericField) singleAtomicField);
}
}
@@ -622,8 +784,43 @@ public JBBPFieldStruct parse(final InputStream in) throws IOException {
* @return the parsed content as the root structure
* @throws IOException it will be thrown for transport errors
*/
- public JBBPFieldStruct parse(final InputStream in, final JBBPVarFieldProcessor varFieldProcessor, final JBBPExternalValueProvider externalValueProvider) throws IOException {
- final JBBPBitInputStream bitInStream = in instanceof JBBPBitInputStream ? (JBBPBitInputStream) in : new JBBPBitInputStream(in, bitOrder);
+ public JBBPFieldStruct parse(
+ final InputStream in,
+ final JBBPVarFieldProcessor varFieldProcessor,
+ final JBBPExternalValueProvider externalValueProvider
+ ) throws IOException {
+ return this.parse(
+ in,
+ varFieldProcessor,
+ externalValueProvider,
+ NO_LIMIT_FOR_ARRAY_SIZE
+ );
+ }
+
+ /**
+ * Parse am input stream with defined external value provider.
+ *
+ * @param in an input stream which content will be parsed, it must not be null
+ * @param varFieldProcessor a var field processor, it may be null if there is
+ * not any var field in a script, otherwise NPE will be thrown during parsing
+ * @param externalValueProvider an external value provider, it can be null but
+ * only if the script doesn't have fields desired the provider
+ * @param arraySizeLimiter limiter to read whole stream arrays, must not be null
+ * @return the parsed content as the root structure
+ * @throws IOException it will be thrown for transport errors
+ * @throws JBBPReachedArraySizeLimitException thrown if reached limit for a whole stream array
+ * @see JBBPArraySizeLimiter#NO_LIMIT_FOR_ARRAY_SIZE
+ * @since 2.1.0
+ */
+ public JBBPFieldStruct parse(
+ final InputStream in,
+ final JBBPVarFieldProcessor varFieldProcessor,
+ final JBBPExternalValueProvider externalValueProvider,
+ final JBBPArraySizeLimiter arraySizeLimiter
+ ) throws IOException {
+ final JBBPBitInputStream bitInStream =
+ in instanceof JBBPBitInputStream ? (JBBPBitInputStream) in :
+ new JBBPBitInputStream(in, bitOrder);
this.finalStreamByteCounter = bitInStream.getCounter();
final JBBPNamedNumericFieldMap fieldMap;
@@ -634,10 +831,13 @@ public JBBPFieldStruct parse(final InputStream in, final JBBPVarFieldProcessor v
}
if (this.compiledBlock.hasVarFields()) {
- JBBPUtils.assertNotNull(varFieldProcessor, "The Script contains VAR fields, a var field processor must be provided");
+ JBBPUtils.assertNotNull(varFieldProcessor,
+ "The Script contains VAR fields, a var field processor must be provided");
}
try {
- return new JBBPFieldStruct(new JBBPNamedFieldInfo("", "", -1), parseStruct(bitInStream, new JBBPIntCounter(), varFieldProcessor, fieldMap, new JBBPIntCounter(), new JBBPIntCounter(), false));
+ return new JBBPFieldStruct(new JBBPNamedFieldInfo("", "", -1),
+ parseStruct(bitInStream, new JBBPIntCounter(), varFieldProcessor, fieldMap,
+ new JBBPIntCounter(), new JBBPIntCounter(), arraySizeLimiter, false));
} finally {
this.finalStreamByteCounter = bitInStream.getCounter();
}
@@ -678,7 +878,9 @@ public JBBPFieldStruct parse(final byte[] array) throws IOException {
* @return the parsed content as the root structure
* @throws IOException it will be thrown for transport errors
*/
- public JBBPFieldStruct parse(final byte[] array, final JBBPVarFieldProcessor varFieldProcessor, final JBBPExternalValueProvider externalValueProvider) throws IOException {
+ public JBBPFieldStruct parse(final byte[] array, final JBBPVarFieldProcessor varFieldProcessor,
+ final JBBPExternalValueProvider externalValueProvider)
+ throws IOException {
JBBPUtils.assertNotNull(array, "Array must not be null");
return this.parse(new ByteArrayInputStream(array), varFieldProcessor, externalValueProvider);
}
@@ -737,8 +939,11 @@ public List convertToSrc(final TargetSources target, final String
className = name.substring(nameStart + 1);
}
- final String resultSources = JBBPToJavaConverter.makeBuilder(this).setMainClassPackage(packageName).setMainClassName(className).build().convert();
- final Map resultMap = Collections.singletonMap(name.replace('.', '/') + ".java", resultSources);
+ final String resultSources =
+ JBBPToJavaConverter.makeBuilder(this).setMainClassPackage(packageName)
+ .setMainClassName(className).build().convert();
+ final Map resultMap =
+ Collections.singletonMap(name.replace('.', '/') + ".java", resultSources);
return Collections.singletonList(new ResultSrcItem() {
@Override
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPParserExpressionArraySizeController.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPParserExpressionArraySizeController.java
new file mode 100644
index 00000000..9d56f5f9
--- /dev/null
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPParserExpressionArraySizeController.java
@@ -0,0 +1,26 @@
+package com.igormaznitsa.jbbp;
+
+import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
+import com.igormaznitsa.jbbp.compiler.varlen.JBBPIntegerValueEvaluator;
+
+/**
+ * Controller to get value for every array field which size calculated by expression.
+ *
+ * @see JBBPParser#setExpressionArraySizeController(JBBPParserExpressionArraySizeController)
+ * @see JBBPParser#getExpressionArraySizeController()
+ * @since 2.1.0
+ */
+@FunctionalInterface
+public interface JBBPParserExpressionArraySizeController {
+ /**
+ * Called for every calculation of an array size by expression.
+ *
+ * @param parser source parser, must not be null
+ * @param expressionEvaluator expression evaluator used for calculation, must not be null
+ * @param fieldInfo target field info, must not be null
+ * @param calculatedArraySize calculated array size
+ * @return array size which can be same as provided size or changed
+ */
+ int onCalculatedArraySize(JBBPParser parser, JBBPIntegerValueEvaluator expressionEvaluator,
+ JBBPNamedFieldInfo fieldInfo, int calculatedArraySize);
+}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPVarFieldProcessor.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPVarFieldProcessor.java
index ec7aebf4..445ded67 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPVarFieldProcessor.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/JBBPVarFieldProcessor.java
@@ -17,11 +17,12 @@
package com.igormaznitsa.jbbp;
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
+import com.igormaznitsa.jbbp.exceptions.JBBPReachedArraySizeLimitException;
+import com.igormaznitsa.jbbp.io.JBBPArraySizeLimiter;
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
import com.igormaznitsa.jbbp.io.JBBPByteOrder;
import com.igormaznitsa.jbbp.model.JBBPAbstractArrayField;
import com.igormaznitsa.jbbp.model.JBBPAbstractField;
-
import java.io.IOException;
/**
@@ -39,10 +40,22 @@ public interface JBBPVarFieldProcessor {
* @param extraValue the extra value for the field, by default it is 0, it is the integer value after ':' char in the field type
* @param byteOrder the byte order for the field, it must not be null
* @param numericFieldMap the numeric field map for the session, it must not be null, it can be used for access to already read values of another numeric fields.
+ * @param arraySizeLimiter limiter to check number of elements during whole stream array read, must not be null
* @return a field array without nulls as values, it must not return null
- * @throws IOException it can be thrown for transport errors or another process exceptions
+ * @throws IOException it can be thrown for transport errors or another process exceptions
+ * @throws JBBPReachedArraySizeLimitException thrown if reached limit for whole stream array
+ * @since 2.1.0
+ * @see JBBPArraySizeLimiter#isBreakReadWholeStream(int, JBBPArraySizeLimiter)
+ * @see JBBPArraySizeLimiter#NO_LIMIT_FOR_ARRAY_SIZE
*/
- JBBPAbstractArrayField extends JBBPAbstractField> readVarArray(JBBPBitInputStream inStream, int arraySize, JBBPNamedFieldInfo fieldName, int extraValue, JBBPByteOrder byteOrder, JBBPNamedNumericFieldMap numericFieldMap) throws IOException;
+ JBBPAbstractArrayField extends JBBPAbstractField> readVarArray(JBBPBitInputStream inStream,
+ int arraySize,
+ JBBPNamedFieldInfo fieldName,
+ int extraValue,
+ JBBPByteOrder byteOrder,
+ JBBPNamedNumericFieldMap numericFieldMap,
+ JBBPArraySizeLimiter arraySizeLimiter)
+ throws IOException;
/**
* Read a field from a stream. The Method must read a field from a stream and return it with the provided name field info.
@@ -59,5 +72,7 @@ public interface JBBPVarFieldProcessor {
* @return a read field object, it must not return null
* @throws IOException it should be thrown for transport errors
*/
- JBBPAbstractField readVarField(JBBPBitInputStream inStream, JBBPNamedFieldInfo fieldName, int extraValue, JBBPByteOrder byteOrder, JBBPNamedNumericFieldMap numericFieldMap) throws IOException;
+ JBBPAbstractField readVarField(JBBPBitInputStream inStream, JBBPNamedFieldInfo fieldName,
+ int extraValue, JBBPByteOrder byteOrder,
+ JBBPNamedNumericFieldMap numericFieldMap) throws IOException;
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiledBlock.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiledBlock.java
index 7a92cdd7..7a9aab5c 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiledBlock.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiledBlock.java
@@ -21,7 +21,6 @@
import com.igormaznitsa.jbbp.exceptions.JBBPException;
import com.igormaznitsa.jbbp.exceptions.JBBPIllegalArgumentException;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
-
import java.util.ArrayList;
import java.util.List;
@@ -34,8 +33,10 @@
public final class JBBPCompiledBlock {
private static final JBBPNamedFieldInfo[] ARRAY_FIELDINFO_EMPTY = new JBBPNamedFieldInfo[0];
- private static final JBBPIntegerValueEvaluator[] ARRAY_INTEVALUATOR_EMPTY = new JBBPIntegerValueEvaluator[0];
- private static final JBBPFieldTypeParameterContainer[] ARRAY_FIELDTYPE_EMPTY = new JBBPFieldTypeParameterContainer[0];
+ private static final JBBPIntegerValueEvaluator[] ARRAY_INTEVALUATOR_EMPTY =
+ new JBBPIntegerValueEvaluator[0];
+ private static final JBBPFieldTypeParameterContainer[] ARRAY_FIELDTYPE_EMPTY =
+ new JBBPFieldTypeParameterContainer[0];
/**
* The Array of named field info items.
@@ -74,7 +75,10 @@ public final class JBBPCompiledBlock {
* @param compiledData compiled data block
* @param hasVarFields the flag shows that te block contains var fields
*/
- private JBBPCompiledBlock(final String source, final JBBPNamedFieldInfo[] namedFields, final JBBPIntegerValueEvaluator[] arraySizeEvaluators, final byte[] compiledData, final boolean hasVarFields, final JBBPFieldTypeParameterContainer[] customTypeFields) {
+ private JBBPCompiledBlock(final String source, final JBBPNamedFieldInfo[] namedFields,
+ final JBBPIntegerValueEvaluator[] arraySizeEvaluators,
+ final byte[] compiledData, final boolean hasVarFields,
+ final JBBPFieldTypeParameterContainer[] customTypeFields) {
this.source = source;
this.namedFieldData = namedFields;
this.hasVarFields = hasVarFields;
@@ -215,7 +219,10 @@ public JBBPCompiledBlock build() {
JBBPUtils.assertNotNull(source, "Source is not defined");
JBBPUtils.assertNotNull(compiledData, "Compiled data is not defined");
- return new JBBPCompiledBlock(this.source, this.namedFields.toArray(ARRAY_FIELDINFO_EMPTY), this.varLenProcessors.isEmpty() ? null : this.varLenProcessors.toArray(ARRAY_INTEVALUATOR_EMPTY), this.compiledData, this.hasVarFields, this.customTypeFields.toArray(ARRAY_FIELDTYPE_EMPTY));
+ return new JBBPCompiledBlock(this.source, this.namedFields.toArray(ARRAY_FIELDINFO_EMPTY),
+ this.varLenProcessors.isEmpty() ? null :
+ this.varLenProcessors.toArray(ARRAY_INTEVALUATOR_EMPTY), this.compiledData,
+ this.hasVarFields, this.customTypeFields.toArray(ARRAY_FIELDTYPE_EMPTY));
}
/**
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiler.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiler.java
index 8c0891d0..94979261 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiler.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompiler.java
@@ -28,8 +28,8 @@
import com.igormaznitsa.jbbp.model.JBBPFieldDouble;
import com.igormaznitsa.jbbp.model.JBBPFieldFloat;
import com.igormaznitsa.jbbp.model.JBBPFieldString;
+import com.igormaznitsa.jbbp.model.JBBPFieldUInt;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -114,12 +114,12 @@ public final class JBBPCompiler {
*/
public static final int FLAG_NAMED = 0x10;
/**
- * The Byte-Code Flag shows that the field is an array but it must be omitted
+ * The Byte-Code Flag shows that the field is an array, but it must be omitted
* for unlimited field arrays.
*/
public static final int FLAG_ARRAY = 0x20;
/**
- * The Byte-Code Flag shows that a multi-byte field must be decoded as
+ * The Byte-Code Flag shows that a multibyte field must be decoded as
* Little-endian one.
*/
public static final int FLAG_LITTLE_ENDIAN = 0x40;
@@ -157,7 +157,8 @@ public static JBBPCompiledBlock compile(final String script) throws IOException
private static void assertTokenNotArray(final String fieldType, final JBBPToken token) {
if (token.getArraySizeAsString() != null) {
final String fieldName = token.getFieldName() == null ? "" : token.getFieldName();
- throw new JBBPCompilationException('\'' + fieldType + "' can't be array (" + fieldName + ')', token);
+ throw new JBBPCompilationException('\'' + fieldType + "' can't be array (" + fieldName + ')',
+ token);
}
}
@@ -169,19 +170,14 @@ private static void assertTokenNamed(final String fieldType, final JBBPToken tok
private static void assertTokenNotNamed(final String fieldType, final JBBPToken token) {
if (token.getFieldName() != null) {
- throw new JBBPCompilationException('\'' + fieldType + "' must not be named (" + token.getFieldName() + ')', token);
+ throw new JBBPCompilationException(
+ '\'' + fieldType + "' must not be named (" + token.getFieldName() + ')', token);
}
}
private static void assertTokenHasExtraData(final String fieldType, final JBBPToken token) {
if (token.getFieldTypeParameters().getExtraData() == null) {
- throw new JBBPCompilationException('\'' + fieldType + "\' doesn't have extra value", token);
- }
- }
-
- private static void assertTokenDoesntHaveExtraData(final String fieldType, final JBBPToken token) {
- if (token.getFieldTypeParameters().getExtraData() != null) {
- throw new JBBPCompilationException('\'' + fieldType + "\' has extra value", token);
+ throw new JBBPCompilationException('\'' + fieldType + "' doesn't have extra value", token);
}
}
@@ -196,7 +192,9 @@ private static void assertTokenDoesntHaveExtraData(final String fieldType, final
* @throws JBBPException it will be thrown for any logical or work exception
* for the parser and compiler
*/
- public static JBBPCompiledBlock compile(final String script, final JBBPCustomFieldTypeProcessor customTypeFieldProcessor) throws IOException {
+ public static JBBPCompiledBlock compile(final String script,
+ final JBBPCustomFieldTypeProcessor customTypeFieldProcessor)
+ throws IOException {
JBBPUtils.assertNotNull(script, "Script must not be null");
final JBBPCompiledBlock.Builder builder = JBBPCompiledBlock.prepare().setSource(script);
@@ -238,7 +236,8 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
int extraFieldNumberAsInt = -1;
int customTypeFieldIndex = -1;
- final boolean extraFieldNumericDataAsExpression = ((code >>> 8) & EXT_FLAG_EXTRA_AS_EXPRESSION) != 0;
+ final boolean extraFieldNumericDataAsExpression =
+ ((code >>> 8) & EXT_FLAG_EXTRA_AS_EXPRESSION) != 0;
final boolean fieldTypeDiff = ((code >>> 8) & EXT_FLAG_EXTRA_DIFF_TYPE) != 0;
switch (code & 0xF) {
@@ -252,7 +251,9 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
case CODE_LONG: {
if ((code & 0x0F) == CODE_CUSTOMTYPE) {
if (extraFieldNumericDataAsExpression) {
- varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance().make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields, out.toByteArray()));
+ varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance()
+ .make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields,
+ out.toByteArray()));
} else {
final String extraDataAsStr = token.getFieldTypeParameters().getExtraData();
if (extraDataAsStr == null) {
@@ -261,12 +262,15 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
try {
extraFieldNumberAsInt = Integer.parseInt(extraDataAsStr);
} catch (NumberFormatException ex) {
- throw new JBBPCompilationException("Can't parse extra data, must be numeric", token);
+ throw new JBBPCompilationException("Can't parse extra data, must be numeric",
+ token);
}
}
writeExtraFieldNumberInCompiled = true;
}
- if (customTypeFieldProcessor.isAllowed(token.getFieldTypeParameters(), token.getFieldName(), extraFieldNumberAsInt, token.isArray())) {
+ if (customTypeFieldProcessor
+ .isAllowed(token.getFieldTypeParameters(), token.getFieldName(),
+ extraFieldNumberAsInt, token.isArray())) {
customTypeFieldIndex = customTypeFields.size();
customTypeFields.add(token.getFieldTypeParameters());
} else {
@@ -285,7 +289,9 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
assertTokenNotNamed("skip", token);
}
if (extraFieldNumericDataAsExpression) {
- varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance().make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields, out.toByteArray()));
+ varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance()
+ .make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields,
+ out.toByteArray()));
} else {
final String extraNumberAsStr = token.getFieldTypeParameters().getExtraData();
writeExtraFieldNumberInCompiled = true;
@@ -309,7 +315,9 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
assertTokenNotNamed("align", token);
if (extraFieldNumericDataAsExpression) {
- varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance().make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields, out.toByteArray()));
+ varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance()
+ .make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields,
+ out.toByteArray()));
} else {
final String extraNumberAsStr = token.getFieldTypeParameters().getExtraData();
writeExtraFieldNumberInCompiled = true;
@@ -323,7 +331,8 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
extraFieldNumberAsInt = -1;
}
if (extraFieldNumberAsInt <= 0) {
- throw new JBBPCompilationException("'align' size must be greater than zero [" + token.getFieldTypeParameters().getExtraData() + ']', token);
+ throw new JBBPCompilationException("'align' size must be greater than zero [" +
+ token.getFieldTypeParameters().getExtraData() + ']', token);
}
}
}
@@ -331,7 +340,9 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
break;
case CODE_BIT: {
if (extraFieldNumericDataAsExpression) {
- varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance().make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields, out.toByteArray()));
+ varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance()
+ .make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields,
+ out.toByteArray()));
} else {
final String extraFieldNumAsStr = token.getFieldTypeParameters().getExtraData();
writeExtraFieldNumberInCompiled = true;
@@ -345,7 +356,9 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
extraFieldNumberAsInt = -1;
}
if (extraFieldNumberAsInt < 1 || extraFieldNumberAsInt > 8) {
- throw new JBBPCompilationException("Bit-width must be 1..8 [" + token.getFieldTypeParameters().getExtraData() + ']', token);
+ throw new JBBPCompilationException(
+ "Bit-width must be 1..8 [" + token.getFieldTypeParameters().getExtraData() +
+ ']', token);
}
}
}
@@ -354,7 +367,9 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
case CODE_VAR: {
hasVarFields = true;
if (extraFieldNumericDataAsExpression) {
- varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance().make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields, out.toByteArray()));
+ varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance()
+ .make(token.getFieldTypeParameters().getExtraDataExpression(), namedFields,
+ out.toByteArray()));
} else {
final String extraFieldNumStr = token.getFieldTypeParameters().getExtraData();
writeExtraFieldNumberInCompiled = true;
@@ -364,7 +379,9 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
try {
extraFieldNumberAsInt = Integer.parseInt(extraFieldNumStr);
} catch (NumberFormatException ex) {
- throw new JBBPCompilationException("Can't parse the extra value of a VAR field, must be integer [" + token.getFieldTypeParameters().getExtraData() + ']', token);
+ throw new JBBPCompilationException(
+ "Can't parse the extra value of a VAR field, must be integer [" +
+ token.getFieldTypeParameters().getExtraData() + ']', token);
}
}
}
@@ -373,22 +390,30 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
case CODE_RESET_COUNTER: {
assertTokenNotArray("Reset counter", token);
assertTokenNotNamed("Reset counter", token);
- assertTokenDoesntHaveExtraData("Reset counter", token);
+ assertTokenHasNotExtraData("Reset counter", token);
}
break;
case CODE_STRUCT_START: {
- final boolean arrayReadTillEnd = (code & FLAG_ARRAY) != 0 && (extraCode & EXT_FLAG_EXPRESSION_OR_WHOLESTREAM) != 0 && "_".equals(token.getArraySizeAsString());
- structureStack.add(new StructStackItem(namedFields.size() + ((code & JBBPCompiler.FLAG_NAMED) == 0 ? 0 : 1), startFieldOffset, arrayReadTillEnd, code, token));
+ final boolean arrayReadTillEnd =
+ (code & FLAG_ARRAY) != 0 && (extraCode & EXT_FLAG_EXPRESSION_OR_WHOLESTREAM) != 0 &&
+ "_".equals(token.getArraySizeAsString());
+ structureStack.add(new StructStackItem(
+ namedFields.size() + ((code & JBBPCompiler.FLAG_NAMED) == 0 ? 0 : 1),
+ startFieldOffset, arrayReadTillEnd, code, token));
}
break;
case CODE_STRUCT_END: {
if (structureStack.isEmpty()) {
- throw new JBBPCompilationException("Detected structure close tag without opening one", token);
+ throw new JBBPCompilationException("Detected structure close tag without opening one",
+ token);
} else {
if (fieldUnrestrictedArrayOffset >= 0) {
final StructStackItem startOfStruct = structureStack.get(structureStack.size() - 1);
- if (startOfStruct.arrayToReadTillEndOfStream && fieldUnrestrictedArrayOffset != startOfStruct.startStructureOffset) {
- throw new JBBPCompilationException("Detected unlimited array of structures but there is already presented one", token);
+ if (startOfStruct.arrayToReadTillEndOfStream &&
+ fieldUnrestrictedArrayOffset != startOfStruct.startStructureOffset) {
+ throw new JBBPCompilationException(
+ "Detected unlimited array of structures but there is already presented one",
+ token);
}
}
@@ -398,28 +423,33 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
}
break;
default:
- throw new Error("Detected unsupported compiled code, notify the developer please [" + code + ']');
+ throw new Error(
+ "Detected unsupported compiled code, notify the developer please [" + code + ']');
}
if ((code & FLAG_ARRAY) == 0) {
- if (structureStack.isEmpty() && (code & 0x0F) != CODE_STRUCT_END && fieldUnrestrictedArrayOffset >= 0) {
- throw new JBBPCompilationException("Detected field defined after unlimited array", token);
+ if (structureStack.isEmpty() && (code & 0x0F) != CODE_STRUCT_END &&
+ fieldUnrestrictedArrayOffset >= 0) {
+ throw new JBBPCompilationException("Detected field defined after unlimited array", token);
}
} else {
if ((extraCode & EXT_FLAG_EXPRESSION_OR_WHOLESTREAM) != 0) {
if ("_".equals(token.getArraySizeAsString())) {
if (fieldUnrestrictedArrayOffset >= 0) {
- throw new JBBPCompilationException("Detected two or more unlimited arrays [" + script + ']', token);
+ throw new JBBPCompilationException(
+ "Detected two or more unlimited arrays [" + script + ']', token);
} else {
fieldUnrestrictedArrayOffset = startFieldOffset;
}
} else {
- varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance().make(token.getArraySizeAsString(), namedFields, out.toByteArray()));
+ varLengthEvaluators.add(JBBPEvaluatorFactory.getInstance()
+ .make(token.getArraySizeAsString(), namedFields, out.toByteArray()));
}
} else {
final int fixedArraySize = token.getArraySizeAsInt();
if (fixedArraySize <= 0) {
- throw new JBBPCompilationException("Detected an array with negative or zero fixed length", token);
+ throw new JBBPCompilationException(
+ "Detected an array with negative or zero fixed length", token);
}
offset += writePackedInt(out, fixedArraySize);
}
@@ -436,31 +466,37 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
if ((code & FLAG_NAMED) != 0) {
final String normalizedName = JBBPUtils.normalizeFieldNameOrPath(token.getFieldName());
assertName(normalizedName, token);
- registerNamedField(normalizedName, structureStack.isEmpty() ? 0 : structureStack.get(structureStack.size() - 1).namedFieldCounter, startFieldOffset, namedFields, token);
+ registerNamedField(normalizedName, structureStack.isEmpty() ? 0 :
+ structureStack.get(structureStack.size() - 1).namedFieldCounter, startFieldOffset,
+ namedFields, token);
} else {
if (currentClosedStructure != null && (currentClosedStructure.code & FLAG_NAMED) != 0) {
// it is structure, process field names
- final String normalizedName = JBBPUtils.normalizeFieldNameOrPath(currentClosedStructure.token.getFieldName());
+ final String normalizedName =
+ JBBPUtils.normalizeFieldNameOrPath(currentClosedStructure.token.getFieldName());
for (int i = namedFields.size() - 1; i >= 0; i--) {
final JBBPNamedFieldInfo f = namedFields.get(i);
if (f.getFieldOffsetInCompiledBlock() <= currentClosedStructure.startStructureOffset) {
break;
}
final String newFullName = normalizedName + '.' + f.getFieldPath();
- namedFields.set(i, new JBBPNamedFieldInfo(newFullName, f.getFieldName(), f.getFieldOffsetInCompiledBlock()));
+ namedFields.set(i, new JBBPNamedFieldInfo(newFullName, f.getFieldName(),
+ f.getFieldOffsetInCompiledBlock()));
}
}
}
}
if (!structureStack.isEmpty()) {
- throw new JBBPCompilationException("Detected non-closed " + structureStack.size() + " structure(s)");
+ throw new JBBPCompilationException(
+ "Detected non-closed " + structureStack.size() + " structure(s)");
}
final byte[] compiledBlock = out.toByteArray();
if (fieldUnrestrictedArrayOffset >= 0) {
- compiledBlock[fieldUnrestrictedArrayOffset] = (byte) (compiledBlock[fieldUnrestrictedArrayOffset] & ~FLAG_ARRAY);
+ compiledBlock[fieldUnrestrictedArrayOffset] =
+ (byte) (compiledBlock[fieldUnrestrictedArrayOffset] & ~FLAG_ARRAY);
}
return builder
@@ -472,6 +508,13 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
.build();
}
+ private static void assertTokenHasNotExtraData(final String fieldType,
+ final JBBPToken token) {
+ if (token.getFieldTypeParameters().getExtraData() != null) {
+ throw new JBBPCompilationException('\'' + fieldType + "' has extra value", token);
+ }
+ }
+
/**
* The Method checks a value for negative.
*
@@ -481,7 +524,9 @@ public static JBBPCompiledBlock compile(final String script, final JBBPCustomFie
*/
private static void assertNonNegativeValue(final int value, final JBBPToken token) {
if (value < 0) {
- throw new JBBPCompilationException("Detected unsupported negative value for a field must have only zero or a positive one", token);
+ throw new JBBPCompilationException(
+ "Detected unsupported negative value for a field must have only zero or a positive one",
+ token);
}
}
@@ -494,7 +539,8 @@ private static void assertNonNegativeValue(final int value, final JBBPToken toke
*/
private static void assertName(final String name, final JBBPToken token) {
if (name.indexOf('.') >= 0) {
- throw new JBBPCompilationException("Detected disallowed char '.' in name [" + name + ']', token);
+ throw new JBBPCompilationException("Detected disallowed char '.' in name [" + name + ']',
+ token);
}
}
@@ -508,11 +554,15 @@ private static void assertName(final String name, final JBBPToken token) {
* @throws JBBPCompilationException if there is already a registered field for
* the path
*/
- private static void registerNamedField(final String normalizedName, final int structureBorder, final int offset, final List namedFields, final JBBPToken token) {
+ private static void registerNamedField(final String normalizedName, final int structureBorder,
+ final int offset,
+ final List namedFields,
+ final JBBPToken token) {
for (int i = namedFields.size() - 1; i >= structureBorder; i--) {
final JBBPNamedFieldInfo info = namedFields.get(i);
if (info.getFieldPath().equals(normalizedName)) {
- throw new JBBPCompilationException("Duplicated named field detected [" + normalizedName + ']', token);
+ throw new JBBPCompilationException(
+ "Duplicated named field detected [" + normalizedName + ']', token);
}
}
namedFields.add(new JBBPNamedFieldInfo(normalizedName, normalizedName, offset));
@@ -540,7 +590,8 @@ private static int writePackedInt(final OutputStream out, final int value) throw
* it can be null
* @return the prepared byte code for the token
*/
- private static int prepareCodeForToken(final JBBPToken token, final JBBPCustomFieldTypeProcessor customTypeFieldProcessor) {
+ private static int prepareCodeForToken(final JBBPToken token,
+ final JBBPCustomFieldTypeProcessor customTypeFieldProcessor) {
int result = -1;
switch (token.getType()) {
case ATOM: {
@@ -550,9 +601,11 @@ private static int prepareCodeForToken(final JBBPToken token, final JBBPCustomFi
final boolean hasExpressionAsExtraNumber = descriptor.hasExpressionAsExtraData();
- result |= token.getArraySizeAsString() == null ? 0 : (token.isVarArrayLength() ? FLAG_ARRAY | FLAG_WIDE | (EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8) : FLAG_ARRAY);
+ result |= token.getArraySizeAsString() == null ? 0 : (token.isVarArrayLength() ?
+ FLAG_ARRAY | FLAG_WIDE | (EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8) : FLAG_ARRAY);
result |= hasExpressionAsExtraNumber ? FLAG_WIDE | (EXT_FLAG_EXTRA_AS_EXPRESSION << 8) : 0;
- result |= token.getFieldTypeParameters().isSpecialField() ? FLAG_WIDE | (EXT_FLAG_EXTRA_DIFF_TYPE << 8) : 0;
+ result |= token.getFieldTypeParameters().isSpecialField() ?
+ FLAG_WIDE | (EXT_FLAG_EXTRA_DIFF_TYPE << 8) : 0;
result |= token.getFieldName() == null ? 0 : FLAG_NAMED;
final String name = descriptor.getTypeName().toLowerCase(Locale.ENGLISH);
@@ -578,6 +631,7 @@ private static int prepareCodeForToken(final JBBPToken token, final JBBPCustomFi
result |= CODE_UBYTE;
break;
case "byte":
+ case JBBPFieldUInt.TYPE_NAME:
result |= CODE_BYTE;
break;
case "ushort":
@@ -609,7 +663,8 @@ private static int prepareCodeForToken(final JBBPToken token, final JBBPCustomFi
}
}
if (unsupportedType) {
- throw new JBBPCompilationException("Unsupported type [" + descriptor.getTypeName() + ']', token);
+ throw new JBBPCompilationException(
+ "Unsupported type [" + descriptor.getTypeName() + ']', token);
}
break;
}
@@ -620,7 +675,8 @@ private static int prepareCodeForToken(final JBBPToken token, final JBBPCustomFi
}
break;
case STRUCT_START: {
- result = token.getArraySizeAsString() == null ? 0 : (token.isVarArrayLength() ? FLAG_ARRAY | FLAG_WIDE | (EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8) : FLAG_ARRAY);
+ result = token.getArraySizeAsString() == null ? 0 : (token.isVarArrayLength() ?
+ FLAG_ARRAY | FLAG_WIDE | (EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8) : FLAG_ARRAY);
result |= token.getFieldName() == null ? 0 : FLAG_NAMED;
result |= CODE_STRUCT_START;
}
@@ -659,7 +715,7 @@ private static final class StructStackItem {
private final int namedFieldCounter;
/**
- * Flag shows that the structure is array which shoukd be read till end of stream
+ * Flag shows that the structure is array which should be read till end of stream
*/
private final boolean arrayToReadTillEndOfStream;
@@ -670,11 +726,13 @@ private static final class StructStackItem {
* start
* @param startStructureOffset the offset of the start structure byte-code
* instruction
- * @param arrayToReadTillEnd if true then it is array to read till end
+ * @param arrayToReadTillEnd if true then it is an array to read till end
* @param code the start byte code
* @param token the token
*/
- private StructStackItem(final int namedFieldCounter, final int startStructureOffset, final boolean arrayToReadTillEnd, final int code, final JBBPToken token) {
+ private StructStackItem(final int namedFieldCounter, final int startStructureOffset,
+ final boolean arrayToReadTillEnd, final int code,
+ final JBBPToken token) {
this.namedFieldCounter = namedFieldCounter;
this.arrayToReadTillEndOfStream = arrayToReadTillEnd;
this.startStructureOffset = startStructureOffset;
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompilerUtils.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompilerUtils.java
index 6194a67e..5bfe4be5 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompilerUtils.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPCompilerUtils.java
@@ -16,13 +16,12 @@
package com.igormaznitsa.jbbp.compiler;
+import static com.igormaznitsa.jbbp.compiler.JBBPCompiler.FLAG_ARRAY;
+
import com.igormaznitsa.jbbp.exceptions.JBBPCompilationException;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
-
import java.util.List;
-import static com.igormaznitsa.jbbp.compiler.JBBPCompiler.FLAG_ARRAY;
-
/**
* Class contains specific common auxiliary methods for parser and compiler classes.
*
@@ -39,7 +38,8 @@ private JBBPCompilerUtils() {
* @param namedFields a list contains named field info items.
* @return the index of a field for the path if found one, -1 otherwise
*/
- public static int findIndexForFieldPath(final String fieldPath, final List namedFields) {
+ public static int findIndexForFieldPath(final String fieldPath,
+ final List namedFields) {
final String normalized = JBBPUtils.normalizeFieldNameOrPath(fieldPath);
int result = -1;
for (int i = namedFields.size() - 1; i >= 0; i--) {
@@ -59,7 +59,8 @@ public static int findIndexForFieldPath(final String fieldPath, final List namedFields) {
+ public static JBBPNamedFieldInfo findForFieldPath(final String fieldPath,
+ final List namedFields) {
final String normalized = JBBPUtils.normalizeFieldNameOrPath(fieldPath);
JBBPNamedFieldInfo result = null;
for (int i = namedFields.size() - 1; i >= 0; i--) {
@@ -73,30 +74,36 @@ public static JBBPNamedFieldInfo findForFieldPath(final String fieldPath, final
}
/**
- * Check a field in a compiled list defined by its named field info, that the field is not an array and it is not inside a structure array.
+ * Check a field in a compiled list defined by it's named field info, that the field is not an array and it is not inside a structure array.
*
* @param fieldToCheck a named field info to be checked, must not be null
* @param namedFieldList a named field info list, must not be null.
* @param compiledScript a compiled script body
*/
- public static void assertFieldIsNotArrayOrInArray(final JBBPNamedFieldInfo fieldToCheck, final List namedFieldList, final byte[] compiledScript) {
+ public static void assertFieldIsNotArrayOrInArray(final JBBPNamedFieldInfo fieldToCheck,
+ final List namedFieldList,
+ final byte[] compiledScript) {
// check that the field is not array
if ((compiledScript[fieldToCheck.getFieldOffsetInCompiledBlock()] & FLAG_ARRAY) != 0) {
- throw new JBBPCompilationException("An Array field can't be used as array size [" + fieldToCheck.getFieldPath() + ']');
+ throw new JBBPCompilationException(
+ "An Array field can't be used as array size [" + fieldToCheck.getFieldPath() + ']');
}
if (fieldToCheck.getFieldPath().indexOf('.') >= 0) {
// the field in structure, check that the structure is not an array or not in an array
- final String[] splittedFieldPath = JBBPUtils.splitString(fieldToCheck.getFieldPath(), '.');
+ final String[] splitFieldPath = JBBPUtils.splitString(fieldToCheck.getFieldPath(), '.');
final StringBuilder fieldPath = new StringBuilder();
// process till the field name because we have already checked the field
- for (int i = 0; i < splittedFieldPath.length - 1; i++) {
+ for (int i = 0; i < splitFieldPath.length - 1; i++) {
if (fieldPath.length() != 0) {
fieldPath.append('.');
}
- fieldPath.append(splittedFieldPath[i]);
- final JBBPNamedFieldInfo structureEnd = JBBPCompilerUtils.findForFieldPath(fieldPath.toString(), namedFieldList);
+ fieldPath.append(splitFieldPath[i]);
+ final JBBPNamedFieldInfo structureEnd =
+ JBBPCompilerUtils.findForFieldPath(fieldPath.toString(), namedFieldList);
if ((compiledScript[structureEnd.getFieldOffsetInCompiledBlock()] & FLAG_ARRAY) != 0) {
- throw new JBBPCompilationException("Field from structure array can't be use as array size [" + fieldToCheck.getFieldPath() + ';' + structureEnd.getFieldPath() + ']');
+ throw new JBBPCompilationException(
+ "Field from structure array can't be use as array size [" +
+ fieldToCheck.getFieldPath() + ';' + structureEnd.getFieldPath() + ']');
}
}
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPNamedFieldInfo.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPNamedFieldInfo.java
index 4b1d4bed..59bb84f8 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPNamedFieldInfo.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/JBBPNamedFieldInfo.java
@@ -17,12 +17,11 @@
package com.igormaznitsa.jbbp.compiler;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
-
import java.io.Serializable;
/**
* The Class describes a named field info item. Such objects are presented
- * inside of compiled blocks only for fields which have names.
+ * inside compiled blocks only for fields which have names.
*
* @since 1.0
*/
@@ -49,7 +48,8 @@ public final class JBBPNamedFieldInfo implements Serializable {
* @param fieldName the field name
* @param offsetInCompiledBlock the offset in the compiled block for the field
*/
- public JBBPNamedFieldInfo(final String fieldPath, final String fieldName, final int offsetInCompiledBlock) {
+ public JBBPNamedFieldInfo(final String fieldPath, final String fieldName,
+ final int offsetInCompiledBlock) {
this.fieldPath = JBBPUtils.normalizeFieldNameOrPath(fieldPath);
this.fieldName = JBBPUtils.normalizeFieldNameOrPath(fieldName);
this.offsetInCompiledBlock = offsetInCompiledBlock;
@@ -95,7 +95,8 @@ public boolean equals(final Object obj) {
if (obj instanceof JBBPNamedFieldInfo) {
final JBBPNamedFieldInfo that = (JBBPNamedFieldInfo) obj;
- result = this.fieldPath.equals(that.fieldPath) && this.offsetInCompiledBlock == that.offsetInCompiledBlock;
+ result = this.fieldPath.equals(that.fieldPath) &&
+ this.offsetInCompiledBlock == that.offsetInCompiledBlock;
}
return result;
}
@@ -107,7 +108,8 @@ public int hashCode() {
@Override
public String toString() {
- return this.getClass().getSimpleName() + "[fieldPath=" + this.fieldPath + ", fieldName=" + this.fieldName + ", offsetInCompiledBlock=" + this.offsetInCompiledBlock + ']';
+ return this.getClass().getSimpleName() + "[fieldPath=" + this.fieldPath + ", fieldName=" +
+ this.fieldName + ", offsetInCompiledBlock=" + this.offsetInCompiledBlock + ']';
}
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/CompiledBlockVisitor.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/CompiledBlockVisitor.java
index c3734bf1..5ab3512b 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/CompiledBlockVisitor.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/CompiledBlockVisitor.java
@@ -88,12 +88,16 @@ public final CompiledBlockVisitor visit() {
final boolean extraFieldNumAsExpr = (ec & JBBPCompiler.EXT_FLAG_EXTRA_AS_EXPRESSION) != 0;
final int code = (ec << 8) | c;
- final JBBPNamedFieldInfo name = (code & JBBPCompiler.FLAG_NAMED) == 0 ? null : this.compiledBlock.getNamedFields()[positionAtNamedFieldList++];
- final JBBPByteOrder byteOrder = (code & JBBPCompiler.FLAG_LITTLE_ENDIAN) == 0 ? JBBPByteOrder.BIG_ENDIAN : JBBPByteOrder.LITTLE_ENDIAN;
+ final JBBPNamedFieldInfo name = (code & JBBPCompiler.FLAG_NAMED) == 0 ? null :
+ this.compiledBlock.getNamedFields()[positionAtNamedFieldList++];
+ final JBBPByteOrder byteOrder =
+ (code & JBBPCompiler.FLAG_LITTLE_ENDIAN) == 0 ? JBBPByteOrder.BIG_ENDIAN :
+ JBBPByteOrder.LITTLE_ENDIAN;
final JBBPIntegerValueEvaluator extraFieldValueEvaluator;
if (extraFieldNumAsExpr) {
- extraFieldValueEvaluator = this.compiledBlock.getArraySizeEvaluators()[positionAtVarLengthProcessors++];
+ extraFieldValueEvaluator =
+ this.compiledBlock.getArraySizeEvaluators()[positionAtVarLengthProcessors++];
} else {
extraFieldValueEvaluator = null;
}
@@ -102,9 +106,11 @@ public final CompiledBlockVisitor visit() {
boolean readWholeStream = false;
- switch (code & (JBBPCompiler.FLAG_ARRAY | (JBBPCompiler.EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8))) {
+ switch (code &
+ (JBBPCompiler.FLAG_ARRAY | (JBBPCompiler.EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8))) {
case JBBPCompiler.FLAG_ARRAY: {
- arraySizeEvaluator = new IntConstValueEvaluator(JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
+ arraySizeEvaluator = new IntConstValueEvaluator(
+ JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
}
break;
case (JBBPCompiler.EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8): {
@@ -113,7 +119,8 @@ public final CompiledBlockVisitor visit() {
}
break;
case JBBPCompiler.FLAG_ARRAY | (JBBPCompiler.EXT_FLAG_EXPRESSION_OR_WHOLESTREAM << 8): {
- arraySizeEvaluator = this.compiledBlock.getArraySizeEvaluators()[positionAtVarLengthProcessors++];
+ arraySizeEvaluator =
+ this.compiledBlock.getArraySizeEvaluators()[positionAtVarLengthProcessors++];
}
break;
default: {
@@ -132,7 +139,9 @@ public final CompiledBlockVisitor visit() {
break;
case JBBPCompiler.CODE_SKIP:
case JBBPCompiler.CODE_ALIGN: {
- final JBBPIntegerValueEvaluator evaluator = extraFieldNumAsExpr ? extraFieldValueEvaluator : new IntConstValueEvaluator(JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
+ final JBBPIntegerValueEvaluator evaluator =
+ extraFieldNumAsExpr ? extraFieldValueEvaluator : new IntConstValueEvaluator(
+ JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
if (altFileType) {
if (theCode == JBBPCompiler.CODE_SKIP) {
visitValField(theOffset, byteOrder, name, evaluator);
@@ -146,8 +155,11 @@ public final CompiledBlockVisitor visit() {
break;
case JBBPCompiler.CODE_BIT: {
- final JBBPIntegerValueEvaluator numberOfBits = extraFieldNumAsExpr ? extraFieldValueEvaluator : new IntConstValueEvaluator(JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
- visitBitField(theOffset, byteOrder, name, numberOfBits, arraySizeEvaluator);
+ final JBBPIntegerValueEvaluator numberOfBits =
+ extraFieldNumAsExpr ? extraFieldValueEvaluator : new IntConstValueEvaluator(
+ JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
+ visitBitField(theOffset, byteOrder, name, readWholeStream, numberOfBits,
+ arraySizeEvaluator);
}
break;
@@ -158,12 +170,13 @@ public final CompiledBlockVisitor visit() {
case JBBPCompiler.CODE_USHORT:
case JBBPCompiler.CODE_INT:
case JBBPCompiler.CODE_LONG: {
- visitPrimitiveField(theOffset, theCode, name, byteOrder, readWholeStream, altFileType, arraySizeEvaluator);
+ visitPrimitiveField(theOffset, theCode, name, byteOrder, readWholeStream, altFileType,
+ arraySizeEvaluator);
}
break;
case JBBPCompiler.CODE_STRUCT_START: {
- visitStructureStart(theOffset, byteOrder, name, arraySizeEvaluator);
+ visitStructureStart(theOffset, byteOrder, readWholeStream, name, arraySizeEvaluator);
}
break;
@@ -174,15 +187,23 @@ public final CompiledBlockVisitor visit() {
break;
case JBBPCompiler.CODE_VAR: {
- final JBBPIntegerValueEvaluator extraDataValueEvaluator = extraFieldNumAsExpr ? extraFieldValueEvaluator : new IntConstValueEvaluator(JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
- visitVarField(theOffset, name, byteOrder, readWholeStream, arraySizeEvaluator, extraDataValueEvaluator);
+ final JBBPIntegerValueEvaluator extraDataValueEvaluator =
+ extraFieldNumAsExpr ? extraFieldValueEvaluator : new IntConstValueEvaluator(
+ JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
+ visitVarField(theOffset, name, byteOrder, readWholeStream, arraySizeEvaluator,
+ extraDataValueEvaluator);
}
break;
case JBBPCompiler.CODE_CUSTOMTYPE: {
- final JBBPIntegerValueEvaluator extraDataValueEvaluator = extraFieldNumAsExpr ? extraFieldValueEvaluator : new IntConstValueEvaluator(JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
- final JBBPFieldTypeParameterContainer fieldTypeInfo = this.compiledBlock.getCustomTypeFields()[JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock)];
- visitCustomField(theOffset, fieldTypeInfo, name, byteOrder, readWholeStream, arraySizeEvaluator, extraDataValueEvaluator);
+ final JBBPIntegerValueEvaluator extraDataValueEvaluator =
+ extraFieldNumAsExpr ? extraFieldValueEvaluator : new IntConstValueEvaluator(
+ JBBPUtils.unpackInt(compiledData, positionAtCompiledBlock));
+ final JBBPFieldTypeParameterContainer fieldTypeInfo =
+ this.compiledBlock.getCustomTypeFields()[JBBPUtils
+ .unpackInt(compiledData, positionAtCompiledBlock)];
+ visitCustomField(theOffset, fieldTypeInfo, name, byteOrder, readWholeStream,
+ arraySizeEvaluator, extraDataValueEvaluator);
}
break;
default:
@@ -205,19 +226,23 @@ public final CompiledBlockVisitor visit() {
* @see JBBPCompiler#CODE_ALIGN
* @see JBBPCompiler#CODE_SKIP
*/
- public void visitActionItem(int offsetInCompiledBlock, int actionType, JBBPIntegerValueEvaluator nullableArgument) {
+ public void visitActionItem(int offsetInCompiledBlock, int actionType,
+ JBBPIntegerValueEvaluator nullableArgument) {
}
/**
- * Visit field contains virtual field with VAL type.
+ * Visit field contains virtual field defined through VAL type.
*
* @param offsetInCompiledBlock offset in the compiled block
- * @param byteOrder byteOrder
+ * @param byteOrder byteOrder
* @param nameFieldInfo name of the field, must not be null
* @param expression expression to calculate value
* @since 1.4.0
*/
- public void visitValField(int offsetInCompiledBlock, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nameFieldInfo, JBBPIntegerValueEvaluator expression) {
+ public void visitValField(int offsetInCompiledBlock,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nameFieldInfo,
+ JBBPIntegerValueEvaluator expression) {
}
/**
@@ -227,7 +252,7 @@ public void visitValField(int offsetInCompiledBlock, JBBPByteOrder byteOrder, JB
* @param primitiveType the primitive type
* @param nullableNameFieldInfo field info, null if the field is anonymous one
* @param byteOrder byte order for the field, must not be null
- * @param readWholeStreamAsArray if true then it is array with unknown size till the stream end
+ * @param readWholeStreamAsArray if true then it is an array with unknown size till the stream end
* @param altFieldType flag shows that field type is alternative one, INT should be recognized as FLOAT and LONG as DOUBLE and BOOL as STRING
* @param nullableArraySize array size if the field is array, null if the field is not array or variable length array
* @see JBBPCompiler#CODE_BYTE
@@ -239,37 +264,106 @@ public void visitValField(int offsetInCompiledBlock, JBBPByteOrder byteOrder, JB
* @see JBBPCompiler#CODE_LONG
* @see JBBPCompiler#CODE_SKIP
*/
- public void visitPrimitiveField(int offsetInCompiledBlock, int primitiveType, JBBPNamedFieldInfo nullableNameFieldInfo, JBBPByteOrder byteOrder, boolean readWholeStreamAsArray, boolean altFieldType, JBBPIntegerValueEvaluator nullableArraySize) {
+ public void visitPrimitiveField(int offsetInCompiledBlock,
+ int primitiveType,
+ JBBPNamedFieldInfo nullableNameFieldInfo,
+ JBBPByteOrder byteOrder,
+ boolean readWholeStreamAsArray,
+ boolean altFieldType,
+ JBBPIntegerValueEvaluator nullableArraySize) {
}
/**
* Visit a variable field (which is defined with var data type)
*
- * @param offsetInCompiledBlock offset in the compiled block
- * @param nullableNameFieldInfo field info, null if the field is anonymous one
- * @param byteOrder byte order for the field, must not be null
- * @param readWholeStreamIntoArray true if whole stream should be read as array of var type, false otherwise
- * @param nullableArraySize if not null then evaluator of array size to be read from stream
- * @param extraDataValueEvaluator if not null then extra data evaluator for the var field
+ * @param offsetInCompiledBlock offset in the compiled block
+ * @param nullableNameFieldInfo field info, null if the field is anonymous one
+ * @param byteOrder byte order for the field, must not be null
+ * @param readWholeStream true if whole stream should be read as array of var type, false otherwise
+ * @param nullableArraySize if not null then evaluator of array size to be read from stream
+ * @param extraDataValue if not null then extra data evaluator for the var field
*/
- public void visitVarField(int offsetInCompiledBlock, JBBPNamedFieldInfo nullableNameFieldInfo, JBBPByteOrder byteOrder, boolean readWholeStreamIntoArray, JBBPIntegerValueEvaluator nullableArraySize, JBBPIntegerValueEvaluator extraDataValueEvaluator) {
+ public void visitVarField(int offsetInCompiledBlock,
+ JBBPNamedFieldInfo nullableNameFieldInfo,
+ JBBPByteOrder byteOrder,
+ boolean readWholeStream,
+ JBBPIntegerValueEvaluator nullableArraySize,
+ JBBPIntegerValueEvaluator extraDataValue) {
}
- public void visitCustomField(int offsetInCompiledBlock, JBBPFieldTypeParameterContainer notNullFieldType, JBBPNamedFieldInfo nullableNameFieldInfo, JBBPByteOrder byteOrder, boolean readWholeStream, JBBPIntegerValueEvaluator nullableArraySizeEvaluator, JBBPIntegerValueEvaluator extraDataValueEvaluator) {
+ /**
+ * Visit a custom type field.
+ *
+ * @param offsetInCompiledBlock offset in the compiled block
+ * @param notNullFieldType field type info, must not be null
+ * @param nullableNameFieldInfo field info, null if the field is anonymous one
+ * @param byteOrder byte order for the field, must not be null
+ * @param readWholeStream true if whole stream should be read as array of var type, false otherwise
+ * @param nullableArraySize if not null then evaluator of array size to be read from stream
+ * @param extraDataValue if not null then extra data evaluator for the var field
+ */
+ public void visitCustomField(int offsetInCompiledBlock,
+ JBBPFieldTypeParameterContainer notNullFieldType,
+ JBBPNamedFieldInfo nullableNameFieldInfo,
+ JBBPByteOrder byteOrder,
+ boolean readWholeStream,
+ JBBPIntegerValueEvaluator nullableArraySize,
+ JBBPIntegerValueEvaluator extraDataValue) {
}
- public void visitBitField(int offsetInCompiledBlock, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNameFieldInfo, JBBPIntegerValueEvaluator notNullFieldSize, JBBPIntegerValueEvaluator nullableArraySize) {
+ /**
+ * Visit a custom type field.
+ *
+ * @param offsetInCompiledBlock offset in the compiled block
+ * @param byteOrder byte order for the field, must not be null
+ * @param nullableNameFieldInfo field info, null if the field is anonymous one
+ * @param readWholeStream true if whole stream should be read as array of var type, false otherwise
+ * @param notNullFieldSize evaluator to calculate size of the field, must not be null
+ * @param nullableArraySize if not null then evaluator of array size to be read from stream
+ */
+ public void visitBitField(int offsetInCompiledBlock,
+ JBBPByteOrder byteOrder,
+ JBBPNamedFieldInfo nullableNameFieldInfo,
+ boolean readWholeStream,
+ JBBPIntegerValueEvaluator notNullFieldSize,
+ JBBPIntegerValueEvaluator nullableArraySize) {
}
- public void visitStructureStart(int offsetInCompiledBlock, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNameFieldInfo, JBBPIntegerValueEvaluator nullableArraySize) {
+ /**
+ * Visit a structure field.
+ *
+ * @param offsetInCompiledBlock offset in the compiled block
+ * @param byteOrder byte order for the field, must not be null
+ * @param readWholeStream true if whole stream should be read as array of var type, false otherwise
+ * @param nullableNameFieldInfo field info, null if the field is anonymous one
+ * @param nullableArraySize if not null then evaluator of array size to be read from stream
+ */
+ public void visitStructureStart(int offsetInCompiledBlock,
+ JBBPByteOrder byteOrder,
+ boolean readWholeStream,
+ JBBPNamedFieldInfo nullableNameFieldInfo,
+ JBBPIntegerValueEvaluator nullableArraySize) {
}
- public void visitStructureEnd(int offsetInCompiledBlock, JBBPNamedFieldInfo nullableNameFieldInfo) {
+ /**
+ * End visit of a structure
+ *
+ * @param offsetInCompiledBlock offset in the compiled block
+ * @param nullableNameFieldInfo field info, null if the field is anonymous one
+ */
+ public void visitStructureEnd(int offsetInCompiledBlock,
+ JBBPNamedFieldInfo nullableNameFieldInfo) {
}
+ /**
+ * Called before visit of each item.
+ */
public void visitStart() {
}
+ /**
+ * Called after visit each item.
+ */
public void visitEnd() {
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/ExpressionEvaluatorVisitor.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/ExpressionEvaluatorVisitor.java
index 8d7059e0..365bee08 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/ExpressionEvaluatorVisitor.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/ExpressionEvaluatorVisitor.java
@@ -47,7 +47,8 @@ public interface ExpressionEvaluatorVisitor {
* @param nullableExternalFieldName name of external field, it will be null for regular field
* @return the visitor instance, must not be null
*/
- ExpressionEvaluatorVisitor visitField(JBBPNamedFieldInfo nullableNameFieldInfo, String nullableExternalFieldName);
+ ExpressionEvaluatorVisitor visitField(JBBPNamedFieldInfo nullableNameFieldInfo,
+ String nullableExternalFieldName);
/**
* Visit operator
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/IntConstValueEvaluator.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/IntConstValueEvaluator.java
index 36c3868f..2a140524 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/IntConstValueEvaluator.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/IntConstValueEvaluator.java
@@ -26,7 +26,7 @@
*
* @since 1.3.0
*/
-final class IntConstValueEvaluator implements JBBPIntegerValueEvaluator {
+public final class IntConstValueEvaluator implements JBBPIntegerValueEvaluator {
private static final long serialVersionUID = 4640385518512384490L;
@@ -40,12 +40,20 @@ final class IntConstValueEvaluator implements JBBPIntegerValueEvaluator {
}
@Override
- public int eval(final JBBPBitInputStream inStream, final int currentCompiledBlockOffset, final JBBPCompiledBlock block, final JBBPNamedNumericFieldMap fieldMap) {
+ public int eval(final JBBPBitInputStream inStream,
+ final int currentCompiledBlockOffset,
+ final JBBPCompiledBlock block,
+ final JBBPNamedNumericFieldMap fieldMap
+ ) {
return this.value;
}
@Override
- public void visitItems(JBBPCompiledBlock block, int currentCompiledBlockOffset, ExpressionEvaluatorVisitor visitor) {
+ public void visitItems(
+ JBBPCompiledBlock block,
+ int currentCompiledBlockOffset,
+ ExpressionEvaluatorVisitor visitor
+ ) {
visitor.visitStart();
visitor.visitConstant(this.value);
visitor.visitEnd();
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/JBBPToJavaConverter.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/JBBPToJavaConverter.java
index 51a96c6f..7b7cb043 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/JBBPToJavaConverter.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/conversion/JBBPToJavaConverter.java
@@ -27,7 +27,6 @@
import static com.igormaznitsa.jbbp.compiler.JBBPCompiler.CODE_UBYTE;
import static com.igormaznitsa.jbbp.compiler.JBBPCompiler.CODE_USHORT;
-
import com.igormaznitsa.jbbp.JBBPParser;
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
import com.igormaznitsa.jbbp.compiler.tokenizer.JBBPFieldTypeParameterContainer;
@@ -56,7 +55,7 @@
* @since 1.3.0
*/
@SuppressWarnings("SpellCheckingInspection")
-public final class JBBPToJavaConverter extends CompiledBlockVisitor {
+public class JBBPToJavaConverter extends CompiledBlockVisitor {
private static final int FLAG_DETECTED_CUSTOM_FIELDS = 1;
private static final int FLAG_DETECTED_EXTERNAL_FIELDS = 2;
@@ -64,68 +63,6 @@ public final class JBBPToJavaConverter extends CompiledBlockVisitor {
private static final int FLAG_ADD_ASSERT_NOT_NEGATIVE_EXPR = 8;
private static final Set RESERVED_JAVA_KEYWORDS;
-
- static {
- final Set reserved = new HashSet<>();
-
- reserved.add("abstract");
- reserved.add("assert");
- reserved.add("boolean");
- reserved.add("break");
- reserved.add("byte");
- reserved.add("case");
- reserved.add("catch");
- reserved.add("char");
- reserved.add("class");
- reserved.add("continue");
- reserved.add("default");
- reserved.add("do");
- reserved.add("double");
- reserved.add("else");
- reserved.add("enum");
- reserved.add("extends");
- reserved.add("final");
- reserved.add("finally");
- reserved.add("float");
- reserved.add("for");
- reserved.add("if");
- reserved.add("implements");
- reserved.add("import");
- reserved.add("instanceof");
- reserved.add("int");
- reserved.add("interface");
- reserved.add("long");
- reserved.add("native");
- reserved.add("new");
- reserved.add("package");
- reserved.add("private");
- reserved.add("protected");
- reserved.add("public");
- reserved.add("return");
- reserved.add("short");
- reserved.add("static");
- reserved.add("strictfp");
- reserved.add("super");
- reserved.add("switch");
- reserved.add("synchronized");
- reserved.add("this");
- reserved.add("throw");
- reserved.add("throws");
- reserved.add("transient");
- reserved.add("try");
- reserved.add("void");
- reserved.add("volatile");
- reserved.add("while");
- reserved.add("true");
- reserved.add("null");
- reserved.add("false");
- reserved.add("var");
- reserved.add("const");
- reserved.add("goto");
-
- RESERVED_JAVA_KEYWORDS = Collections.unmodifiableSet(reserved);
- }
-
/**
* Name of the field to be used as link to the root structure instance in
* child structures.
@@ -143,6 +80,19 @@ public final class JBBPToJavaConverter extends CompiledBlockVisitor {
* Name of the output stream argument.
*/
private static final String NAME_OUTPUT_STREAM = "Out";
+
+ static {
+
+ RESERVED_JAVA_KEYWORDS =
+ Set.of("abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class",
+ "continue", "default", "do", "double", "else", "enum", "extends", "final", "finally",
+ "float", "for", "if", "implements", "import", "instanceof", "int", "interface", "long",
+ "native", "new", "package", "private", "protected", "public", "return", "short",
+ "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws",
+ "transient", "try", "void", "volatile", "while", "true", "null", "false", "var",
+ "const", "goto");
+ }
+
/**
* Detected flags.
*/
@@ -218,7 +168,8 @@ private void registerNamedField(final JBBPNamedFieldInfo fieldInfo, final FieldT
if (this.foundNamedFields.containsKey(fieldInfo)) {
throw new Error("Detected duplication of named field : " + fieldInfo);
}
- this.foundNamedFields.put(fieldInfo, new NamedFieldInfo(fieldInfo, this.getCurrentStruct(), fieldType));
+ this.foundNamedFields
+ .put(fieldInfo, new NamedFieldInfo(fieldInfo, this.getCurrentStruct(), fieldType));
}
}
@@ -258,7 +209,7 @@ public void visitEnd() {
buffer.printCommentMultiLinesWithIndent(this.builder.headComment);
}
- if (this.builder.mainClassPackage != null && this.builder.mainClassPackage.length() != 0) {
+ if (this.builder.mainClassPackage != null && !this.builder.mainClassPackage.isEmpty()) {
buffer.print("package ").print(this.builder.mainClassPackage).println(";");
}
@@ -279,61 +230,82 @@ public void visitEnd() {
buffer.println();
this.specialSection.println();
- this.specialSection.printJavaDocLinesWithIndent("The Constant contains parser flags\n@see JBBPParser#FLAG_SKIP_REMAINING_FIELDS_IF_EOF\n@see JBBPParser#FLAG_NEGATIVE_EXPRESSION_RESULT_AS_ZERO");
- this.specialSection.indent().printf("protected static final int %s = %d;", NAME_PARSER_FLAGS, this.parserFlags);
+ this.specialSection.printJavaDocLinesWithIndent(
+ "The Constant contains parser flags\n@see JBBPParser#FLAG_SKIP_REMAINING_FIELDS_IF_EOF\n@see JBBPParser#FLAG_NEGATIVE_EXPRESSION_RESULT_AS_ZERO");
+ this.specialSection.indent()
+ .printf("protected static final int %s = %d;", NAME_PARSER_FLAGS, this.parserFlags);
final int detected = this.flagSet.get();
if ((detected & FLAG_DETECTED_CUSTOM_FIELDS) != 0) {
- this.specialMethods.printJavaDocLinesWithIndent("Reading of custom fields\n@param sourceStruct source structure holding the field, must not be null\n@param inStream the input stream, must not be null\n@param typeParameterContainer info about field type, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, default value 0\n@param readWholeStream flag to read the stream as array till the stream end if true\n@param arraySize if array then it is zero or great\n@exception IOException if data can't be read\n@return read value as abstract field, must not be null");
- this.specialMethods.println("public abstract JBBPAbstractField readCustomFieldType(Object sourceStruct, JBBPBitInputStream inStream, JBBPFieldTypeParameterContainer typeParameterContainer, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean readWholeStream, int arraySize) throws IOException;");
+ this.specialMethods.printJavaDocLinesWithIndent(
+ "Reading of custom fields\n@param sourceStruct source structure holding the field, must not be null\n@param inStream the input stream, must not be null\n@param typeParameterContainer info about field type, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, default value 0\n@param readWholeStream flag to read the stream as array till the stream end if true\n@param arraySize if array then it is zero or great\n@exception IOException if data can't be read\n@return read value as abstract field, must not be null");
+ this.specialMethods.println(
+ "public abstract JBBPAbstractField readCustomFieldType(Object sourceStruct, JBBPBitInputStream inStream, JBBPFieldTypeParameterContainer typeParameterContainer, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean readWholeStream, int arraySize) throws IOException;");
this.specialMethods.println();
- this.specialMethods.printJavaDocLinesWithIndent("Writing custom fields\n@param sourceStruct source structure holding the field, must not be null\n@param outStream the output stream, must not be null\n@param fieldValue value to be written\n@param typeParameterContainer info about field type, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, default value is 0\n@param wholeArray true if to write whole array\n@param arraySize if array then it is zero or great\n@exception IOException if data can't be written");
- this.specialMethods.println("public abstract void writeCustomFieldType(Object sourceStruct, JBBPBitOutputStream outStream, JBBPAbstractField fieldValue, JBBPFieldTypeParameterContainer typeParameterContainer, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean wholeArray, int arraySize) throws IOException;");
+ this.specialMethods.printJavaDocLinesWithIndent(
+ "Writing custom fields\n@param sourceStruct source structure holding the field, must not be null\n@param outStream the output stream, must not be null\n@param fieldValue value to be written\n@param typeParameterContainer info about field type, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, default value is 0\n@param wholeArray true if to write whole array\n@param arraySize if array then it is zero or great\n@exception IOException if data can't be written");
+ this.specialMethods.println(
+ "public abstract void writeCustomFieldType(Object sourceStruct, JBBPBitOutputStream outStream, JBBPAbstractField fieldValue, JBBPFieldTypeParameterContainer typeParameterContainer, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean wholeArray, int arraySize) throws IOException;");
}
if ((detected & FLAG_DETECTED_EXTERNAL_FIELDS) != 0) {
if (!this.specialMethods.isEmpty()) {
this.specialMethods.println();
}
- this.specialMethods.printJavaDocLinesWithIndent("Method is called from expressions to provide value\n@param sourceStruct source structure holding the field, must not be null\n@param valueName name of value to be provided, must not be null\n@return integer value for the named parameter");
- this.specialMethods.println("public abstract int getNamedValue(Object sourceStruct, String valueName);");
+ this.specialMethods.printJavaDocLinesWithIndent(
+ "Method is called from expressions to provide value\n@param sourceStruct source structure holding the field, must not be null\n@param valueName name of value to be provided, must not be null\n@return integer value for the named parameter");
+ this.specialMethods
+ .println("public abstract int getNamedValue(Object sourceStruct, String valueName);");
}
if ((detected & FLAG_DETECTED_VAR_FIELDS) != 0) {
if (!this.specialMethods.isEmpty()) {
this.specialMethods.println();
}
- this.specialMethods.printJavaDocLinesWithIndent("Read variable field\n@param sourceStruct source structure holding the field, must not be null\n@param inStream the input stream, must not be null\n@param byteOrder\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, -1 if not defined\n@return\n@exception IOException");
- this.specialMethods.println("public abstract JBBPAbstractField readVarField(Object sourceStruct, JBBPBitInputStream inStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue) throws IOException;");
+ this.specialMethods.printJavaDocLinesWithIndent(
+ "Read variable field\n@param sourceStruct source structure holding the field, must not be null\n@param inStream the input stream, must not be null\n@param byteOrder\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, -1 if not defined\n@return\n@exception IOException");
+ this.specialMethods.println(
+ "public abstract JBBPAbstractField readVarField(Object sourceStruct, JBBPBitInputStream inStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue) throws IOException;");
this.specialMethods.println();
- this.specialMethods.printJavaDocLinesWithIndent("Read variable array field\n@param sourceStruct source structure holding the field, must not be null\n@param inStream the input stream, must not be null\n@param byteOrder byte order to be used for reading, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, -1 if not defined\n@param readWholeStream if true then whole stream should be read\n@param arraySize size of array to read (if whole stream flag is false)\n@return array object contains read data, must not be null\n@exception IOException if error during data reading");
- this.specialMethods.println("public abstract JBBPAbstractArrayField extends JBBPAbstractField> readVarArray(Object sourceStruct, JBBPBitInputStream inStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean readWholeStream, int arraySize) throws IOException;");
+ this.specialMethods.printJavaDocLinesWithIndent(
+ "Read variable array field\n@param sourceStruct source structure holding the field, must not be null\n@param inStream the input stream, must not be null\n@param byteOrder byte order to be used for reading, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, -1 if not defined\n@param readWholeStream if true then whole stream should be read\n@param arraySize size of array to read (if whole stream flag is false)\n@return array object contains read data, must not be null\n@exception IOException if error during data reading");
+ this.specialMethods.println(
+ "public abstract JBBPAbstractArrayField extends JBBPAbstractField> readVarArray(Object sourceStruct, JBBPBitInputStream inStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, boolean readWholeStream, int arraySize) throws IOException;");
this.specialMethods.println();
- this.specialMethods.printJavaDocLinesWithIndent("Read variable field\n@param sourceStruct source structure holding the field, must not be null\n@param value field value, must not be null\n@param outStream the output stream, must not be null,\n@param byteOrder byte order to be used for reading, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, -1 if not defined\n@exception IOException it is thrown if any transport error during operation");
- this.specialMethods.println("public abstract void writeVarField(Object sourceStruct, JBBPAbstractField value, JBBPBitOutputStream outStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue) throws IOException;");
+ this.specialMethods.printJavaDocLinesWithIndent(
+ "Read variable field\n@param sourceStruct source structure holding the field, must not be null\n@param value field value, must not be null\n@param outStream the output stream, must not be null,\n@param byteOrder byte order to be used for reading, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, -1 if not defined\n@exception IOException it is thrown if any transport error during operation");
+ this.specialMethods.println(
+ "public abstract void writeVarField(Object sourceStruct, JBBPAbstractField value, JBBPBitOutputStream outStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue) throws IOException;");
this.specialMethods.println();
- this.specialMethods.printJavaDocLinesWithIndent("Write variable array\n@param sourceStruct source structure holding the field, must not be null\n@param array array value to be written, must not be null\n@param outStream the output stream, must not be null\n@param byteOrder byte order to be used for reading, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, -1 if not defined\n@param arraySizeToWrite\n@exception IOException it is thrown if any transport error during operation");
- this.specialMethods.println("public abstract void writeVarArray(Object sourceStruct, JBBPAbstractArrayField extends JBBPAbstractField> array, JBBPBitOutputStream outStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, int arraySizeToWrite) throws IOException;");
+ this.specialMethods.printJavaDocLinesWithIndent(
+ "Write variable array\n@param sourceStruct source structure holding the field, must not be null\n@param array array value to be written, must not be null\n@param outStream the output stream, must not be null\n@param byteOrder byte order to be used for reading, must not be null\n@param nullableNamedFieldInfo info abut field name, it can be null\n@param extraValue value from extra field part, -1 if not defined\n@param arraySizeToWrite\n@exception IOException it is thrown if any transport error during operation");
+ this.specialMethods.println(
+ "public abstract void writeVarArray(Object sourceStruct, JBBPAbstractArrayField extends JBBPAbstractField> array, JBBPBitOutputStream outStream, JBBPByteOrder byteOrder, JBBPNamedFieldInfo nullableNamedFieldInfo, int extraValue, int arraySizeToWrite) throws IOException;");
}
if ((detected & FLAG_ADD_ASSERT_NOT_NEGATIVE_EXPR) != 0) {
if (!this.specialMethods.isEmpty()) {
this.specialMethods.println();
}
- this.specialMethods.println("private static int assrtExprNotNeg(final int value) { if (value<0) throw new IllegalArgumentException(\"Negative value in expression\"); return value; }");
+ this.specialMethods.println(
+ "private static int assrtExprNotNeg(final int value) { if (value<0) throw new IllegalArgumentException(\"Negative value in expression\"); return value; }");
}
final String specialMethodsText = this.specialMethods.toString();
- final boolean hasAbstractMethods = (this.flagSet.get() & (FLAG_DETECTED_CUSTOM_FIELDS | FLAG_DETECTED_VAR_FIELDS | FLAG_DETECTED_EXTERNAL_FIELDS)) != 0 || this.builder.doMainClassAbstract;
+ final boolean hasAbstractMethods = (this.flagSet.get() &
+ (FLAG_DETECTED_CUSTOM_FIELDS | FLAG_DETECTED_VAR_FIELDS | FLAG_DETECTED_EXTERNAL_FIELDS)) !=
+ 0 || this.builder.doMainClassAbstract;
- buffer.printJavaDocLinesWithIndent("Generated from JBBP script by internal JBBP Class Source Generator");
+ buffer.printJavaDocLinesWithIndent(
+ "Generated from JBBP script by internal JBBP Class Source Generator");
final Struct rootStruct = this.structStack.get(0);
if (this.builder.addNewInstanceMethods) {
- rootStruct.misc.println(String.format("public Object %s(Class> aClass) {", JBBPMapper.MAKE_CLASS_INSTANCE_METHOD_NAME));
+ rootStruct.misc.println(String.format("public Object %s(Class> aClass) {",
+ JBBPMapper.MAKE_CLASS_INSTANCE_METHOD_NAME));
rootStruct.misc.incIndent();
for (final Struct c : rootStruct.children) {
@@ -356,7 +328,7 @@ public void visitEnd() {
this.builder.mapSubClassesInterfaces,
this.builder.mapSubClassesSuperclasses,
this.specialSection.toString(),
- specialMethodsText.length() == 0 ? null : specialMethodsText,
+ specialMethodsText.isEmpty() ? null : specialMethodsText,
this.builder.mainClassCustomText,
true
);
@@ -365,12 +337,22 @@ public void visitEnd() {
}
@Override
- public void visitStructureStart(final int offsetInCompiledBlock, final JBBPByteOrder byteOrder, final JBBPNamedFieldInfo nullableNameFieldInfo, final JBBPIntegerValueEvaluator nullableArraySize) {
- final String structName = (nullableNameFieldInfo == null ? makeAnonymousStructName() : prepFldName(nullableNameFieldInfo.getFieldName())).toLowerCase(Locale.ENGLISH);
+ public void visitStructureStart(final int offsetInCompiledBlock,
+ final JBBPByteOrder byteOrder,
+ final boolean readWholeStream,
+ final JBBPNamedFieldInfo nullableNameFieldInfo,
+ final JBBPIntegerValueEvaluator nullableArraySize) {
+ final String structName = (nullableNameFieldInfo == null ? makeAnonymousStructName() :
+ prepFldName(nullableNameFieldInfo.getFieldName())).toLowerCase(Locale.ENGLISH);
final String structBaseTypeName = structName.toUpperCase(Locale.ENGLISH);
- final String arraySizeIn = nullableArraySize == null ? null : evaluatorToString(NAME_INPUT_STREAM, offsetInCompiledBlock, nullableArraySize, this.flagSet, true);
- final String arraySizeOut = nullableArraySize == null ? null : evaluatorToString(NAME_OUTPUT_STREAM, offsetInCompiledBlock, nullableArraySize, this.flagSet, true);
- final Struct newStruct = new Struct(this.getCurrentStruct(), structBaseTypeName, "public" + (builder.internalClassesNotStatic ? "" : " static"));
+ final String arraySizeIn = nullableArraySize == null ? null :
+ evaluatorToString(NAME_INPUT_STREAM, offsetInCompiledBlock, nullableArraySize, this.flagSet,
+ true);
+ final String arraySizeOut = nullableArraySize == null ? null :
+ evaluatorToString(NAME_OUTPUT_STREAM, offsetInCompiledBlock, nullableArraySize,
+ this.flagSet, true);
+ final Struct newStruct = new Struct(this.getCurrentStruct(), structBaseTypeName,
+ "public" + (builder.internalClassesNotStatic ? "" : " static"));
final String fieldModifier = makeModifier(nullableNameFieldInfo);
@@ -388,43 +370,60 @@ public void visitStructureStart(final int offsetInCompiledBlock, final JBBPByteO
if (nullableArraySize == null) {
structType = structBaseTypeName;
if (this.builder.generateFields) {
- printField(nullableNameFieldInfo, byteOrder, false, offsetInCompiledBlock, getCurrentStruct().getFields().indent(), null, fieldModifier, structType, structName);
+ printField(nullableNameFieldInfo, byteOrder, false, offsetInCompiledBlock,
+ getCurrentStruct().getFields().indent(), null, fieldModifier, structType, structName);
}
processSkipRemainingFlag();
processSkipRemainingFlagForWriting("this." + structName);
this.getCurrentStruct().getReadFunc().indent()
- .printf("if ( this.%1$s == null) { this.%1$s = new %2$s(%3$s);}", structName, structType, pathToRootObject)
- .printf(" %s.read(%s);%n", toType.length() == 0 ? "this." + structName : '(' + toType + "this." + structName + ')', NAME_INPUT_STREAM);
- this.getCurrentStruct().getWriteFunc().indent().print(toType.length() == 0 ? structName : '(' + toType + structName + ')').println(".write(Out);");
+ .printf("if ( this.%1$s == null) { this.%1$s = new %2$s(%3$s);}", structName, structType,
+ pathToRootObject)
+ .printf(" %s.read(%s);%n", toType.isEmpty() ? "this." + structName :
+ '(' + toType + "this." + structName + ')', NAME_INPUT_STREAM);
+ this.getCurrentStruct().getWriteFunc().indent()
+ .print(toType.isEmpty() ? structName : '(' + toType + structName + ')')
+ .println(".write(Out);");
} else {
structType = structBaseTypeName + " []";
if (this.builder.generateFields) {
- printField(nullableNameFieldInfo, byteOrder, true, offsetInCompiledBlock, getCurrentStruct().getFields().indent(), null, fieldModifier, structType, structName);
+ printField(nullableNameFieldInfo, byteOrder, true, offsetInCompiledBlock,
+ getCurrentStruct().getFields().indent(), null, fieldModifier, structType, structName);
}
processSkipRemainingFlag();
processSkipRemainingFlagForWriting("this." + structName);
- if ("-1".equals(arraySizeIn)) {
+ if (readWholeStream) {
this.getCurrentStruct().getReadFunc().indent()
- .printf("List<%3$s> __%1$s_tmplst__ = new ArrayList<%3$s>(); while (%5$s.hasAvailableData()){ __%1$s_tmplst__.add(new %3$s(%4$s).read(%5$s));} this.%1$s = __%1$s_tmplst__.toArray(new %3$s[__%1$s_tmplst__.size()]);__%1$s_tmplst__ = null;%n",
+ .printf(
+ "List<%3$s> __%1$s_tmplst__ = new ArrayList<%3$s>(); while (%5$s.hasAvailableData()){ __%1$s_tmplst__.add(new %3$s(%4$s).read(%5$s));} this.%1$s = __%1$s_tmplst__.toArray(new %3$s[__%1$s_tmplst__.size()]);__%1$s_tmplst__ = null;%n",
structName,
arraySizeIn,
structBaseTypeName,
pathToRootObject,
NAME_INPUT_STREAM);
- this.getCurrentStruct().getWriteFunc().indent().printf("for (int I=0;I mapClassName
* @return the builder instance, must not be null
* @since 1.4.0
*/
- public Builder setMapSubClassesSuperclasses(final Map mapClassNameToSuperclasses) {
+ public Builder setMapSubClassesSuperclasses(
+ final Map mapClassNameToSuperclasses) {
assertNonLocked();
this.mapSubClassesSuperclasses.clear();
if (mapClassNameToSuperclasses != null) {
@@ -1529,7 +1689,7 @@ public Builder setHeadComment(final String text) {
/**
* Disable generate fields, useful if some super class extended and its
* fields should be used instead of generated ones. If disable then all code
- * will be generated but without class fields. By default field generate is
+ * will be generated but without class fields. By default, field generate is
* enabled.
*
* @return the builder instance, must not be null
@@ -1541,7 +1701,7 @@ public Builder disableGenerateFields() {
}
/**
- * Build converter with provided parameters. NB! It locks builder parameters
+ * Build converter with provided parameters. NB! It locks builder parameters,
* and they can't be changed in future.
*
* @return a converter instance.
@@ -1569,7 +1729,8 @@ private static class Struct {
private final String path;
private Struct(final Struct parent, final String className, final String classModifiers) {
- this.path = parent == null ? "" : parent.path + (parent.path.length() == 0 ? "" : ".") + className.toLowerCase(Locale.ENGLISH);
+ this.path = parent == null ? "" : parent.path + (parent.path.isEmpty() ? "" : ".") +
+ className.toLowerCase(Locale.ENGLISH);
this.classModifiers = classModifiers;
this.className = className;
this.parent = parent;
@@ -1615,7 +1776,8 @@ void write(
final String specialMethods,
final String customText,
final boolean useSuperclassForReadWrite) {
- final String interfaceForGetSet = mapStructInterfaces == null ? null : mapStructInterfaces.get(this.getPath());
+ final String interfaceForGetSet =
+ mapStructInterfaces == null ? null : mapStructInterfaces.get(this.getPath());
buffer.indent().printf(
"%s%sclass %s%s%s {%n",
@@ -1623,7 +1785,10 @@ void write(
extraModifier == null ? " " : ' ' + extraModifier + ' ',
this.className,
superClass != null ? " extends " + superClass + ' ' : "",
- interfaceForGetSet == null ? implementedInterfaces != null && !implementedInterfaces.isEmpty() ? " implements " + interfaces2str(implementedInterfaces) + ' ' : "" : " implements " + interfaceForGetSet
+ interfaceForGetSet == null ?
+ implementedInterfaces != null && !implementedInterfaces.isEmpty() ?
+ " implements " + interfaces2str(implementedInterfaces) + ' ' : "" :
+ " implements " + interfaceForGetSet
);
buffer.incIndent();
@@ -1632,13 +1797,15 @@ void write(
}
for (final Struct c : this.children) {
- c.write(buffer, null, mapStructSuperclasses.get(c.getPath()), null, mapStructInterfaces, mapStructSuperclasses, null, null, null, false);
+ c.write(buffer, null, mapStructSuperclasses.get(c.getPath()), null, mapStructInterfaces,
+ mapStructSuperclasses, null, null, null, false);
}
buffer.println();
buffer.printLinesWithIndent(this.fields.toString());
if (this.parent != null) {
- buffer.indent().println("private final " + findRoot().className + ' ' + NAME_ROOT_STRUCT + ';');
+ buffer.indent()
+ .println("private final " + findRoot().className + ' ' + NAME_ROOT_STRUCT + ';');
}
buffer.println();
@@ -1656,7 +1823,8 @@ void write(
buffer.println();
- buffer.indent().printf("public %s read(final JBBPBitInputStream In) throws IOException {%n", useSuperclassForReadWrite && superClass != null ? superClass : this.className);
+ buffer.indent().printf("public %s read(final JBBPBitInputStream In) throws IOException {%n",
+ useSuperclassForReadWrite && superClass != null ? superClass : this.className);
buffer.incIndent();
buffer.printLinesWithIndent(this.readFunc.toString());
buffer.indent().println("return this;");
@@ -1665,7 +1833,9 @@ void write(
buffer.println();
- buffer.indent().printf("public %s write(final JBBPBitOutputStream Out) throws IOException {%n", useSuperclassForReadWrite && superClass != null ? superClass : this.className);
+ buffer.indent()
+ .printf("public %s write(final JBBPBitOutputStream Out) throws IOException {%n",
+ useSuperclassForReadWrite && superClass != null ? superClass : this.className);
buffer.incIndent();
buffer.printLinesWithIndent(this.writeFunc.toString());
buffer.indent().println("return this;");
@@ -1690,7 +1860,7 @@ void write(
buffer.println();
}
- if (customText != null && customText.length() != 0) {
+ if (customText != null && !customText.isEmpty()) {
buffer.printCommentLinesWithIndent("------ Custom section START");
buffer.printLinesWithIndent(customText);
buffer.printCommentLinesWithIndent("------ Custom section END");
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPFieldTypeParameterContainer.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPFieldTypeParameterContainer.java
index d74ebb38..ac9b0c1a 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPFieldTypeParameterContainer.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPFieldTypeParameterContainer.java
@@ -20,7 +20,7 @@
import com.igormaznitsa.jbbp.model.JBBPFieldDouble;
import com.igormaznitsa.jbbp.model.JBBPFieldFloat;
import com.igormaznitsa.jbbp.model.JBBPFieldString;
-
+import com.igormaznitsa.jbbp.model.JBBPFieldUInt;
import java.io.Serializable;
/**
@@ -52,7 +52,8 @@ public final class JBBPFieldTypeParameterContainer implements Serializable {
* @param typeName the type of the field, can be null
* @param extraData the extra data placed after ':' char, can be null
*/
- public JBBPFieldTypeParameterContainer(final JBBPByteOrder byteOrder, final String typeName, final String extraData) {
+ public JBBPFieldTypeParameterContainer(final JBBPByteOrder byteOrder, final String typeName,
+ final String extraData) {
this.byteOrder = byteOrder;
this.typeName = typeName;
this.extraData = extraData;
@@ -108,16 +109,21 @@ public boolean hasExpressionAsExtraData() {
}
/**
- * Check that the type is a special one ('floatj', 'doublej', 'stringj' or 'value').
+ * Check that the type is a special one ('floatj', 'doublej', 'stringj', 'uint' or 'value').
*
* @return true if the type is a special one
* @see JBBPFieldFloat#TYPE_NAME
* @see JBBPFieldDouble#TYPE_NAME
* @see JBBPFieldString#TYPE_NAME
+ * @see JBBPFieldUInt#TYPE_NAME
* @since 1.4.0
*/
public boolean isSpecialField() {
- return this.typeName.equals(JBBPFieldFloat.TYPE_NAME) || this.typeName.equals(JBBPFieldDouble.TYPE_NAME) || this.typeName.equals(JBBPFieldString.TYPE_NAME) || this.typeName.equals("val");
+ return this.typeName.equals(JBBPFieldFloat.TYPE_NAME)
+ || this.typeName.equals(JBBPFieldDouble.TYPE_NAME)
+ || this.typeName.equals(JBBPFieldString.TYPE_NAME)
+ || this.typeName.equals(JBBPFieldUInt.TYPE_NAME)
+ || this.typeName.equals("val");
}
@Override
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPToken.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPToken.java
index 60b61ba3..7f248fb7 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPToken.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPToken.java
@@ -17,7 +17,6 @@
package com.igormaznitsa.jbbp.compiler.tokenizer;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
-
import java.io.Serializable;
/**
@@ -59,7 +58,9 @@ public final class JBBPToken implements Serializable {
* @param arrayLength the string value of array size, it can be null
* @param fieldName the field name, it can be null
*/
- JBBPToken(final JBBPTokenType type, final int position, final JBBPFieldTypeParameterContainer fieldTypeParameters, final String arrayLength, final String fieldName) {
+ JBBPToken(final JBBPTokenType type, final int position,
+ final JBBPFieldTypeParameterContainer fieldTypeParameters, final String arrayLength,
+ final String fieldName) {
JBBPUtils.assertNotNull(type, "Type must not be null");
this.type = type;
this.position = position;
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPTokenizer.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPTokenizer.java
index 126f9944..caefbbd0 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPTokenizer.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/tokenizer/JBBPTokenizer.java
@@ -22,8 +22,8 @@
import com.igormaznitsa.jbbp.model.JBBPFieldDouble;
import com.igormaznitsa.jbbp.model.JBBPFieldFloat;
import com.igormaznitsa.jbbp.model.JBBPFieldString;
+import com.igormaznitsa.jbbp.model.JBBPFieldUInt;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
-
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
@@ -44,11 +44,14 @@ public final class JBBPTokenizer implements Iterable, IteratorWARNING! DO NOT UNESCAPE '}' AND '{' CHARS BECAUSE IT MAKES INCOMPATIBILITY WITH ANDROID!
*/
- private static final Pattern PATTERN = Pattern.compile("\\s*//.*$|\\s*(\\})|\\s*([^\\s;\\[\\]\\}\\{]+)?\\s*(?:\\[\\s*([^\\[\\]\\{\\};]+)\\s*\\])?\\s*([^\\d\\s;\\[\\]\\}\\{/][^\\s;\\[\\]\\}\\{/]*)?\\s*([\\{;])", Pattern.MULTILINE);
+ private static final Pattern PATTERN = Pattern.compile(
+ "\\s*//.*$|\\s*(\\})|\\s*([^\\s;\\[\\]\\}\\{]+)?\\s*(?:\\[\\s*([^\\[\\]\\{\\};]+)\\s*\\])?\\s*([^\\d\\s;\\[\\]\\}\\{/][^\\s;\\[\\]\\}\\{/]*)?\\s*([\\{;])",
+ Pattern.MULTILINE);
/**
* The Pattern to break field type to parameters.
*/
- private static final Pattern FIELD_TYPE_BREAK_PATTERN = Pattern.compile("^([<>])?([\\w][\\w$]*)(?::((?:[-]?\\d+)|(?:\\(.+\\))))?$");
+ private static final Pattern FIELD_TYPE_BREAK_PATTERN =
+ Pattern.compile("^([<>])?([\\w][\\w$]*)(?::((?:[-]?\\d+)|(?:\\(.+\\))))?$");
/**
* Inside table to keep disabled names for fields.
*/
@@ -59,6 +62,7 @@ public final class JBBPTokenizer implements Iterable, Iterator".equals(groupTypeByteOrder)) {
+ byteOrder = JBBPByteOrder.BIG_ENDIAN;
+ } else if ("<".equals(groupTypeByteOrder)) {
+ byteOrder = JBBPByteOrder.LITTLE_ENDIAN;
+ } else {
+ throw new Error(
+ "Illegal byte order char, unexpected error, contact developer please ["
+ + fieldType + ']');
+ }
+ } else {
+ byteOrder = JBBPByteOrder.BIG_ENDIAN;
+ }
+ return byteOrder;
+ }
+
/**
* Inside method to read the next token from the string and place it into
* inside storage.
@@ -145,9 +168,13 @@ private void readNextItem() {
final String groupName = this.matcher.group(4);
final String groupEnder = this.matcher.group(5);
- final String skipString = this.processingString.substring(Math.max(this.lastCharSubstringFound, 0), matcher.start()).trim();
- if (skipString.length() != 0 && !skipString.startsWith("//")) {
- this.detectedException = new JBBPTokenizerException(skipString, Math.max(this.lastCharSubstringFound, 0));
+ final String skipString =
+ this.processingString.substring(Math.max(this.lastCharSubstringFound, 0), matcher.start())
+ .trim();
+ if (!skipString.isEmpty() && !skipString.startsWith("//")) {
+ this.detectedException =
+ new JBBPTokenizerException(skipString, this.processingString,
+ Math.max(this.lastCharSubstringFound, 0));
} else {
JBBPTokenType type = JBBPTokenType.ATOM;
@@ -157,15 +184,22 @@ private void readNextItem() {
// {
type = JBBPTokenType.STRUCT_START;
if (groupName != null) {
- final int position = matcher.start() + groupWholeFound.length() - groupWholeFoundTrimmed.length();
- this.detectedException = new JBBPTokenizerException("Wrong structure format, it must have only name (and may be array definition)", position);
+ final int position =
+ matcher.start() + groupWholeFound.length() - groupWholeFoundTrimmed.length();
+ this.detectedException = new JBBPTokenizerException(
+ "Wrong structure format, it must have only name (and may be array definition)",
+ this.processingString,
+ position);
return;
}
} else if (groupCloseStruct != null) {
type = JBBPTokenType.STRUCT_END;
} else if (groupTypeOrName == null) {
- final int position = matcher.start() + groupWholeFound.length() - groupWholeFoundTrimmed.length();
- this.detectedException = new JBBPTokenizerException("Detected atomic field definition without type", position);
+ final int position =
+ matcher.start() + groupWholeFound.length() - groupWholeFoundTrimmed.length();
+ this.detectedException =
+ new JBBPTokenizerException("Detected atomic field definition without type",
+ this.processingString, position);
return;
}
@@ -206,24 +240,17 @@ private void readNextItem() {
wrongFormat = false;
- JBBPByteOrder byteOrder;
- if (groupTypeByteOrder != null) {
- if (">".equals(groupTypeByteOrder)) {
- byteOrder = JBBPByteOrder.BIG_ENDIAN;
- } else if ("<".equals(groupTypeByteOrder)) {
- byteOrder = JBBPByteOrder.LITTLE_ENDIAN;
- } else {
- throw new Error("Illegal byte order char, unexpected error, contact developer please [" + fieldType + ']');
- }
- } else {
- byteOrder = JBBPByteOrder.BIG_ENDIAN;
- }
-
- parsedType = new JBBPFieldTypeParameterContainer(byteOrder, groupTypeName, groupTypeExtraField);
+ JBBPByteOrder byteOrder = getJbbpByteOrder(groupTypeByteOrder, fieldType);
+
+ parsedType =
+ new JBBPFieldTypeParameterContainer(byteOrder, groupTypeName, groupTypeExtraField);
}
if (wrongFormat) {
- this.detectedException = new JBBPTokenizerException("Wrong format of type definition [" + fieldType + ']', position);
+ this.detectedException =
+ new JBBPTokenizerException("Wrong format of type definition [" + fieldType + ']',
+ this.processingString,
+ position);
return;
}
}
@@ -233,11 +260,15 @@ private void readNextItem() {
}
} else {
if (this.lastCharSubstringFound < 0) {
- this.detectedException = new JBBPTokenizerException("Wrong format of whole string", 0);
+ this.detectedException =
+ new JBBPTokenizerException("Wrong format of whole string", this.processingString, 0);
} else {
final String restOfString = this.processingString.substring(this.lastCharSubstringFound);
- if (restOfString.trim().length() != 0) {
- throw new JBBPTokenizerException("Can't recognize a part of script [" + restOfString + ']', this.lastCharSubstringFound);
+ if (!restOfString.trim().isEmpty()) {
+ throw new JBBPTokenizerException(
+ "Can't recognize a part of script [" + restOfString + ']',
+ this.processingString,
+ this.lastCharSubstringFound);
}
}
this.nextItem = null;
@@ -256,22 +287,25 @@ private JBBPTokenizerException checkFieldName(final String name, final int posit
if (name != null) {
final String normalized = JBBPUtils.normalizeFieldNameOrPath(name);
if (normalized.indexOf('.') >= 0) {
- return new JBBPTokenizerException("Field name must not contain '.' char", position);
+ return new JBBPTokenizerException("Field name must not contain '.' char",
+ this.processingString, position);
}
- if (normalized.length() > 0) {
+ if (!normalized.isEmpty()) {
if (normalized.equals("_")
|| normalized.equals("$$")
|| normalized.startsWith("$")
|| Character.isDigit(normalized.charAt(0))
) {
- return new JBBPTokenizerException("'" + name + "' can't be field name", position);
+ return new JBBPTokenizerException("'" + name + "' can't be field name",
+ this.processingString, position);
}
for (int i = 1; i < normalized.length(); i++) {
final char chr = normalized.charAt(i);
if (chr != '_' && !Character.isLetterOrDigit(chr)) {
- return new JBBPTokenizerException("Char '" + chr + "' not allowed in name", position);
+ return new JBBPTokenizerException("Char '" + chr + "' not allowed in name",
+ this.processingString, position);
}
}
}
@@ -279,7 +313,6 @@ private JBBPTokenizerException checkFieldName(final String name, final int posit
return null;
}
- @SuppressWarnings("NullableProblems")
@Override
public Iterator iterator() {
return this;
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPEvaluatorFactory.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPEvaluatorFactory.java
index 2d78d932..2cafd9b1 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPEvaluatorFactory.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPEvaluatorFactory.java
@@ -18,7 +18,6 @@
import com.igormaznitsa.jbbp.compiler.JBBPCompilerUtils;
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
-
import java.util.List;
/**
@@ -53,7 +52,9 @@ public static JBBPEvaluatorFactory getInstance() {
* @see JBBPExpressionEvaluator
* @see JBBPOnlyFieldEvaluator
*/
- public JBBPIntegerValueEvaluator make(final String expression, final List namedFields, final byte[] compiledScript) {
+ public JBBPIntegerValueEvaluator make(final String expression,
+ final List namedFields,
+ final byte[] compiledScript) {
final JBBPIntegerValueEvaluator result;
if (JBBPExpressionEvaluator.hasExpressionOperators(expression)) {
@@ -75,7 +76,8 @@ public JBBPIntegerValueEvaluator make(final String expression, final List>", ">>>"};
+ private static final String[] SYMBOLS =
+ new String[] {"(", "", "", "", "~", "-", "+", "+", "-", "*", "/", "%", "|", "^", "&", "<<",
+ ">>", ">>>"};
/**
* Array of first chars of operators to recognize a string as possible expression.
*/
- private static final char[] OPERATOR_FIRST_CHARS = new char[] {'(', '+', '-', '*', '/', '%', '|', '&', '^', '~', ')', '>', '<'};
+ private static final char[] OPERATOR_FIRST_CHARS =
+ new char[] {'(', '+', '-', '*', '/', '%', '|', '&', '^', '~', ')', '>', '<'};
/**
* The Pattern to parse an expression.
*/
- private static final Pattern PATTERN = Pattern.compile("([0-9]+)|([()])|(<<|>>>|>>|[%*+\\-/&|^~])|([\\S][^<>\\s+%*\\-/()&|^~]*)");
+ private static final Pattern PATTERN =
+ Pattern.compile("([0-9]+)|([()])|(<<|>>>|>>|[%*+\\-/&|^~])|([\\S][^<>\\s+%*\\-/()&|^~]*)");
/**
* The Array contains byte code of compiled expression.
*/
@@ -162,7 +167,9 @@ public final class JBBPExpressionEvaluator implements JBBPIntegerValueEvaluator
* @param compiledData the current compiled data block of JBBP parent script for the expression, must not be null
* @throws JBBPCompilationException if any problem in compilation
*/
- public JBBPExpressionEvaluator(final String expression, final List namedFields, final byte[] compiledData) {
+ public JBBPExpressionEvaluator(final String expression,
+ final List namedFields,
+ final byte[] compiledData) {
this.expressionSource = expression;
final Matcher matcher = PATTERN.matcher(expression);
@@ -185,9 +192,10 @@ public JBBPExpressionEvaluator(final String expression, final List= 0) {
// check for skipped substring
- final String substr = expression.substring(lastFound, matcher.start());
- if (substr.trim().length() != 0) {
- throw new JBBPCompilationException("Can't recognize part of expression '" + substr + "' [" + expression + ']');
+ final String subString = expression.substring(lastFound, matcher.start());
+ if (!subString.trim().isEmpty()) {
+ throw new JBBPCompilationException(
+ "Can't recognize part of expression '" + subString + "' [" + expression + ']');
}
}
@@ -215,7 +223,8 @@ public JBBPExpressionEvaluator(final String expression, final List= 0) {
- switch (unaryOperatorCode) {
- case CODE_UNARYPLUS:
- case CODE_ADD: {
- // do nothing
- }
- break;
- case CODE_UNARYMINUS:
- case CODE_MINUS: {
- parsed = -parsed;
- }
- break;
- case CODE_NOT: {
- parsed = ~parsed;
- }
- break;
- default: {
- throw new Error("Unsupported unary operator [" + SYMBOLS[unaryOperatorCode] + ']');
- }
- }
- }
+ int parsed = getParsed(number, unaryOperatorCode);
unaryOperatorCode = -1;
compiledScript.write(CODE_CONST);
@@ -383,14 +372,18 @@ public JBBPExpressionEvaluator(final String expression, final List 0) {
- throw new JBBPCompilationException("Unary operator without argument '" + SYMBOLS[unaryOperatorCode] + "' [" + this.expressionSource + ']');
+ throw new JBBPCompilationException(
+ "Unary operator without argument '" + SYMBOLS[unaryOperatorCode] + "' [" +
+ this.expressionSource + ']');
}
if (counterOperators == 0) {
@@ -404,26 +397,56 @@ public JBBPExpressionEvaluator(final String expression, final List= 0) {
+ switch (unaryOperatorCode) {
+ case CODE_UNARYPLUS:
+ case CODE_ADD: {
+ // do nothing
+ }
+ break;
+ case CODE_UNARYMINUS:
+ case CODE_MINUS: {
+ parsed = -parsed;
+ }
+ break;
+ case CODE_NOT: {
+ parsed = ~parsed;
+ }
+ break;
+ default: {
+ throw new Error("Unsupported unary operator [" + SYMBOLS[unaryOperatorCode] + ']');
+ }
+ }
+ }
+ return parsed;
+ }
+
/**
* Encode code of an operator to code of similar unary operator.
*
* @param code a code of operator.
- * @return code of an unary similar operator if it exists, the same code otherwise
+ * @return code of a unary similar operator if it exists, the same code otherwise
*/
private static int codeToUnary(final int code) {
final int result;
@@ -514,7 +537,8 @@ public static boolean hasExpressionOperators(final String str) {
*/
private void assertUnaryOperator(final String operator) {
if (!("+".equals(operator) || "-".equals(operator) || "~".equals(operator))) {
- throw new JBBPCompilationException("Wrong unary operator '" + operator + "' [" + this.expressionSource + ']');
+ throw new JBBPCompilationException(
+ "Wrong unary operator '" + operator + "' [" + this.expressionSource + ']');
}
}
@@ -547,7 +571,8 @@ private int calculateMaxStackDepth() {
case CODE_MINUS:
case CODE_XOR: {
if (stackPosition < 2) {
- throw new JBBPEvalException("Operator '" + code2operator(code) + "' needs two operands", this);
+ throw new JBBPEvalException("Operator '" + code2operator(code) + "' needs two operands",
+ this);
}
// decrease for one position
stackPosition--;
@@ -558,7 +583,8 @@ private int calculateMaxStackDepth() {
case CODE_NOT: {
// stack not changed
if (stackPosition < 1) {
- throw new JBBPEvalException("Operator '" + code2operator(code) + "' needs operand", this);
+ throw new JBBPEvalException("Operator '" + code2operator(code) + "' needs operand",
+ this);
}
}
break;
@@ -568,7 +594,9 @@ private int calculateMaxStackDepth() {
}
if (stackPosition != 1) {
- throw new JBBPEvalException("Wrong expression [" + this.expressionSource + "] (" + stackPosition + ':' + stackMaxPosition + ')', this);
+ throw new JBBPEvalException(
+ "Wrong expression [" + this.expressionSource + "] (" + stackPosition + ':' +
+ stackMaxPosition + ')', this);
}
return stackMaxPosition;
}
@@ -594,7 +622,9 @@ public int getMaxStackDepth() {
* @throws JBBPEvalException if there is any problem during processing
*/
@Override
- public int eval(final JBBPBitInputStream inStream, final int currentCompiledBlockOffset, final JBBPCompiledBlock compiledBlockData, final JBBPNamedNumericFieldMap fieldMap) {
+ public int eval(final JBBPBitInputStream inStream, final int currentCompiledBlockOffset,
+ final JBBPCompiledBlock compiledBlockData,
+ final JBBPNamedNumericFieldMap fieldMap) {
final int[] stack = new int[this.maxStackDepth];
int stackDepth = 0;
@@ -610,12 +640,15 @@ public int eval(final JBBPBitInputStream inStream, final int currentCompiledBloc
final int value;
if (code == CODE_EXTVAR) {
- value = "$".equals(this.externalValueNames[index]) ? (int) inStream.getCounter() : fieldMap.getExternalFieldValue(this.externalValueNames[index], compiledBlockData, this);
+ value = "$".equals(this.externalValueNames[index]) ? (int) inStream.getCounter() :
+ fieldMap
+ .getExternalFieldValue(this.externalValueNames[index], compiledBlockData, this);
} else {
final JBBPNamedFieldInfo namedField = compiledBlockData.getNamedFields()[index];
final JBBPNumericField numericField = fieldMap.get(namedField);
if (numericField == null) {
- throw new java.lang.ArithmeticException("Can't find field '" + namedField.getFieldName() + "' among numeric fields");
+ throw new java.lang.ArithmeticException(
+ "Can't find field '" + namedField.getFieldName() + "' among numeric fields");
} else {
value = fieldMap.get(namedField).getAsInt();
}
@@ -703,7 +736,8 @@ public int eval(final JBBPBitInputStream inStream, final int currentCompiledBloc
}
@Override
- public void visitItems(final JBBPCompiledBlock block, final int currentCompiledBlockOffset, final ExpressionEvaluatorVisitor visitor) {
+ public void visitItems(final JBBPCompiledBlock block, final int currentCompiledBlockOffset,
+ final ExpressionEvaluatorVisitor visitor) {
visitor.visitStart();
final JBBPIntCounter counter = new JBBPIntCounter();
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPIntegerValueEvaluator.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPIntegerValueEvaluator.java
index 3cc3be25..7a697bad 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPIntegerValueEvaluator.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPIntegerValueEvaluator.java
@@ -20,7 +20,6 @@
import com.igormaznitsa.jbbp.compiler.JBBPCompiledBlock;
import com.igormaznitsa.jbbp.compiler.conversion.ExpressionEvaluatorVisitor;
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
-
import java.io.Serializable;
/**
@@ -38,7 +37,8 @@ public interface JBBPIntegerValueEvaluator extends Serializable {
* @param fieldMap a named numeric field map
* @return calculated value as integer
*/
- int eval(JBBPBitInputStream inStream, int currentCompiledBlockOffset, JBBPCompiledBlock block, JBBPNamedNumericFieldMap fieldMap);
+ int eval(JBBPBitInputStream inStream, int currentCompiledBlockOffset, JBBPCompiledBlock block,
+ JBBPNamedNumericFieldMap fieldMap);
/**
* Visit all expression items
@@ -48,5 +48,6 @@ public interface JBBPIntegerValueEvaluator extends Serializable {
* @param visitor the visitor to visit items, must not be null
* @since 1.3.0
*/
- void visitItems(JBBPCompiledBlock block, int currentCompiledBlockOffset, ExpressionEvaluatorVisitor visitor);
+ void visitItems(JBBPCompiledBlock block, int currentCompiledBlockOffset,
+ ExpressionEvaluatorVisitor visitor);
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPOnlyFieldEvaluator.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPOnlyFieldEvaluator.java
index efd3b494..519c6c22 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPOnlyFieldEvaluator.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/compiler/varlen/JBBPOnlyFieldEvaluator.java
@@ -53,13 +53,15 @@ public JBBPOnlyFieldEvaluator(final String externalFieldName, final int namedFie
}
@Override
- public int eval(final JBBPBitInputStream inStream, final int currentCompiledBlockOffset, final JBBPCompiledBlock block, final JBBPNamedNumericFieldMap fieldMap) {
+ public int eval(final JBBPBitInputStream inStream, final int currentCompiledBlockOffset,
+ final JBBPCompiledBlock block, final JBBPNamedNumericFieldMap fieldMap) {
final int result;
if (this.externalFieldName == null) {
final JBBPNamedFieldInfo namedField = block.getNamedFields()[this.namedFieldIndex];
final JBBPNumericField numericField = fieldMap.get(namedField);
if (numericField == null) {
- throw new java.lang.ArithmeticException("Can't find field '" + namedField.getFieldName() + "' among numeric fields");
+ throw new java.lang.ArithmeticException(
+ "Can't find field '" + namedField.getFieldName() + "' among numeric fields");
} else {
result = numericField.getAsInt();
}
@@ -73,11 +75,13 @@ public int eval(final JBBPBitInputStream inStream, final int currentCompiledBloc
@Override
public String toString() {
- return this.externalFieldName == null ? "NamedFieldIndex=" + this.namedFieldIndex : this.externalFieldName;
+ return this.externalFieldName == null ? "NamedFieldIndex=" + this.namedFieldIndex :
+ this.externalFieldName;
}
@Override
- public void visitItems(final JBBPCompiledBlock block, final int currentCompiledBlockOffset, final ExpressionEvaluatorVisitor visitor) {
+ public void visitItems(final JBBPCompiledBlock block, final int currentCompiledBlockOffset,
+ final ExpressionEvaluatorVisitor visitor) {
visitor.visitStart();
if (this.externalFieldName == null) {
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPEvalException.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPEvalException.java
index ce403cf0..cd287baa 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPEvalException.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPEvalException.java
@@ -48,7 +48,8 @@ public JBBPEvalException(final String message, final JBBPIntegerValueEvaluator e
* @param evaluator a cause evaluator, can be null
* @param cause a cause exception, can be null
*/
- public JBBPEvalException(final String message, final JBBPIntegerValueEvaluator evaluator, Throwable cause) {
+ public JBBPEvalException(final String message, final JBBPIntegerValueEvaluator evaluator,
+ Throwable cause) {
super(message, cause);
this.evaluator = evaluator;
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPFinderException.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPFinderException.java
index 21047a15..090af415 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPFinderException.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPFinderException.java
@@ -32,7 +32,7 @@ public class JBBPFinderException extends JBBPException {
private final String nameOrPath;
/**
- * The Field type of a field to be searched. It may contain null.
+ * The Field type of field to be searched. It may contain null.
*/
private final Class extends JBBPAbstractField> fieldType;
@@ -43,7 +43,8 @@ public class JBBPFinderException extends JBBPException {
* @param nameOrPath the name of the path for used for search process, it can be null
* @param fieldType the field type used for the search process, it can be null
*/
- public JBBPFinderException(final String message, final String nameOrPath, final Class extends JBBPAbstractField> fieldType) {
+ public JBBPFinderException(final String message, final String nameOrPath,
+ final Class extends JBBPAbstractField> fieldType) {
super(message);
this.nameOrPath = nameOrPath;
this.fieldType = fieldType;
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPMapperException.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPMapperException.java
index ab57c0dd..7de1f65a 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPMapperException.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPMapperException.java
@@ -17,7 +17,6 @@
package com.igormaznitsa.jbbp.exceptions;
import com.igormaznitsa.jbbp.model.JBBPAbstractField;
-
import java.lang.reflect.Field;
/**
@@ -51,7 +50,9 @@ public class JBBPMapperException extends JBBPException {
* @param mappingClassField the class field which mapping is wrong
* @param cause the root cause for the exception, it can be null
*/
- public JBBPMapperException(final String message, final JBBPAbstractField field, final Class> mappingClass, final Field mappingClassField, final Throwable cause) {
+ public JBBPMapperException(final String message, final JBBPAbstractField field,
+ final Class> mappingClass, final Field mappingClassField,
+ final Throwable cause) {
super(message, cause);
this.field = field;
this.mappingClassField = mappingClassField;
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPNumericFieldValueConversionException.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPNumericFieldValueConversionException.java
new file mode 100644
index 00000000..0490d86d
--- /dev/null
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPNumericFieldValueConversionException.java
@@ -0,0 +1,67 @@
+package com.igormaznitsa.jbbp.exceptions;
+
+import com.igormaznitsa.jbbp.model.JBBPNumericField;
+
+/**
+ * Exception to indicate error during value conversion process.
+ *
+ * @since 2.0.4
+ */
+public class JBBPNumericFieldValueConversionException extends JBBPException {
+
+ private final JBBPNumericField source;
+
+ /**
+ * Get source field.
+ *
+ * @return source field for exception, can be null
+ */
+ public JBBPNumericField getSource() {
+ return this.source;
+ }
+
+ /**
+ * Constructor to provide source field and message.
+ *
+ * @param source source field. can be null
+ * @param message message, can be null
+ */
+ public JBBPNumericFieldValueConversionException(final JBBPNumericField source,
+ final String message) {
+ this(source, message, null);
+ }
+
+ /**
+ * Constructor to provide source field, message and cause error.
+ *
+ * @param source source field. can be null
+ * @param message message, can be null
+ * @param cause cause error, can be null
+ */
+ public JBBPNumericFieldValueConversionException(final JBBPNumericField source,
+ final String message, final Throwable cause) {
+ super(message, cause);
+ this.source = source;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder result = new StringBuilder(getClass().getName());
+ final String message = this.getLocalizedMessage();
+ final JBBPNumericField source = this.getSource();
+
+ result.append('(');
+ result
+ .append("message=").append(message).append(',')
+ .append("source=").append(source);
+
+ final Throwable cause = this.getCause();
+ if (cause != null) {
+ result.append(",cause=").append(cause.getClass().getName());
+ }
+
+ result.append(')');
+
+ return result.toString();
+ }
+}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPReachedArraySizeLimitException.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPReachedArraySizeLimitException.java
new file mode 100644
index 00000000..b4c0ecfd
--- /dev/null
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPReachedArraySizeLimitException.java
@@ -0,0 +1,38 @@
+package com.igormaznitsa.jbbp.exceptions;
+
+/**
+ * Exception thrown if reached limit of items for whole stream array.
+ *
+ * @since 2.1.0
+ */
+public class JBBPReachedArraySizeLimitException extends JBBPIOException {
+
+ private final int readSize;
+ private final int limitSize;
+
+ public JBBPReachedArraySizeLimitException(
+ final String message,
+ final int readSize,
+ final int limitSize
+ ) {
+ super(message);
+ this.readSize = readSize;
+ this.limitSize = limitSize;
+ }
+
+ public int getReadSize() {
+ return this.readSize;
+ }
+
+ public int getLimitSize() {
+ return this.limitSize;
+ }
+
+ @Override
+ public String toString() {
+ return JBBPReachedArraySizeLimitException.class.getSimpleName() + '{' +
+ "readSize=" + this.readSize +
+ ", limitSize=" + this.limitSize +
+ '}';
+ }
+}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPTokenizerException.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPTokenizerException.java
index 74a5c0bf..2ba1996d 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPTokenizerException.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPTokenizerException.java
@@ -17,29 +17,106 @@
package com.igormaznitsa.jbbp.exceptions;
/**
- * The Exception can be thrown during parsing sources for tokens and allows to figure out the position of the problematic token.
+ * The Exception can be thrown during parsing sources for tokens and allows to figure
+ * out the position of the problematic token.
*
* @since 1.0
*/
public class JBBPTokenizerException extends JBBPCompilationException {
- private static final long serialVersionUID = -1132154077305894146L;
+ private static final long serialVersionUID = -1132154077305893246L;
/**
* The Token position.
*/
private final int position;
+ private final String errorPart;
+
/**
- * The Constructor.
+ * Constructor.
*
* @param message the exception message.
+ * @param script the script contains error, can be null
* @param pos the position of a problematic token inside sources.
+ * @since 2.0.3
*/
- public JBBPTokenizerException(final String message, final int pos) {
+ public JBBPTokenizerException(final String message, final String script, final int pos) {
super(message);
+ this.errorPart = script == null ? "" : extractErrorPartText(script, pos);
this.position = pos;
}
+ /**
+ * Auxiliary internal method to extract error part from script around specific position.
+ *
+ * @param script the error script to be processed, must not be null
+ * @param errorPosition the error position in the script
+ * @return error part of the script as string, must not be null
+ * @since 2.0.3
+ */
+ private static String extractErrorPartText(final String script, final int errorPosition) {
+ if (errorPosition >= script.length() || errorPosition < 0) {
+ return "";
+ }
+ final int maxLengthWing = 16;
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append(script.charAt(errorPosition));
+ int errorPositionAtBuffer = 0;
+ int leftPosition = errorPosition - 1;
+ int rightPosition = errorPosition + 1;
+ int leftNonSpaceCounter = 0;
+ int rightNonSpaceCounter = 0;
+ for (int i = 0; i < maxLengthWing; i++) {
+ if (leftPosition >= 0) {
+ final char chr = script.charAt(leftPosition);
+ if (Character.isISOControl(chr)
+ || (i > 2 && leftNonSpaceCounter > 0 && Character.isSpaceChar(chr))) {
+ leftPosition = -1;
+ } else {
+ buffer.insert(0, chr);
+ leftNonSpaceCounter += Character.isSpaceChar(chr) ? 1 : 0;
+ errorPositionAtBuffer++;
+ leftPosition--;
+ }
+ }
+ if (rightPosition >= 0 && rightPosition < script.length()) {
+ final char chr = script.charAt(rightPosition);
+ if (Character.isISOControl(chr)
+ || (i > 2 && rightNonSpaceCounter > 0 && Character.isSpaceChar(chr))) {
+ rightPosition = -1;
+ } else {
+ buffer.append(chr);
+ rightNonSpaceCounter += Character.isSpaceChar(chr) ? 1 : 0;
+ rightPosition++;
+ }
+ }
+ }
+ final String errorMarkerLeft = " ->";
+ final String errorMarkerRight = "<- ";
+ buffer.insert(errorPositionAtBuffer + 1, errorMarkerRight);
+ buffer.insert(errorPositionAtBuffer, errorMarkerLeft);
+ errorPositionAtBuffer += errorMarkerLeft.length();
+
+ if (Character.isISOControl(buffer.charAt(errorPositionAtBuffer))) {
+ String hex = Integer.toHexString(buffer.charAt(errorPositionAtBuffer));
+ hex = "\\u" + "0000".substring(hex.length()) + hex;
+
+ buffer.delete(errorPositionAtBuffer, errorPositionAtBuffer + 1);
+ buffer.insert(errorPositionAtBuffer, hex);
+ }
+ return buffer.toString().trim();
+ }
+
+ /**
+ * Get error part of script where error position marked by !>..<!
+ *
+ * @return error part of the script in position, or empty if it was impossible to extract the part
+ * @since 2.0.3
+ */
+ public String getErrorPart() {
+ return this.errorPart;
+ }
+
/**
* get the position in sources of the problematic token.
*
@@ -48,4 +125,10 @@ public JBBPTokenizerException(final String message, final int pos) {
public int getPosition() {
return this.position;
}
+
+ @Override
+ public String toString() {
+ return this.getLocalizedMessage() + " (pos=" + this.position + ", errorPart=\"" +
+ this.errorPart + "\")";
+ }
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPTooManyFieldsFoundException.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPTooManyFieldsFoundException.java
index 5af394d2..0aa276e9 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPTooManyFieldsFoundException.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/exceptions/JBBPTooManyFieldsFoundException.java
@@ -39,7 +39,9 @@ public class JBBPTooManyFieldsFoundException extends JBBPFinderException {
* @param nameOrPath the name or the path used for search
* @param fieldType the field type used for search
*/
- public JBBPTooManyFieldsFoundException(final int numberOfInstances, final String message, final String nameOrPath, final Class extends JBBPAbstractField> fieldType) {
+ public JBBPTooManyFieldsFoundException(final int numberOfInstances, final String message,
+ final String nameOrPath,
+ final Class extends JBBPAbstractField> fieldType) {
super(message, nameOrPath, fieldType);
this.numberOfInstances = numberOfInstances;
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/AbstractMappedClassFieldObserver.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/AbstractMappedClassFieldObserver.java
index dd47cae7..cf0ca197 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/AbstractMappedClassFieldObserver.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/AbstractMappedClassFieldObserver.java
@@ -19,6 +19,7 @@
import com.igormaznitsa.jbbp.exceptions.JBBPException;
import com.igormaznitsa.jbbp.exceptions.JBBPIllegalArgumentException;
import com.igormaznitsa.jbbp.mapper.Bin;
+import com.igormaznitsa.jbbp.mapper.BinFieldFilter;
import com.igormaznitsa.jbbp.mapper.BinType;
import com.igormaznitsa.jbbp.mapper.JBBPMapper;
import com.igormaznitsa.jbbp.mapper.MappedFieldRecord;
@@ -26,6 +27,8 @@
import com.igormaznitsa.jbbp.model.JBBPFieldLong;
import com.igormaznitsa.jbbp.model.JBBPFieldShort;
import com.igormaznitsa.jbbp.model.JBBPFieldString;
+import com.igormaznitsa.jbbp.model.JBBPFieldUInt;
+import com.igormaznitsa.jbbp.utils.BinAnnotationWrapper;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -66,7 +69,8 @@ private static Object readFieldValue(final Object obj, final MappedFieldRecord r
*/
private static void assertFieldArray(final Field field) {
if (!field.getType().isArray()) {
- throw new IllegalArgumentException("Detected non-array field marked to be written as an array [" + field + ']');
+ throw new IllegalArgumentException(
+ "Detected non-array field marked to be written as an array [" + field + ']');
}
}
@@ -75,30 +79,87 @@ private static void assertFieldArray(final Field field) {
*
* @param obj an object which is an instance of a mapped class, must not be null
* @param field a field where the object has been found, it can be null for first call
+ * @param binAnnotationWrapper wrapper to replace Bin annotation values for processing fields, can be null to be ignored
* @param customFieldProcessor a processor for custom fields, it can be null
* @see Bin
+ * @since 2.0.2
*/
- protected void processObject(final Object obj, Field field, final Object customFieldProcessor) {
+ protected void processObject(
+ final Object obj,
+ final Field field,
+ final BinAnnotationWrapper binAnnotationWrapper,
+ final Object customFieldProcessor
+ ) {
+ this.processObject(obj, field, binAnnotationWrapper, null, customFieldProcessor);
+ }
+
+ /**
+ * Process an object. It works only with classes and fields marked by Bin annotations. It doesn't process classes and fields marked by DslBinCustom annotations.
+ *
+ * @param obj an object which is an instance of a mapped class, must not be null
+ * @param field a field where the object has been found, it can be null for first call
+ * @param binAnnotationWrapper wrapper to replace Bin annotation values for processing fields, can be null to be ignored
+ * @param binFieldFilter filter for mapped fields, allows to exclude some of them, can be null
+ * @param customFieldProcessor a processor for custom fields, it can be null
+ * @see Bin
+ * @since 2.0.4
+ */
+ protected void processObject(
+ final Object obj,
+ final Field field,
+ final BinAnnotationWrapper binAnnotationWrapper,
+ final BinFieldFilter binFieldFilter,
+ final Object customFieldProcessor
+ ) {
JBBPUtils.assertNotNull(obj, "Object must not be null");
- final List orderedFields = JBBPMapper.findAffectedFields(obj);
+ final List orderedFields = JBBPMapper.findAffectedFields(obj, binFieldFilter);
final Bin clazzAnno = obj.getClass().getAnnotation(Bin.class);
final Bin fieldAnno = field == null ? null : field.getAnnotation(Bin.class);
- this.onStructStart(obj, field, clazzAnno == null ? fieldAnno : clazzAnno);
+ final Bin binAnno = clazzAnno == null ? fieldAnno : clazzAnno;
- for (final MappedFieldRecord rec : orderedFields) {
- Bin binAnno = rec.binAnnotation;
+ if (binFieldFilter == null || binFieldFilter.isAllowed(binAnno, field)) {
+ this.onStructStart(obj, field, binAnno);
- if (binAnno.custom() && customFieldProcessor == null) {
- throw new JBBPIllegalArgumentException("Class '" + obj.getClass().getName() + "' contains field '" + rec.mappingField.getName() + "\' which is custom one, you must provide JBBPCustomFieldWriter instance to save it.");
+ for (final MappedFieldRecord rec : orderedFields) {
+ final Bin annotation = binAnnotationWrapper == null ? rec.binAnnotation :
+ binAnnotationWrapper.setWrapped(rec.binAnnotation);
+
+ if (binFieldFilter == null || binFieldFilter.isAllowed(annotation, rec.mappingField)) {
+ if (annotation.custom() && customFieldProcessor == null) {
+ throw new JBBPIllegalArgumentException(
+ "Class '" + obj.getClass().getName() + "' contains field '" +
+ rec.mappingField.getName() +
+ "' which is custom one, you must provide JBBPCustomFieldWriter instance to save it.");
+ }
+ processObjectField(obj, rec, annotation, customFieldProcessor, binFieldFilter);
+ }
}
- processObjectField(obj, rec, binAnno, customFieldProcessor);
+ this.onStructEnd(obj, field, binAnno);
}
+ }
- this.onStructEnd(obj, field, clazzAnno == null ? fieldAnno : clazzAnno);
+ /**
+ * Inside auxiliary method to process a field of an object.
+ *
+ * @param obj the object which field under processing, must not be null
+ * @param fieldRecord internal record about the field, must not be null
+ * @param annotation the annotation to be used as data source about the field,
+ * must not be null
+ * @param customFieldProcessor an object which will be provided for processing
+ * of custom fields, must not be null if object contains custom fields
+ * @since 2.0.4
+ */
+ protected void processObjectField(
+ final Object obj,
+ final MappedFieldRecord fieldRecord,
+ final Bin annotation,
+ final Object customFieldProcessor
+ ) {
+ this.processObjectField(obj, fieldRecord, annotation, customFieldProcessor, null);
}
/**
@@ -110,13 +171,25 @@ protected void processObject(final Object obj, Field field, final Object customF
* must not be null
* @param customFieldProcessor an object which will be provided for processing
* of custom fields, must not be null if object contains custom fields
+ * @param binFieldFilter filter allows to exclude some fields from process, can be null
+ * @since 2.0.4
*/
- protected void processObjectField(final Object obj, final MappedFieldRecord fieldRecord, final Bin annotation, final Object customFieldProcessor) {
+ protected void processObjectField(
+ final Object obj,
+ final MappedFieldRecord fieldRecord,
+ final Bin annotation,
+ final Object customFieldProcessor,
+ final BinFieldFilter binFieldFilter
+ ) {
final Field field = fieldRecord.mappingField;
+
if (annotation.custom()) {
- this.onFieldCustom(obj, field, annotation, customFieldProcessor, readFieldValue(obj, fieldRecord));
+ this.onFieldCustom(obj, field, annotation, customFieldProcessor,
+ readFieldValue(obj, fieldRecord));
} else {
final Class> fieldType = field.getType();
+ final BinAnnotationWrapper wrapper =
+ annotation instanceof BinAnnotationWrapper ? (BinAnnotationWrapper) annotation : null;
final BinType type;
if (annotation.type() == BinType.UNDEFINED) {
@@ -131,7 +204,8 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
case BIT: {
final JBBPBitNumber bitNumber = annotation.bitNumber();
if (fieldType == boolean.class) {
- this.onFieldBits(obj, field, annotation, bitNumber, ((Boolean) readFieldValue(obj, fieldRecord)) ? 0xFF : 0x00);
+ this.onFieldBits(obj, field, annotation, bitNumber,
+ ((Boolean) readFieldValue(obj, fieldRecord)) ? 0xFF : 0x00);
} else {
byte value = ((Number) readFieldValue(obj, fieldRecord)).byteValue();
if (reverseBits) {
@@ -145,7 +219,8 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
if (fieldType == boolean.class) {
onFieldBool(obj, field, annotation, (Boolean) readFieldValue(obj, fieldRecord));
} else {
- onFieldBool(obj, field, annotation, ((Number) readFieldValue(obj, fieldRecord)).longValue() != 0);
+ onFieldBool(obj, field, annotation,
+ ((Number) readFieldValue(obj, fieldRecord)).longValue() != 0);
}
}
break;
@@ -181,6 +256,15 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
this.onFieldInt(obj, field, annotation, value);
}
break;
+ case UINT: {
+ long value;
+ value = ((Number) readFieldValue(obj, fieldRecord)).longValue();
+ if (reverseBits) {
+ value = (int) JBBPFieldUInt.reverseBits(value);
+ }
+ this.onFieldUInt(obj, field, annotation, (int) value);
+ }
+ break;
case FLOAT: {
float value;
if (float.class == fieldType) {
@@ -189,7 +273,8 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
value = ((Number) readFieldValue(obj, fieldRecord)).floatValue();
}
if (reverseBits) {
- value = Float.intBitsToFloat((int) JBBPFieldInt.reverseBits(Float.floatToIntBits(value)));
+ value =
+ Float.intBitsToFloat((int) JBBPFieldInt.reverseBits(Float.floatToIntBits(value)));
}
this.onFieldFloat(obj, field, annotation, value);
}
@@ -227,13 +312,14 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
}
if (reverseBits) {
- value = Double.longBitsToDouble(JBBPFieldLong.reverseBits(Double.doubleToLongBits(value)));
+ value =
+ Double.longBitsToDouble(JBBPFieldLong.reverseBits(Double.doubleToLongBits(value)));
}
this.onFieldDouble(obj, field, annotation, value);
}
break;
case STRUCT: {
- processObject(readFieldValue(obj, fieldRecord), field, customFieldProcessor);
+ processObject(readFieldValue(obj, fieldRecord), field, wrapper, binFieldFilter, customFieldProcessor);
}
break;
default: {
@@ -249,7 +335,8 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
if (fieldType.getComponentType() == boolean.class) {
for (int i = 0; i < len; i++) {
- this.onFieldBits(obj, field, annotation, bitNumber, (Boolean) Array.get(array, i) ? 0xFF : 0x00);
+ this.onFieldBits(obj, field, annotation, bitNumber,
+ (Boolean) Array.get(array, i) ? 0xFF : 0x00);
}
} else {
for (int i = 0; i < len; i++) {
@@ -358,13 +445,29 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
for (int i = 0; i < len; i++) {
float value = Array.getFloat(array, i);
if (reverseBits) {
- value = Float.intBitsToFloat((int) JBBPFieldInt.reverseBits(Float.floatToIntBits(value)));
+ value = Float
+ .intBitsToFloat((int) JBBPFieldInt.reverseBits(Float.floatToIntBits(value)));
}
this.onFieldFloat(obj, field, annotation, value);
}
this.onArrayEnd(obj, field, annotation);
}
break;
+ case UINT_ARRAY: {
+ assertFieldArray(field);
+ final int len = Array.getLength(array);
+ this.onArrayStart(obj, field, annotation, len);
+ for (int i = 0; i < len; i++) {
+ long value = ((Number) Array.get(array, i)).longValue();
+ if (reverseBits) {
+ value = JBBPFieldUInt.reverseBits(value);
+ }
+ this.onFieldUInt(obj, field, annotation, (int) value);
+ }
+
+ this.onArrayEnd(obj, field, annotation);
+ }
+ break;
case INT_ARRAY: {
assertFieldArray(field);
final int len = Array.getLength(array);
@@ -416,7 +519,8 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
for (int i = 0; i < len; i++) {
double value = ((Number) Array.get(array, i)).doubleValue();
if (reverseBits) {
- value = Double.longBitsToDouble(JBBPFieldLong.reverseBits(Double.doubleToLongBits(value)));
+ value = Double
+ .longBitsToDouble(JBBPFieldLong.reverseBits(Double.doubleToLongBits(value)));
}
this.onFieldDouble(obj, field, annotation, value);
}
@@ -428,13 +532,14 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
final int len = Array.getLength(array);
this.onArrayStart(obj, field, annotation, len);
for (int i = 0; i < len; i++) {
- this.processObject(Array.get(array, i), field, customFieldProcessor);
+ this.processObject(Array.get(array, i), field, wrapper, binFieldFilter, customFieldProcessor);
}
this.onArrayEnd(obj, field, annotation);
}
break;
default: {
- throw new Error("Unexpected situation for field type, contact developer [" + type + ']');
+ throw new Error(
+ "Unexpected situation for field type, contact developer [" + type + ']');
}
}
}
@@ -452,7 +557,8 @@ protected void processObjectField(final Object obj, final MappedFieldRecord fiel
* @param customFieldProcessor processor for custom fields, must not be null
* @param value the value of the custom field
*/
- protected void onFieldCustom(final Object obj, final Field field, final Bin annotation, final Object customFieldProcessor, final Object value) {
+ protected void onFieldCustom(final Object obj, final Field field, final Bin annotation,
+ final Object customFieldProcessor, final Object value) {
}
@@ -465,7 +571,8 @@ protected void onFieldCustom(final Object obj, final Field field, final Bin anno
* @param bitNumber number of bits for the field, must not be null
* @param value the value of the field
*/
- protected void onFieldBits(final Object obj, final Field field, final Bin annotation, final JBBPBitNumber bitNumber, final int value) {
+ protected void onFieldBits(final Object obj, final Field field, final Bin annotation,
+ final JBBPBitNumber bitNumber, final int value) {
}
@@ -477,7 +584,8 @@ protected void onFieldBits(final Object obj, final Field field, final Bin annota
* @param annotation the annotation for field, must not be null
* @param value the value of the field
*/
- protected void onFieldBool(final Object obj, final Field field, final Bin annotation, final boolean value) {
+ protected void onFieldBool(final Object obj, final Field field, final Bin annotation,
+ final boolean value) {
}
@@ -490,7 +598,8 @@ protected void onFieldBool(final Object obj, final Field field, final Bin annota
* @param signed flag shows that the field id signed
* @param value the value of the field
*/
- protected void onFieldByte(final Object obj, final Field field, final Bin annotation, final boolean signed, final int value) {
+ protected void onFieldByte(final Object obj, final Field field, final Bin annotation,
+ final boolean signed, final int value) {
}
@@ -503,7 +612,8 @@ protected void onFieldByte(final Object obj, final Field field, final Bin annota
* @param signed flag shows that the field id signed
* @param value the value of the field
*/
- protected void onFieldShort(final Object obj, final Field field, final Bin annotation, final boolean signed, final int value) {
+ protected void onFieldShort(final Object obj, final Field field, final Bin annotation,
+ final boolean signed, final int value) {
}
@@ -515,7 +625,22 @@ protected void onFieldShort(final Object obj, final Field field, final Bin annot
* @param annotation the annotation for field, must not be null
* @param value the value of the field
*/
- protected void onFieldInt(final Object obj, final Field field, final Bin annotation, final int value) {
+ protected void onFieldInt(final Object obj, final Field field, final Bin annotation,
+ final int value) {
+
+ }
+
+ /**
+ * Notification about unsigned integer field.
+ *
+ * @param obj the object instance, must not be null
+ * @param field the field, must not be null
+ * @param annotation the annotation for field, must not be null
+ * @param value the value of the field
+ * @since 2.0.4
+ */
+ protected void onFieldUInt(final Object obj, final Field field, final Bin annotation,
+ final int value) {
}
@@ -528,7 +653,8 @@ protected void onFieldInt(final Object obj, final Field field, final Bin annotat
* @param value the value of the field
* @since 1.4.0
*/
- protected void onFieldFloat(final Object obj, final Field field, final Bin annotation, final float value) {
+ protected void onFieldFloat(final Object obj, final Field field, final Bin annotation,
+ final float value) {
}
@@ -541,7 +667,8 @@ protected void onFieldFloat(final Object obj, final Field field, final Bin annot
* @param value the value of the field
* @since 1.4.0
*/
- protected void onFieldString(final Object obj, final Field field, final Bin annotation, final String value) {
+ protected void onFieldString(final Object obj, final Field field, final Bin annotation,
+ final String value) {
}
@@ -554,7 +681,8 @@ protected void onFieldString(final Object obj, final Field field, final Bin anno
* @param value the value of the field
* @since 1.4.0
*/
- protected void onFieldDouble(final Object obj, final Field field, final Bin annotation, final double value) {
+ protected void onFieldDouble(final Object obj, final Field field, final Bin annotation,
+ final double value) {
}
@@ -566,7 +694,8 @@ protected void onFieldDouble(final Object obj, final Field field, final Bin anno
* @param annotation the annotation for field, must not be null
* @param value the value of the field
*/
- protected void onFieldLong(final Object obj, final Field field, final Bin annotation, final long value) {
+ protected void onFieldLong(final Object obj, final Field field, final Bin annotation,
+ final long value) {
}
@@ -600,7 +729,8 @@ protected void onStructEnd(final Object obj, final Field field, final Bin annota
* @param annotation the annotation for field, must not be null
* @param length the length of the array
*/
- protected void onArrayStart(final Object obj, final Field field, final Bin annotation, final int length) {
+ protected void onArrayStart(final Object obj, final Field field, final Bin annotation,
+ final int length) {
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPArraySizeLimiter.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPArraySizeLimiter.java
new file mode 100644
index 00000000..de7f094d
--- /dev/null
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPArraySizeLimiter.java
@@ -0,0 +1,52 @@
+package com.igormaznitsa.jbbp.io;
+
+import com.igormaznitsa.jbbp.exceptions.JBBPReachedArraySizeLimitException;
+
+/**
+ * Interface describing an object which provides limit to read array items.
+ *
+ * @since 2.1.0
+ */
+@FunctionalInterface
+public interface JBBPArraySizeLimiter {
+ /**
+ * Read arrays without limits.
+ */
+ JBBPArraySizeLimiter NO_LIMIT_FOR_ARRAY_SIZE = () -> 0;
+
+ /**
+ * Check number of read items for whole stream array and return flag if read should be stopped or throw exception if required.
+ *
+ * @param readItems number of currently read array items
+ * @param limiter limiter provides number of allowed items, must not be null
+ * @return true if read must be stopped immediately, false otherwise
+ * @throws JBBPReachedArraySizeLimitException it will be thrown if reach of limit is not allowed
+ */
+ static boolean isBreakReadWholeStream(
+ final int readItems,
+ final JBBPArraySizeLimiter limiter
+ ) {
+ final int limit = limiter.getArrayItemsLimit();
+ if (limit == 0) {
+ return false;
+ }
+ if (limit > 0) {
+ if (readItems > limit) {
+ throw new JBBPReachedArraySizeLimitException(
+ "Detected too big array during stream rest read: " + readItems, readItems,
+ Math.abs(limit));
+ } else {
+ return false;
+ }
+ } else {
+ return readItems >= Math.abs(limit);
+ }
+ }
+
+ /**
+ * Get allowed size of array to read.
+ *
+ * @return 0 means no limit, positive value means allowed number of items with exception throwing if read more items, negative value means number of read values and stop read if exceeded.
+ */
+ int getArrayItemsLimit();
+}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java
index 796a8231..2bb56cf3 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java
@@ -16,9 +16,11 @@
package com.igormaznitsa.jbbp.io;
+import static com.igormaznitsa.jbbp.io.JBBPArraySizeLimiter.isBreakReadWholeStream;
+
+import com.igormaznitsa.jbbp.exceptions.JBBPReachedArraySizeLimitException;
import com.igormaznitsa.jbbp.utils.JBBPSystemProperty;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
-
import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
@@ -36,18 +38,24 @@ public class JBBPBitInputStream extends FilterInputStream implements JBBPCountab
/**
* The Initial an Array buffer size for whole stream read.
*/
- protected static final int INITIAL_ARRAY_BUFFER_SIZE = JBBPSystemProperty.PROPERTY_INPUT_INITIAL_ARRAY_BUFFER_SIZE.getAsInteger(32);
+ protected static final int INITIAL_ARRAY_BUFFER_SIZE =
+ JBBPSystemProperty.PROPERTY_INPUT_INITIAL_ARRAY_BUFFER_SIZE.getAsInteger(32);
+ /**
+ * Allow return accumulated read data if end of stream and not full required bit field read.
+ *
+ * @since 3.0.1
+ */
+ private final boolean enablePartialBitsOnEOF;
/**
- * Flag shows that bit operations must be processed for MSB0 (most significant
- * bit 0) mode.
+ * Contains bit mode for bit operations.
*/
- private final boolean msb0;
+ private final JBBPBitOrder bitOrderMode;
/**
- * The Inside bit buffer,
+ * Internal bit buffer,
*/
private int bitBuffer;
/**
- * The Inside counter of bits in the bit buffer.
+ * Internal counter of bits in the bit buffer.
*/
private int bitsInBuffer;
/**
@@ -55,39 +63,124 @@ public class JBBPBitInputStream extends FilterInputStream implements JBBPCountab
*/
private long byteCounter;
/**
- * Inside temp variable to keep the bit buffer temporarily.
+ * Internal temp variable to keep the bit buffer temporarily.
*/
private int markedBitBuffer;
/**
- * Inside temp variable to keep the bit buffer counter temporarily.
+ * Internal temp variable to keep the bit buffer counter temporarily.
*/
private int markedBitsInBuffer;
/**
- * Inside temp variable to keep the byte counter temporarily.
+ * Internal temp variable to keep the byte counter temporarily.
*/
private long markedByteCounter;
+ /**
+ * Internal flag shows that read stopped for whole stream array read limit reach.
+ *
+ * @since 2.1.0
+ */
+ private boolean detectedArrayLimit;
/**
- * A Constructor, the LSB0 bit order will be used by default.
+ * Flag shows that during last read some bit field was not fully read.
*
- * @param in an input stream to be filtered.
+ * @see JBBPBitInputStream#isEnablePartialBitsOnEOF()
+ * @since 3.0.1
*/
- public JBBPBitInputStream(final InputStream in) {
- this(in, JBBPBitOrder.LSB0);
- }
+ private boolean detectedPartlyReadBitField;
/**
* A Constructor.
+ * By default, if missing part of bit field in the end of stream then current accumulated data will be returned.
*
* @param in an input stream to be filtered.
* @param order a bit order mode for the filter.
* @see JBBPBitOrder#LSB0
* @see JBBPBitOrder#MSB0
+ * @see JBBPBitOrder#MSB0_DIRECT
*/
public JBBPBitInputStream(final InputStream in, final JBBPBitOrder order) {
+ this(in, order, true);
+ }
+
+ /**
+ * A Constructor, the LSB0 bit order will be used by default.
+ * By default, if missing part of bit field in the end of stream then current accumulated data will be returned.
+ *
+ * @param in an input stream to be filtered.
+ */
+ public JBBPBitInputStream(final InputStream in) {
+ this(in, JBBPBitOrder.LSB0);
+ }
+
+ /**
+ * A Constructor, the LSB0 bit order will be used by default.
+ *
+ * @param in an input stream to be filtered.
+ * @param enablePartialBitsOnEOF if true then already accumulated partly read bit field data returned in case EOF, -1 otherwise.
+ * @since 3.0.1
+ */
+ public JBBPBitInputStream(final InputStream in, final boolean enablePartialBitsOnEOF) {
+ this(in, JBBPBitOrder.LSB0, enablePartialBitsOnEOF);
+ }
+
+ /**
+ * Create wrapping bit input stream.
+ *
+ * @param in the base input stream, must not be null
+ * @param order a bitness order mode for the filter.
+ * @param enablePartialBitsOnEOF if true then partly read bit data is returned in end of stream, -1 returned otherwise even if there is partly read bits data.
+ * @since 3.0.1
+ */
+ public JBBPBitInputStream(final InputStream in, final JBBPBitOrder order,
+ final boolean enablePartialBitsOnEOF) {
super(in);
this.bitsInBuffer = 0;
- this.msb0 = order == JBBPBitOrder.MSB0;
+ this.bitOrderMode = order;
+ this.enablePartialBitsOnEOF = enablePartialBitsOnEOF;
+ }
+
+ /**
+ * Shows that during last read some bit field was not fully read.
+ *
+ * @see JBBPBitInputStream#isEnablePartialBitsOnEOF()
+ * @since 3.0.1
+ */
+ public boolean isDetectedPartlyReadBitField() {
+ return this.detectedPartlyReadBitField;
+ }
+
+ /**
+ * Get flag shows behavior if end of file but presented bit data in buffer.
+ * If true then partly read bit data is returned in end of stream, -1 returned otherwise even if there is partly read bits data.
+ *
+ * @return boolean flag for the behavior, true if allowed
+ * @since 3.0.1
+ */
+ public boolean isEnablePartialBitsOnEOF() {
+ return this.enablePartialBitsOnEOF;
+ }
+
+ /**
+ * Flag shows that read of array was stopped for array limiter restrictions.
+ *
+ * @return true if array limiter restrictions detected, false otherwise
+ * @see JBBPArraySizeLimiter
+ * @since 2.1.0
+ */
+ public boolean isDetectedArrayLimit() {
+ return this.detectedArrayLimit;
+ }
+
+ /**
+ * Set value for array limit detected flag. It is important to set the flag for correct processing of parsing.
+ *
+ * @param value true or false.
+ * @see com.igormaznitsa.jbbp.JBBPParser
+ * @since 2.1.0
+ */
+ public void setDetectedArrayLimit(final boolean value) {
+ this.detectedArrayLimit = value;
}
/**
@@ -99,6 +192,24 @@ public JBBPBitInputStream(final InputStream in, final JBBPBitOrder order) {
* @throws IOException it will be thrown for transport error
*/
public boolean[] readBoolArray(final int items) throws IOException {
+ return this.readBoolArray(items, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read array of boolean values.
+ *
+ * @param items number of items to be read, if less than zero then read whole
+ * stream till the end
+ * @param arraySizeLimiter limiter provides number of allowed array items, must not be null
+ * @return read values as boolean array
+ * @throws IOException it will be thrown for transport error
+ * @throws JBBPReachedArraySizeLimitException if reached limit of read
+ * @since 2.1.0
+ */
+ public boolean[] readBoolArray(final int items,
+ final JBBPArraySizeLimiter arraySizeLimiter)
+ throws IOException {
+ this.setDetectedArrayLimit(false);
int pos = 0;
byte[] buffer;
if (items < 0) {
@@ -111,10 +222,19 @@ public boolean[] readBoolArray(final int items) throws IOException {
}
pos += read;
+ if (isBreakReadWholeStream(pos, arraySizeLimiter)) {
+ this.setDetectedArrayLimit(true);
+ final int limit = arraySizeLimiter.getArrayItemsLimit();
+ if (limit < 0) {
+ pos = Math.min(pos, Math.abs(limit));
+ }
+ break;
+ }
+
if (buffer.length == pos) {
- final byte[] newbuffer = new byte[buffer.length << 1];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
+ final byte[] newBuffer = new byte[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
}
}
} else {
@@ -138,49 +258,70 @@ public boolean[] readBoolArray(final int items) throws IOException {
return result;
}
- private byte[] _readArray(final int items, final JBBPBitNumber bitNumber) throws IOException {
- final boolean readByteArray = bitNumber == null;
+ @Override
+ public int read(final byte[] array, final int offset, final int length) throws IOException {
+ return this.read(array, offset, length, this.enablePartialBitsOnEOF);
+ }
- int pos = 0;
- if (items < 0) {
- byte[] buffer = new byte[INITIAL_ARRAY_BUFFER_SIZE];
- // till end
- while (true) {
- final int next = readByteArray ? read() : readBits(bitNumber);
- if (next < 0) {
+ /**
+ * Reads up to {@code len} bytes of data from this input stream
+ * into an array of bytes. If {@code len} is not zero, the method
+ * blocks until some input is available; otherwise, no
+ * bytes are read and {@code 0} is returned.
+ *
+ * @param array target array
+ * @param offset offset in the target array
+ * @param length the length of data portion to be read
+ * @param enablePartialBitsOnEOF if true then already accumulated partly read bit field data returned in case EOF, -1 otherwise.
+ * @return number of read bytes from the wrapped input stream
+ * @throws IOException thrown if any transport error
+ * @since 3.0.1
+ */
+ public int read(final byte[] array, final int offset, final int length,
+ final boolean enablePartialBitsOnEOF) throws IOException {
+ this.detectedPartlyReadBitField = false;
+ if (this.bitsInBuffer == 0) {
+ int readBytes = 0;
+ int tempOffset = offset;
+ int tempLength = length;
+ while (tempLength > 0) {
+ int read = this.in.read(array, tempOffset, tempLength);
+ if (read < 0) {
+ readBytes = readBytes == 0 ? read : readBytes;
break;
}
- if (buffer.length == pos) {
- final byte[] newbuffer = new byte[buffer.length << 1];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
- }
- buffer[pos++] = (byte) next;
+ tempLength -= read;
+ tempOffset += read;
+ readBytes += read;
+ this.byteCounter += read;
}
- if (buffer.length == pos) {
- return buffer;
+
+ if (this.bitOrderMode == JBBPBitOrder.MSB0) {
+ int index = offset;
+ int number = readBytes;
+ while (number > 0) {
+ array[index] = JBBPUtils.reverseBitsInByte(array[index]);
+ index++;
+ number--;
+ }
}
- final byte[] result = new byte[pos];
- System.arraycopy(buffer, 0, result, 0, pos);
- return result;
+
+ return readBytes;
} else {
- // number
- final byte[] buffer = new byte[items];
- if (readByteArray) {
- final int read = this.read(buffer, 0, items);
- if (read != items) {
- throw new EOFException("Have read only " + read + " byte(s) instead of " + items + " byte(s)");
- }
- } else {
- for (int i = 0; i < items; i++) {
- final int next = readBits(bitNumber);
- if (next < 0) {
- throw new EOFException("Have read only " + i + " bit portions instead of " + items);
- }
- buffer[i] = (byte) next;
+ int count = length;
+ int i = offset;
+ boolean partlyReadBits = false;
+ while (count > 0) {
+ final int nextByte = this.readBits(JBBPBitNumber.BITS_8, enablePartialBitsOnEOF);
+ partlyReadBits |= this.detectedPartlyReadBitField;
+ if (nextByte < 0) {
+ break;
}
+ count--;
+ array[i++] = (byte) nextByte;
}
- return buffer;
+ this.detectedPartlyReadBitField = partlyReadBits;
+ return length - count;
}
}
@@ -195,7 +336,26 @@ private byte[] _readArray(final int items, final JBBPBitNumber bitNumber) throws
* operation
*/
public byte[] readBitsArray(final int items, final JBBPBitNumber bitNumber) throws IOException {
- return _readArray(items, bitNumber);
+ return this.readBitsArray(items, bitNumber, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read array of bit sequence.
+ *
+ * @param items number of items to be read, if less than zero then read whole
+ * @param bitNumber bit number for each bit sequence item, must be 1..8
+ * stream till the end
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return array of read bit items as a byte array
+ * @throws JBBPReachedArraySizeLimitException if reached limit of read
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @since 2.1.0
+ */
+ public byte[] readBitsArray(final int items, final JBBPBitNumber bitNumber,
+ final JBBPArraySizeLimiter arraySizeLimiter)
+ throws IOException {
+ return internalReadArray(items, bitNumber, arraySizeLimiter);
}
/**
@@ -208,7 +368,23 @@ public byte[] readBitsArray(final int items, final JBBPBitNumber bitNumber) thro
* operation
*/
public byte[] readByteArray(final int items) throws IOException {
- return _readArray(items, null);
+ return this.readBitsArray(items, null, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read number of bytes for the stream.
+ *
+ * @param items number of items to be read, if less than zero then read whole
+ * stream till the end
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return read byte items as a byte array
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @since 2.1.0
+ */
+ public byte[] readByteArray(final int items, final JBBPArraySizeLimiter arraySizeLimiter)
+ throws IOException {
+ return internalReadArray(items, null, arraySizeLimiter);
}
/**
@@ -224,263 +400,440 @@ public byte[] readByteArray(final int items) throws IOException {
* @since 1.3.0
*/
public byte[] readByteArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
- final byte[] result = _readArray(items, null);
- if (byteOrder == JBBPByteOrder.LITTLE_ENDIAN) {
- JBBPUtils.reverseArray(result);
- }
- return result;
+ return this.readByteArray(items, byteOrder, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
}
/**
- * Read number of short items from the input stream.
+ * Read number of bytes for the stream. Invert their order if byte order is LITTLE_ENDIAN
*
- * @param items number of items to be read from the input stream, if less than
- * zero then all stream till the end will be read
- * @param byteOrder the order of bytes to be used to decode short values
- * @return read items as a short array
- * @throws IOException it will be thrown for any transport problem during the
- * operation
- * @see JBBPByteOrder#BIG_ENDIAN
+ * @param items number of items to be read, if less than zero then read whole
+ * stream till the end
+ * @param byteOrder desired order of bytes
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return read byte items as a byte array, if byte order is LITTLE_ENDIAN then the result array will be reversed one
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @throws JBBPReachedArraySizeLimitException if reached limit of array read
* @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.1.0
*/
- public short[] readShortArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ public byte[] readByteArray(
+ final int items,
+ final JBBPByteOrder byteOrder,
+ final JBBPArraySizeLimiter arraySizeLimiter
+ ) throws IOException {
+ final byte[] result = internalReadArray(items, null, arraySizeLimiter);
+ if (byteOrder == JBBPByteOrder.LITTLE_ENDIAN) {
+ JBBPUtils.reverseArray(result);
+ }
+ return result;
+ }
+
+ @Override
+ public void mark(final int readLimit) {
+ in.mark(readLimit);
+ this.markedBitBuffer = this.bitBuffer;
+ this.markedByteCounter = this.byteCounter;
+ this.markedBitsInBuffer = this.bitsInBuffer;
+ }
+
+ private byte[] internalReadArray(
+ final int items,
+ final JBBPBitNumber bitNumber,
+ final JBBPArraySizeLimiter streamLimiter
+ ) throws IOException {
+ this.detectedPartlyReadBitField = false;
+ final boolean readByteArray = bitNumber == null;
+ this.setDetectedArrayLimit(false);
int pos = 0;
if (items < 0) {
- short[] buffer = new short[INITIAL_ARRAY_BUFFER_SIZE];
+ byte[] buffer = new byte[INITIAL_ARRAY_BUFFER_SIZE];
// till end
- while (hasAvailableData()) {
- final int next = readUnsignedShort(byteOrder);
+ while (true) {
+ final int next =
+ readByteArray ? read() : this.readBits(bitNumber, this.enablePartialBitsOnEOF);
+ if (next < 0) {
+ break;
+ }
if (buffer.length == pos) {
- final short[] newbuffer = new short[buffer.length << 1];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
+ final byte[] newBuffer = new byte[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
+ }
+ buffer[pos++] = (byte) next;
+ if (isBreakReadWholeStream(pos, streamLimiter)) {
+ this.setDetectedArrayLimit(true);
+ break;
}
- buffer[pos++] = (short) next;
}
if (buffer.length == pos) {
return buffer;
}
- final short[] result = new short[pos];
+ final byte[] result = new byte[pos];
System.arraycopy(buffer, 0, result, 0, pos);
return result;
} else {
// number
- final short[] buffer = new short[items];
- for (int i = 0; i < items; i++) {
- buffer[i] = (short) readUnsignedShort(byteOrder);
+ final byte[] buffer = new byte[items];
+ if (readByteArray) {
+ final int read = this.read(buffer, 0, items);
+ if (read != items) {
+ throw new EOFException(
+ "Have read only " + read + " byte(s) instead of " + items + " byte(s)");
+ }
+ } else {
+ for (int i = 0; i < items; i++) {
+ final int next = this.readBits(bitNumber, this.enablePartialBitsOnEOF);
+ if (next < 0) {
+ throw new EOFException("Have read only " + i + " bit portions instead of " + items);
+ }
+ buffer[i] = (byte) next;
+ }
}
return buffer;
}
}
/**
- * Read number of unsigned short items from the input stream.
+ * Read number of short items from the input stream.
*
* @param items number of items to be read from the input stream, if less than
* zero then all stream till the end will be read
* @param byteOrder the order of bytes to be used to decode short values
- * @return read items as a char array
+ * @return read items as a short array
* @throws IOException it will be thrown for any transport problem during the
* operation
* @see JBBPByteOrder#BIG_ENDIAN
* @see JBBPByteOrder#LITTLE_ENDIAN
- * @since 1.3
*/
- public char[] readUShortArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ public short[] readShortArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ return this.readShortArray(items, byteOrder, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read number of short items from the input stream.
+ *
+ * @param items number of items to be read from the input stream, if less than
+ * zero then all stream till the end will be read
+ * @param byteOrder the order of bytes to be used to decode short values
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return read items as a short array
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @throws JBBPReachedArraySizeLimitException if reached limit of array read
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.1.0
+ */
+ public short[] readShortArray(final int items, final JBBPByteOrder byteOrder,
+ final JBBPArraySizeLimiter arraySizeLimiter)
+ throws IOException {
+ this.setDetectedArrayLimit(false);
int pos = 0;
if (items < 0) {
- char[] buffer = new char[INITIAL_ARRAY_BUFFER_SIZE];
+ short[] buffer = new short[INITIAL_ARRAY_BUFFER_SIZE];
// till end
while (hasAvailableData()) {
final int next = readUnsignedShort(byteOrder);
if (buffer.length == pos) {
- final char[] newbuffer = new char[buffer.length << 1];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
+ final short[] newBuffer = new short[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
+ }
+ buffer[pos++] = (short) next;
+ if (isBreakReadWholeStream(pos, arraySizeLimiter)) {
+ this.setDetectedArrayLimit(true);
+ break;
}
- buffer[pos++] = (char) next;
}
if (buffer.length == pos) {
return buffer;
}
- final char[] result = new char[pos];
+ final short[] result = new short[pos];
System.arraycopy(buffer, 0, result, 0, pos);
return result;
} else {
// number
- final char[] buffer = new char[items];
+ final short[] buffer = new short[items];
for (int i = 0; i < items; i++) {
- buffer[i] = (char) readUnsignedShort(byteOrder);
+ buffer[i] = (short) readUnsignedShort(byteOrder);
}
return buffer;
}
}
/**
- * Read number of integer items from the input stream.
+ * Read number of unsigned integer items from the input stream.
*
* @param items number of items to be read from the input stream, if less than
* zero then all stream till the end will be read
* @param byteOrder the order of bytes to be used to decode values
- * @return read items as an integer array
+ * @return read items as an unsigned integer array represented through long
* @throws IOException it will be thrown for any transport problem during the
* operation
* @see JBBPByteOrder#BIG_ENDIAN
* @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.0.4
*/
- public int[] readIntArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ public long[] readUIntArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ return this.readUIntArray(items, byteOrder, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read number of unsigned integer items from the input stream.
+ *
+ * @param items number of items to be read from the input stream, if less than
+ * zero then all stream till the end will be read
+ * @param byteOrder the order of bytes to be used to decode values
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return read items as an unsigned integer array represented through long
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @throws JBBPReachedArraySizeLimitException if reached limit of array read
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.1.0
+ */
+ public long[] readUIntArray(
+ final int items,
+ final JBBPByteOrder byteOrder,
+ final JBBPArraySizeLimiter arraySizeLimiter
+ ) throws IOException {
+ this.setDetectedArrayLimit(false);
int pos = 0;
if (items < 0) {
- int[] buffer = new int[INITIAL_ARRAY_BUFFER_SIZE];
+ long[] buffer = new long[INITIAL_ARRAY_BUFFER_SIZE];
// till end
while (hasAvailableData()) {
- final int next = readInt(byteOrder);
+ final long next = readUInt(byteOrder);
if (buffer.length == pos) {
- final int[] newbuffer = new int[buffer.length << 1];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
+ final long[] newBuffer = new long[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
}
buffer[pos++] = next;
+ if (isBreakReadWholeStream(pos, arraySizeLimiter)) {
+ this.setDetectedArrayLimit(true);
+ break;
+ }
}
if (buffer.length == pos) {
return buffer;
}
- final int[] result = new int[pos];
+ final long[] result = new long[pos];
System.arraycopy(buffer, 0, result, 0, pos);
return result;
} else {
// number
- final int[] buffer = new int[items];
+ final long[] buffer = new long[items];
for (int i = 0; i < items; i++) {
- buffer[i] = readInt(byteOrder);
+ buffer[i] = readUInt(byteOrder);
}
return buffer;
}
}
/**
- * Read number of float items from the input stream.
+ * Read number of unsigned short items from the input stream.
*
* @param items number of items to be read from the input stream, if less than
* zero then all stream till the end will be read
- * @param byteOrder the order of bytes to be used to decode values
- * @return read items as float array
+ * @param byteOrder the order of bytes to be used to decode short values
+ * @return read items as a char array
* @throws IOException it will be thrown for any transport problem during the
* operation
* @see JBBPByteOrder#BIG_ENDIAN
* @see JBBPByteOrder#LITTLE_ENDIAN
- * @since 1.4.0
+ * @since 1.3
*/
- public float[] readFloatArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ public char[] readUShortArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ return this.readUShortArray(items, byteOrder, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read number of unsigned short items from the input stream.
+ *
+ * @param items number of items to be read from the input stream, if less than
+ * zero then all stream till the end will be read
+ * @param byteOrder the order of bytes to be used to decode short values
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return read items as a char array
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @throws JBBPReachedArraySizeLimitException if reached limit of array read
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.1.0
+ */
+ public char[] readUShortArray(final int items, final JBBPByteOrder byteOrder,
+ final JBBPArraySizeLimiter arraySizeLimiter)
+ throws IOException {
+ this.setDetectedArrayLimit(false);
int pos = 0;
if (items < 0) {
- float[] buffer = new float[INITIAL_ARRAY_BUFFER_SIZE];
+ char[] buffer = new char[INITIAL_ARRAY_BUFFER_SIZE];
// till end
while (hasAvailableData()) {
- final float next = readFloat(byteOrder);
+ final int next = readUnsignedShort(byteOrder);
if (buffer.length == pos) {
- final float[] newbuffer = new float[buffer.length << 1];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
+ final char[] newBuffer = new char[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
+ }
+ buffer[pos++] = (char) next;
+ if (isBreakReadWholeStream(pos, arraySizeLimiter)) {
+ this.setDetectedArrayLimit(true);
+ break;
}
- buffer[pos++] = next;
}
if (buffer.length == pos) {
return buffer;
}
- final float[] result = new float[pos];
+ final char[] result = new char[pos];
System.arraycopy(buffer, 0, result, 0, pos);
return result;
} else {
// number
- final float[] buffer = new float[items];
+ final char[] buffer = new char[items];
for (int i = 0; i < items; i++) {
- buffer[i] = readFloat(byteOrder);
+ buffer[i] = (char) readUnsignedShort(byteOrder);
}
return buffer;
}
}
/**
- * Read number of long items from the input stream.
+ * Read number of integer items from the input stream.
*
* @param items number of items to be read from the input stream, if less than
* zero then all stream till the end will be read
* @param byteOrder the order of bytes to be used to decode values
- * @return read items as a long array
+ * @return read items as an integer array
* @throws IOException it will be thrown for any transport problem during the
* operation
* @see JBBPByteOrder#BIG_ENDIAN
* @see JBBPByteOrder#LITTLE_ENDIAN
*/
- public long[] readLongArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ public int[] readIntArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ return this.readIntArray(items, byteOrder, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read number of integer items from the input stream.
+ *
+ * @param items number of items to be read from the input stream, if less than
+ * zero then all stream till the end will be read
+ * @param byteOrder the order of bytes to be used to decode values
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return read items as an integer array
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @throws JBBPReachedArraySizeLimitException if reached limit of array read
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ */
+ public int[] readIntArray(final int items, final JBBPByteOrder byteOrder,
+ final JBBPArraySizeLimiter arraySizeLimiter) throws IOException {
+ this.setDetectedArrayLimit(false);
int pos = 0;
if (items < 0) {
- long[] buffer = new long[INITIAL_ARRAY_BUFFER_SIZE];
+ int[] buffer = new int[INITIAL_ARRAY_BUFFER_SIZE];
// till end
while (hasAvailableData()) {
- final long next = readLong(byteOrder);
+ final int next = readInt(byteOrder);
if (buffer.length == pos) {
- final long[] newbuffer = new long[buffer.length << 1];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
+ final int[] newBuffer = new int[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
}
buffer[pos++] = next;
+ if (isBreakReadWholeStream(pos, arraySizeLimiter)) {
+ this.setDetectedArrayLimit(true);
+ break;
+ }
}
if (buffer.length == pos) {
return buffer;
}
- final long[] result = new long[pos];
+ final int[] result = new int[pos];
System.arraycopy(buffer, 0, result, 0, pos);
return result;
} else {
// number
- final long[] buffer = new long[items];
+ final int[] buffer = new int[items];
for (int i = 0; i < items; i++) {
- buffer[i] = readLong(byteOrder);
+ buffer[i] = readInt(byteOrder);
}
return buffer;
}
}
/**
- * Read number of double items from the input stream.
+ * Read number of float items from the input stream.
*
* @param items number of items to be read from the input stream, if less than
* zero then all stream till the end will be read
* @param byteOrder the order of bytes to be used to decode values
- * @return read items as a double array
+ * @return read items as float array
* @throws IOException it will be thrown for any transport problem during the
* operation
* @see JBBPByteOrder#BIG_ENDIAN
* @see JBBPByteOrder#LITTLE_ENDIAN
* @since 1.4.0
*/
- public double[] readDoubleArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ public float[] readFloatArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ return this.readFloatArray(items, byteOrder, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read number of float items from the input stream.
+ *
+ * @param items number of items to be read from the input stream, if less than
+ * zero then all stream till the end will be read
+ * @param byteOrder the order of bytes to be used to decode values
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return read items as float array
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @throws JBBPReachedArraySizeLimitException if reached limit of array read
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.1.0
+ */
+ public float[] readFloatArray(
+ final int items,
+ final JBBPByteOrder byteOrder,
+ final JBBPArraySizeLimiter arraySizeLimiter
+ ) throws IOException {
+ this.setDetectedArrayLimit(false);
int pos = 0;
if (items < 0) {
- double[] buffer = new double[INITIAL_ARRAY_BUFFER_SIZE];
+ float[] buffer = new float[INITIAL_ARRAY_BUFFER_SIZE];
// till end
while (hasAvailableData()) {
- final long next = readLong(byteOrder);
+ final float next = readFloat(byteOrder);
if (buffer.length == pos) {
- final double[] newbuffer = new double[buffer.length << 1];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
+ final float[] newBuffer = new float[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
+ }
+ buffer[pos++] = next;
+ if (isBreakReadWholeStream(pos, arraySizeLimiter)) {
+ this.setDetectedArrayLimit(true);
+ break;
}
- buffer[pos++] = Double.longBitsToDouble(next);
}
if (buffer.length == pos) {
return buffer;
}
- final double[] result = new double[pos];
+ final float[] result = new float[pos];
System.arraycopy(buffer, 0, result, 0, pos);
return result;
} else {
// number
- final double[] buffer = new double[items];
+ final float[] buffer = new float[items];
for (int i = 0; i < items; i++) {
- buffer[i] = readDouble(byteOrder);
+ buffer[i] = readFloat(byteOrder);
}
return buffer;
}
@@ -489,7 +842,7 @@ public double[] readDoubleArray(final int items, final JBBPByteOrder byteOrder)
/**
* Read a unsigned short value from the stream.
*
- * @param byteOrder he order of bytes to be used to decode the read value
+ * @param byteOrder the order of bytes to be used to decode the read value
* @return the unsigned short value read from stream
* @throws IOException it will be thrown for any transport problem during the
* operation
@@ -528,6 +881,26 @@ public int readInt(final JBBPByteOrder byteOrder) throws IOException {
}
}
+ /**
+ * Read an unsigned integer value from the stream.
+ *
+ * @param byteOrder the order of bytes to be used to decode the read value
+ * @return the unsigned integer value from the stream
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @throws EOFException if the end of the stream has been reached
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.0.4
+ */
+ public long readUInt(final JBBPByteOrder byteOrder) throws IOException {
+ if (byteOrder == JBBPByteOrder.BIG_ENDIAN) {
+ return (((long) readUnsignedShort(byteOrder) << 16) | readUnsignedShort(byteOrder));
+ } else {
+ return readUnsignedShort(byteOrder) | ((long) readUnsignedShort(byteOrder) << 16);
+ }
+ }
+
/**
* Read a float value from the stream.
*
@@ -563,9 +936,11 @@ public float readFloat(final JBBPByteOrder byteOrder) throws IOException {
*/
public long readLong(final JBBPByteOrder byteOrder) throws IOException {
if (byteOrder == JBBPByteOrder.BIG_ENDIAN) {
- return (((long) readInt(byteOrder) & 0xFFFFFFFFL) << 32) | ((long) readInt(byteOrder) & 0xFFFFFFFFL);
+ return (((long) readInt(byteOrder) & 0xFFFFFFFFL) << 32) |
+ ((long) readInt(byteOrder) & 0xFFFFFFFFL);
} else {
- return ((long) readInt(byteOrder) & 0xFFFFFFFFL) | (((long) readInt(byteOrder) & 0xFFFFFFFFL) << 32);
+ return ((long) readInt(byteOrder) & 0xFFFFFFFFL) |
+ (((long) readInt(byteOrder) & 0xFFFFFFFFL) << 32);
}
}
@@ -584,9 +959,11 @@ public long readLong(final JBBPByteOrder byteOrder) throws IOException {
public double readDouble(final JBBPByteOrder byteOrder) throws IOException {
final long value;
if (byteOrder == JBBPByteOrder.BIG_ENDIAN) {
- value = (((long) readInt(byteOrder) & 0xFFFFFFFFL) << 32) | ((long) readInt(byteOrder) & 0xFFFFFFFFL);
+ value = (((long) readInt(byteOrder) & 0xFFFFFFFFL) << 32) |
+ ((long) readInt(byteOrder) & 0xFFFFFFFFL);
} else {
- value = ((long) readInt(byteOrder) & 0xFFFFFFFFL) | (((long) readInt(byteOrder) & 0xFFFFFFFFL) << 32);
+ value = ((long) readInt(byteOrder) & 0xFFFFFFFFL) |
+ (((long) readInt(byteOrder) & 0xFFFFFFFFL) << 32);
}
return Double.longBitsToDouble(value);
}
@@ -627,10 +1004,11 @@ public int getBufferedBitsNumber() {
* @return the bit order parameter
* @see JBBPBitOrder#LSB0
* @see JBBPBitOrder#MSB0
+ * @see JBBPBitOrder#MSB0_DIRECT
*/
@Override
public JBBPBitOrder getBitOrder() {
- return this.msb0 ? JBBPBitOrder.MSB0 : JBBPBitOrder.LSB0;
+ return this.bitOrderMode;
}
/**
@@ -642,8 +1020,8 @@ public JBBPBitOrder getBitOrder() {
* @since 1.3.0
*/
public byte readBitField(final JBBPBitNumber numOfBitsToRead) throws IOException {
- final int value = this.readBits(numOfBitsToRead);
- if (value < 0) {
+ final int value = this.readBits(numOfBitsToRead, this.enablePartialBitsOnEOF);
+ if (value < 0 || this.isDetectedPartlyReadBitField()) {
throw new EOFException("Can't read bits from stream [" + numOfBitsToRead + ']');
}
return (byte) value;
@@ -652,7 +1030,7 @@ public byte readBitField(final JBBPBitNumber numOfBitsToRead) throws IOException
/**
* Read number of bits from the input stream. It reads bits from input stream
* since 0 bit and make reversion to return bits in the right order when 0 bit
- * is 0 bit. if the stream is completed early than the data read then reading
+ * is 0 bit. if the stream is completed earlier than the data read then reading
* is just stopped and read value returned. The First read bit is placed as
* 0th bit.
*
@@ -662,8 +1040,26 @@ public byte readBitField(final JBBPBitNumber numOfBitsToRead) throws IOException
* @throws NullPointerException if number of bits to be read is null
*/
public int readBits(final JBBPBitNumber numOfBitsToRead) throws IOException {
- int result;
+ return this.readBits(numOfBitsToRead, this.enablePartialBitsOnEOF);
+ }
+ /**
+ * Read number of bits from the input stream. It reads bits from input stream
+ * since 0 bit and make reversion to return bits in the order according the thread mode.
+ * Behaviour in case of missing bit data can be tuned by the special argument flag and if it is true then -1 returned otherwise current accumulated bit data returned.
+ *
+ * @param numOfBitsToRead the number of bits to be read, must be 1..8
+ * @param enablePartialBitsOnEOF if true then already accumulated partly read bit field data returned in case EOF, -1 otherwise.
+ * @return the read bits as integer, -1 if the end of stream has been reached or if allowed end of stream flag and not all bits read.
+ * @throws IOException it will be thrown for transport errors to be read
+ * @throws NullPointerException if number of bits to be read is null
+ * @since 3.0.1
+ */
+ public int readBits(final JBBPBitNumber numOfBitsToRead,
+ final boolean enablePartialBitsOnEOF)
+ throws IOException {
+ int result;
+ this.detectedPartlyReadBitField = false;
final int numOfBitsAsNumber = numOfBitsToRead.getBitNumber();
if (this.bitsInBuffer == 0 && numOfBitsAsNumber == 8) {
@@ -671,12 +1067,14 @@ public int readBits(final JBBPBitNumber numOfBitsToRead) throws IOException {
if (result >= 0) {
this.byteCounter++;
}
- return result;
} else {
result = 0;
if (numOfBitsAsNumber == this.bitsInBuffer) {
result = this.bitBuffer;
+ if (this.bitOrderMode == JBBPBitOrder.MSB0_DIRECT) {
+ result >>>= this.bitsInBuffer;
+ }
this.bitBuffer = 0;
this.bitsInBuffer = 0;
this.byteCounter++;
@@ -689,35 +1087,75 @@ public int readBits(final JBBPBitNumber numOfBitsToRead) throws IOException {
final boolean doIncCounter = theBitBufferCounter != 0;
- while (i > 0) {
- if (theBitBufferCounter == 0) {
- if (doIncCounter) {
- this.byteCounter++;
- }
- final int nextByte = this.readByteFromStream();
- if (nextByte < 0) {
- if (i == numOfBitsAsNumber) {
- return nextByte;
+ if (this.bitOrderMode == JBBPBitOrder.MSB0_DIRECT) {
+ while (i > 0) {
+ if (theBitBufferCounter == 0) {
+ if (doIncCounter) {
+ this.byteCounter++;
+ }
+ final int nextByte = this.readByteFromStream();
+ if (nextByte < 0) {
+ if (i == numOfBitsAsNumber) {
+ return nextByte;
+ } else {
+ this.detectedPartlyReadBitField = true;
+ if (enablePartialBitsOnEOF) {
+ break;
+ } else {
+ this.bitsInBuffer = 0;
+ return -1;
+ }
+ }
} else {
- break;
+ theBitBuffer = nextByte;
+ theBitBufferCounter = 8;
}
- } else {
- theBitBuffer = nextByte;
- theBitBufferCounter = 8;
}
+
+ result = (result << 1) | ((theBitBuffer >>> 7) & 1);
+ theBitBuffer = (theBitBuffer << 1) & 0xFF;
+ theBitBufferCounter--;
+ i--;
}
+ } else {
+ while (i > 0) {
+ if (theBitBufferCounter == 0) {
+ if (doIncCounter) {
+ this.byteCounter++;
+ }
+ final int nextByte = this.readByteFromStream();
+ if (nextByte < 0) {
+ if (i == numOfBitsAsNumber) {
+ return nextByte;
+ } else {
+ this.detectedPartlyReadBitField = true;
+ if (enablePartialBitsOnEOF) {
+ break;
+ } else {
+ this.bitsInBuffer = 0;
+ return -1;
+ }
+ }
+ } else {
+ theBitBuffer = nextByte;
+ theBitBufferCounter = 8;
+ }
+ }
- result = (result << 1) | (theBitBuffer & 1);
- theBitBuffer >>= 1;
- theBitBufferCounter--;
- i--;
+ result = (result << 1) | (theBitBuffer & 1);
+ theBitBuffer >>= 1;
+ theBitBufferCounter--;
+ i--;
+ }
+ result = JBBPUtils.reverseBitsInByte(JBBPBitNumber.decode(numOfBitsAsNumber - i),
+ (byte) result) &
+ 0xFF;
}
this.bitBuffer = theBitBuffer;
this.bitsInBuffer = theBitBufferCounter;
-
- return JBBPUtils.reverseBitsInByte(JBBPBitNumber.decode(numOfBitsAsNumber - i), (byte) result) & 0xFF;
}
+ return result;
}
/**
@@ -749,19 +1187,81 @@ public int readByte() throws IOException {
}
@Override
- public synchronized void reset() throws IOException {
+ public void reset() throws IOException {
in.reset();
this.bitBuffer = this.markedBitBuffer;
this.byteCounter = this.markedByteCounter;
this.bitsInBuffer = this.markedBitsInBuffer;
}
- @Override
- public synchronized void mark(final int readlimit) {
- in.mark(readlimit);
- this.markedBitBuffer = this.bitBuffer;
- this.markedByteCounter = this.byteCounter;
- this.markedBitsInBuffer = this.bitsInBuffer;
+ /**
+ * Read number of long items from the input stream.
+ *
+ * @param items number of items to be read from the input stream, if less than
+ * zero then all stream till the end will be read
+ * @param byteOrder the order of bytes to be used to decode values
+ * @return read items as a long array
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ */
+ public long[] readLongArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ return this.readLongArray(items, byteOrder, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read number of long items from the input stream.
+ *
+ * @param items number of items to be read from the input stream, if less than
+ * zero then all stream till the end will be read
+ * @param byteOrder the order of bytes to be used to decode values
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return read items as a long array
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @throws JBBPReachedArraySizeLimitException if reached limit of read
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.1.0
+ */
+ public long[] readLongArray(
+ final int items,
+ final JBBPByteOrder byteOrder,
+ final JBBPArraySizeLimiter arraySizeLimiter
+ ) throws IOException {
+ this.setDetectedArrayLimit(false);
+ int pos = 0;
+ if (items < 0) {
+ long[] buffer = new long[INITIAL_ARRAY_BUFFER_SIZE];
+ // till end
+ while (hasAvailableData()) {
+ final long next = readLong(byteOrder);
+ if (buffer.length == pos) {
+ final long[] newBuffer = new long[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
+ }
+ buffer[pos++] = next;
+ if (isBreakReadWholeStream(pos, arraySizeLimiter)) {
+ this.setDetectedArrayLimit(true);
+ break;
+ }
+ }
+ if (buffer.length == pos) {
+ return buffer;
+ }
+ final long[] result = new long[pos];
+ System.arraycopy(buffer, 0, result, 0, pos);
+ return result;
+ } else {
+ // number
+ final long[] buffer = new long[items];
+ for (int i = 0; i < items; i++) {
+ buffer[i] = readLong(byteOrder);
+ }
+ return buffer;
+ }
}
/**
@@ -812,35 +1312,90 @@ public long skip(final long numOfBytes) throws IOException {
}
/**
- * Inside method to read a byte from stream.
+ * Internal method to read a byte from wrapped stream.
*
* @return the read byte or -1 if the end of the stream has been reached
* @throws IOException it will be thrown for transport errors
*/
private int readByteFromStream() throws IOException {
+ this.detectedPartlyReadBitField = false;
int result = this.in.read();
- if (result >= 0 && this.msb0) {
+ if (result >= 0 && this.bitOrderMode == JBBPBitOrder.MSB0) {
result = JBBPUtils.reverseBitsInByte((byte) result) & 0xFF;
}
return result;
}
/**
- * Read the next stream byte into bit buffer.
+ * Read number of double items from the input stream.
*
- * @return the read byte or -1 if the endo of stream has been reached.
- * @throws IOException it will be thrown for transport errors
+ * @param items number of items to be read from the input stream, if less than
+ * zero then all stream till the end will be read
+ * @param byteOrder the order of bytes to be used to decode values
+ * @return read items as a double array
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 1.4.0
*/
- private int loadNextByteInBuffer() throws IOException {
- final int value = this.readByteFromStream();
- if (value < 0) {
- return value;
- }
-
- this.bitBuffer = value;
- this.bitsInBuffer = 8;
+ public double[] readDoubleArray(final int items, final JBBPByteOrder byteOrder)
+ throws IOException {
+ return this.readDoubleArray(items, byteOrder, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
- return value;
+ /**
+ * Read number of double items from the input stream.
+ *
+ * @param items number of items to be read from the input stream, if less than
+ * zero then all stream till the end will be read
+ * @param byteOrder the order of bytes to be used to decode values
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return read items as a double array
+ * @throws IOException it will be thrown for any transport problem during the
+ * operation
+ * @throws JBBPReachedArraySizeLimitException if reached limit of array read
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.1.0
+ */
+ public double[] readDoubleArray(
+ final int items,
+ final JBBPByteOrder byteOrder,
+ final JBBPArraySizeLimiter arraySizeLimiter
+ ) throws IOException {
+ this.setDetectedArrayLimit(false);
+ int pos = 0;
+ if (items < 0) {
+ double[] buffer = new double[INITIAL_ARRAY_BUFFER_SIZE];
+ // till end
+ while (hasAvailableData()) {
+ final long next = readLong(byteOrder);
+ if (buffer.length == pos) {
+ final double[] newBuffer = new double[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
+ }
+ buffer[pos++] = Double.longBitsToDouble(next);
+ if (isBreakReadWholeStream(pos, arraySizeLimiter)) {
+ this.setDetectedArrayLimit(true);
+ break;
+ }
+ }
+ if (buffer.length == pos) {
+ return buffer;
+ }
+ final double[] result = new double[pos];
+ System.arraycopy(buffer, 0, result, 0, pos);
+ return result;
+ } else {
+ // number
+ final double[] buffer = new double[items];
+ for (int i = 0; i < items; i++) {
+ buffer[i] = readDouble(byteOrder);
+ }
+ return buffer;
+ }
}
/**
@@ -866,49 +1421,22 @@ public boolean hasAvailableData() throws IOException {
return this.bitsInBuffer > 0 || loadNextByteInBuffer() >= 0;
}
- @SuppressWarnings("NullableProblems")
- @Override
- public int read(final byte[] array, final int offset, final int length) throws IOException {
- if (this.bitsInBuffer == 0) {
- int readBytes = 0;
- int tmpoffset = offset;
- int tmplen = length;
- while (tmplen > 0) {
- int read = this.in.read(array, tmpoffset, tmplen);
- if (read < 0) {
- readBytes = readBytes == 0 ? read : readBytes;
- break;
- }
- tmplen -= read;
- tmpoffset += read;
- readBytes += read;
- this.byteCounter += read;
- }
+ /**
+ * Read the next stream byte into bit buffer.
+ *
+ * @return the read byte or -1 if the end of stream has been reached.
+ * @throws IOException it will be thrown for transport errors
+ */
+ private int loadNextByteInBuffer() throws IOException {
+ final int value = this.readByteFromStream();
+ if (value < 0) {
+ return value;
+ }
- if (this.msb0) {
- int index = offset;
- int number = readBytes;
- while (number > 0) {
- array[index] = JBBPUtils.reverseBitsInByte(array[index]);
- index++;
- number--;
- }
- }
+ this.bitBuffer = value;
+ this.bitsInBuffer = 8;
- return readBytes;
- } else {
- int count = length;
- int i = offset;
- while (count > 0) {
- final int nextByte = this.readBits(JBBPBitNumber.BITS_8);
- if (nextByte < 0) {
- break;
- }
- count--;
- array[i++] = (byte) nextByte;
- }
- return length - count;
- }
+ return value;
}
/**
@@ -930,7 +1458,6 @@ public void resetCounter() {
this.byteCounter = 0L;
}
- @SuppressWarnings("NullableProblems")
@Override
public int read(final byte[] array) throws IOException {
return this.read(array, 0, array.length);
@@ -1016,9 +1543,8 @@ public String readString(final JBBPByteOrder byteOrder) throws IOException {
return result;
}
-
/**
- * Read array of srings from stream.
+ * Read array of strings from stream.
*
* @param items number of items, or -1 if read whole stream
* @param byteOrder order of bytes in structure, must not be null
@@ -1027,7 +1553,29 @@ public String readString(final JBBPByteOrder byteOrder) throws IOException {
* @see JBBPBitOutputStream#writeStringArray(String[], JBBPByteOrder)
* @since 1.4.0
*/
- public String[] readStringArray(final int items, final JBBPByteOrder byteOrder) throws IOException {
+ public String[] readStringArray(final int items, final JBBPByteOrder byteOrder)
+ throws IOException {
+ return this.readStringArray(items, byteOrder, JBBPArraySizeLimiter.NO_LIMIT_FOR_ARRAY_SIZE);
+ }
+
+ /**
+ * Read array of strings from stream.
+ *
+ * @param items number of items, or -1 if read whole stream
+ * @param byteOrder order of bytes in structure, must not be null
+ * @param arraySizeLimiter limiter provides number of allowed array items for non-limited array, must not be null
+ * @return array, it can contain null among values, must not be null
+ * @throws IOException thrown for transport errors
+ * @throws JBBPReachedArraySizeLimitException if reached limit of array read
+ * @see JBBPBitOutputStream#writeStringArray(String[], JBBPByteOrder)
+ * @since 2.1.0
+ */
+ public String[] readStringArray(
+ final int items,
+ final JBBPByteOrder byteOrder,
+ final JBBPArraySizeLimiter arraySizeLimiter
+ ) throws IOException {
+ this.setDetectedArrayLimit(false);
int pos = 0;
if (items < 0) {
String[] buffer = new String[INITIAL_ARRAY_BUFFER_SIZE];
@@ -1035,11 +1583,15 @@ public String[] readStringArray(final int items, final JBBPByteOrder byteOrder)
while (hasAvailableData()) {
final String next = readString(byteOrder);
if (buffer.length == pos) {
- final String[] newbuffer = new String[buffer.length << 1];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
+ final String[] newBuffer = new String[buffer.length << 1];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
}
buffer[pos++] = next;
+ if (isBreakReadWholeStream(pos, arraySizeLimiter)) {
+ this.setDetectedArrayLimit(true);
+ break;
+ }
}
if (buffer.length == pos) {
return buffer;
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOrder.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOrder.java
index cc9ca19a..dd72eacd 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOrder.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOrder.java
@@ -17,18 +17,26 @@
package com.igormaznitsa.jbbp.io;
/**
- * Constants for bit order of reading operations.
+ * Constants for a bit order of reading operations.
*
* @since 1.0
*/
public enum JBBPBitOrder {
/**
* Most Significant Bit First means that the most significant bit will arrive first, the 7th bit will be read as the first one.
+ * Read data wille be presented in reverse format for Java because Java is LSB0.
*/
MSB0,
/**
* Least Significant Bit First means that the least significant bit will arrive first, the 0th bit will be read as the first one.
* It is default order for Java.
*/
- LSB0
+ LSB0,
+ /**
+ * Most Significant Bit First means that the most significant bit will arrive first, the 7th bit will be read as the first one.
+ * In opposite to MSB0 it doesn't make reverse for data during read and write.
+ *
+ * @since 3.0.1
+ */
+ MSB0_DIRECT
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOutputStream.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOutputStream.java
index 69a84f2d..dbbe4a35 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOutputStream.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOutputStream.java
@@ -16,6 +16,8 @@
package com.igormaznitsa.jbbp.io;
+import static java.util.Objects.requireNonNull;
+
import com.igormaznitsa.jbbp.utils.JBBPUtils;
import java.io.FilterOutputStream;
import java.io.IOException;
@@ -28,16 +30,15 @@
*/
public class JBBPBitOutputStream extends FilterOutputStream implements JBBPCountableBitStream {
/**
- * Flag shows that bit operations must be processed for MSB0 (most significant
- * bit 0) mode.
+ * Contains bit mode for bit operations.
*/
- private final boolean msb0;
+ private final JBBPBitOrder bitOrderMode;
/**
- * Inside bit buffer.
+ * Internal bit buffer.
*/
private int bitBuffer;
/**
- * Number of bits inside the bit buffer.
+ * Number of bits buffered by the bit buffer.
*/
private int bitBufferCount;
/**
@@ -46,7 +47,7 @@ public class JBBPBitOutputStream extends FilterOutputStream implements JBBPCount
private long byteCounter;
/**
- * A Constructor. The Default LSB0 bit mode will be used for bit writing operations.
+ * A Constructor. The Default LSB0 bit mode will be used for a bit writing operations.
*
* @param out the output stream to be filtered.
*/
@@ -57,14 +58,14 @@ public JBBPBitOutputStream(final OutputStream out) {
/**
* A Constructor.
*
- * @param out an output stream to be filtered.
- * @param order a bit writing mode to used for writing operations.
+ * @param out an output stream to be filtered.
+ * @param bitOrderMode a bit writing mode to used for writing operations.
* @see JBBPBitOrder#LSB0
* @see JBBPBitOrder#MSB0
*/
- public JBBPBitOutputStream(final OutputStream out, final JBBPBitOrder order) {
+ public JBBPBitOutputStream(final OutputStream out, final JBBPBitOrder bitOrderMode) {
super(out);
- this.msb0 = order == JBBPBitOrder.MSB0;
+ this.bitOrderMode = requireNonNull(bitOrderMode, "Bit order mode must not be null");
}
/**
@@ -76,7 +77,7 @@ public JBBPBitOutputStream(final OutputStream out, final JBBPBitOrder order) {
*/
@Override
public JBBPBitOrder getBitOrder() {
- return this.msb0 ? JBBPBitOrder.MSB0 : JBBPBitOrder.LSB0;
+ return this.bitOrderMode;
}
/**
@@ -118,7 +119,28 @@ public void writeInt(final int value, final JBBPByteOrder byteOrder) throws IOEx
}
/**
- * Write an float value into the output stream.
+ * Write an unsigned integer value into the output stream.
+ *
+ * @param value a value to be written into the output stream.
+ * @param byteOrder the byte order of the value bytes to be used for writing.
+ * @throws IOException it will be thrown for transport errors
+ * @see JBBPByteOrder#BIG_ENDIAN
+ * @see JBBPByteOrder#LITTLE_ENDIAN
+ * @since 2.0.4
+ */
+ public void writeUInt(final long value, final JBBPByteOrder byteOrder) throws IOException {
+ final int v = (int) value;
+ if (byteOrder == JBBPByteOrder.BIG_ENDIAN) {
+ this.writeShort(v >>> 16, byteOrder);
+ this.writeShort(v, byteOrder);
+ } else {
+ this.writeShort(v, byteOrder);
+ this.writeShort(v >>> 16, byteOrder);
+ }
+ }
+
+ /**
+ * Write a float value into the output stream.
*
* @param value a value to be written into the output stream.
* @param byteOrder the byte order of the value bytes to be used for writing.
@@ -189,9 +211,9 @@ public long getCounter() {
}
/**
- * Get the inside bit buffer value.
+ * Get the internal bit buffer value.
*
- * @return the inside bit buffer value
+ * @return the internal bit buffer value
*/
@Override
public int getBitBuffer() {
@@ -199,7 +221,7 @@ public int getBitBuffer() {
}
/**
- * Get the number of bits cached in the inside bit buffer.
+ * Get the number of bits cached in the internal bit buffer.
*
* @return the number of cached bits in the bit buffer
*/
@@ -226,10 +248,9 @@ public void flush() throws IOException {
this.out.flush();
}
- @SuppressWarnings("NullableProblems")
@Override
public void write(final byte[] b, final int off, final int len) throws IOException {
- if (this.msb0 || this.bitBufferCount != 0) {
+ if (this.bitOrderMode == JBBPBitOrder.MSB0 || this.bitBufferCount != 0) {
int i = off;
int cnt = len;
while (cnt > 0) {
@@ -242,7 +263,6 @@ public void write(final byte[] b, final int off, final int len) throws IOExcepti
}
}
- @SuppressWarnings("NullableProblems")
@Override
public void write(final byte[] b) throws IOException {
this.write(b, 0, b.length);
@@ -258,29 +278,47 @@ public void write(final byte[] b) throws IOException {
*/
public void writeBits(final int value, final JBBPBitNumber bitNumber) throws IOException {
if (this.bitBufferCount == 0 && bitNumber == JBBPBitNumber.BITS_8) {
- write(value);
+ this.write(value);
} else {
- final int initialMask;
int mask;
- initialMask = 1;
- mask = initialMask << this.bitBufferCount;
-
- int accum = value;
+ int accumulator = value;
int i = bitNumber.getBitNumber();
- while (i > 0) {
- this.bitBuffer = this.bitBuffer | ((accum & 1) == 0 ? 0 : mask);
- accum >>= 1;
-
- mask = mask << 1;
-
- i--;
- this.bitBufferCount++;
- if (this.bitBufferCount == 8) {
- this.bitBufferCount = 0;
- writeByte(this.bitBuffer);
- mask = initialMask;
- this.bitBuffer = 0;
+ if (this.bitOrderMode == JBBPBitOrder.MSB0_DIRECT) {
+ final int initialMask = 0x80;
+ mask = initialMask >> this.bitBufferCount;
+ final int accumulatorMask = 1 << (bitNumber.getBitNumber() - 1);
+ while (i > 0) {
+ this.bitBuffer = this.bitBuffer | ((accumulator & accumulatorMask) == 0 ? 0 : mask);
+ accumulator <<= 1;
+ mask >>= 1;
+
+ i--;
+ this.bitBufferCount++;
+ if (this.bitBufferCount == 8) {
+ this.bitBufferCount = 0;
+ writeByte(this.bitBuffer);
+ mask = initialMask;
+ this.bitBuffer = 0;
+ }
+ }
+ } else {
+ final int initialMask = 1;
+ mask = initialMask << this.bitBufferCount;
+ while (i > 0) {
+ this.bitBuffer = this.bitBuffer | ((accumulator & 1) == 0 ? 0 : mask);
+
+ accumulator >>= 1;
+ mask = mask << 1;
+
+ i--;
+ this.bitBufferCount++;
+ if (this.bitBufferCount == 8) {
+ this.bitBufferCount = 0;
+ writeByte(this.bitBuffer);
+ mask = initialMask;
+ this.bitBuffer = 0;
+ }
}
}
}
@@ -308,13 +346,13 @@ public void align(final long alignByteNumber) throws IOException {
}
/**
- * Inside method to write a byte into wrapped stream.
+ * Internal method to write a byte into wrapped stream.
*
* @param value a byte value to be written
* @throws IOException it will be thrown for transport problems
*/
private void writeByte(int value) throws IOException {
- if (this.msb0) {
+ if (this.bitOrderMode == JBBPBitOrder.MSB0) {
value = JBBPUtils.reverseBitsInByte((byte) value) & 0xFF;
}
this.out.write(value);
@@ -330,9 +368,9 @@ public void close() throws IOException {
@Override
public void write(final int value) throws IOException {
if (this.bitBufferCount == 0) {
- writeByte(value);
+ this.writeByte(value);
} else {
- writeBits(value, JBBPBitNumber.BITS_8);
+ this.writeBits(value, JBBPBitNumber.BITS_8);
}
}
@@ -346,7 +384,8 @@ public void write(final int value) throws IOException {
* @see JBBPByteOrder#LITTLE_ENDIAN
* @since 1.3.0
*/
- public void writeBytes(final byte[] array, final int length, final JBBPByteOrder byteOrder) throws IOException {
+ public void writeBytes(final byte[] array, final int length, final JBBPByteOrder byteOrder)
+ throws IOException {
if (byteOrder == JBBPByteOrder.LITTLE_ENDIAN) {
int i = length < 0 ? array.length - 1 : length - 1;
while (i >= 0) {
@@ -358,7 +397,7 @@ public void writeBytes(final byte[] array, final int length, final JBBPByteOrder
}
/**
- * Reset the byte counter for the stream. The Inside bit buffer will be reset also.
+ * Reset the byte counter for the stream. The internal bit buffer will be reset also.
*/
@Override
public void resetCounter() {
@@ -380,7 +419,7 @@ public void resetCounter() {
public void writeString(final String value, final JBBPByteOrder order) throws IOException {
if (value == null) {
this.write(0xFF);
- } else if (value.length() == 0) {
+ } else if (value.isEmpty()) {
this.write(0);
} else {
final byte[] array = JBBPUtils.strToUtf8(value);
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPByteOrder.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPByteOrder.java
index 7b3da313..2dd4b619 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPByteOrder.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPByteOrder.java
@@ -17,7 +17,7 @@
package com.igormaznitsa.jbbp.io;
/**
- * Constants define byte order for multi-byte values to be read or written into streams.
+ * Constants define byte order for multibyte values to be read or written into streams.
*
* @since 1.0
*/
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPCountableBitStream.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPCountableBitStream.java
index 4476e922..f2f5fd43 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPCountableBitStream.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPCountableBitStream.java
@@ -45,7 +45,7 @@ public interface JBBPCountableBitStream {
void resetCounter();
/**
- * Get the inside stream bit buffer.
+ * Get the inside stream a bit buffer.
*
* @return the value from inside the stream bit buffer
*/
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPCustomFieldWriter.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPCustomFieldWriter.java
index 45123923..c3764e3e 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPCustomFieldWriter.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPCustomFieldWriter.java
@@ -17,7 +17,6 @@
package com.igormaznitsa.jbbp.io;
import com.igormaznitsa.jbbp.mapper.Bin;
-
import java.io.IOException;
import java.lang.reflect.Field;
@@ -40,5 +39,7 @@ public interface JBBPCustomFieldWriter {
* @param value the value found in the field, can be null
* @throws IOException it will be thrown if it is impossible to process field data and save them into the stream
*/
- void writeCustomField(final JBBPOut context, final JBBPBitOutputStream outStream, final Object instanceToSave, final Field instanceCustomField, final Bin fieldAnnotation, final Object value) throws IOException;
+ void writeCustomField(final JBBPOut context, final JBBPBitOutputStream outStream,
+ final Object instanceToSave, final Field instanceCustomField,
+ final Bin fieldAnnotation, final Object value) throws IOException;
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOut.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOut.java
index 20ed7b1c..62e1cd5e 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOut.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOut.java
@@ -16,10 +16,14 @@
package com.igormaznitsa.jbbp.io;
+import static com.igormaznitsa.jbbp.utils.JBBPUtils.assertNotNull;
+
import com.igormaznitsa.jbbp.exceptions.JBBPIOException;
import com.igormaznitsa.jbbp.mapper.Bin;
+import com.igormaznitsa.jbbp.mapper.BinFieldFilter;
import com.igormaznitsa.jbbp.mapper.JBBPMapper;
import com.igormaznitsa.jbbp.model.JBBPFieldShort;
+import com.igormaznitsa.jbbp.utils.BinAnnotationWrapper;
import com.igormaznitsa.jbbp.utils.JBBPUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -32,7 +36,7 @@
*
* @since 1.0
*/
-public final class JBBPOut extends AbstractMappedClassFieldObserver {
+public class JBBPOut extends AbstractMappedClassFieldObserver {
/**
* The Default byte outOrder.
@@ -60,11 +64,11 @@ public final class JBBPOut extends AbstractMappedClassFieldObserver {
*/
private boolean processCommands = true;
/**
- * The Byte outOrder for operations of multi-byte value output.
+ * The Byte outOrder for operations of multibyte value output.
*/
private JBBPByteOrder byteOrder;
/**
- * The Flags shows that the processing has been ended.
+ * The Flags show that the processing has been ended.
*/
private boolean ended;
@@ -77,15 +81,19 @@ public final class JBBPOut extends AbstractMappedClassFieldObserver {
* @throws IllegalArgumentException if defined a bit stream which parameters
* incompatible with defined ones
*/
- private JBBPOut(final OutputStream outStream, final JBBPByteOrder byteOrder, final JBBPBitOrder bitOrder) {
- JBBPUtils.assertNotNull(outStream, "Out stream must not be null");
- JBBPUtils.assertNotNull(byteOrder, "Byte order must not be null");
- JBBPUtils.assertNotNull(bitOrder, "Bit order must not be null");
+ private JBBPOut(final OutputStream outStream, final JBBPByteOrder byteOrder,
+ final JBBPBitOrder bitOrder) {
+ assertNotNull(outStream, "Out stream must not be null");
+ assertNotNull(byteOrder, "Byte order must not be null");
+ assertNotNull(bitOrder, "Bit order must not be null");
- this.outStream = outStream instanceof JBBPBitOutputStream ? (JBBPBitOutputStream) outStream : new JBBPBitOutputStream(outStream, bitOrder);
+ this.outStream = outStream instanceof JBBPBitOutputStream ? (JBBPBitOutputStream) outStream :
+ new JBBPBitOutputStream(outStream, bitOrder);
this.bitOrder = this.outStream.getBitOrder();
if (this.bitOrder != bitOrder) {
- throw new IllegalArgumentException("Detected JBBPBitOutputStream as argument with already defined different bit order [" + this.bitOrder + ']');
+ throw new IllegalArgumentException(
+ "Detected JBBPBitOutputStream as argument with already defined different bit order [" +
+ this.bitOrder + ']');
}
this.byteOrder = byteOrder;
@@ -116,7 +124,8 @@ public static JBBPOut BeginBin(final JBBPByteOrder byteOrder, final JBBPBitOrder
* @param bitOrder the bit outOrder for the session
* @return the new DSL session generated for the stream with parameters
*/
- public static JBBPOut BeginBin(final OutputStream out, final JBBPByteOrder byteOrder, final JBBPBitOrder bitOrder) {
+ public static JBBPOut BeginBin(final OutputStream out, final JBBPByteOrder byteOrder,
+ final JBBPBitOrder bitOrder) {
return new JBBPOut(out, byteOrder, bitOrder);
}
@@ -140,7 +149,8 @@ public static JBBPOut BeginBin() {
* inside byte array stream.
*/
public static JBBPOut BeginBin(final int initialSize) {
- return new JBBPOut(new ByteArrayOutputStream(initialSize), DEFAULT_BYTE_ORDER, DEFAULT_BIT_ORDER);
+ return new JBBPOut(new ByteArrayOutputStream(initialSize), DEFAULT_BYTE_ORDER,
+ DEFAULT_BIT_ORDER);
}
/**
@@ -182,7 +192,7 @@ public static JBBPOut BeginBin(final JBBPBitOrder bitOrder) {
* @param array an object to be checked for null.
*/
private static void assertArrayNotNull(final Object array) {
- JBBPUtils.assertNotNull(array, "Array must not be null");
+ assertNotNull(array, "Array must not be null");
}
/**
@@ -191,7 +201,7 @@ private static void assertArrayNotNull(final Object array) {
* @param str an object to be checked for null.
*/
private static void assertStringNotNull(final String str) {
- JBBPUtils.assertNotNull(str, "String must not be null");
+ assertNotNull(str, "String must not be null");
}
/**
@@ -261,7 +271,7 @@ public JBBPOut Skip(int numberOfBytes) throws IOException {
*/
public JBBPOut ByteOrder(final JBBPByteOrder value) {
assertNotEnded();
- JBBPUtils.assertNotNull(value, "Byte order must not be null");
+ assertNotNull(value, "Byte order must not be null");
if (this.processCommands) {
this.byteOrder = value;
}
@@ -300,7 +310,7 @@ public JBBPOut Bit(final byte value) throws IOException {
}
/**
- * Write lowest bits of bytes from an array.
+ * Write the lowest bits of bytes from an array.
*
* @param value a byte array, lowest bit of each byte will be saved as a bit
* into the output stream, it must not be null
@@ -319,7 +329,7 @@ public JBBPOut Bit(final byte[] value) throws IOException {
}
/**
- * Write lowest bits of integers from an array.
+ * Write the lowest bits of integers from an array.
*
* @param value an integer array, lowest bit of each integer value will be
* saved as a bit into the output stream, it must not be null
@@ -341,7 +351,7 @@ public JBBPOut Bit(final int... value) throws IOException {
* Write bits represented as boolean flags into the output stream.
*
* @param value a boolean array which values will be saved into the output
- * stream as bits, true is bit on, false is bit off. It must not be null
+ * stream as bits, true is a bit on, false is bit off. It must not be null
* @return the DSL session.
* @throws IOException it will be thrown for transport errors
*/
@@ -378,7 +388,7 @@ private void _writeBits(final JBBPBitNumber numberOfBits, final int value) throw
*/
public JBBPOut Bits(final JBBPBitNumber numberOfBits, final int value) throws IOException {
assertNotEnded();
- JBBPUtils.assertNotNull(numberOfBits, "Number of bits must not be null");
+ assertNotNull(numberOfBits, "Number of bits must not be null");
if (this.processCommands) {
_writeBits(numberOfBits, value);
}
@@ -396,7 +406,7 @@ public JBBPOut Bits(final JBBPBitNumber numberOfBits, final int value) throws IO
*/
public JBBPOut Bits(final JBBPBitNumber numberOfBits, final int... value) throws IOException {
assertNotEnded();
- JBBPUtils.assertNotNull(value, "Array must not be null");
+ assertNotNull(value, "Array must not be null");
if (this.processCommands) {
for (final int v : value) {
_writeBits(numberOfBits, v);
@@ -416,7 +426,7 @@ public JBBPOut Bits(final JBBPBitNumber numberOfBits, final int... value) throws
*/
public JBBPOut Bits(final JBBPBitNumber numberOfBits, final byte[] value) throws IOException {
assertNotEnded();
- JBBPUtils.assertNotNull(value, "Array must not be null");
+ assertNotNull(value, "Array must not be null");
if (this.processCommands) {
for (final byte b : value) {
_writeBits(numberOfBits, b);
@@ -799,6 +809,20 @@ public JBBPOut Int(final int... value) throws IOException {
return this;
}
+ @Override
+ protected void onFieldUInt(final Object obj, final Field field, final Bin annotation,
+ final int value) {
+ final JBBPByteOrder old = this.byteOrder;
+ try {
+ this.byteOrder = annotation.byteOrder();
+ this.UInt(value);
+ } catch (IOException ex) {
+ throw new JBBPIOException("Can't write unsigned int value", ex);
+ } finally {
+ this.byteOrder = old;
+ }
+ }
+
/**
* Write a float value array as integer bits into the stream.
*
@@ -936,7 +960,7 @@ public JBBPOut Long(final long... value) throws IOException {
*/
public JBBPOut Var(final JBBPOutVarProcessor processor, final Object... args) throws IOException {
assertNotEnded();
- JBBPUtils.assertNotNull(processor, "Var processor must not be null");
+ assertNotNull(processor, "Var processor must not be null");
if (this.processCommands) {
this.processCommands = processor.processVarOut(this, this.outStream, args);
}
@@ -995,26 +1019,49 @@ protected void assertNotEnded() {
/**
* Save fields of an object marked by Bin annotation. Fields will be ordered
- * through {@link Bin#order()} field, NB! By default Java doesn't keep field
+ * through {@link Bin#order()} field, NB! By default, Java doesn't keep field
* outOrder. Ordered fields of class will be saved into internal cache for speed
* but the cache can be reset through {@link JBBPMapper#clearFieldCache()}
+ * Warning! it doesn't affect byte order provided in Bin annotations of object.
*
* @param object an object to be saved into stream, must not be null
* @return the context
* @throws IOException it will be thrown for any transport error
* @see JBBPMapper#clearFieldCache()
+ * @see #BinForceByteOrder(Object)
* @see Bin
* @since 1.1
*/
public JBBPOut Bin(final Object object) throws IOException {
- return this.Bin(object, null);
+ return this.Bin(object, null, null, null);
}
/**
* Save fields of an object marked by Bin annotation. Fields will be ordered
- * through {@link Bin#order()} field, NB! By default Java doesn't keep field
+ * through {@link Bin#order()} field, NB! By default, Java doesn't keep field
* outOrder. Ordered fields of class will be saved into internal cache for speed
* but the cache can be reset through {@link JBBPMapper#clearFieldCache()}
+ * Warning! it doesn't affect byte order provided in Bin annotations of object.
+ *
+ * @param object an object to be saved into stream, must not be null
+ * @param binFieldFilter filter to exclude some fields from process, can be null
+ * @return the context
+ * @throws IOException it will be thrown for any transport error
+ * @see JBBPMapper#clearFieldCache()
+ * @see #BinForceByteOrder(Object)
+ * @see Bin
+ * @since 2.0.4
+ */
+ public JBBPOut Bin(final Object object, final BinFieldFilter binFieldFilter) throws IOException {
+ return this.Bin(object, null, null, binFieldFilter);
+ }
+
+ /**
+ * Save fields of an object marked by Bin annotation. Fields will be ordered
+ * through {@link Bin#order()} field, NB! By default, Java doesn't keep field
+ * outOrder. Ordered fields of class will be saved into internal cache for speed
+ * but the cache can be reset through {@link JBBPMapper#clearFieldCache()}
+ * Warning! it doesn't affect byte order provided in Bin annotations of object.
*
* @param object an object to be saved into stream, must not be null
* @param customFieldWriter a custom field writer to be used for saving of
@@ -1022,18 +1069,106 @@ public JBBPOut Bin(final Object object) throws IOException {
* @return the context
* @see JBBPMapper#clearFieldCache()
* @see Bin
+ * @see #BinForceByteOrder(Object, JBBPCustomFieldWriter)
* @since 1.1
*/
public JBBPOut Bin(final Object object, final JBBPCustomFieldWriter customFieldWriter) {
+ return this.Bin(object, null, customFieldWriter);
+ }
+
+ /**
+ * Save fields of an object marked by Bin annotation. Fields will be ordered
+ * through {@link Bin#order()} field, NB! By default, Java doesn't keep field
+ * outOrder. Ordered fields of class will be saved into internal cache for speed
+ * but the cache can be reset through {@link JBBPMapper#clearFieldCache()}
+ * Warning! it doesn't affect byte order provided in Bin annotations of object.
+ *
+ * @param object an object to be saved into stream, must not be null
+ * @param customFieldWriter a custom field writer to be used for saving of
+ * custom fields of the object, it can be null
+ * @param binFieldFilter filter to exclude fields from process, can be null
+ * @return the context
+ * @see JBBPMapper#clearFieldCache()
+ * @see Bin
+ * @see #BinForceByteOrder(Object, JBBPCustomFieldWriter)
+ * @since 2.0.4
+ */
+ public JBBPOut Bin(final Object object, final JBBPCustomFieldWriter customFieldWriter, final BinFieldFilter binFieldFilter) {
+ return this.Bin(object, null, customFieldWriter, binFieldFilter);
+ }
+
+ /**
+ * Save fields of object but bin annotation wrapper can be provided to replace some annotation field values in all field annotations.
+ *
+ * @param object an object to be saved into stream, must not be null
+ * @param binAnnotationWrapper wrapper for all bin annotations, can be null
+ * @param customFieldWriter a custom field writer to be used for saving of
+ * custom fields of the object, it can be null
+ * @return the context
+ * @since 2.0.2
+ */
+ public JBBPOut Bin(final Object object,
+ final BinAnnotationWrapper binAnnotationWrapper,
+ final JBBPCustomFieldWriter customFieldWriter) {
+ return this.Bin(object, binAnnotationWrapper, customFieldWriter, null);
+ }
+
+ /**
+ * Save fields of object but bin annotation wrapper can be provided to replace some annotation field values in all field annotations.
+ *
+ * @param object an object to be saved into stream, must not be null
+ * @param binAnnotationWrapper wrapper for all bin annotations, can be null
+ * @param customFieldWriter a custom field writer to be used for saving of
+ * custom fields of the object, it can be null
+ * @param binFieldFilter filter to exclude some fields from process, can be null
+ * @return the context
+ * @since 2.0.4
+ */
+ public JBBPOut Bin(final Object object,
+ final BinAnnotationWrapper binAnnotationWrapper,
+ final JBBPCustomFieldWriter customFieldWriter,
+ final BinFieldFilter binFieldFilter) {
if (this.processCommands) {
- this.processObject(object, null, customFieldWriter);
+ this.processObject(object, null, binAnnotationWrapper, binFieldFilter, customFieldWriter);
}
-
return this;
}
+ /**
+ * Works like {@link #Bin(Object)} but forcing override of all annotation byte order values by the JBBPOut byte order.
+ *
+ * @param object an object to be saved into stream, must not be null
+ * @return the context
+ * @throws IOException it will be thrown for any transport error
+ * @see JBBPMapper#clearFieldCache()
+ * @see Bin
+ * @see Bin#byteOrder()
+ * @since 2.0.2
+ */
+ public JBBPOut BinForceByteOrder(final Object object) throws IOException {
+ return this.BinForceByteOrder(object, null);
+ }
+
+ /**
+ * Works like {@link #Bin(Object, JBBPCustomFieldWriter)} but forcing override of all annotation byte order values by the context byte order.
+ *
+ * @param object an object to be saved into stream, must not be null
+ * @param customFieldWriter a custom field writer to be used for saving of
+ * custom fields of the object, it can be null
+ * @return the context
+ * @see #ByteOrder(JBBPByteOrder)
+ * @see Bin#byteOrder()
+ * @since 2.0.2
+ */
+ public JBBPOut BinForceByteOrder(final Object object,
+ final JBBPCustomFieldWriter customFieldWriter) {
+ return this
+ .Bin(object, new BinAnnotationWrapper().setByteOrder(this.byteOrder), customFieldWriter);
+ }
+
@Override
- protected void onFieldFloat(final Object obj, final Field field, final Bin annotation, final float value) {
+ protected void onFieldFloat(final Object obj, final Field field, final Bin annotation,
+ final float value) {
final JBBPByteOrder old = this.byteOrder;
try {
this.byteOrder = annotation.byteOrder();
@@ -1046,7 +1181,8 @@ protected void onFieldFloat(final Object obj, final Field field, final Bin annot
}
@Override
- protected void onFieldString(final Object obj, final Field field, final Bin annotation, final String value) {
+ protected void onFieldString(final Object obj, final Field field, final Bin annotation,
+ final String value) {
final JBBPByteOrder old = this.byteOrder;
try {
this.byteOrder = annotation.byteOrder();
@@ -1059,7 +1195,8 @@ protected void onFieldString(final Object obj, final Field field, final Bin anno
}
@Override
- protected void onFieldDouble(final Object obj, final Field field, final Bin annotation, final double value) {
+ protected void onFieldDouble(final Object obj, final Field field, final Bin annotation,
+ final double value) {
final JBBPByteOrder old = this.byteOrder;
try {
this.byteOrder = annotation.byteOrder();
@@ -1072,7 +1209,8 @@ protected void onFieldDouble(final Object obj, final Field field, final Bin anno
}
@Override
- protected void onFieldLong(final Object obj, final Field field, final Bin annotation, final long value) {
+ protected void onFieldLong(final Object obj, final Field field, final Bin annotation,
+ final long value) {
final JBBPByteOrder old = this.byteOrder;
try {
this.byteOrder = annotation.byteOrder();
@@ -1085,7 +1223,8 @@ protected void onFieldLong(final Object obj, final Field field, final Bin annota
}
@Override
- protected void onFieldInt(final Object obj, final Field field, final Bin annotation, final int value) {
+ protected void onFieldInt(final Object obj, final Field field, final Bin annotation,
+ final int value) {
final JBBPByteOrder old = this.byteOrder;
try {
this.byteOrder = annotation.byteOrder();
@@ -1097,8 +1236,28 @@ protected void onFieldInt(final Object obj, final Field field, final Bin annotat
}
}
+ /**
+ * Write each long value as unsigned integer one into the session stream.
+ *
+ * @param value a long value array which values should be written into
+ * @return the DSl session
+ * @throws IOException it will be thrown for transport errors
+ * @since 2.0.4
+ */
+ public JBBPOut UInt(final long... value) throws IOException {
+ assertNotEnded();
+ assertArrayNotNull(value);
+ if (this.processCommands) {
+ for (final long v : value) {
+ _writeInt((int) v);
+ }
+ }
+ return this;
+ }
+
@Override
- protected void onFieldShort(final Object obj, final Field field, final Bin annotation, final boolean signed, final int value) {
+ protected void onFieldShort(final Object obj, final Field field, final Bin annotation,
+ final boolean signed, final int value) {
final JBBPByteOrder old = this.byteOrder;
try {
this.byteOrder = annotation.byteOrder();
@@ -1111,7 +1270,8 @@ protected void onFieldShort(final Object obj, final Field field, final Bin annot
}
@Override
- protected void onFieldByte(final Object obj, final Field field, final Bin annotation, final boolean signed, final int value) {
+ protected void onFieldByte(final Object obj, final Field field, final Bin annotation,
+ final boolean signed, final int value) {
try {
this.Byte(value);
} catch (IOException ex) {
@@ -1120,7 +1280,8 @@ protected void onFieldByte(final Object obj, final Field field, final Bin annota
}
@Override
- protected void onFieldBool(final Object obj, final Field field, final Bin annotation, final boolean value) {
+ protected void onFieldBool(final Object obj, final Field field, final Bin annotation,
+ final boolean value) {
try {
this.Bool(value, annotation.bitOrder());
} catch (IOException ex) {
@@ -1129,7 +1290,8 @@ protected void onFieldBool(final Object obj, final Field field, final Bin annota
}
@Override
- protected void onFieldBits(final Object obj, final Field field, final Bin annotation, final JBBPBitNumber bitNumber, final int value) {
+ protected void onFieldBits(final Object obj, final Field field, final Bin annotation,
+ final JBBPBitNumber bitNumber, final int value) {
try {
this.Bits(bitNumber, value);
} catch (IOException ex) {
@@ -1138,7 +1300,8 @@ protected void onFieldBits(final Object obj, final Field field, final Bin annota
}
@Override
- protected void onFieldCustom(final Object obj, final Field field, final Bin annotation, final Object customFieldProcessor, final Object value) {
+ protected void onFieldCustom(final Object obj, final Field field, final Bin annotation,
+ final Object customFieldProcessor, final Object value) {
try {
final JBBPCustomFieldWriter writer = (JBBPCustomFieldWriter) customFieldProcessor;
writer.writeCustomField(this, this.outStream, obj, field, annotation, value);
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOutVarProcessor.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOutVarProcessor.java
index 973b84fb..b83fbc12 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOutVarProcessor.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOutVarProcessor.java
@@ -33,5 +33,6 @@ public interface JBBPOutVarProcessor {
* @return true is to continue processing of DSL commands, false skip all commands till the End()
* @throws IOException it should be thrown for transport errors
*/
- boolean processVarOut(JBBPOut context, JBBPBitOutputStream outStream, Object... args) throws IOException;
+ boolean processVarOut(JBBPOut context, JBBPBitOutputStream outStream, Object... args)
+ throws IOException;
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/Bin.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/Bin.java
index 2988d34a..37a4fb1e 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/Bin.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/Bin.java
@@ -30,15 +30,14 @@
/**
* The annotation describes a field in a class which can be mapped and loaded
- * from parsed a JBBP structure. Also it can be used for whole class but in the
+ * from parsed a JBBP structure, also it can be used for whole class but in the
* case be careful and use default name and path values. The Class is not thread safe.
- *
* Since 2.0.0 was removed prefix 'out' for fields which contained it.
*
* @since 1.0
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target( {ElementType.FIELD, ElementType.TYPE})
+@Target({ElementType.FIELD, ElementType.TYPE})
@Inherited
public @interface Bin {
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/BinFieldFilter.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/BinFieldFilter.java
new file mode 100644
index 00000000..eb7fb24d
--- /dev/null
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/BinFieldFilter.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2022 Igor Maznitsa.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.igormaznitsa.jbbp.mapper;
+
+import java.lang.reflect.Field;
+
+/**
+ * Filter allows cheeking Bin annotation and fields during mapping or writing operations.
+ *
+ * @see com.igormaznitsa.jbbp.io.JBBPOut
+ * @see JBBPMapper#map
+ * @see com.igormaznitsa.jbbp.io.JBBPOut#Bin
+ * @since 2.0.4
+ */
+public interface BinFieldFilter {
+ /**
+ * Check annotation and field that they allowed.
+ *
+ * @param annotation bin annotation, must not be null
+ * @param field marked field, can be null
+ * @return true if field allowed, false otherwise
+ */
+ boolean isAllowed(Bin annotation, Field field);
+}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/BinType.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/BinType.java
index 1f3a2a2f..d7f36d29 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/BinType.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/BinType.java
@@ -28,6 +28,7 @@
import com.igormaznitsa.jbbp.model.JBBPFieldArrayString;
import com.igormaznitsa.jbbp.model.JBBPFieldArrayStruct;
import com.igormaznitsa.jbbp.model.JBBPFieldArrayUByte;
+import com.igormaznitsa.jbbp.model.JBBPFieldArrayUInt;
import com.igormaznitsa.jbbp.model.JBBPFieldArrayUShort;
import com.igormaznitsa.jbbp.model.JBBPFieldBit;
import com.igormaznitsa.jbbp.model.JBBPFieldBoolean;
@@ -40,6 +41,7 @@
import com.igormaznitsa.jbbp.model.JBBPFieldString;
import com.igormaznitsa.jbbp.model.JBBPFieldStruct;
import com.igormaznitsa.jbbp.model.JBBPFieldUByte;
+import com.igormaznitsa.jbbp.model.JBBPFieldUInt;
import com.igormaznitsa.jbbp.model.JBBPFieldUShort;
/**
@@ -83,6 +85,12 @@ public enum BinType {
* A Mapping field will be mapped to a parsed integer field.
*/
INT(JBBPFieldInt.class, false),
+ /**
+ * A Mapping field will be mapped to a parsed unsigned integer field.
+ *
+ * @since 2.0.4
+ */
+ UINT(JBBPFieldUInt.class, false),
/**
* A Mapping field will be mapped to a parsed double field.
*
@@ -133,6 +141,10 @@ public enum BinType {
* A Mapping field will be mapped to a parsed integer array field.
*/
INT_ARRAY(JBBPFieldArrayInt.class, true),
+ /**
+ * A Mapping field will be mapped to a parsed unsigned integer array field.
+ */
+ UINT_ARRAY(JBBPFieldArrayUInt.class, true),
/**
* A Mapping field will be mapped to a parsed long array field.
*/
@@ -172,7 +184,7 @@ public enum BinType {
/**
* The Flag shows that the type describes an array.
*/
- private final boolean isarray;
+ private final boolean arrayFlag;
/**
* The Field class for the value.
@@ -181,7 +193,7 @@ public enum BinType {
*/
BinType(final Class extends JBBPAbstractField> fieldClass, final boolean array) {
this.fieldClass = fieldClass;
- this.isarray = array;
+ this.arrayFlag = array;
}
/**
@@ -255,7 +267,7 @@ public static BinType findCompatible(final Class> fieldClazz) {
* @return true if the type is an array, false otherwise
*/
public boolean isArray() {
- return this.isarray;
+ return this.arrayFlag;
}
/**
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/JBBPMapper.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/JBBPMapper.java
index 93144865..adb58652 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/JBBPMapper.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/JBBPMapper.java
@@ -49,7 +49,8 @@ public final class JBBPMapper {
* @since 1.1
*/
public static final int FLAG_IGNORE_MISSING_VALUES = 1;
- private static final Map, List> CACHED_FIELDS = new ConcurrentHashMap<>();
+ private static final Map, List> CACHED_FIELDS =
+ new ConcurrentHashMap<>();
/**
* Create a class instance, map binary data of a structure for its path to its
@@ -57,7 +58,7 @@ public final class JBBPMapper {
*
* @param the mapping class type
* @param root a parsed structure to be used as the root, must not be null
- * @param structPath the path of a structure inside of the root to be mapped
+ * @param structPath the path of a structure inside the root to be mapped
* to the class, must not be null
* @param instance object to be filled by values, must not be null
* @param instantiators functions to produce class instance by request, must not be null
@@ -66,7 +67,8 @@ public final class JBBPMapper {
* @since 2.0.0
*/
@SafeVarargs
- public static T map(final JBBPFieldStruct root, final String structPath, final T instance, final Function, Object>... instantiators) {
+ public static T map(final JBBPFieldStruct root, final String structPath, final T instance,
+ final Function, Object>... instantiators) {
return map(root, structPath, instance, null, instantiators);
}
@@ -76,7 +78,7 @@ public static T map(final JBBPFieldStruct root, final String structPath, fin
*
* @param the mapping class type
* @param root a parsed structure to be used as the root, must not be null
- * @param structPath the path of a structure inside of the root to be mapped
+ * @param structPath the path of a structure inside the root to be mapped
* to the class, must not be null
* @param instance object to be filled by values, must not be null
* @param flags special flags to tune mapping process
@@ -88,7 +90,8 @@ public static T map(final JBBPFieldStruct root, final String structPath, fin
* @since 2.0.0
*/
@SafeVarargs
- public static T map(final JBBPFieldStruct root, final String structPath, final T instance, final int flags, final Function, Object>... instantiators) {
+ public static T map(final JBBPFieldStruct root, final String structPath, final T instance,
+ final int flags, final Function, Object>... instantiators) {
return map(root, structPath, instance, null, flags, instantiators);
}
@@ -98,7 +101,7 @@ public static T map(final JBBPFieldStruct root, final String structPath, fin
*
* @param the mapping class type
* @param root a parsed structure to be used as the root, must not be null
- * @param structPath the path of a structure inside of the root to be mapped
+ * @param structPath the path of a structure inside the root to be mapped
* to the class, must not be null
* @param instance instance to be filled by values, must not be null
* @param customFieldProcessor a custom field processor to provide custom
@@ -111,7 +114,9 @@ public static T map(final JBBPFieldStruct root, final String structPath, fin
* @since 2.0.0
*/
@SafeVarargs
- public static T map(final JBBPFieldStruct root, final String structPath, final T instance, final JBBPMapperCustomFieldProcessor customFieldProcessor, final Function, Object>... instantiators) {
+ public static T map(final JBBPFieldStruct root, final String structPath, final T instance,
+ final JBBPMapperCustomFieldProcessor customFieldProcessor,
+ final Function, Object>... instantiators) {
return map(root, structPath, instance, customFieldProcessor, 0, instantiators);
}
@@ -121,7 +126,7 @@ public static T map(final JBBPFieldStruct root, final String structPath, fin
*
* @param the mapping class type
* @param root a parsed structure to be used as the root, must not be null
- * @param structPath the path of a structure inside of the root to be mapped
+ * @param structPath the path of a structure inside the root to be mapped
* to the class, must not be null
* @param instance object to be filled by values, must not be null
* @param customFieldProcessor a custom field processor to provide custom
@@ -136,11 +141,15 @@ public static T map(final JBBPFieldStruct root, final String structPath, fin
* @since 2.0.0
*/
@SafeVarargs
- public static T map(final JBBPFieldStruct root, final String structPath, final T instance, final JBBPMapperCustomFieldProcessor customFieldProcessor, final int flags, final Function, Object>... instantiators) {
+ public static T map(final JBBPFieldStruct root, final String structPath, final T instance,
+ final JBBPMapperCustomFieldProcessor customFieldProcessor,
+ final int flags, final Function, Object>... instantiators) {
JBBPUtils.assertNotNull(structPath, "Path must not be null");
final JBBPFieldStruct struct = root.findFieldForPathAndType(structPath, JBBPFieldStruct.class);
if (struct == null) {
- throw new JBBPMapperException("Can't find a structure field for its path [" + structPath + ']', null, instance.getClass(), null, null);
+ throw new JBBPMapperException(
+ "Can't find a structure field for its path [" + structPath + ']', null,
+ instance.getClass(), null, null);
}
return map(struct, instance, customFieldProcessor, flags, instantiators);
}
@@ -161,7 +170,8 @@ public static T map(final JBBPFieldStruct root, final String structPath, fin
* @since 2.0.0
*/
@SafeVarargs
- public static T map(final JBBPFieldStruct root, final T instance, final Function, Object>... instantiators) {
+ public static T map(final JBBPFieldStruct root, final T instance,
+ final Function, Object>... instantiators) {
return map(root, instance, null, instantiators);
}
@@ -184,7 +194,8 @@ public static T map(final JBBPFieldStruct root, final T instance, final Func
* @since 2.0.0
*/
@SafeVarargs
- public static T map(final JBBPFieldStruct root, final T instance, final int flags, final Function, Object>... instantiators) {
+ public static T map(final JBBPFieldStruct root, final T instance, final int flags,
+ final Function, Object>... instantiators) {
return map(root, instance, null, flags, instantiators);
}
@@ -205,44 +216,59 @@ public static T map(final JBBPFieldStruct root, final T instance, final int
* @throws JBBPMapperException for any error
*/
@SafeVarargs
- public static T map(final JBBPFieldStruct rootStructure, final T instance, final JBBPMapperCustomFieldProcessor customFieldProcessor, final Function, Object>... instantiators) {
+ public static T map(final JBBPFieldStruct rootStructure, final T instance,
+ final JBBPMapperCustomFieldProcessor customFieldProcessor,
+ final Function, Object>... instantiators) {
return map(rootStructure, instance, customFieldProcessor, 0, instantiators);
}
@SafeVarargs
@SuppressWarnings("varargs")
private static void processFieldOfMappedClass(
- final MappedFieldRecord record,
- final JBBPFieldStruct rootStructure,
- final Object instance,
- final JBBPMapperCustomFieldProcessor customFieldProcessor,
- final int flags,
- final Function, Object>... instantiators
+ final MappedFieldRecord record,
+ final JBBPFieldStruct rootStructure,
+ final Object instance,
+ final JBBPMapperCustomFieldProcessor customFieldProcessor,
+ final int flags,
+ final BinFieldFilter binFieldFilter,
+ final Function, Object>... instantiators
) {
if (record.binAnnotation.custom()) {
- JBBPUtils.assertNotNull(customFieldProcessor, "There is a custom mapping field, in the case you must provide a custom mapping field processor");
- final Object value = customFieldProcessor.prepareObjectForMapping(rootStructure, record.binAnnotation, record.mappingField);
+ JBBPUtils.assertNotNull(customFieldProcessor,
+ "There is a custom mapping field, in the case you must provide a custom mapping field processor");
+ final Object value = customFieldProcessor
+ .prepareObjectForMapping(rootStructure, record.binAnnotation, record.mappingField);
MappedFieldRecord.setFieldValue(instance, record.setter, record.mappingField, null, value);
} else {
final JBBPAbstractField binField;
- if (record.fieldPath.length() == 0) {
- binField = record.fieldName.length() == 0 ? rootStructure.findFieldForType(record.fieldType.getFieldClass()) : rootStructure.findFieldForNameAndType(record.fieldName, record.fieldType.getFieldClass());
+ if (record.fieldPath.isEmpty()) {
+ binField = record.fieldName.isEmpty() ?
+ rootStructure.findFieldForType(record.fieldType.getFieldClass()) : rootStructure
+ .findFieldForNameAndType(record.fieldName, record.fieldType.getFieldClass());
} else {
- binField = rootStructure.findFieldForPathAndType(record.fieldPath, record.fieldType.getFieldClass());
+ binField = rootStructure
+ .findFieldForPathAndType(record.fieldPath, record.fieldType.getFieldClass());
}
if (binField == null) {
if ((flags & FLAG_IGNORE_MISSING_VALUES) != 0) {
return;
}
- throw new JBBPMapperException("Can't find value for mapping field [" + record.mappingField + ']', null, record.mappingClass, record.mappingField, null);
+ throw new JBBPMapperException(
+ "Can't find value for mapping field [" + record.mappingField + ']', null,
+ record.mappingClass, record.mappingField, null);
}
- if (record.bitWideField && record.mappedBitNumber != JBBPBitNumber.BITS_8 && ((BitEntity) binField).getBitWidth() != record.mappedBitNumber) {
- throw new JBBPMapperException("Can't map mapping field because wrong field bitness [" + record.mappedBitNumber + "!=" + ((BitEntity) binField).getBitWidth().getBitNumber() + ']', null, record.mappingClass, record.mappingField, null);
+ if (record.bitWideField && record.mappedBitNumber != JBBPBitNumber.BITS_8 &&
+ ((BitEntity) binField).getBitWidth() != record.mappedBitNumber) {
+ throw new JBBPMapperException(
+ "Can't map mapping field because wrong field bitness [" + record.mappedBitNumber +
+ "!=" + ((BitEntity) binField).getBitWidth().getBitNumber() + ']', null,
+ record.mappingClass, record.mappingField, null);
}
- record.proc.apply(record, rootStructure, instance, customFieldProcessor, binField, flags, instantiators);
+ record.proc.apply(record, rootStructure, instance, customFieldProcessor, binField, flags,
+ binFieldFilter, instantiators);
}
}
@@ -267,19 +293,53 @@ private static void processFieldOfMappedClass(
*/
@SafeVarargs
@SuppressWarnings("varargs")
- public static T map(final JBBPFieldStruct rootStructure, final T instance, final JBBPMapperCustomFieldProcessor customFieldProcessor, final int flags, final Function, Object>... instantiators) {
+ public static T map(final JBBPFieldStruct rootStructure, final T instance,
+ final JBBPMapperCustomFieldProcessor customFieldProcessor,
+ final int flags,
+ final Function, Object>... instantiators) {
+ return map(rootStructure, instance, customFieldProcessor, flags, null, instantiators);
+ }
+
+ /**
+ * Map a structure to a class instance.
+ *
+ * @param the mapping class type
+ * @param rootStructure a structure to be mapped, must not be null
+ * @param instance a class instance to be destination for map
+ * operations, must not be null
+ * @param customFieldProcessor a custom field processor to provide custom
+ * values, it can be null if there is not any mapping field desires the
+ * processor
+ * @param flags special flags for mapping process
+ * @param binFieldFilter filter allows to exclude some fields from process, can be null
+ * @param instantiators functions to produce class instance by request, must
+ * not be null
+ * @return the processed class instance, the same which was the argument for
+ * the method.
+ * @throws JBBPMapperException for any error
+ * @see #FLAG_IGNORE_MISSING_VALUES
+ * @since 2.0.4
+ */
+ @SafeVarargs
+ @SuppressWarnings("varargs")
+ public static T map(final JBBPFieldStruct rootStructure, final T instance,
+ final JBBPMapperCustomFieldProcessor customFieldProcessor,
+ final int flags,
+ final BinFieldFilter binFieldFilter,
+ final Function, Object>... instantiators) {
JBBPUtils.assertNotNull(rootStructure, "The Root structure must not be null");
JBBPUtils.assertNotNull(instance, "The Mapping class instance must not be null");
// Don't use forEach() for Android compatibility!
- for (final MappedFieldRecord record : findAffectedFields(instance)) {
+ for (final MappedFieldRecord record : findAffectedFields(instance, binFieldFilter)) {
processFieldOfMappedClass(
- record,
- rootStructure,
- instance,
- customFieldProcessor,
- flags,
- instantiators
+ record,
+ rootStructure,
+ instance,
+ customFieldProcessor,
+ flags,
+ binFieldFilter,
+ instantiators
);
}
return instance;
@@ -304,7 +364,7 @@ public static void clearFieldCache() {
CACHED_FIELDS.clear();
}
- public static List findAffectedFields(final Object instance) {
+ public static List findAffectedFields(final Object instance, final BinFieldFilter binFieldFilter) {
final Class> mappingClass = instance.getClass();
List result = CACHED_FIELDS.get(mappingClass);
@@ -319,8 +379,8 @@ public static List findAffectedFields(final Object instance)
while (current != null) {
final String packageName = current.getPackage().getName();
if (packageName.startsWith("java.")
- || packageName.startsWith("javax.")
- || packageName.startsWith("android.")
+ || packageName.startsWith("javax.")
+ || packageName.startsWith("android.")
) {
break;
}
@@ -334,15 +394,16 @@ public static List findAffectedFields(final Object instance)
final Bin fieldAnno = mappingField.getAnnotation(Bin.class);
final Bin mappedAnno;
- if ((fieldAnno == null && defaultAnno == null) || mappingField.getName().indexOf('$') >= 0) {
+ if ((fieldAnno == null && defaultAnno == null) ||
+ mappingField.getName().indexOf('$') >= 0) {
continue;
}
mappedAnno = fieldAnno == null ? defaultAnno : fieldAnno;
if (fieldAnno == null) {
if (Modifier.isTransient(fieldModifiers)
- || Modifier.isStatic(fieldModifiers)
- || Modifier.isFinal(fieldModifiers)) {
+ || Modifier.isStatic(fieldModifiers)
+ || Modifier.isFinal(fieldModifiers)) {
continue;
}
} else {
@@ -355,26 +416,33 @@ public static List findAffectedFields(final Object instance)
disallowedModifier = null;
}
if (disallowedModifier != null) {
- throw new JBBPMapperException("Detected @Bin marked " + disallowedModifier + " field", null, processingClazz, mappingField, null);
+ throw new JBBPMapperException("Detected @Bin marked " + disallowedModifier + " field",
+ null, processingClazz, mappingField, null);
}
}
- final NullableTriple auxMethods = findAuxFieldMethods(processingClazz, mappingField);
+ final NullableTriple auxMethods =
+ findAuxFieldMethods(processingClazz, mappingField);
final Method fieldGenerator = auxMethods.getA();
final Method fieldGetter = auxMethods.getB();
final Method fieldSetter = auxMethods.getC();
- if (mappingField.getType().isPrimitive() && fieldSetter == null && Modifier.isPrivate(mappingField.getModifiers())) {
- throw new JBBPMapperException("Detected private primitive field, mapping requires setter", null, processingClazz, mappingField, null);
+ if (mappingField.getType().isPrimitive() && fieldSetter == null &&
+ Modifier.isPrivate(mappingField.getModifiers())) {
+ throw new JBBPMapperException(
+ "Detected private primitive field, mapping requires setter", null, processingClazz,
+ mappingField, null);
}
- if (fieldGetter == null && fieldGenerator == null && !ReflectUtils.isPotentiallyAccessibleField(mappingField)) {
+ if (fieldGetter == null && fieldGenerator == null &&
+ !ReflectUtils.isPotentiallyAccessibleField(mappingField)) {
mappingField = ReflectUtils.makeAccessible(mappingField);
}
try {
- result.add(new MappedFieldRecord(mappingField, fieldGenerator, fieldSetter, fieldGetter, mappingClass, mappedAnno));
+ result.add(new MappedFieldRecord(mappingField, fieldGenerator, fieldSetter, fieldGetter,
+ mappingClass, mappedAnno));
} catch (IllegalStateException ex) {
throw new JBBPMapperException(ex.getMessage(), null, mappingClass, mappingField, ex);
}
@@ -386,10 +454,21 @@ public static List findAffectedFields(final Object instance)
CACHED_FIELDS.put(mappingClass, result);
}
+ if (binFieldFilter != null) {
+ final List filteredRecords = new ArrayList<>();
+ for (final MappedFieldRecord r : result) {
+ if (binFieldFilter.isAllowed(r.binAnnotation, r.mappingField)) {
+ filteredRecords.add(r);
+ }
+ }
+ result = filteredRecords;
+ }
+
return result;
}
- private static NullableTriple findAuxFieldMethods(final Class> klazz, final Field field) {
+ private static NullableTriple findAuxFieldMethods(final Class> klazz,
+ final Field field) {
final String lowerCasedFieldName = field.getName().toLowerCase(Locale.ENGLISH);
final String generatorName = "make" + lowerCasedFieldName;
final String getterName = "get" + lowerCasedFieldName;
@@ -417,7 +496,8 @@ private static NullableTriple findAuxFieldMethods(final
}
}
- if (args.length == 1 && setter == null && lcMethodName.equals(setterName) && field.getType().isAssignableFrom(args[0])) {
+ if (args.length == 1 && setter == null && lcMethodName.equals(setterName) &&
+ field.getType().isAssignableFrom(args[0])) {
setter = m;
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/JBBPMapperCustomFieldProcessor.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/JBBPMapperCustomFieldProcessor.java
index 3a5a6d55..a46bca3e 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/JBBPMapperCustomFieldProcessor.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/JBBPMapperCustomFieldProcessor.java
@@ -17,7 +17,6 @@
package com.igormaznitsa.jbbp.mapper;
import com.igormaznitsa.jbbp.model.JBBPFieldStruct;
-
import java.lang.reflect.Field;
/**
@@ -34,5 +33,6 @@ public interface JBBPMapperCustomFieldProcessor {
* @param field the mapping field in a mapping class, must not be null
* @return an object which will be set to the field in a mapping class instance, it can be null for non-primitive fields
*/
- Object prepareObjectForMapping(final JBBPFieldStruct parsedBlock, final Bin annotation, final Field field);
+ Object prepareObjectForMapping(final JBBPFieldStruct parsedBlock, final Bin annotation,
+ final Field field);
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/MappedFieldRecord.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/MappedFieldRecord.java
index bb1131fd..07084e8c 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/MappedFieldRecord.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/mapper/MappedFieldRecord.java
@@ -2,7 +2,6 @@
import static com.igormaznitsa.jbbp.mapper.JBBPMapper.MAKE_CLASS_INSTANCE_METHOD_NAME;
-
import com.igormaznitsa.jbbp.exceptions.JBBPMapperException;
import com.igormaznitsa.jbbp.io.JBBPBitNumber;
import com.igormaznitsa.jbbp.io.JBBPBitOrder;
@@ -15,6 +14,7 @@
import com.igormaznitsa.jbbp.model.JBBPFieldArrayShort;
import com.igormaznitsa.jbbp.model.JBBPFieldArrayStruct;
import com.igormaznitsa.jbbp.model.JBBPFieldArrayUByte;
+import com.igormaznitsa.jbbp.model.JBBPFieldArrayUInt;
import com.igormaznitsa.jbbp.model.JBBPFieldArrayUShort;
import com.igormaznitsa.jbbp.model.JBBPFieldInt;
import com.igormaznitsa.jbbp.model.JBBPFieldLong;
@@ -29,128 +29,162 @@
import java.lang.reflect.Modifier;
public final class MappedFieldRecord implements Comparable {
- private static final Function, Object> STATIC_MAKE_CLASS_INSTANCE_INSTANTIATOR = (Class> klazz) -> {
- Class> currentClass = klazz;
- Object result = null;
- boolean find;
- do {
- try {
- final Method method = currentClass.getMethod(MAKE_CLASS_INSTANCE_METHOD_NAME, Class.class);
- if (Modifier.isStatic(method.getModifiers())) {
- result = method.invoke(null, klazz);
- }
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(String.format("Can't get access to static method %s(%ss) in %s", MAKE_CLASS_INSTANCE_METHOD_NAME, klazz, currentClass), ex);
- } catch (InvocationTargetException ex) {
- throw new RuntimeException(String.format("Can't call static method %s(%s) in %s", MAKE_CLASS_INSTANCE_METHOD_NAME, klazz, currentClass), ex);
- } catch (NoSuchMethodException ex) {
- // do nothing!
- }
- if (result == null) {
- if (currentClass.isLocalClass()) {
- currentClass = currentClass.getEnclosingClass();
- find = currentClass != null;
- } else {
- find = false;
+ private static final Function, Object> STATIC_MAKE_CLASS_INSTANCE_INSTANTIATOR =
+ (Class> klazz) -> {
+ Class> currentClass = klazz;
+ Object result = null;
+ boolean find;
+ do {
+ try {
+ final Method method =
+ currentClass.getMethod(MAKE_CLASS_INSTANCE_METHOD_NAME, Class.class);
+ if (Modifier.isStatic(method.getModifiers())) {
+ result = method.invoke(null, klazz);
+ }
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(String
+ .format("Can't get access to static method %s(%ss) in %s",
+ MAKE_CLASS_INSTANCE_METHOD_NAME, klazz, currentClass), ex);
+ } catch (InvocationTargetException ex) {
+ throw new RuntimeException(String
+ .format("Can't call static method %s(%s) in %s", MAKE_CLASS_INSTANCE_METHOD_NAME,
+ klazz, currentClass), ex);
+ } catch (NoSuchMethodException ex) {
+ // do nothing!
+ }
+ if (result == null) {
+ if (currentClass.isLocalClass()) {
+ currentClass = currentClass.getEnclosingClass();
+ find = currentClass != null;
+ } else {
+ find = false;
+ }
+ } else {
+ find = false;
+ }
+ } while (find);
+ return result;
+ };
+ private static final Function, Object> DEFAULT_CONSTRUCTOR_INSTANTIATOR =
+ (Class> aClass) -> {
+ try {
+ if (!aClass.isLocalClass() || Modifier.isStatic(aClass.getModifiers())) {
+ return aClass.getConstructor().newInstance();
+ } else {
+ return null;
+ }
+ } catch (NoSuchMethodException ex) {
+ return null;
+ } catch (InvocationTargetException ex) {
+ throw new RuntimeException(
+ String.format("Error during default constructor call, class %s", aClass), ex);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(
+ String.format("Can't get access to default constructor , class %s", aClass), ex);
+ } catch (InstantiationException ex) {
+ throw new RuntimeException(String.format("Can't make instance of class %s", aClass), ex);
}
- } else {
- find = false;
- }
- } while (find);
- return result;
- };
- private static final Function, Object> DEFAULT_CONSTRUCTOR_INSTANTIATOR = (Class> aClass) -> {
- try {
- if (!aClass.isLocalClass() || Modifier.isStatic(aClass.getModifiers())) {
- return aClass.getConstructor().newInstance();
- } else {
- return null;
- }
- } catch (NoSuchMethodException ex) {
- return null;
- } catch (InvocationTargetException ex) {
- throw new RuntimeException(String.format("Error during default constructor call, class %s", aClass), ex);
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(String.format("Can't get access to default constructor , class %s", aClass), ex);
- } catch (InstantiationException ex) {
- throw new RuntimeException(String.format("Can't make instance of class %s", aClass), ex);
- }
- };
- private static final FieldProcessor PROC_ARRAYS = (record, rootStructure, instance, customFieldProcessor, binField, flags, instantiators) -> {
+ };
+ private static final FieldProcessor PROC_ARRAYS =
+ (record, rootStructure, instance, customFieldProcessor, binField, flags, binFieldFilter, instantiators) -> {
- if (binField instanceof JBBPAbstractArrayField) {
- if (binField instanceof JBBPFieldArrayStruct) {
- // structure
- final JBBPFieldArrayStruct structArray = (JBBPFieldArrayStruct) binField;
- final Class> componentType = record.mappingField.getType().getComponentType();
+ if (binField instanceof JBBPAbstractArrayField) {
+ if (binField instanceof JBBPFieldArrayStruct) {
+ // structure
+ final JBBPFieldArrayStruct structArray = (JBBPFieldArrayStruct) binField;
+ final Class> componentType = record.mappingField.getType().getComponentType();
- Object valueArray = getFieldValue(instance, record.getter, record.mappingField);
+ Object valueArray = getFieldValue(instance, record.getter, record.mappingField);
- valueArray = valueArray == null ? Array.newInstance(componentType, structArray.size()) : valueArray;
+ valueArray = valueArray == null ? Array.newInstance(componentType, structArray.size()) :
+ valueArray;
- if (Array.getLength(valueArray) != structArray.size()) {
- throw new JBBPMapperException("Can't map an array field for different expected size [" + Array.getLength(valueArray) + "!=" + structArray.size() + ']', binField, record.mappingClass, record.mappingField, null);
- }
+ if (Array.getLength(valueArray) != structArray.size()) {
+ throw new JBBPMapperException(
+ "Can't map an array field for different expected size [" +
+ Array.getLength(valueArray) + "!=" + structArray.size() + ']', binField,
+ record.mappingClass, record.mappingField, null);
+ }
- for (int i = 0; i < structArray.size(); i++) {
- final Object curInstance = Array.get(valueArray, i);
- if (curInstance == null) {
- Array.set(valueArray, i, JBBPMapper.map(structArray.getElementAt(i), tryMakeInstance(componentType, binField, instance, record.mappingField, instantiators), customFieldProcessor, instantiators));
+ for (int i = 0; i < structArray.size(); i++) {
+ final Object curInstance = Array.get(valueArray, i);
+ if (curInstance == null) {
+ Array.set(valueArray, i, JBBPMapper.map(structArray.getElementAt(i),
+ tryMakeInstance(componentType, binField, instance, record.mappingField,
+ instantiators), customFieldProcessor, 0, binFieldFilter, instantiators));
+ } else {
+ Array.set(valueArray, i,
+ JBBPMapper.map(structArray.getElementAt(i), curInstance, customFieldProcessor, 0, binFieldFilter));
+ }
+ }
+ setFieldValue(instance, record.setter, record.mappingField, binField, valueArray);
} else {
- Array.set(valueArray, i, JBBPMapper.map(structArray.getElementAt(i), curInstance, customFieldProcessor));
+ // primitive
+ mapArrayField(instance, record.setter, record.mappingField,
+ (JBBPAbstractArrayField>) binField,
+ record.binAnnotation.bitOrder() == JBBPBitOrder.MSB0);
}
+ } else {
+ throw new JBBPMapperException("Can't map a non-array value to an array mapping field",
+ binField, record.mappingClass, record.mappingField, null);
}
- setFieldValue(instance, record.setter, record.mappingField, binField, valueArray);
- } else {
- // primitive
- mapArrayField(instance, record.setter, record.mappingField, (JBBPAbstractArrayField>) binField, record.binAnnotation.bitOrder() == JBBPBitOrder.MSB0);
- }
- } else {
- throw new JBBPMapperException("Can't map a non-array value to an array mapping field", binField, record.mappingClass, record.mappingField, null);
- }
- };
- private static final FieldProcessor PROC_NUM = (record, rootStructure, instance, customFieldProcessor, binField, flags, instantiators) -> {
- if (binField instanceof JBBPNumericField) {
- mapNumericField(instance, record.setter, record.mappingField, (JBBPNumericField) binField, record.binAnnotation.bitOrder() == JBBPBitOrder.MSB0);
- } else if (binField instanceof JBBPFieldString) {
- if (record.mappingField.getType().isPrimitive()) {
- throw new JBBPMapperException("Can't map string to a primitive mapping field", binField, record.mappingClass, record.mappingField, null);
- } else {
- setFieldValue(instance, record.setter, record.mappingField, binField, ((JBBPFieldString) binField).getAsString());
- }
- } else if (binField instanceof JBBPFieldStruct) {
- if (record.mappingField.getType().isPrimitive()) {
- throw new JBBPMapperException("Can't map structure to a primitive mapping field", binField, record.mappingClass, record.mappingField, null);
- } else {
- final Object curValue = getFieldValue(instance, record.getter, record.mappingField);
- if (curValue == null) {
- if (record.instanceMaker == null) {
- setFieldValue(instance, record.setter, record.mappingField, binField, JBBPMapper.map((JBBPFieldStruct) binField, tryMakeInstance(record.mappingField.getType(), binField, instance, record.mappingField, instantiators), customFieldProcessor));
+ };
+ private static final FieldProcessor PROC_NUM =
+ (record, rootStructure, instance, customFieldProcessor, binField, flags, binFieldFilter, instantiators) -> {
+ if (binField instanceof JBBPNumericField) {
+ mapNumericField(instance, record.setter, record.mappingField, (JBBPNumericField) binField,
+ record.binAnnotation.bitOrder() == JBBPBitOrder.MSB0);
+ } else if (binField instanceof JBBPFieldString) {
+ if (record.mappingField.getType().isPrimitive()) {
+ throw new JBBPMapperException("Can't map string to a primitive mapping field", binField,
+ record.mappingClass, record.mappingField, null);
+ } else {
+ setFieldValue(instance, record.setter, record.mappingField, binField,
+ ((JBBPFieldString) binField).getAsString());
+ }
+ } else if (binField instanceof JBBPFieldStruct) {
+ if (record.mappingField.getType().isPrimitive()) {
+ throw new JBBPMapperException("Can't map structure to a primitive mapping field",
+ binField, record.mappingClass, record.mappingField, null);
} else {
- try {
- JBBPMapper.map((JBBPFieldStruct) binField, record.instanceMaker.invoke(instance));
- } catch (Exception ex) {
- throw new JBBPMapperException("Can't map field which member generatet by instance", binField, record.mappingClass, record.mappingField, ex);
+ final Object curValue = getFieldValue(instance, record.getter, record.mappingField);
+ if (curValue == null) {
+ if (record.instanceMaker == null) {
+ setFieldValue(instance, record.setter, record.mappingField, binField, JBBPMapper
+ .map((JBBPFieldStruct) binField,
+ tryMakeInstance(record.mappingField.getType(), binField, instance,
+ record.mappingField, instantiators), customFieldProcessor, 0, binFieldFilter));
+ } else {
+ try {
+ JBBPMapper.map((JBBPFieldStruct) binField, record.instanceMaker.invoke(instance));
+ } catch (Exception ex) {
+ throw new JBBPMapperException(
+ "Can't map field which member generated by instance", binField,
+ record.mappingClass, record.mappingField, ex);
+ }
+ }
+ } else {
+ setFieldValue(instance, record.setter, record.mappingField, binField,
+ JBBPMapper.map((JBBPFieldStruct) binField, curValue, customFieldProcessor));
}
}
} else {
- setFieldValue(instance, record.setter, record.mappingField, binField, JBBPMapper.map((JBBPFieldStruct) binField, curValue, customFieldProcessor));
- }
- }
- } else {
- boolean processed = false;
- if (record.mappingField.getType() == String.class && binField instanceof JBBPAbstractArrayField) {
- final String convertedValue = convertFieldValueToString((JBBPAbstractArrayField>) binField);
- if (convertedValue != null) {
- setFieldValue(instance, record.setter, record.mappingField, binField, convertedValue);
- processed = true;
+ boolean processed = false;
+ if (record.mappingField.getType() == String.class &&
+ binField instanceof JBBPAbstractArrayField) {
+ final String convertedValue =
+ convertFieldValueToString((JBBPAbstractArrayField>) binField);
+ if (convertedValue != null) {
+ setFieldValue(instance, record.setter, record.mappingField, binField, convertedValue);
+ processed = true;
+ }
+ }
+ if (!processed) {
+ throw new JBBPMapperException("Can't map a field for its value incompatibility",
+ binField, record.mappingClass, record.mappingField, null);
+ }
}
- }
- if (!processed) {
- throw new JBBPMapperException("Can't map a field for its value incompatibility", binField, record.mappingClass, record.mappingField, null);
- }
- }
- };
+ };
public final Field mappingField;
public final Class> mappingClass;
@@ -182,19 +216,21 @@ public final class MappedFieldRecord implements Comparable {
this.mappedBitNumber = binAnnotation.bitNumber();
if (binAnnotation.type() == BinType.UNDEFINED) {
- BinType thetype = BinType.findCompatible(mappingField.getType());
- if (thetype == null) {
+ BinType compatibleBinType = BinType.findCompatible(mappingField.getType());
+ if (compatibleBinType == null) {
throw new IllegalStateException("Can't find compatible mapped type for field");
- } else if (this.mappedBitNumber.getBitNumber() < 8 && !(thetype == BinType.STRUCT || thetype == BinType.STRUCT_ARRAY)) {
- thetype = thetype.isArray() ? BinType.BIT_ARRAY : BinType.BIT;
+ } else if (this.mappedBitNumber.getBitNumber() < 8 &&
+ !(compatibleBinType == BinType.STRUCT || compatibleBinType == BinType.STRUCT_ARRAY)) {
+ compatibleBinType = compatibleBinType.isArray() ? BinType.BIT_ARRAY : BinType.BIT;
}
- this.fieldType = thetype;
+ this.fieldType = compatibleBinType;
} else {
this.fieldType = binAnnotation.type();
}
this.bitWideField = this.fieldType == BinType.BIT || fieldType == BinType.BIT_ARRAY;
- this.fieldName = binAnnotation.name().length() == 0 ? mappingField.getName() : binAnnotation.name();
+ this.fieldName =
+ binAnnotation.name().isEmpty() ? mappingField.getName() : binAnnotation.name();
this.fieldPath = binAnnotation.path();
if (this.mappingField.getType().isArray()) {
@@ -215,30 +251,60 @@ public final class MappedFieldRecord implements Comparable {
* @param invertBitOrder flag shows that values of an array must be bit
* reversed before set
*/
- private static void mapArrayField(final Object mappingClassInstance, final Method setter, final Field mappingField, final JBBPAbstractArrayField> arrayField, final boolean invertBitOrder) {
+ private static void mapArrayField(final Object mappingClassInstance, final Method setter,
+ final Field mappingField,
+ final JBBPAbstractArrayField> arrayField,
+ final boolean invertBitOrder) {
try {
final Object value;
- if (arrayField instanceof JBBPFieldArrayLong && mappingField.getType().getComponentType() == double.class) {
- final long[] longarray = (long[]) arrayField.getValueArrayAsObject(invertBitOrder);
- final double[] doublearray = new double[longarray.length];
- for (int i = 0; i < longarray.length; i++) {
- doublearray[i] = Double.longBitsToDouble(longarray[i]);
+ if (arrayField instanceof JBBPFieldArrayLong &&
+ mappingField.getType().getComponentType() == double.class) {
+ final long[] longArray = (long[]) arrayField.getValueArrayAsObject(invertBitOrder);
+ final double[] doubleArray = new double[longArray.length];
+ for (int i = 0; i < longArray.length; i++) {
+ doubleArray[i] = Double.longBitsToDouble(longArray[i]);
+ }
+ value = doubleArray;
+ } else if (arrayField instanceof JBBPFieldArrayUInt &&
+ mappingField.getType().getComponentType() == double.class) {
+ final long[] longArray = (long[]) arrayField.getValueArrayAsObject(invertBitOrder);
+ final double[] doubleArray = new double[longArray.length];
+ for (int i = 0; i < longArray.length; i++) {
+ doubleArray[i] = Double.longBitsToDouble(longArray[i]);
+ }
+ value = doubleArray;
+ } else if (arrayField instanceof JBBPFieldArrayInt &&
+ mappingField.getType().getComponentType() == float.class) {
+ final int[] intArray = (int[]) arrayField.getValueArrayAsObject(invertBitOrder);
+ final float[] floatArray = new float[intArray.length];
+ for (int i = 0; i < intArray.length; i++) {
+ floatArray[i] = Float.intBitsToFloat(intArray[i]);
+ }
+ value = floatArray;
+ } else if (arrayField instanceof JBBPFieldArrayUInt &&
+ mappingField.getType().getComponentType() == float.class) {
+ final long[] longArray = (long[]) arrayField.getValueArrayAsObject(invertBitOrder);
+ final float[] floatArray = new float[longArray.length];
+ for (int i = 0; i < longArray.length; i++) {
+ floatArray[i] = Float.intBitsToFloat((int) longArray[i]);
}
- value = doublearray;
- } else if (arrayField instanceof JBBPFieldArrayInt && mappingField.getType().getComponentType() == float.class) {
- final int[] intarray = (int[]) arrayField.getValueArrayAsObject(invertBitOrder);
- final float[] floatarray = new float[intarray.length];
- for (int i = 0; i < intarray.length; i++) {
- floatarray[i] = Float.intBitsToFloat(intarray[i]);
+ value = floatArray;
+ } else if (arrayField instanceof JBBPFieldArrayUInt &&
+ mappingField.getType().getComponentType() == int.class) {
+ final long[] longArray = (long[]) arrayField.getValueArrayAsObject(invertBitOrder);
+ final int[] intArray = new int[longArray.length];
+ for (int i = 0; i < longArray.length; i++) {
+ intArray[i] = (int) longArray[i];
}
- value = floatarray;
- } else if (arrayField instanceof JBBPFieldArrayUShort && mappingField.getType().getComponentType() == char.class) {
- final short[] shortarray = (short[]) arrayField.getValueArrayAsObject(invertBitOrder);
- final char[] chararray = new char[shortarray.length];
- for (int i = 0; i < shortarray.length; i++) {
- chararray[i] = (char) shortarray[i];
+ value = intArray;
+ } else if (arrayField instanceof JBBPFieldArrayUShort &&
+ mappingField.getType().getComponentType() == char.class) {
+ final short[] shortArray = (short[]) arrayField.getValueArrayAsObject(invertBitOrder);
+ final char[] charArray = new char[shortArray.length];
+ for (int i = 0; i < shortArray.length; i++) {
+ charArray[i] = (char) shortArray[i];
}
- value = chararray;
+ value = charArray;
} else {
value = arrayField.getValueArrayAsObject(invertBitOrder);
}
@@ -248,11 +314,14 @@ private static void mapArrayField(final Object mappingClassInstance, final Metho
setter.invoke(mappingClassInstance, value);
}
} catch (IllegalAccessException ex) {
- throw new JBBPMapperException("Can't get access to a mapping field", arrayField, mappingClassInstance.getClass(), mappingField, ex);
+ throw new JBBPMapperException("Can't get access to a mapping field", arrayField,
+ mappingClassInstance.getClass(), mappingField, ex);
} catch (IllegalArgumentException ex) {
- throw new JBBPMapperException("Can't set argument to a mapping field", arrayField, mappingClassInstance.getClass(), mappingField, ex);
+ throw new JBBPMapperException("Can't set argument to a mapping field", arrayField,
+ mappingClassInstance.getClass(), mappingField, ex);
} catch (InvocationTargetException ex) {
- throw new JBBPMapperException("Can't set argument to field through setter", arrayField, mappingClassInstance.getClass(), mappingField, ex);
+ throw new JBBPMapperException("Can't set argument to field through setter", arrayField,
+ mappingClassInstance.getClass(), mappingField, ex);
}
}
@@ -313,11 +382,14 @@ private static String convertFieldValueToString(final JBBPAbstractArrayField>
* @param invertBitOrder flag shows that the parsed numeric field value must
* be reversed in its bit before setting
*/
- private static void mapNumericField(final Object mappingClassInstance, final Method setter, final Field mappingField, final JBBPNumericField numericField, final boolean invertBitOrder) {
+ private static void mapNumericField(final Object mappingClassInstance, final Method setter,
+ final Field mappingField, final JBBPNumericField numericField,
+ final boolean invertBitOrder) {
final Class> fieldClass = mappingField.getType();
try {
if (fieldClass == byte.class) {
- final byte value = (byte) (invertBitOrder ? numericField.getAsInvertedBitOrder() : numericField.getAsInt());
+ final byte value = (byte) (invertBitOrder ? numericField.getAsInvertedBitOrder() :
+ numericField.getAsInt());
if (setter == null) {
mappingField.setByte(mappingClassInstance, value);
} else {
@@ -330,28 +402,32 @@ private static void mapNumericField(final Object mappingClassInstance, final Met
setter.invoke(mappingClassInstance, numericField.getAsBool());
}
} else if (fieldClass == char.class) {
- final char value = (char) (invertBitOrder ? numericField.getAsInvertedBitOrder() : numericField.getAsInt());
+ final char value = (char) (invertBitOrder ? numericField.getAsInvertedBitOrder() :
+ numericField.getAsInt());
if (setter == null) {
mappingField.setChar(mappingClassInstance, value);
} else {
setter.invoke(mappingClassInstance, value);
}
} else if (fieldClass == short.class) {
- final short value = (short) (invertBitOrder ? numericField.getAsInvertedBitOrder() : numericField.getAsInt());
+ final short value = (short) (invertBitOrder ? numericField.getAsInvertedBitOrder() :
+ numericField.getAsInt());
if (setter == null) {
mappingField.setShort(mappingClassInstance, value);
} else {
setter.invoke(mappingClassInstance, value);
}
} else if (fieldClass == int.class) {
- final int value = (int) (invertBitOrder ? numericField.getAsInvertedBitOrder() : numericField.getAsInt());
+ final int value =
+ (int) (invertBitOrder ? numericField.getAsInvertedBitOrder() : numericField.getAsInt());
if (setter == null) {
mappingField.setInt(mappingClassInstance, value);
} else {
setter.invoke(mappingClassInstance, value);
}
} else if (fieldClass == long.class) {
- final long value = (invertBitOrder ? numericField.getAsInvertedBitOrder() : numericField.getAsLong());
+ final long value =
+ (invertBitOrder ? numericField.getAsInvertedBitOrder() : numericField.getAsLong());
if (setter == null) {
mappingField.setLong(mappingClassInstance, value);
} else {
@@ -360,9 +436,13 @@ private static void mapNumericField(final Object mappingClassInstance, final Met
} else if (fieldClass == float.class) {
final float value;
if (numericField instanceof JBBPFieldInt) {
- value = invertBitOrder ? Float.intBitsToFloat((int) numericField.getAsInvertedBitOrder()) : Float.intBitsToFloat(numericField.getAsInt());
+ value =
+ invertBitOrder ? Float.intBitsToFloat((int) numericField.getAsInvertedBitOrder()) :
+ Float.intBitsToFloat(numericField.getAsInt());
} else {
- value = invertBitOrder ? Float.intBitsToFloat((int) numericField.getAsInvertedBitOrder()) : numericField.getAsFloat();
+ value =
+ invertBitOrder ? Float.intBitsToFloat((int) numericField.getAsInvertedBitOrder()) :
+ numericField.getAsFloat();
}
if (setter == null) {
mappingField.setFloat(mappingClassInstance, value);
@@ -372,9 +452,11 @@ private static void mapNumericField(final Object mappingClassInstance, final Met
} else if (fieldClass == double.class) {
final double value;
if (numericField instanceof JBBPFieldLong) {
- value = invertBitOrder ? Double.longBitsToDouble(numericField.getAsInvertedBitOrder()) : Double.longBitsToDouble(numericField.getAsLong());
+ value = invertBitOrder ? Double.longBitsToDouble(numericField.getAsInvertedBitOrder()) :
+ Double.longBitsToDouble(numericField.getAsLong());
} else {
- value = invertBitOrder ? Double.longBitsToDouble(numericField.getAsInvertedBitOrder()) : numericField.getAsDouble();
+ value = invertBitOrder ? Double.longBitsToDouble(numericField.getAsInvertedBitOrder()) :
+ numericField.getAsDouble();
}
if (setter == null) {
mappingField.setDouble(mappingClassInstance, value);
@@ -382,14 +464,19 @@ private static void mapNumericField(final Object mappingClassInstance, final Met
setter.invoke(mappingClassInstance, value);
}
} else {
- throw new JBBPMapperException("Unsupported mapping class field type to be mapped for binary parsed data", (JBBPAbstractField) numericField, mappingClassInstance.getClass(), mappingField, null);
+ throw new JBBPMapperException(
+ "Unsupported mapping class field type to be mapped for binary parsed data",
+ (JBBPAbstractField) numericField, mappingClassInstance.getClass(), mappingField, null);
}
} catch (IllegalAccessException ex) {
- throw new JBBPMapperException("Can't get access to a mapping field", (JBBPAbstractField) numericField, mappingClassInstance.getClass(), mappingField, ex);
+ throw new JBBPMapperException("Can't get access to a mapping field",
+ (JBBPAbstractField) numericField, mappingClassInstance.getClass(), mappingField, ex);
} catch (IllegalArgumentException ex) {
- throw new JBBPMapperException("Can't set argument to a mapping field", (JBBPAbstractField) numericField, mappingClassInstance.getClass(), mappingField, ex);
+ throw new JBBPMapperException("Can't set argument to a mapping field",
+ (JBBPAbstractField) numericField, mappingClassInstance.getClass(), mappingField, ex);
} catch (InvocationTargetException ex) {
- throw new JBBPMapperException("Can't set argument to a mapping field through setter", (JBBPAbstractField) numericField, mappingClassInstance.getClass(), mappingField, ex);
+ throw new JBBPMapperException("Can't set argument to a mapping field through setter",
+ (JBBPAbstractField) numericField, mappingClassInstance.getClass(), mappingField, ex);
}
}
@@ -402,7 +489,8 @@ private static void mapNumericField(final Object mappingClassInstance, final Met
* null
* @return the field value for the class instance
*/
- private static Object getFieldValue(final Object classInstance, final Method getter, final Field classField) {
+ private static Object getFieldValue(final Object classInstance, final Method getter,
+ final Field classField) {
try {
if (getter == null) {
return classField.get(classInstance);
@@ -410,11 +498,14 @@ private static Object getFieldValue(final Object classInstance, final Method get
return getter.invoke(classInstance);
}
} catch (IllegalArgumentException ex) {
- throw new JBBPMapperException("Can't set get value from a mapping field", null, classInstance.getClass(), classField, ex);
+ throw new JBBPMapperException("Can't set get value from a mapping field", null,
+ classInstance.getClass(), classField, ex);
} catch (IllegalAccessException ex) {
- throw new JBBPMapperException("Can't get access to a mapping field", null, classInstance.getClass(), classField, ex);
+ throw new JBBPMapperException("Can't get access to a mapping field", null,
+ classInstance.getClass(), classField, ex);
} catch (InvocationTargetException ex) {
- throw new JBBPMapperException("Can't get field value through getter", null, classInstance.getClass(), classField, ex);
+ throw new JBBPMapperException("Can't get field value through getter", null,
+ classInstance.getClass(), classField, ex);
}
}
@@ -429,7 +520,8 @@ private static Object getFieldValue(final Object classInstance, final Method get
* @param binField a parsed bin field which value will be set, can be null
* @param value a value to be set to the class field
*/
- static void setFieldValue(final Object classInstance, final Method setter, final Field classField, final JBBPAbstractField binField, final Object value) {
+ static void setFieldValue(final Object classInstance, final Method setter, final Field classField,
+ final JBBPAbstractField binField, final Object value) {
try {
if (setter == null) {
classField.set(classInstance, value);
@@ -437,21 +529,23 @@ static void setFieldValue(final Object classInstance, final Method setter, final
setter.invoke(classInstance, value);
}
} catch (IllegalArgumentException ex) {
- throw new JBBPMapperException("Can't set value to a mapping field", binField, classInstance.getClass(), classField, ex);
+ throw new JBBPMapperException("Can't set value to a mapping field", binField,
+ classInstance.getClass(), classField, ex);
} catch (IllegalAccessException ex) {
- throw new JBBPMapperException("Can't get access to a mapping field", binField, classInstance.getClass(), classField, ex);
+ throw new JBBPMapperException("Can't get access to a mapping field", binField,
+ classInstance.getClass(), classField, ex);
} catch (InvocationTargetException ex) {
- throw new JBBPMapperException("Can't set field value through setter", binField, classInstance.getClass(), classField, ex);
+ throw new JBBPMapperException("Can't set field value through setter", binField,
+ classInstance.getClass(), classField, ex);
}
}
- @SuppressWarnings("TryWithIdenticalCatches")
private static T tryMakeInstance(
- final Class type,
- final JBBPAbstractField binField,
- final Object mappingObject,
- final Field mappingField,
- final Function, Object>[] instantiators
+ final Class type,
+ final JBBPAbstractField binField,
+ final Object mappingObject,
+ final Field mappingField,
+ final Function, Object>[] instantiators
) {
T result = null;
for (final Function, Object> instantiator : instantiators) {
@@ -464,21 +558,26 @@ private static T tryMakeInstance(
if (result == null) {
Exception detectedException = null;
try {
- final Method method = mappingObject.getClass().getMethod(MAKE_CLASS_INSTANCE_METHOD_NAME, Class.class);
+ final Method method =
+ mappingObject.getClass().getMethod(MAKE_CLASS_INSTANCE_METHOD_NAME, Class.class);
if (!Modifier.isStatic(method.getModifiers())) {
- result = type.cast(mappingObject.getClass().getMethod(MAKE_CLASS_INSTANCE_METHOD_NAME, Class.class).invoke(mappingObject, type));
+ result = type.cast(
+ mappingObject.getClass().getMethod(MAKE_CLASS_INSTANCE_METHOD_NAME, Class.class)
+ .invoke(mappingObject, type));
}
} catch (NoSuchMethodException ex) {
// do nothing
} catch (IllegalAccessException ex) {
- // WARNING! Don't replace by multicatch for Android compatibility!
+ // WARNING! Don't replace by multi-catch for Android compatibility!
detectedException = ex;
} catch (InvocationTargetException ex) {
detectedException = ex;
}
if (detectedException != null) {
- throw new RuntimeException(String.format("Error during %s(%s) call", MAKE_CLASS_INSTANCE_METHOD_NAME, mappingObject.getClass()), detectedException);
+ throw new RuntimeException(String
+ .format("Error during %s(%s) call", MAKE_CLASS_INSTANCE_METHOD_NAME,
+ mappingObject.getClass()), detectedException);
}
if (result == null) {
@@ -489,26 +588,13 @@ private static T tryMakeInstance(
}
if (result == null) {
- throw new JBBPMapperException(String.format("Can't create instance of %s", type), binField, mappingObject.getClass(), mappingField, null);
+ throw new JBBPMapperException(String.format("Can't create instance of %s", type), binField,
+ mappingObject.getClass(), mappingField, null);
}
}
return result;
}
-
- interface FieldProcessor {
- @SuppressWarnings("unchecked")
- void apply(
- MappedFieldRecord record,
- JBBPFieldStruct rootStructure,
- Object instance,
- JBBPMapperCustomFieldProcessor customFieldProcessor,
- JBBPAbstractField binField,
- int flags,
- Function, Object>... instantiators
- );
- }
-
@Override
public int compareTo(final MappedFieldRecord o) {
final int thisOrder = this.binAnnotation.order();
@@ -522,4 +608,18 @@ public int compareTo(final MappedFieldRecord o) {
}
return result;
}
+
+ public interface FieldProcessor {
+ @SuppressWarnings("unchecked")
+ void apply(
+ MappedFieldRecord record,
+ JBBPFieldStruct rootStructure,
+ Object instance,
+ JBBPMapperCustomFieldProcessor customFieldProcessor,
+ JBBPAbstractField binField,
+ int flags,
+ BinFieldFilter binFieldFilter,
+ Function, Object>... instantiators
+ );
+ }
}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/AbstractFieldByteArray.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/AbstractFieldByteArray.java
index e268b3c2..19d81373 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/AbstractFieldByteArray.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/AbstractFieldByteArray.java
@@ -25,7 +25,8 @@
* @param type of array item.
* @since 1.1.1
*/
-abstract class AbstractFieldByteArray extends JBBPAbstractArrayField implements JBBPNumericArray {
+abstract class AbstractFieldByteArray extends JBBPAbstractArrayField
+ implements JBBPNumericArray {
private static final long serialVersionUID = -884448637983315505L;
protected final byte[] array;
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPAbstractArrayField.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPAbstractArrayField.java
index 29cdd2e1..e8980b84 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPAbstractArrayField.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPAbstractArrayField.java
@@ -17,7 +17,6 @@
package com.igormaznitsa.jbbp.model;
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
-
import java.util.Iterator;
import java.util.NoSuchElementException;
@@ -27,7 +26,8 @@
* @param type of field which can be contained in the array
* @since 1.0
*/
-public abstract class JBBPAbstractArrayField extends JBBPAbstractField implements Iterable {
+public abstract class JBBPAbstractArrayField extends JBBPAbstractField
+ implements Iterable {
private static final long serialVersionUID = -9007994400543951290L;
/**
@@ -67,10 +67,9 @@ public JBBPAbstractArrayField(final JBBPNamedFieldInfo name) {
*
* @return an iterator for the array
*/
- @SuppressWarnings("NullableProblems")
@Override
public Iterator iterator() {
- return new Iterator() {
+ return new Iterator<>() {
private int index = 0;
@Override
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPAbstractField.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPAbstractField.java
index 199edcfb..becfee2c 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPAbstractField.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPAbstractField.java
@@ -17,7 +17,6 @@
package com.igormaznitsa.jbbp.model;
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
-
import java.io.Serializable;
/**
@@ -36,7 +35,7 @@ public abstract class JBBPAbstractField implements Serializable, JBBPNamedField
/**
* The Variable can hold some payload. It is not used by JBBP and can be used
- * without restrictions. By default it is null. The Field is not thread safe.
+ * without restrictions. By default, it is null. The Field is not thread safe.
*
* @since 1.2.0
*/
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayBit.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayBit.java
index 26e7af9f..2111feea 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayBit.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayBit.java
@@ -25,7 +25,8 @@
*
* @since 1.0
*/
-public final class JBBPFieldArrayBit extends JBBPAbstractArrayField implements BitEntity, JBBPNumericArray {
+public final class JBBPFieldArrayBit extends JBBPAbstractArrayField
+ implements BitEntity, JBBPNumericArray {
private static final long serialVersionUID = -4589044511663149591L;
/**
@@ -46,7 +47,8 @@ public final class JBBPFieldArrayBit extends JBBPAbstractArrayField implements JBBPNumericArray {
+public final class JBBPFieldArrayBoolean extends JBBPAbstractArrayField
+ implements JBBPNumericArray {
private static final long serialVersionUID = -7896549257985728694L;
/**
* The Inside value storage.
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayByte.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayByte.java
index 48591cf0..cac10922 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayByte.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayByte.java
@@ -23,7 +23,8 @@
*
* @since 1.0
*/
-public final class JBBPFieldArrayByte extends AbstractFieldByteArray implements JBBPNumericArray {
+public final class JBBPFieldArrayByte extends AbstractFieldByteArray
+ implements JBBPNumericArray {
private static final long serialVersionUID = -8100947416351943918L;
/**
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayDouble.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayDouble.java
index bcd5b434..bdb3b9de 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayDouble.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayDouble.java
@@ -24,7 +24,8 @@
*
* @since 1.4.0
*/
-public final class JBBPFieldArrayDouble extends JBBPAbstractArrayField implements JBBPNumericArray {
+public final class JBBPFieldArrayDouble extends JBBPAbstractArrayField
+ implements JBBPNumericArray {
private static final long serialVersionUID = -2146959311724853264L;
/**
* Inside value storage.
@@ -89,7 +90,8 @@ public Object getValueArrayAsObject(final boolean reverseBits) {
if (reverseBits) {
result = this.array.clone();
for (int i = 0; i < result.length; i++) {
- result[i] = Double.longBitsToDouble(JBBPFieldLong.reverseBits(Double.doubleToLongBits(result[i])));
+ result[i] =
+ Double.longBitsToDouble(JBBPFieldLong.reverseBits(Double.doubleToLongBits(result[i])));
}
} else {
result = this.array.clone();
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayFloat.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayFloat.java
index 3da153f9..7d3c0457 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayFloat.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayFloat.java
@@ -24,7 +24,8 @@
*
* @since 1.4.0
*/
-public final class JBBPFieldArrayFloat extends JBBPAbstractArrayField implements JBBPNumericArray {
+public final class JBBPFieldArrayFloat extends JBBPAbstractArrayField
+ implements JBBPNumericArray {
private static final long serialVersionUID = 6839868800303265190L;
/**
* Inside storage.
@@ -89,7 +90,8 @@ public Object getValueArrayAsObject(final boolean reverseBits) {
if (reverseBits) {
result = this.array.clone();
for (int i = 0; i < result.length; i++) {
- result[i] = Float.intBitsToFloat((int) JBBPFieldInt.reverseBits(Float.floatToIntBits(result[i])));
+ result[i] =
+ Float.intBitsToFloat((int) JBBPFieldInt.reverseBits(Float.floatToIntBits(result[i])));
}
} else {
result = this.array.clone();
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayInt.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayInt.java
index 7eb02052..c82dafdc 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayInt.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayInt.java
@@ -24,7 +24,8 @@
*
* @since 1.0
*/
-public final class JBBPFieldArrayInt extends JBBPAbstractArrayField implements JBBPNumericArray {
+public final class JBBPFieldArrayInt extends JBBPAbstractArrayField
+ implements JBBPNumericArray {
private static final long serialVersionUID = 6839868800303265190L;
/**
* Inside storage.
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayLong.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayLong.java
index ebcd3eb9..c7df0276 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayLong.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayLong.java
@@ -24,7 +24,8 @@
*
* @since 1.0
*/
-public final class JBBPFieldArrayLong extends JBBPAbstractArrayField implements JBBPNumericArray {
+public final class JBBPFieldArrayLong extends JBBPAbstractArrayField
+ implements JBBPNumericArray {
private static final long serialVersionUID = -2146959300724853264L;
/**
* Inside value storage.
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayShort.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayShort.java
index 2f317873..7bcb74e0 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayShort.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayShort.java
@@ -24,7 +24,8 @@
*
* @since 1.0
*/
-public final class JBBPFieldArrayShort extends JBBPAbstractArrayField implements JBBPNumericArray {
+public final class JBBPFieldArrayShort extends JBBPAbstractArrayField
+ implements JBBPNumericArray {
private static final long serialVersionUID = 6119269534023759155L;
/**
* Inside value storage.
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUByte.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUByte.java
index fd0469fb..017ef023 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUByte.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUByte.java
@@ -19,7 +19,7 @@
import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
/**
- * Describes a unsigned byte array.
+ * Describes an unsigned byte array.
*
* @since 1.0
*/
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUInt.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUInt.java
new file mode 100644
index 00000000..29db7503
--- /dev/null
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUInt.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2017 Igor Maznitsa.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.igormaznitsa.jbbp.model;
+
+import com.igormaznitsa.jbbp.compiler.JBBPNamedFieldInfo;
+import com.igormaznitsa.jbbp.utils.JBBPUtils;
+
+/**
+ * Describes a long array.
+ *
+ * @since 1.0
+ */
+public final class JBBPFieldArrayUInt extends JBBPAbstractArrayField
+ implements JBBPNumericArray {
+ private static final long serialVersionUID = -2146953450724853264L;
+ /**
+ * Inside value storage.
+ */
+ private final int[] array;
+
+ /**
+ * The Constructor.
+ *
+ * @param name a field name info, it can be null
+ * @param array a value array, it must not be null
+ */
+ public JBBPFieldArrayUInt(final JBBPNamedFieldInfo name, final int[] array) {
+ super(name);
+ JBBPUtils.assertNotNull(array, "Array must not be null");
+ this.array = array;
+ }
+
+ /**
+ * get the value array
+ *
+ * @return the value array as a long array
+ */
+ public long[] getArray() {
+ long[] result = new long[this.array.length];
+ for (int i = 0; i < this.array.length; i++) {
+ result[i] = (long) this.array[i] & 0xFFFFFFFFL;
+ }
+ return result;
+ }
+
+ /**
+ * Get internal array of signed integers representing unsigned integers.
+ *
+ * @return the internal integer array, must not be null
+ * @since 2.0.4
+ */
+ public int[] getInternalArray() {
+ return this.array;
+ }
+
+ @Override
+ public int size() {
+ return this.array.length;
+ }
+
+ @Override
+ public JBBPFieldUInt getElementAt(final int index) {
+ final JBBPFieldUInt result =
+ new JBBPFieldUInt(this.fieldNameInfo, (long) this.array[index] & 0xFFFFFFFFL);
+ result.payload = this.payload;
+ return result;
+ }
+
+ @Override
+ public Object getValueArrayAsObject(final boolean reverseBits) {
+ final long[] result = new long[this.array.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] =
+ (reverseBits ? JBBPFieldInt.reverseBits(this.array[i]) : this.array[i]) & 0xFFFFFFFFL;
+ }
+ return result;
+ }
+
+ @Override
+ public int getAsInt(final int index) {
+ return this.array[index];
+ }
+
+ @Override
+ public long getAsLong(final int index) {
+ return (long) this.array[index] & 0xFFFFFFFFL;
+ }
+
+ @Override
+ public boolean getAsBool(final int index) {
+ return this.array[index] != 0L;
+ }
+
+ @Override
+ public String getTypeAsString() {
+ return "uint " + '[' + this.array.length + ']';
+ }
+}
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUShort.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUShort.java
index 826016e6..ce841194 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUShort.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldArrayUShort.java
@@ -20,11 +20,12 @@
import com.igormaznitsa.jbbp.utils.JBBPUtils;
/**
- * Describes a unsigned short array.
+ * Describes an unsigned short array.
*
* @since 1.0
*/
-public final class JBBPFieldArrayUShort extends JBBPAbstractArrayField implements JBBPNumericArray {
+public final class JBBPFieldArrayUShort extends JBBPAbstractArrayField
+ implements JBBPNumericArray {
private static final long serialVersionUID = -220078798710257343L;
/**
* Inside value storage.
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldBit.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldBit.java
index 326588dc..7b04e17e 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldBit.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldBit.java
@@ -44,7 +44,8 @@ public final class JBBPFieldBit extends JBBPAbstractField implements JBBPNumeric
* @param value the field value
* @param bitNumber number of valuable bits in the value, must not be null
*/
- public JBBPFieldBit(final JBBPNamedFieldInfo name, final int value, final JBBPBitNumber bitNumber) {
+ public JBBPFieldBit(final JBBPNamedFieldInfo name, final int value,
+ final JBBPBitNumber bitNumber) {
super(name);
JBBPUtils.assertNotNull(bitNumber, "Number of bits must not be null");
this.bitNumber = bitNumber;
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldLong.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldLong.java
index 06ebe83a..9adc6574 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldLong.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldLong.java
@@ -58,7 +58,8 @@ public static long reverseBits(final long value) {
final long b6 = JBBPUtils.reverseBitsInByte((byte) (value >> 48)) & 0xFFL;
final long b7 = JBBPUtils.reverseBitsInByte((byte) (value >> 56)) & 0xFFL;
- return (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
+ return (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) |
+ b7;
}
@Override
diff --git a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldString.java b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldString.java
index f13055d2..8154f6d0 100644
--- a/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldString.java
+++ b/jbbp/src/main/java/com/igormaznitsa/jbbp/model/JBBPFieldString.java
@@ -25,15 +25,14 @@
*/
public final class JBBPFieldString extends JBBPAbstractField {
- private static final long serialVersionUID = -2861961302858335702L;
public static final String TYPE_NAME = "stringj";
-
+ private static final long serialVersionUID = -2861961302858335702L;
private final String str;
/**
* A Constructor.
*
- * @param name a field name info, it can be null
+ * @param name a field name info, it can be null
* @param nullableValue a value, it can be null
*/
public JBBPFieldString(final JBBPNamedFieldInfo name, final String nullableValue) {
@@ -41,14 +40,6 @@ public JBBPFieldString(final JBBPNamedFieldInfo name, final String nullableValue
this.str = nullableValue;
}
- /**
- * Get the saved value.
- * @return the value as String, it can be null
- */
- public String getAsString() {
- return this.str;
- }
-
/**
* Get the reversed bit representation of the value.
*
@@ -60,8 +51,8 @@ public static String reverseBits(final String value) {
if (value != null) {
final char[] chars = value.toCharArray();
- for(int i=0; i T findFieldForType(final Class fieldType
}
}
if (counter > 1) {
- throw new JBBPTooManyFieldsFoundException(counter, "Detected more than one field", null, fieldType);
+ throw new JBBPTooManyFieldsFoundException(counter, "Detected more than one field", null,
+ fieldType);
}
return result;
}
@@ -164,7 +167,8 @@ public T findLastFieldForType(final Class field
}
@Override
- public T findFieldForNameAndType(final String fieldName, final Class fieldType) {
+ public T findFieldForNameAndType(final String fieldName,
+ final Class fieldType) {
final String normalizedName = JBBPUtils.normalizeFieldNameOrPath(fieldName);
T result = null;
@@ -209,7 +213,8 @@ public boolean pathExists(final String fieldPath) {
}
@Override
- public T findFieldForPathAndType(final String fieldPath, final Class fieldType) {
+ public T findFieldForPathAndType(final String fieldPath,
+ final Class fieldType) {
final JBBPAbstractField field = this.findFieldForPath(fieldPath);
T result = null;
@@ -232,7 +237,8 @@ public T findFieldForPathAndType(final String fiel
* @since 2.0.0
*/
@SafeVarargs
- public final T mapTo(final String path, final T instance, final Function, Object>... instantiators) {
+ public final T mapTo(final String path, final T instance,
+ final Function, Object>... instantiators) {
return JBBPMapper.map(this, path, instance, instantiators);
}
@@ -250,7 +256,8 @@ public final T mapTo(final String path, final T instance, final Function T mapTo(final String path, final T instance, final int flags, final Function, Object>... instantiators) {
+ public final T mapTo(final String path, final T instance, final int flags,
+ final Function, Object>... instantiators) {
return JBBPMapper.map(this, path, instance, flags, instantiators);
}
@@ -267,7 +274,9 @@ public final T mapTo(final String path, final T instance, final int flags, f
* @since 2.0.0
*/
@SafeVarargs
- public final T mapTo(final String path, final T instance, final JBBPMapperCustomFieldProcessor customFieldProcessor, final Function, Object>... instantiators) {
+ public final T mapTo(final String path, final T instance,
+ final JBBPMapperCustomFieldProcessor customFieldProcessor,
+ final Function, Object>... instantiators) {
return JBBPMapper.map(this, path, instance, customFieldProcessor, instantiators);
}
@@ -286,7 +295,9 @@ public final T mapTo(final String path, final T instance, final JBBPMapperCu
* @since 2.0.0
*/
@SafeVarargs
- public final