├── .github
└── workflows
│ └── maven.yml
├── .gitignore
├── README.md
├── licence.txt
├── pom.xml
└── src
├── main
└── java
│ └── fr
│ └── devnied
│ └── bitlib
│ ├── BitUtils.java
│ └── BytesUtils.java
└── test
├── java
└── fr
│ └── devnied
│ └── bitlib
│ ├── BitUtilsTest.java
│ └── BytesUtilsTest.java
└── resources
└── log4j.properties
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | name: Bit-lib4j CI
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 | strategy:
14 | matrix:
15 | java: [ 7, 8, 9, 10, 11]
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: Set up JDK ${{ matrix.java }}
19 | uses: actions/setup-java@v2
20 | with:
21 | distribution: 'zulu'
22 | java-version: ${{ matrix.java }}
23 | - name: Build with Maven
24 | run: mvn -B clean package
25 |
26 | finish:
27 | needs: build
28 | runs-on: ubuntu-latest
29 | steps:
30 | - uses: actions/checkout@v2
31 | - name: Set up JDK 1.8
32 | uses: actions/setup-java@v2
33 | with:
34 | distribution: 'zulu'
35 | java-version: 8
36 | - name: Build with Maven
37 | run: mvn -B clean cobertura:cobertura coveralls:report -DrepoToken=${{ secrets.COVERALLS_TOKEN }}
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Directories #
2 | /build/
3 | /bin/
4 | target/
5 | .idea
6 | *.iml
7 |
8 | # OS Files #
9 | .DS_Store
10 |
11 | *.class
12 |
13 | # Package Files #
14 | *.war
15 | *.ear
16 | *.db
17 |
18 | ######################
19 | # Windows
20 | ######################
21 |
22 | # Windows image file caches
23 | Thumbs.db
24 |
25 | # Folder config file
26 | Desktop.ini
27 |
28 | ######################
29 | # OSX
30 | ######################
31 |
32 | .svn
33 |
34 | # Thumbnails
35 | ._*
36 |
37 | # Files that might appear on external disk
38 | .Spotlight-V100
39 | .Trashes
40 |
41 |
42 | ######################
43 | # Eclipse
44 | ######################
45 |
46 | *.pydevproject
47 | .project
48 | .metadata
49 | bin/**
50 | tmp/**
51 | tmp/**/*
52 | *.tmp
53 | *.bak
54 | *.swp
55 | *~.nib
56 | local.properties
57 | .classpath
58 | .settings/
59 | .loadpath
60 | /src/main/resources/rebel.xml
61 | # External tool builders
62 | .externalToolBuilders/
63 |
64 | # Locally stored "Eclipse launch configurations"
65 | *.launch
66 |
67 | # CDT-specific
68 | .cproject
69 |
70 | # PDT-specific
71 | .buildpath
72 | pom.xml.releaseBackup
73 |
74 | release.properties
75 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Bit-lib4j  [](https://coveralls.io/github/devnied/Bit-lib4j?branch=master) [](https://maven-badges.herokuapp.com/maven-central/com.github.devnied/bit-lib4j)
2 | ========
3 |
4 | Bit-Lib4j is an useful library to handle bytes or bits in Java.
5 | With this library you can read/write data in a byte array with a custom size for Java primitive types.
6 |
7 | ## Simple API
8 |
9 | It is very easy to get started with bit-lib4j:
10 |
11 | * Read data from byte array
12 |
13 | ```java
14 | byte[] array = new byte[]{0x12,0x25}
15 | BitUtils bit = new BitUtils(array);
16 | int res = bit.getNextInteger(4); // read the first 4 bits to an integer
17 | ```
18 |
19 | * Create byte array with bit
20 |
21 | ```java
22 | BitUtils bit = new BitUtils(8);
23 | bit.setNextInteger(3,3); // set an integer on 3 bits
24 | bit.setNextInteger(1,5); // set one value on 5 bits
25 |
26 | // Result
27 | bit.getData(); // return Ox61 (0110 0001b)
28 | ```
29 |
30 | * Read/write signed values
31 |
32 | ```java
33 | BitUtils bit = new BitUtils(4);
34 | bit.setNextInteger(-2 , 4); // set an integer (-2) on 4 bits
35 |
36 | // Result
37 | bit.getNextIntegerSigned(4); // return -2
38 | ```
39 | You can also use ```getNextSignedLong()``` to handle long signed values.
40 |
41 |
42 | ## Handle bytes more easily
43 |
44 | The class ByteUtils provided static methods to convert byte array to String, String to byte array, int to byte array, byte array to binary representation.
45 |
46 |
47 | More documentation into the [wiki](https://github.com/devnied/Bit-lib4j/wiki)
48 |
49 | ## Download
50 |
51 | ### Maven
52 |
53 | ```xml
54 |
55 | com.github.devnied
56 | bit-lib4j
57 | 1.5.2
58 |
59 | ```
60 |
61 | ### JAR
62 |
63 | You can download this library on [Maven central](http://search.maven.org/#search%7Cga%7C1%7Cbit-lib4j) or in Github [release tab](https://github.com/devnied/Bit-lib4j/releases)
64 |
65 | ## Dependencies
66 |
67 | If you are not using Maven or some other dependency management tool that can understand Maven repositories, the list below is what you need to run bit-lib4j.
68 |
69 | **Runtime Dependencies**
70 | * slf4j-api 1.7.30
71 |
72 | ## Bugs
73 |
74 | Please report bugs and feature requests to the GitHub issue tracker.
75 | Forks and Pull Requests are also welcome.
76 |
77 | ## Author
78 |
79 | **Millau Julien**
80 |
81 | + [http://twitter.com/devnied](http://twitter.com/devnied)
82 | + [http://github.com/devnied](http://github.com/devnied)
83 |
84 |
85 | ## Copyright and license
86 |
87 | Copyright 2020 Millau Julien.
88 |
89 | Licensed under the Apache License, Version 2.0 (the "License");
90 | you may not use this work except in compliance with the License.
91 | You may obtain a copy of the License in the LICENSE file, or at:
92 |
93 | [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
94 |
95 | Unless required by applicable law or agreed to in writing, software
96 | distributed under the License is distributed on an "AS IS" BASIS,
97 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
98 | See the License for the specific language governing permissions and
99 | limitations under the License.
100 |
101 | [](https://github.com/igrigorik/ga-beacon)
102 |
--------------------------------------------------------------------------------
/licence.txt:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2013 Millau Julien
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.github.devnied
4 | bit-lib4j
5 | jar
6 | 1.5.3-SNAPSHOT
7 | bit-lib4j
8 |
9 |
10 | org.sonatype.oss
11 | oss-parent
12 | 7
13 |
14 |
15 | 2013
16 |
17 | Useful library to manipulate bits in Java.
18 | Read and write data in a byte array with a custom size for Java types
19 |
20 |
21 | https://github.com/devnied/Bit-lib4j/
22 |
23 |
24 | MILLAU Julien
25 | devnied
26 | mxjulien@gmail.com
27 |
28 | Java Developer
29 |
30 |
31 |
32 |
33 |
34 | The Apache Software License, Version 2.0
35 | http://www.apache.org/licenses/LICENSE-2.0.txt
36 | repo
37 |
38 |
39 |
40 |
41 | scm:git:git@github.com:devnied/Bit-lib4j.git
42 | scm:git:git@github.com:devnied/Bit-lib4j.git
43 | scm:git:git@github.com:devnied/Bit-lib4j.git
44 | HEAD
45 |
46 |
47 |
48 |
49 |
50 | 1.7.32
51 |
52 |
53 |
54 |
55 |
56 | org.slf4j
57 | slf4j-api
58 | ${slf4j.version}
59 |
60 |
61 | org.slf4j
62 | slf4j-log4j12
63 | ${slf4j.version}
64 | test
65 |
66 |
67 |
68 | org.apache.logging.log4j
69 | log4j-core
70 | 2.17.0
71 | test
72 |
73 |
74 |
75 |
76 | junit
77 | junit
78 | 4.13.2
79 | test
80 |
81 |
82 | org.easytesting
83 | fest-assert
84 | 1.4
85 | test
86 |
87 |
88 |
89 |
90 |
91 | sonatype-nexus-snapshots
92 | Sonatype Nexus Snapshots
93 | https://oss.sonatype.org/content/repositories/snapshots
94 |
95 |
96 | sonatype-nexus-staging
97 | Nexus Release Repository
98 | https://oss.sonatype.org/service/local/staging/deploy/maven2
99 |
100 |
101 |
102 |
103 | install
104 |
105 |
106 | maven-compiler-plugin
107 | 3.8.1
108 |
109 | 1.6
110 | 1.6
111 | UTF-8
112 |
113 |
114 |
115 | org.apache.maven.plugins
116 | maven-resources-plugin
117 | 3.1.0
118 |
119 | UTF-8
120 |
121 |
122 |
123 | org.apache.maven.plugins
124 | maven-release-plugin
125 | 2.5.3
126 |
127 | forked-path
128 | true
129 |
130 |
131 |
132 | maven-source-plugin
133 | 3.2.1
134 |
135 |
136 | attach-sources
137 |
138 | jar
139 |
140 |
141 |
142 |
143 |
144 | org.eluder.coveralls
145 | coveralls-maven-plugin
146 | 4.3.0
147 |
148 |
149 | org.codehaus.mojo
150 | cobertura-maven-plugin
151 | 2.7
152 |
153 | xml
154 | 256m
155 |
156 | true
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 | release-sign-artifacts
166 |
167 |
168 | performRelease
169 | true
170 |
171 |
172 |
173 |
174 |
175 | org.apache.maven.plugins
176 | maven-gpg-plugin
177 |
178 |
179 | sign-artifacts
180 | verify
181 |
182 | sign
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
--------------------------------------------------------------------------------
/src/main/java/fr/devnied/bitlib/BitUtils.java:
--------------------------------------------------------------------------------
1 | package fr.devnied.bitlib;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.nio.Buffer;
7 | import java.nio.ByteBuffer;
8 | import java.nio.charset.Charset;
9 | import java.text.ParseException;
10 | import java.text.SimpleDateFormat;
11 | import java.util.Arrays;
12 | import java.util.Date;
13 |
14 | /**
15 | * Class to manage bit with java
16 | *
17 | * @author Millau Julien
18 | *
19 | */
20 | public final class BitUtils {
21 | /***
22 | * Bit utils class logger
23 | */
24 | private static final Logger LOGGER = LoggerFactory.getLogger(BitUtils.class.getName());
25 | /**
26 | * Constant for byte size
27 | */
28 | public static final int BYTE_SIZE = Byte.SIZE;
29 | /**
30 | * Constant for byte size (float)
31 | */
32 | public static final float BYTE_SIZE_F = Byte.SIZE;
33 | /**
34 | * 255 init value
35 | */
36 | private static final int DEFAULT_VALUE = 0xFF;
37 | /**
38 | * Constant for the default charset
39 | */
40 | private static final Charset DEFAULT_CHARSET = Charset.forName("ASCII");
41 |
42 | /**
43 | * Simple date format (yyyMMdd)
44 | */
45 | public static final String DATE_FORMAT = "yyyyMMdd";
46 |
47 | /**
48 | * Table of read byte
49 | */
50 | private final byte[] byteTab;
51 |
52 | /**
53 | * Current index
54 | */
55 | private int currentBitIndex;
56 |
57 | /**
58 | * Size in bit of the byte tab
59 | */
60 | private final int size;
61 |
62 | /**
63 | * Constructor of the class
64 | *
65 | * @param pByte
66 | * byte read
67 | */
68 | public BitUtils(final byte[] pByte) {
69 | byteTab = new byte[pByte.length];
70 | System.arraycopy(pByte, 0, byteTab, 0, pByte.length);
71 | size = pByte.length * BYTE_SIZE;
72 | }
73 |
74 | /**
75 | * Constructor for empty byte tab
76 | *
77 | * @param pSize
78 | * the size of the tab in bit
79 | */
80 | public BitUtils(final int pSize) {
81 | byteTab = new byte[(int) Math.ceil(pSize / BYTE_SIZE_F)];
82 | size = pSize;
83 | }
84 |
85 | /**
86 | * Add pIndex to the current value of bitIndex
87 | *
88 | * @param pIndex
89 | * the value to add to bitIndex
90 | */
91 | public void addCurrentBitIndex(final int pIndex) {
92 | currentBitIndex += pIndex;
93 | if (currentBitIndex < 0) {
94 | currentBitIndex = 0;
95 | }
96 | }
97 |
98 | /**
99 | * Getter for the currentBitIndex
100 | *
101 | * @return the currentBitIndex
102 | */
103 | public int getCurrentBitIndex() {
104 | return currentBitIndex;
105 | }
106 |
107 | /**
108 | * Method to get all data
109 | *
110 | * @return a byte tab which contain all data
111 | */
112 | public byte[] getData() {
113 | byte[] ret = new byte[byteTab.length];
114 | System.arraycopy(byteTab, 0, ret, 0, byteTab.length);
115 | return ret;
116 | }
117 |
118 | /**
119 | * This method is used to get a mask dynamically
120 | *
121 | * @param pIndex
122 | * start index of the mask
123 | * @param pLength
124 | * size of mask
125 | * @return the mask in byte
126 | */
127 | public byte getMask(final int pIndex, final int pLength) {
128 | byte ret = (byte) DEFAULT_VALUE;
129 | // Add X 0 to the left
130 | ret = (byte) (ret << pIndex);
131 | ret = (byte) ((ret & DEFAULT_VALUE) >> pIndex);
132 | // Add X 0 to the right
133 | int dec = BYTE_SIZE - (pLength + pIndex);
134 | if (dec > 0) {
135 | ret = (byte) (ret >> dec);
136 | ret = (byte) (ret << dec);
137 | }
138 | return ret;
139 | }
140 |
141 | /**
142 | * Get the Next boolean (read 1 bit)
143 | *
144 | * @return true or false
145 | */
146 | public boolean getNextBoolean() {
147 | return getNextInteger(1) == 1;
148 | }
149 |
150 | /**
151 | * Method used to get the next byte and shift read data to the beginning of
152 | * the array.
153 | * (Ex 00110000b if we start read 2 bit at index 2 the data returned will be
154 | * 11000000b)
155 | *
156 | * @param pSize
157 | * the size in bit to read
158 | * @return the byte array read
159 | */
160 | public byte[] getNextByte(final int pSize) {
161 | return getNextByte(pSize, true);
162 | }
163 |
164 | /**
165 | * Method to get The next bytes with the specified size
166 | *
167 | * @param pSize
168 | * the size in bit to read
169 | * @param pShift
170 | * boolean to indicate if the data read will be shift to the
171 | * left.
172 | *
173 | *
if true : (Ex 10110000b if we start read 2 bit at index 2
174 | * the returned data will be 11000000b)
175 | *
if false : (Ex 10110000b if we start read 2 bit at index 2
176 | * the returned data will be 00110000b)
177 | *
178 | * @return a byte array
179 | */
180 | public byte[] getNextByte(final int pSize, final boolean pShift) {
181 | byte[] tab = new byte[(int) Math.ceil(pSize / BYTE_SIZE_F)];
182 |
183 | if (currentBitIndex % BYTE_SIZE != 0) {
184 | int index = 0;
185 | int max = currentBitIndex + pSize;
186 | while (currentBitIndex < max) {
187 | int mod = currentBitIndex % BYTE_SIZE;
188 | int modTab = index % BYTE_SIZE;
189 | int length = Math.min(max - currentBitIndex, Math.min(BYTE_SIZE - mod, BYTE_SIZE - modTab));
190 | byte val = (byte) (byteTab[currentBitIndex / BYTE_SIZE] & getMask(mod, length));
191 | if (pShift || pSize % BYTE_SIZE == 0) {
192 | if (mod != 0) {
193 | val = (byte) (val << Math.min(mod, BYTE_SIZE - length));
194 | } else {
195 | val = (byte) ((val & DEFAULT_VALUE) >> modTab);
196 | }
197 | }
198 | tab[index / BYTE_SIZE] |= val;
199 | currentBitIndex += length;
200 | index += length;
201 | }
202 | if (!pShift && pSize % BYTE_SIZE != 0) {
203 | tab[tab.length - 1] = (byte) (tab[tab.length - 1] & getMask((max - pSize - 1) % BYTE_SIZE, BYTE_SIZE));
204 | }
205 | } else {
206 | System.arraycopy(byteTab, currentBitIndex / BYTE_SIZE, tab, 0, tab.length);
207 | int val = pSize % BYTE_SIZE;
208 | if (val == 0) {
209 | val = BYTE_SIZE;
210 | }
211 | tab[tab.length - 1] = (byte) (tab[tab.length - 1] & getMask(currentBitIndex % BYTE_SIZE, val));
212 | currentBitIndex += pSize;
213 | }
214 |
215 | return tab;
216 | }
217 |
218 | /**
219 | * Method to get the next date
220 | *
221 | * @param pSize
222 | * the size of the string date in bit
223 | * @param pPattern
224 | * the Date pattern
225 | * @return a date object or null
226 | */
227 | public Date getNextDate(final int pSize, final String pPattern) {
228 | return getNextDate(pSize, pPattern, false);
229 | }
230 |
231 | /**
232 | * Method to get the next date
233 | *
234 | * @param pSize
235 | * the size of the string date in bit
236 | * @param pPattern
237 | * the Date pattern
238 | * @param pUseBcd
239 | * get the Date with BCD format (Binary coded decimal)
240 | * @return a date object or null
241 | */
242 | public Date getNextDate(final int pSize, final String pPattern, final boolean pUseBcd) {
243 | Date date = null;
244 | // create date formatter
245 | SimpleDateFormat sdf = new SimpleDateFormat(pPattern);
246 | // get String
247 | String dateTxt = null;
248 | if (pUseBcd) {
249 | dateTxt = getNextHexaString(pSize);
250 | } else {
251 | dateTxt = getNextString(pSize);
252 | }
253 |
254 | try {
255 | date = sdf.parse(dateTxt);
256 | } catch (ParseException e) {
257 | LOGGER.error("Parsing date error. date:" + dateTxt + " pattern:" + pPattern, e);
258 | }
259 | return date;
260 | }
261 |
262 | /**
263 | * This method is used to get the next String in Hexa
264 | *
265 | * @param pSize
266 | * the length of the string in bit
267 | * @return the string
268 | */
269 | public String getNextHexaString(final int pSize) {
270 | return BytesUtils.bytesToStringNoSpace(getNextByte(pSize, true));
271 | }
272 |
273 | /**
274 | * Method used to get get a signed long with the specified size
275 | * @param pLength length of long to get (must be lower than 64)
276 | * @return the long value
277 | */
278 | public long getNextLongSigned(final int pLength) {
279 | if (pLength > Long.SIZE) {
280 | throw new IllegalArgumentException("Long overflow with length > 64");
281 | }
282 | long decimal = getNextLong(pLength);
283 | long signMask = 1L << pLength - 1;
284 |
285 | if ( (decimal & signMask) != 0) {
286 | return - (signMask - (signMask ^ decimal));
287 | }
288 | return decimal;
289 | }
290 |
291 | /**
292 | * Method used to get get a signed integer with the specified size
293 | * @param pLength the length of the integer (must be lower than 32)
294 | * @return the integer value
295 | */
296 | public int getNextIntegerSigned(final int pLength) {
297 | if (pLength > Integer.SIZE) {
298 | throw new IllegalArgumentException("Integer overflow with length > 32");
299 | }
300 | return (int) getNextLongSigned(pLength);
301 | }
302 |
303 | /**
304 | * This method is used to get a long with the specified size
305 | *
306 | * Be careful with java long bit sign. This method doesn't handle signed values.
307 | * For that, @see BitUtils.getNextLongSigned()
308 | *
309 | * @param pLength
310 | * the length of the data to read in bit
311 | * @return an long
312 | */
313 | public long getNextLong(final int pLength) {
314 | // allocate Size of Integer
315 | ByteBuffer buffer = ByteBuffer.allocate(BYTE_SIZE * 2);
316 | // final value
317 | long finalValue = 0;
318 | // Incremental value
319 | long currentValue = 0;
320 | // Size to read
321 | int readSize = pLength;
322 | // length max of the index
323 | int max = currentBitIndex + pLength;
324 | while (currentBitIndex < max) {
325 | int mod = currentBitIndex % BYTE_SIZE;
326 | // apply the mask to the selected byte
327 | currentValue = byteTab[currentBitIndex / BYTE_SIZE] & getMask(mod, readSize) & DEFAULT_VALUE;
328 | // Shift right the read value
329 | int dec = Math.max(BYTE_SIZE - (mod + readSize), 0);
330 | currentValue = (currentValue & DEFAULT_VALUE) >>> dec & DEFAULT_VALUE;
331 | // Shift left the previously read value and add the current value
332 | finalValue = finalValue << Math.min(readSize, BYTE_SIZE) | currentValue;
333 | // calculate read value size
334 | int val = BYTE_SIZE - mod;
335 | // Decrease the size left
336 | readSize = readSize - val;
337 | currentBitIndex = Math.min(currentBitIndex + val, max);
338 | }
339 | buffer.putLong(finalValue);
340 | // reset the current bytebuffer index to 0
341 | ((Buffer)buffer).rewind();
342 | // return integer
343 | return buffer.getLong();
344 | }
345 |
346 | /**
347 | * This method is used to get an integer with the specified size
348 | *
349 | * Be careful with java integer bit sign. This method doesn't handle signed values.
350 | * For that, @see BitUtils.getNextIntegerSigned()
351 | *
352 | * @param pLength
353 | * the length of the data to read in bit
354 | * @return an integer
355 | */
356 | public int getNextInteger(final int pLength) {
357 | return (int) (getNextLong(pLength));
358 | }
359 |
360 | /**
361 | * This method is used to get the next String with the specified size with
362 | * the charset ASCII
363 | *
364 | * @param pSize
365 | * the length of the string in bit
366 | * @return the string
367 | */
368 | public String getNextString(final int pSize) {
369 | return getNextString(pSize, DEFAULT_CHARSET);
370 | }
371 |
372 | /**
373 | * This method is used to get the next String with the specified size
374 | *
375 | * @param pSize
376 | * the length of the string int bit
377 | * @param pCharset
378 | * the charset
379 | * @return the string
380 | */
381 | public String getNextString(final int pSize, final Charset pCharset) {
382 | return new String(getNextByte(pSize, true), pCharset);
383 | }
384 |
385 | /**
386 | * Method used to get the size of the bit array
387 | *
388 | * @return the size in bits of the current bit array
389 | */
390 | public int getSize() {
391 | return size;
392 | }
393 |
394 | /**
395 | * Reset the current bit index to the initial position
396 | */
397 | public void reset() {
398 | setCurrentBitIndex(0);
399 | }
400 |
401 | /**
402 | * Method used to clear data and reset current bit index
403 | */
404 | public void clear() {
405 | Arrays.fill(byteTab, (byte) 0);
406 | reset();
407 | }
408 |
409 | /**
410 | * Set to 0 the next N bits
411 | *
412 | * @param pLength
413 | * the number of bit to set at 0
414 | */
415 | public void resetNextBits(final int pLength) {
416 | int max = currentBitIndex + pLength;
417 | while (currentBitIndex < max) {
418 | int mod = currentBitIndex % BYTE_SIZE;
419 | int length = Math.min(max - currentBitIndex, BYTE_SIZE - mod);
420 | byteTab[currentBitIndex / BYTE_SIZE] &= ~getMask(mod, length);
421 | currentBitIndex += length;
422 | }
423 | }
424 |
425 | /**
426 | * Setter currentBitIndex
427 | *
428 | * @param pCurrentBitIndex
429 | * the currentBitIndex to set
430 | */
431 | public void setCurrentBitIndex(final int pCurrentBitIndex) {
432 | currentBitIndex = pCurrentBitIndex;
433 | }
434 |
435 | /**
436 | * Method to set a boolean
437 | *
438 | * @param pBoolean
439 | * the boolean to set
440 | */
441 | public void setNextBoolean(final boolean pBoolean) {
442 | if (pBoolean) {
443 | setNextInteger(1, 1);
444 | } else {
445 | setNextInteger(0, 1);
446 | }
447 | }
448 |
449 | /**
450 | * Method to write bytes with the max length
451 | *
452 | * @param pValue
453 | * the value to write
454 | * @param pLength
455 | * the length of the data in bits
456 | */
457 | public void setNextByte(final byte[] pValue, final int pLength) {
458 | setNextByte(pValue, pLength, true);
459 | }
460 |
461 | /**
462 | * Method to write bytes with the max length
463 | *
464 | * @param pValue
465 | * the value to write
466 | * @param pLength
467 | * the length of the data in bits
468 | * @param pPadBefore
469 | * if true pad with 0
470 | */
471 | public void setNextByte(final byte[] pValue, final int pLength, final boolean pPadBefore) {
472 | int totalSize = (int) Math.ceil(pLength / BYTE_SIZE_F);
473 | ByteBuffer buffer = ByteBuffer.allocate(totalSize);
474 | int size = Math.max(totalSize - pValue.length, 0);
475 | if (pPadBefore) {
476 | for (int i = 0; i < size; i++) {
477 | buffer.put((byte) 0);
478 | }
479 | }
480 | buffer.put(pValue, 0, Math.min(totalSize, pValue.length));
481 | if (!pPadBefore) {
482 | for (int i = 0; i < size; i++) {
483 | buffer.put((byte) 0);
484 | }
485 | }
486 | byte[] tab = buffer.array();
487 | if (currentBitIndex % BYTE_SIZE != 0) {
488 | int index = 0;
489 | int max = currentBitIndex + pLength;
490 | while (currentBitIndex < max) {
491 | int mod = currentBitIndex % BYTE_SIZE;
492 | int modTab = index % BYTE_SIZE;
493 | int length = Math.min(max - currentBitIndex, Math.min(BYTE_SIZE - mod, BYTE_SIZE - modTab));
494 | byte val = (byte) (tab[index / BYTE_SIZE] & getMask(modTab, length));
495 | if (mod == 0) {
496 | val = (byte) (val << Math.min(modTab, BYTE_SIZE - length));
497 | } else {
498 | val = (byte) ((val & DEFAULT_VALUE) >> mod);
499 | }
500 | byteTab[currentBitIndex / BYTE_SIZE] |= val;
501 | currentBitIndex += length;
502 | index += length;
503 | }
504 |
505 | } else {
506 | System.arraycopy(tab, 0, byteTab, currentBitIndex / BYTE_SIZE, tab.length);
507 | currentBitIndex += pLength;
508 | }
509 | }
510 |
511 | /**
512 | * Method to write a date
513 | *
514 | * @param pValue
515 | * the value to write
516 | * @param pPattern
517 | * the Date pattern
518 | */
519 | public void setNextDate(final Date pValue, final String pPattern) {
520 | setNextDate(pValue, pPattern, false);
521 | }
522 |
523 | /**
524 | * Method to write a date
525 | *
526 | * @param pValue
527 | * the value to write
528 | * @param pPattern
529 | * the Date pattern
530 | * @param pUseBcd
531 | * write date as BCD (binary coded decimal)
532 | */
533 | public void setNextDate(final Date pValue, final String pPattern, final boolean pUseBcd) {
534 | // create date formatter
535 | SimpleDateFormat sdf = new SimpleDateFormat(pPattern);
536 | String value = sdf.format(pValue);
537 |
538 | if (pUseBcd) {
539 | setNextHexaString(value, value.length() * 4);
540 | } else {
541 | setNextString(value, value.length() * 8);
542 | }
543 | }
544 |
545 | /**
546 | * Method to write Hexa String with the max length
547 | *
548 | * @param pValue
549 | * the value to write
550 | * @param pLength
551 | * the length of the data in bits
552 | */
553 | public void setNextHexaString(final String pValue, final int pLength) {
554 | setNextByte(BytesUtils.fromString(pValue), pLength);
555 | }
556 |
557 | /**
558 | * Add Long to the current position with the specified size
559 | *
560 | * Be careful with java long bit sign
561 | *
562 | * @param pValue
563 | * the value to set
564 | *
565 | * @param pLength
566 | * the length of the long
567 | */
568 | public void setNextLong(final long pValue, final int pLength) {
569 |
570 | if (pLength > Long.SIZE) {
571 | throw new IllegalArgumentException("Long overflow with length > 64");
572 | }
573 |
574 | setNextValue(pValue, pLength, Long.SIZE - 1);
575 | }
576 |
577 | /**
578 | * Add Value to the current position with the specified size
579 | *
580 | * @param pValue
581 | * value to add
582 | * @param pLength
583 | * length of the value
584 | * @param pMaxSize
585 | * max size in bits
586 | */
587 | private void setNextValue(final long pValue, final int pLength, final int pMaxSize) {
588 | long value = pValue;
589 | // Set to max value if pValue cannot be stored on pLength bits.
590 | long bitMax = (long) Math.pow(2, Math.min(pLength, pMaxSize));
591 | if (pValue > bitMax) {
592 | value = bitMax - 1;
593 | }
594 | // size to wrote
595 | int writeSize = pLength;
596 | while (writeSize > 0) {
597 | // modulo
598 | int mod = currentBitIndex % BYTE_SIZE;
599 | byte ret = 0;
600 | if (mod == 0 && writeSize <= BYTE_SIZE || pLength < BYTE_SIZE - mod) {
601 | // shift left value
602 | ret = (byte) (value << BYTE_SIZE - (writeSize + mod));
603 | } else {
604 | // shift right
605 | long length = Long.toBinaryString(value).length();
606 | ret = (byte) (value >> writeSize - length - (BYTE_SIZE - length - mod));
607 | }
608 | byteTab[currentBitIndex / BYTE_SIZE] |= ret;
609 | long val = Math.min(writeSize, BYTE_SIZE - mod);
610 | writeSize -= val;
611 | currentBitIndex += val;
612 | }
613 | }
614 |
615 | /**
616 | * Add Integer to the current position with the specified size
617 | *
618 | * Be careful with java integer bit sign
619 | *
620 | * @param pValue
621 | * the value to set
622 | *
623 | * @param pLength
624 | * the length of the integer
625 | */
626 | public void setNextInteger(final int pValue, final int pLength) {
627 |
628 | if (pLength > Integer.SIZE) {
629 | throw new IllegalArgumentException("Integer overflow with length > 32");
630 | }
631 |
632 | setNextValue(pValue, pLength, Integer.SIZE - 1);
633 | }
634 |
635 | /**
636 | * Method to write String
637 | *
638 | * @param pValue
639 | * the string to write
640 | *
641 | * @param pLength
642 | * the length of the integer
643 | */
644 | public void setNextString(final String pValue, final int pLength) {
645 | setNextString(pValue, pLength, true);
646 | }
647 |
648 | /**
649 | * Method to write a String
650 | *
651 | * @param pValue
652 | * the string to write
653 | * @param pLength
654 | * the string length
655 | * @param pPaddedBefore
656 | * indicate if the string is padded before or after
657 | */
658 | public void setNextString(final String pValue, final int pLength, final boolean pPaddedBefore) {
659 | setNextByte(pValue.getBytes(Charset.defaultCharset()), pLength, pPaddedBefore);
660 | }
661 | }
662 |
--------------------------------------------------------------------------------
/src/main/java/fr/devnied/bitlib/BytesUtils.java:
--------------------------------------------------------------------------------
1 | package fr.devnied.bitlib;
2 |
3 | import java.math.BigInteger;
4 |
5 | /**
6 | * Class used to manage String/byte/int converter
7 | *
8 | * @author Millau Julien
9 | *
10 | */
11 | public final class BytesUtils {
12 |
13 | /**
14 | * Integer bit size
15 | */
16 | private static final int MAX_BIT_INTEGER = 31;
17 |
18 | /**
19 | * Constant for Hexa
20 | */
21 | private static final int HEXA = 16;
22 |
23 | /**
24 | * Byte left mask
25 | */
26 | private static final int LEFT_MASK = 0xF0;
27 |
28 | /**
29 | * Byte right mask
30 | */
31 | private static final int RIGHT_MASK = 0xF;
32 |
33 | /**
34 | * Char digit 0 (0x30) :
35 | *