52 | */
53 | private static final int CHAR_DIGIT_SEVEN = 0x37;
54 |
55 | /**
56 | * Char space
57 | */
58 | private static final char CHAR_SPACE = (char) 0x20;
59 |
60 | /**
61 | * Method used to convert byte array to int
62 | *
63 | * @param byteArray
64 | * byte array to convert
65 | * @return int value
66 | */
67 | public static int byteArrayToInt(final byte[] byteArray) {
68 | if (byteArray == null) {
69 | throw new IllegalArgumentException("Parameter 'byteArray' cannot be null");
70 | }
71 | return byteArrayToInt(byteArray, 0, byteArray.length);
72 | }
73 |
74 | /**
75 | * Method used to convert byte array to int
76 | *
77 | * @param byteArray
78 | * byte array to convert
79 | * @param startPos
80 | * start position in array in the
81 | * @param length
82 | * length of data
83 | * @return int value of byte array
84 | */
85 | public static int byteArrayToInt(final byte[] byteArray, final int startPos, final int length) {
86 | if (byteArray == null) {
87 | throw new IllegalArgumentException("Parameter 'byteArray' cannot be null");
88 | }
89 | if (length <= 0 || length > 4) {
90 | throw new IllegalArgumentException("Length must be between 1 and 4. Length = " + length);
91 | }
92 | if (startPos < 0 || byteArray.length < startPos + length) {
93 | throw new IllegalArgumentException("Length or startPos not valid");
94 | }
95 | int value = 0;
96 | for (int i = 0; i < length; i++) {
97 | value += (byteArray[startPos + i] & 0xFF) << 8 * (length - i - 1);
98 | }
99 | return value;
100 | }
101 |
102 | /**
103 | * Method to convert bytes to string with space between bytes
104 | *
105 | * @param pBytes
106 | * Bytes to convert
107 | *
108 | * @return a string
109 | */
110 | public static String bytesToString(final byte[] pBytes) {
111 | return formatByte(pBytes, true, false);
112 | }
113 |
114 | /**
115 | * Method to convert bytes to string with space between bytes
116 | *
117 | * bytes to convert
118 | *
119 | * @param pBytes
120 | * Bytes to convert
121 | * @param pTruncate
122 | * true to remove 0 left byte value
123 | * @return a string
124 | */
125 | public static String bytesToString(final byte[] pBytes, final boolean pTruncate) {
126 | return formatByte(pBytes, true, pTruncate);
127 | }
128 |
129 | /**
130 | * Method to convert byte to string without space between byte
131 | *
132 | * @param pByte
133 | * byte to convert
134 | * @return a string
135 | */
136 | public static String bytesToStringNoSpace(final byte pByte) {
137 | return formatByte(new byte[] { pByte }, false, false);
138 | }
139 |
140 | /**
141 | * Method to convert bytes to string without space between bytes
142 | *
143 | * @param pBytes
144 | * bytes to convert
145 | * @return a string
146 | */
147 | public static String bytesToStringNoSpace(final byte[] pBytes) {
148 | return formatByte(pBytes, false, false);
149 | }
150 |
151 | /**
152 | * Method to convert bytes to string without space between bytes
153 | *
154 | * @param pBytes
155 | * bytes to convert
156 | * @param pTruncate
157 | * true to remove 0 left byte value
158 | * @return a string
159 | */
160 | public static String bytesToStringNoSpace(final byte[] pBytes, final boolean pTruncate) {
161 | return formatByte(pBytes, false, pTruncate);
162 | }
163 |
164 | /**
165 | * Private method to format bytes to hexa string
166 | *
167 | * @param pByte
168 | * the bytes to format
169 | * @param pSpace
170 | * true if add spaces between bytes
171 | * @param pTruncate
172 | * true to remove 0 left bytes value
173 | * @return a string containing the requested string
174 | */
175 | private static String formatByte(final byte[] pByte, final boolean pSpace, final boolean pTruncate) {
176 | String result;
177 | if (pByte == null) {
178 | result = "";
179 | } else {
180 | int i = 0;
181 | if (pTruncate) {
182 | while (i < pByte.length && pByte[i] == 0) {
183 | i++;
184 | }
185 | }
186 | if (i < pByte.length) {
187 | int sizeMultiplier = pSpace ? 3 : 2;
188 | char[] c = new char[(pByte.length - i) * sizeMultiplier];
189 | byte b;
190 | for (int j = 0; i < pByte.length; i++, j++) {
191 | b = (byte) ((pByte[i] & LEFT_MASK) >> 4);
192 | c[j] = (char) (b > 9 ? b + CHAR_DIGIT_SEVEN : b + CHAR_DIGIT_ZERO);
193 | b = (byte) (pByte[i] & RIGHT_MASK);
194 | c[++j] = (char) (b > 9 ? b + CHAR_DIGIT_SEVEN : b + CHAR_DIGIT_ZERO);
195 | if (pSpace) {
196 | c[++j] = CHAR_SPACE;
197 | }
198 | }
199 | result = pSpace ? new String(c, 0, c.length - 1) : new String(c);
200 | } else {
201 | result = "";
202 | }
203 | }
204 | return result;
205 | }
206 |
207 | /**
208 | * Method to get bytes form string
209 | *
210 | * @param pData
211 | * String to parse
212 | * @return a table of string
213 | */
214 | public static byte[] fromString(final String pData) {
215 | if (pData == null) {
216 | throw new IllegalArgumentException("Argument can't be null");
217 | }
218 | StringBuilder sb = new StringBuilder(pData);
219 | int j = 0;
220 | for (int i = 0; i < sb.length(); i++) {
221 | if (!Character.isWhitespace(sb.charAt(i))) {
222 | sb.setCharAt(j++, sb.charAt(i));
223 | }
224 | }
225 | sb.delete(j, sb.length());
226 | if (sb.length() % 2 != 0) {
227 | throw new IllegalArgumentException("Hex binary needs to be even-length :" + pData);
228 | }
229 | byte[] result = new byte[sb.length() / 2];
230 | j = 0;
231 | for (int i = 0; i < sb.length(); i += 2) {
232 | result[j++] = (byte) ((Character.digit(sb.charAt(i), 16) << 4) + Character.digit(sb.charAt(i + 1), 16));
233 | }
234 | return result;
235 | }
236 |
237 | /**
238 | * Test if bit at given index of given value is = 1.
239 | *
240 | * @param pVal
241 | * value to test
242 | * @param pBitIndex
243 | * bit index between 0 and 31
244 | * @return true bit at given index of give value is = 1
245 | */
246 | public static boolean matchBitByBitIndex(final int pVal, final int pBitIndex) {
247 | if (pBitIndex < 0 || pBitIndex > MAX_BIT_INTEGER) {
248 | throw new IllegalArgumentException(
249 | "parameter 'pBitIndex' must be between 0 and 31. pBitIndex=" + pBitIndex);
250 | }
251 | return (pVal & 1 << pBitIndex) != 0;
252 | }
253 |
254 | /**
255 | * Method used to set a bit index to 1 or 0.
256 | *
257 | * @param pData
258 | * data to modify
259 | * @param pBitIndex
260 | * index to set
261 | * @param pOn
262 | * set bit at specified index to 1 or 0
263 | * @return the modified byte
264 | */
265 | public static byte setBit(final byte pData, final int pBitIndex, final boolean pOn) {
266 | if (pBitIndex < 0 || pBitIndex > 7) {
267 | throw new IllegalArgumentException("parameter 'pBitIndex' must be between 0 and 7. pBitIndex=" + pBitIndex);
268 | }
269 | byte ret = pData;
270 | if (pOn) { // Set bit
271 | ret |= 1 << pBitIndex;
272 | } else { // Unset bit
273 | ret &= ~(1 << pBitIndex);
274 | }
275 | return ret;
276 | }
277 |
278 | /**
279 | * Convert byte array to binary String
280 | *
281 | * @param pBytes
282 | * byte array to convert
283 | * @return a binary representation of the byte array
284 | */
285 | public static String toBinary(final byte[] pBytes) {
286 | String ret = null;
287 | if (pBytes != null && pBytes.length > 0) {
288 | BigInteger val = new BigInteger(bytesToStringNoSpace(pBytes), HEXA);
289 | StringBuilder build = new StringBuilder(val.toString(2));
290 | // left pad with 0 to fit byte size
291 | for (int i = build.length(); i < pBytes.length * BitUtils.BYTE_SIZE; i++) {
292 | build.insert(0, 0);
293 | }
294 | ret = build.toString();
295 | }
296 | return ret;
297 | }
298 |
299 | /**
300 | * Method used to convert integer to byet array
301 | *
302 | * @param value
303 | * the value to convert
304 | * @return a byte array
305 | */
306 | public static byte[] toByteArray(final int value) {
307 | return new byte[] { //
308 | (byte) (value >> 24), //
309 | (byte) (value >> 16), //
310 | (byte) (value >> 8), //
311 | (byte) value //
312 | };
313 | }
314 |
315 | /**
316 | * private constructor
317 | */
318 | private BytesUtils() {
319 | }
320 | }
321 |
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/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/test/java/fr/devnied/bitlib/BitUtilsTest.java:
--------------------------------------------------------------------------------
1 | package fr.devnied.bitlib;
2 |
3 | import org.fest.assertions.Assertions;
4 | import org.junit.Assert;
5 | import org.junit.Test;
6 |
7 | import java.text.ParseException;
8 | import java.text.SimpleDateFormat;
9 | import java.util.Date;
10 |
11 | /**
12 | * Class to test the bitutils class
13 | *
14 | * @author Millau Julien
15 | *
16 | */
17 | public final class BitUtilsTest {
18 |
19 | /**
20 | * Test byte value
21 | */
22 | private final byte[] test = new byte[] { (byte) 0x11, (byte) 0x00, (byte) 0x00, (byte) 0x67, (byte) 0xEF };
23 |
24 | /**
25 | * @throws ParseException
26 | */
27 | @Test
28 | public void testBitIndex() throws ParseException {
29 |
30 | BitUtils bit = new BitUtils(test);
31 |
32 | Assertions.assertThat(bit.getCurrentBitIndex()).isEqualTo(0);
33 | Assertions.assertThat(bit.getNextInteger(4)).isEqualTo(1);
34 | Assertions.assertThat(bit.getCurrentBitIndex()).isEqualTo(4);
35 | bit.setCurrentBitIndex(5);
36 | bit.addCurrentBitIndex(-1);
37 | bit.addCurrentBitIndex(1);
38 | Assertions.assertThat(bit.getCurrentBitIndex()).isEqualTo(5);
39 | Assertions.assertThat(bit.getNextInteger(3)).isEqualTo(1);
40 | bit.addCurrentBitIndex(-1000);
41 | Assertions.assertThat(bit.getCurrentBitIndex()).isEqualTo(0);
42 |
43 | BitUtils bit2 = new BitUtils(new byte[] { (byte) 0xFE });
44 | bit2.addCurrentBitIndex(7);
45 | Assertions.assertThat(bit2.getNextBoolean()).isEqualTo(false);
46 |
47 | }
48 |
49 | /**
50 | * Test the method getData
51 | */
52 | @Test
53 | public void testGetData() {
54 |
55 | BitUtils bit = new BitUtils(test);
56 | Assertions.assertThat(bit.getData()).isEqualTo(test);
57 | }
58 |
59 | /**
60 | * Test the method get Hexa String
61 | */
62 | @Test
63 | public void testGetHexaString() {
64 |
65 | BitUtils bit = new BitUtils(test);
66 |
67 | Assertions.assertThat(bit.getNextHexaString(8)).isEqualTo("11");
68 | Assertions.assertThat(bit.getNextHexaString(16)).isEqualTo("0000");
69 | Assertions.assertThat(bit.getNextHexaString(8)).isEqualTo("67");
70 | Assertions.assertThat(bit.getNextHexaString(8)).isEqualTo("EF");
71 | }
72 |
73 | @Test
74 | public void testGetNextByte() {
75 | BitUtils bit = new BitUtils(test);
76 | Assertions.assertThat(bit.getNextByte(4, false)).isEqualTo(new byte[] { 0x10 });
77 | Assertions.assertThat(bit.getNextByte(4, false)).isEqualTo(new byte[] { 0x01 });
78 | Assertions.assertThat(bit.getNextByte(16, false)).isEqualTo(new byte[] { 0x00, 0x00 });
79 | Assertions.assertThat(bit.getNextByte(2, false)).isEqualTo(new byte[] { 0x40 });
80 | Assertions.assertThat(bit.getNextByte(2, false)).isEqualTo(new byte[] { 0x20 });
81 | bit.reset();
82 | Assertions.assertThat(bit.getNextByte(2, false)).isEqualTo(new byte[] { 0x00 });
83 | Assertions.assertThat(bit.getNextByte(8, false)).isEqualTo(new byte[] { 0x44 });
84 | bit.reset();
85 | Assertions.assertThat(bit.getNextByte(4)).isEqualTo(new byte[] { 0x10 });
86 | Assertions.assertThat(bit.getNextByte(4)).isEqualTo(new byte[] { 0x10 });
87 |
88 | bit = new BitUtils(new byte[] { 0x44, (byte) 0xFE });
89 | Assertions.assertThat(bit.getNextByte(4, false)).isEqualTo(new byte[] { 0x40 });
90 | Assertions.assertThat(bit.getNextByte(8, false)).isEqualTo(new byte[] { (byte) 0x4F });
91 | Assertions.assertThat(bit.getNextByte(4, false)).isEqualTo(new byte[] { (byte) 0x0E });
92 | bit.reset();
93 | Assertions.assertThat(bit.getNextByte(4, true)).isEqualTo(new byte[] { 0x40 });
94 | Assertions.assertThat(bit.getNextByte(8, true)).isEqualTo(new byte[] { (byte) 0x4F });
95 | Assertions.assertThat(bit.getNextByte(4, true)).isEqualTo(new byte[] { (byte) 0xE0 });
96 | }
97 |
98 | /**
99 | * @throws ParseException
100 | */
101 | @Test
102 | public void testGetNextDate() throws ParseException {
103 |
104 | String val = "20130108";
105 | BitUtils bit = new BitUtils(val.getBytes());
106 | SimpleDateFormat sdf = new SimpleDateFormat(BitUtils.DATE_FORMAT);
107 | Date d = sdf.parse(val);
108 |
109 | Assertions.assertThat(bit.getNextDate(8 * 8, BitUtils.DATE_FORMAT)).isEqualTo(d);
110 | bit.reset();
111 |
112 | String valYear = "2013";
113 | SimpleDateFormat sdfyear = new SimpleDateFormat("yyyy");
114 | Date year = sdfyear.parse(valYear);
115 |
116 | Assertions.assertThat(bit.getNextDate(4 * 8, "yyyy")).isEqualTo(year);
117 | bit.reset();
118 |
119 | Assertions.assertThat(bit.getNextDate(4 * 8, BitUtils.DATE_FORMAT)).isEqualTo(null);
120 |
121 | bit = new BitUtils(BytesUtils.fromString(val));
122 | Assertions.assertThat(bit.getNextDate(8 * 4, BitUtils.DATE_FORMAT, true)).isEqualTo(d);
123 |
124 | }
125 |
126 | /**
127 | * Method to test the GetNextint method
128 | */
129 | @Test
130 | public void testGetNextInt() {
131 |
132 | BitUtils bit = new BitUtils(test);
133 |
134 | Assertions.assertThat(bit.getNextInteger(4)).isEqualTo(1);
135 | Assertions.assertThat(bit.getNextInteger(20)).isEqualTo(65536);
136 | Assertions.assertThat(bit.getNextInteger(1)).isEqualTo(0);
137 | Assertions.assertThat(bit.getNextInteger(4)).isEqualTo(12);
138 | Assertions.assertThat(bit.getNextInteger(1)).isEqualTo(1);
139 | Assertions.assertThat(bit.getNextInteger(4)).isEqualTo(15);
140 | Assertions.assertThat(bit.getNextInteger(1)).isEqualTo(1);
141 | Assertions.assertThat(bit.getNextInteger(5)).isEqualTo(15);
142 |
143 | BitUtils bit2 = new BitUtils(new byte[] { (byte) 0x04, (byte) 0x21, 0x60 });
144 | Assertions.assertThat(bit2.getNextInteger(2)).isEqualTo(0);
145 | Assertions.assertThat(bit2.getNextInteger(14)).isEqualTo(1057);
146 | Assertions.assertThat(bit2.getNextInteger(1)).isEqualTo(0);
147 | Assertions.assertThat(bit2.getNextInteger(1)).isEqualTo(1);
148 | Assertions.assertThat(bit2.getNextInteger(1)).isEqualTo(1);
149 | Assertions.assertThat(bit2.getNextInteger(1)).isEqualTo(0);
150 | }
151 |
152 | /**
153 | * Test the
154 | */
155 | @Test
156 | public void testGetNextString() {
157 |
158 | String val = "TEST VaLeUr e'*/";
159 | BitUtils bit = new BitUtils(val.getBytes());
160 | Assertions.assertThat(bit.getNextString(val.length() * 8)).isEqualTo(val);
161 |
162 | BitUtils bit2 = new BitUtils(val.getBytes());
163 | Assertions.assertThat(bit2.getNextString(2 * 8)).isEqualTo("TE");
164 | Assertions.assertThat(bit2.getNextString(2 * 8)).isEqualTo("ST");
165 | Assertions.assertThat(bit2.getNextString(4 * 8)).isEqualTo(" VaL");
166 | Assertions.assertThat(bit2.getNextString(8 * 8)).isEqualTo("eUr e'*/");
167 | }
168 |
169 | /**
170 | * Test the method get/set boolean
171 | */
172 | @Test
173 | public void testGetSetBoolean() {
174 |
175 | BitUtils bit = new BitUtils(8);
176 | bit.setNextBoolean(false);
177 | bit.setNextBoolean(true);
178 | bit.setNextBoolean(false);
179 | bit.setNextBoolean(false);
180 | bit.reset();
181 |
182 | Assertions.assertThat(bit.getData()).isEqualTo(new byte[] { (byte) 0x40 });
183 | Assertions.assertThat(bit.getNextBoolean()).isEqualTo(false);
184 | Assertions.assertThat(bit.getNextBoolean()).isEqualTo(true);
185 | Assertions.assertThat(bit.getNextBoolean()).isEqualTo(false);
186 | Assertions.assertThat(bit.getNextBoolean()).isEqualTo(false);
187 | }
188 |
189 | /**
190 | * Test the mask function
191 | */
192 | @Test
193 | public void testMask() {
194 |
195 | BitUtils bit = new BitUtils(test);
196 |
197 | Assertions.assertThat(bit.getMask(0, 1)).isEqualTo((byte) 0x80);
198 | Assertions.assertThat(bit.getMask(2, 2)).isEqualTo((byte) 0x30);
199 | Assertions.assertThat(bit.getMask(0, 2)).isEqualTo((byte) 0xC0);
200 | Assertions.assertThat(bit.getMask(3, 4)).isEqualTo((byte) 0x1E);
201 | Assertions.assertThat(bit.getMask(7, 1)).isEqualTo((byte) 0x01);
202 | Assertions.assertThat(bit.getMask(0, 8)).isEqualTo((byte) 0xFF);
203 | Assertions.assertThat(bit.getMask(2, 2)).isEqualTo((byte) 0x30);
204 | Assertions.assertThat(bit.getMask(1, 6)).isEqualTo((byte) 0x7E);
205 | }
206 |
207 | /**
208 | * Unit test for resetNextBits
209 | */
210 | @Test
211 | public void testResetNextBits() {
212 | BitUtils bit = new BitUtils(10);
213 | bit.setNextInteger(1000, 8);
214 | bit.reset();
215 | Assertions.assertThat(bit.getNextHexaString(8)).isEqualTo("FF");
216 | bit.reset();
217 | bit.resetNextBits(4);
218 | bit.reset();
219 | Assertions.assertThat(bit.getNextHexaString(8)).isEqualTo("0F");
220 | bit = new BitUtils(new byte[] { (byte) 0xFF, (byte) 0xFF });
221 | bit.resetNextBits(12);
222 | bit.reset();
223 | Assertions.assertThat(bit.getNextHexaString(16)).isEqualTo("000F");
224 | bit = new BitUtils(new byte[] { (byte) 0xFF, (byte) 0xFF });
225 | bit.addCurrentBitIndex(2);
226 | bit.resetNextBits(11);
227 | bit.reset();
228 | Assertions.assertThat(bit.getNextHexaString(16)).isEqualTo("C007");
229 | }
230 |
231 | /**
232 | * Test the method to set an integer
233 | */
234 | @Test
235 | public void testSetInteger() {
236 |
237 | BitUtils bit3 = new BitUtils(128);
238 | bit3.setNextInteger(10, 6);
239 | bit3.setNextInteger(23, 12);
240 | bit3.setNextInteger(5, 8);
241 | bit3.setNextInteger(930, 16);
242 | bit3.setNextInteger(5, 3);
243 | bit3.setNextInteger(159, 8);
244 | bit3.setNextInteger(7, 3);
245 | bit3.reset();
246 |
247 | Assertions.assertThat(bit3.getNextInteger(6)).isEqualTo(10);
248 | Assertions.assertThat(bit3.getNextInteger(12)).isEqualTo(23);
249 | Assertions.assertThat(bit3.getNextInteger(8)).isEqualTo(5);
250 | Assertions.assertThat(bit3.getNextInteger(16)).isEqualTo(930);
251 | Assertions.assertThat(bit3.getNextInteger(3)).isEqualTo(5);
252 | Assertions.assertThat(bit3.getNextInteger(8)).isEqualTo(159);
253 | Assertions.assertThat(bit3.getNextInteger(3)).isEqualTo(7);
254 |
255 | BitUtils bit2 = new BitUtils(128);
256 | bit2.setNextInteger(3, 2);
257 | bit2.setNextInteger(1057, 14);
258 | bit2.setNextInteger(1, 1);
259 | bit2.setNextInteger(1532, 15);
260 | bit2.setNextInteger(8, 8);
261 | bit2.setNextInteger(1532, 15);
262 |
263 | bit2.reset();
264 |
265 | Assertions.assertThat(bit2.getNextInteger(2)).isEqualTo(3);
266 | Assertions.assertThat(bit2.getNextInteger(14)).isEqualTo(1057);
267 | Assertions.assertThat(bit2.getNextInteger(1)).isEqualTo(1);
268 | Assertions.assertThat(bit2.getNextInteger(15)).isEqualTo(1532);
269 | Assertions.assertThat(bit2.getNextInteger(8)).isEqualTo(8);
270 | Assertions.assertThat(bit2.getNextInteger(15)).isEqualTo(1532);
271 |
272 | BitUtils bit = new BitUtils(64);
273 | bit.setNextInteger(3, 2);
274 | bit.setNextInteger(255, 8);
275 | bit.setNextInteger(0, 2);
276 | bit.setNextInteger(15, 4);
277 | bit.setNextInteger(2, 2);
278 | bit.setNextInteger(3, 3);
279 | bit.setNextInteger(1, 1);
280 | bit.setNextInteger(0, 1);
281 | bit.setNextInteger(1, 1);
282 | bit.reset();
283 |
284 | Assertions.assertThat(bit.getNextInteger(2)).isEqualTo(3);
285 | Assertions.assertThat(bit.getNextInteger(8)).isEqualTo(255);
286 | Assertions.assertThat(bit.getNextInteger(2)).isEqualTo(0);
287 | Assertions.assertThat(bit.getNextInteger(4)).isEqualTo(15);
288 | Assertions.assertThat(bit.getNextInteger(2)).isEqualTo(2);
289 | Assertions.assertThat(bit.getNextInteger(3)).isEqualTo(3);
290 | Assertions.assertThat(bit.getNextInteger(1)).isEqualTo(1);
291 | Assertions.assertThat(bit.getNextInteger(1)).isEqualTo(0);
292 | Assertions.assertThat(bit.getNextInteger(1)).isEqualTo(1);
293 |
294 | bit.clear();
295 | try {
296 | bit.setNextInteger(500, 33);
297 | Assert.fail();
298 | } catch (IllegalArgumentException iae) {
299 | }
300 | bit.clear();
301 | bit.setNextInteger(127, 5);
302 | bit.reset();
303 | Assertions.assertThat(bit.getNextInteger(5)).isEqualTo(31);
304 | }
305 |
306 | @Test
307 | public void testOverflowValueInSize() {
308 | BitUtils bit = new BitUtils(64);
309 | bit.setNextInteger(Integer.MAX_VALUE, 3);
310 | bit.reset();
311 | Assertions.assertThat(bit.getNextInteger(3)).isEqualTo(7);
312 |
313 | bit.clear();
314 | bit.setNextLong(Long.MAX_VALUE, 40);
315 | bit.reset();
316 | Assertions.assertThat(bit.getNextLong(40)).isEqualTo(1099511627775L);
317 | }
318 |
319 | @Test
320 | public void testMaxMinValueInteger() {
321 | BitUtils bit = new BitUtils(64);
322 | bit.setNextInteger(Integer.MIN_VALUE, 32);
323 | bit.reset();
324 | Assertions.assertThat(bit.getNextHexaString(32)).isEqualTo("80000000");
325 | bit.reset();
326 | Assertions.assertThat(bit.getNextInteger(32)).isEqualTo(Integer.MIN_VALUE);
327 |
328 | bit.clear();
329 | bit.setNextInteger(Integer.MAX_VALUE, 32);
330 | bit.reset();
331 | Assertions.assertThat(bit.getNextHexaString(32)).isEqualTo("7FFFFFFF");
332 | bit.reset();
333 | Assertions.assertThat(bit.getNextInteger(32)).isEqualTo(Integer.MAX_VALUE);
334 | }
335 |
336 | /**
337 | * Test the method to set an long
338 | */
339 | @Test
340 | public void testSetLong() {
341 |
342 | BitUtils bit3 = new BitUtils(128);
343 | bit3.setNextLong(10, 6);
344 | bit3.setNextLong(23, 12);
345 | bit3.setNextLong(5, 8);
346 | bit3.setNextLong(930, 16);
347 | bit3.setNextLong(5, 3);
348 | bit3.setNextLong(159, 8);
349 | bit3.setNextLong(7, 3);
350 | bit3.reset();
351 |
352 | Assertions.assertThat(bit3.getNextLong(6)).isEqualTo(10);
353 | Assertions.assertThat(bit3.getNextLong(12)).isEqualTo(23);
354 | Assertions.assertThat(bit3.getNextLong(8)).isEqualTo(5);
355 | Assertions.assertThat(bit3.getNextLong(16)).isEqualTo(930);
356 | Assertions.assertThat(bit3.getNextLong(3)).isEqualTo(5);
357 | Assertions.assertThat(bit3.getNextLong(8)).isEqualTo(159);
358 | Assertions.assertThat(bit3.getNextLong(3)).isEqualTo(7);
359 |
360 | BitUtils bit2 = new BitUtils(128);
361 | bit2.setNextLong(3, 2);
362 | bit2.setNextLong(1057, 14);
363 | bit2.setNextLong(1, 1);
364 | bit2.setNextLong(1532, 15);
365 | bit2.setNextLong(8, 8);
366 | bit2.setNextLong(1532, 15);
367 |
368 | bit2.reset();
369 |
370 | Assertions.assertThat(bit2.getNextLong(2)).isEqualTo(3);
371 | Assertions.assertThat(bit2.getNextLong(14)).isEqualTo(1057);
372 | Assertions.assertThat(bit2.getNextLong(1)).isEqualTo(1);
373 | Assertions.assertThat(bit2.getNextLong(15)).isEqualTo(1532);
374 | Assertions.assertThat(bit2.getNextLong(8)).isEqualTo(8);
375 | Assertions.assertThat(bit2.getNextLong(15)).isEqualTo(1532);
376 |
377 | BitUtils bit = new BitUtils(64);
378 | bit.setNextLong(3, 2);
379 | bit.setNextLong(255, 8);
380 | bit.setNextLong(0, 2);
381 | bit.setNextLong(15, 4);
382 | bit.setNextLong(2, 2);
383 | bit.setNextLong(3, 3);
384 | bit.setNextLong(1, 1);
385 | bit.setNextLong(0, 1);
386 | bit.setNextLong(1, 1);
387 | bit.reset();
388 |
389 | Assertions.assertThat(bit.getNextLong(2)).isEqualTo(3);
390 | Assertions.assertThat(bit.getNextLong(8)).isEqualTo(255);
391 | Assertions.assertThat(bit.getNextLong(2)).isEqualTo(0);
392 | Assertions.assertThat(bit.getNextLong(4)).isEqualTo(15);
393 | Assertions.assertThat(bit.getNextLong(2)).isEqualTo(2);
394 | Assertions.assertThat(bit.getNextLong(3)).isEqualTo(3);
395 | Assertions.assertThat(bit.getNextLong(1)).isEqualTo(1);
396 | Assertions.assertThat(bit.getNextLong(1)).isEqualTo(0);
397 | Assertions.assertThat(bit.getNextLong(1)).isEqualTo(1);
398 |
399 | bit.reset();
400 | try {
401 | bit.setNextLong(500, 65);
402 | Assert.fail();
403 | } catch (IllegalArgumentException iae) {
404 | }
405 | }
406 |
407 | @Test
408 | public void testMaxMinValueLong() {
409 | BitUtils bit = new BitUtils(64);
410 | bit.setNextLong(Long.MIN_VALUE, 64);
411 | bit.reset();
412 | Assertions.assertThat(bit.getNextHexaString(64)).isEqualTo("8000000000000000");
413 | bit.reset();
414 | Assertions.assertThat(bit.getNextLong(64)).isEqualTo(Long.MIN_VALUE);
415 |
416 | bit.clear();
417 | bit.setNextLong(Long.MAX_VALUE, 64);
418 | bit.reset();
419 | Assertions.assertThat(bit.getNextHexaString(64)).isEqualTo("7FFFFFFFFFFFFFFF");
420 | bit.reset();
421 | Assertions.assertThat(bit.getNextLong(64)).isEqualTo(Long.MAX_VALUE);
422 | }
423 |
424 | @Test
425 | public void testLongMaxMinValue(){
426 | BitUtils bit = new BitUtils(64);
427 | bit.setNextHexaString("FFFFFFFFFFFFFFFF", 64);
428 | bit.reset();
429 | Assertions.assertThat(bit.getNextInteger(64)).isEqualTo(-1);
430 | }
431 |
432 | /**
433 | * Test the method to set an integer
434 | */
435 | @Test
436 | public void testSetIntegerOverflow() {
437 |
438 | BitUtils bit = new BitUtils(128);
439 | bit.setNextInteger(10, 2);
440 | bit.setNextInteger(256, 1);
441 | bit.reset();
442 | Assertions.assertThat(bit.getNextInteger(2)).isEqualTo(3);
443 | Assertions.assertThat(bit.getNextInteger(1)).isEqualTo(1);
444 | }
445 |
446 | /**
447 | * Test the method to set bytes
448 | */
449 | @Test
450 | public void testSetNextByte() {
451 |
452 | byte[] tab = new byte[] { (byte) 0x12, (byte) 0x20 };
453 | BitUtils bit = new BitUtils(tab.length * 8 * 2);
454 | bit.setNextByte(tab, tab.length * 8);
455 | bit.setNextByte(tab, tab.length * 8);
456 | bit.reset();
457 |
458 | Assertions.assertThat(bit.getNextHexaString(tab.length * 8)).isEqualTo("1220");
459 | Assertions.assertThat(bit.getNextHexaString(tab.length * 8)).isEqualTo("1220");
460 |
461 | byte[] tab2 = new byte[] { (byte) 0x22, (byte) 0x50 };
462 | BitUtils bit2 = new BitUtils(16);
463 | bit2.setNextInteger(3, 3);
464 | bit2.setNextByte(tab2, 13);
465 | bit2.reset();
466 |
467 | Assertions.assertThat(bit2.getNextHexaString(16)).isEqualTo("644A");
468 | }
469 |
470 | /**
471 | * Test the method to set bytes
472 | */
473 | @Test
474 | public void testSetNextByte2() {
475 |
476 | byte[] tab = new byte[] { (byte) 0x12 };
477 | BitUtils bit = new BitUtils(9);
478 | bit.setNextInteger(1, 1);
479 | bit.setNextByte(tab, 8);
480 | bit.reset();
481 |
482 | Assertions.assertThat(bit.getNextHexaString(9)).isEqualTo("8900");
483 | bit.reset();
484 | Assertions.assertThat(bit.getNextHexaString(8)).isEqualTo("89");
485 | }
486 |
487 | @Test
488 | public void testSetNextDate() throws ParseException {
489 |
490 | String val = "20130108";
491 | BitUtils bit = new BitUtils(100);
492 | SimpleDateFormat sdf = new SimpleDateFormat(BitUtils.DATE_FORMAT);
493 | Date d = sdf.parse(val);
494 | bit.setNextDate(d, BitUtils.DATE_FORMAT);
495 | bit.reset();
496 | Assertions.assertThat(sdf.format(bit.getNextDate(8 * 8, BitUtils.DATE_FORMAT))).isEqualTo(val);
497 | bit.reset();
498 | bit.setNextDate(d, BitUtils.DATE_FORMAT, true);
499 | bit.reset();
500 | Assertions.assertThat(bit.getNextHexaString(8 * 4)).isEqualTo(val);
501 | }
502 |
503 | /**
504 | * Test the method to set an hexa string
505 | */
506 | @Test
507 | public void testSetNextHexaString() {
508 |
509 | String text1 = "1122334455";
510 | BitUtils bit = new BitUtils(text1.length() * 4 + 1);
511 | bit.setNextBoolean(true);
512 | bit.setNextHexaString(text1, text1.length() * 4);
513 | bit.reset();
514 | Assertions.assertThat(bit.getNextBoolean()).isEqualTo(true);
515 | Assertions.assertThat(bit.getNextHexaString(text1.length() * 4)).isEqualTo(text1);
516 | bit.reset();
517 | Assertions.assertThat(bit.getNextBoolean()).isEqualTo(true);
518 | Assertions.assertThat(bit.getNextHexaString(text1.length() / 2 * 4)).isEqualTo("112230");
519 |
520 | bit = new BitUtils(20);
521 | try {
522 | bit.setNextHexaString("AAB", 20);
523 | org.junit.Assert.fail();
524 | } catch (IllegalArgumentException iae) {
525 | org.junit.Assert.assertTrue(true);
526 | }
527 |
528 | }
529 |
530 | /**
531 | * Test the method to set an integer
532 | */
533 | @Test
534 | public void testSetPaddedString() {
535 |
536 | String text = "123456789";
537 | BitUtils bit = new BitUtils(160);
538 | bit.setNextString(text, 10 * 8, true);
539 | bit.setNextString(text, 10 * 8, false);
540 | bit.reset();
541 | Assertions.assertThat(bit.getNextString(10 * 8)).isEqualTo('\0' + text);
542 | Assertions.assertThat(bit.getNextString(10 * 8)).isEqualTo(text + '\0');
543 | }
544 |
545 | /**
546 | * Test the method to set an integer
547 | */
548 | @Test
549 | public void testSetString() {
550 |
551 | String text1 = "test";
552 | String text2 = " OK";
553 | BitUtils bit = new BitUtils((text1.length() + text2.length()) * 8 + 5);
554 | bit.setNextInteger(3, 5);
555 | bit.setNextString(text1, text1.length() * 8);
556 | bit.setNextString(text2, 2 * 8);
557 | bit.reset();
558 |
559 | Assertions.assertThat(bit.getNextInteger(5)).isEqualTo(3);
560 | Assertions.assertThat(bit.getNextString(text1.length() * 8)).isEqualTo(text1);
561 | Assertions.assertThat(bit.getNextString(2 * 8)).isEqualTo(" O");
562 | bit.reset();
563 | Assertions.assertThat(bit.getNextInteger(5)).isEqualTo(3);
564 | Assertions.assertThat(bit.getNextString((text1.length() + 2) * 8)).isEqualTo(text1 + " O");
565 | }
566 |
567 | /**
568 | * Unit test for size
569 | */
570 | @Test
571 | public void testSize() {
572 | BitUtils bit = new BitUtils(289);
573 | Assertions.assertThat(bit.getSize()).isEqualTo(289);
574 |
575 | bit = new BitUtils(new byte[] { 0x33, 0x12 });
576 | Assertions.assertThat(bit.getSize()).isEqualTo(2 * 8);
577 | }
578 |
579 | /**
580 | * Unit test for signed value
581 | */
582 | @Test
583 | public void testSign() {
584 | BitUtils bit = new BitUtils(Long.SIZE);
585 | bit.setNextInteger(-2, 4);
586 | bit.reset();
587 | Assertions.assertThat(bit.getNextIntegerSigned(4)).isEqualTo(-2);
588 | bit.clear();
589 | bit.setNextInteger(0, 8);
590 | bit.reset();
591 | Assertions.assertThat(bit.getNextIntegerSigned(8)).isEqualTo(0);
592 | bit.clear();
593 | bit.setNextInteger(127, 8);
594 | bit.reset();
595 | Assertions.assertThat(bit.getNextIntegerSigned(8)).isEqualTo(127);
596 | bit.clear();
597 | bit.setNextInteger(-128, 8);
598 | bit.reset();
599 | Assertions.assertThat(bit.getNextIntegerSigned(8)).isEqualTo(-128);
600 | bit.clear();
601 | bit.setNextInteger(-256, 16);
602 | bit.reset();
603 | Assertions.assertThat(bit.getNextIntegerSigned(16)).isEqualTo(-256);
604 | bit.clear();
605 | bit.setNextInteger(Integer.MIN_VALUE, Integer.SIZE);
606 | bit.reset();
607 | Assertions.assertThat(bit.getNextIntegerSigned(Integer.SIZE)).isEqualTo(Integer.MIN_VALUE);
608 | bit.clear();
609 | bit.setNextLong(Long.MIN_VALUE, Long.SIZE);
610 | bit.reset();
611 | Assertions.assertThat(bit.getNextLongSigned(Long.SIZE)).isEqualTo(Long.MIN_VALUE);
612 | }
613 |
614 | /**
615 | * Unit test for signed value
616 | */
617 | @Test(expected = IllegalArgumentException.class)
618 | public void testOverflowIntegerSign() {
619 | BitUtils bit = new BitUtils(Integer.SIZE);
620 | bit.setNextInteger(-2, 4);
621 | bit.reset();
622 | Assertions.assertThat(bit.getNextIntegerSigned(33)).isEqualTo(-2);
623 | }
624 |
625 | /**
626 | * Unit test for signed value
627 | */
628 | @Test(expected = IllegalArgumentException.class)
629 | public void testOverflowLongSign() {
630 | BitUtils bit = new BitUtils(Long.SIZE);
631 | bit.setNextInteger(-2, 4);
632 | bit.reset();
633 | Assertions.assertThat(bit.getNextLongSigned(65)).isEqualTo(-2);
634 | }
635 |
636 | }
637 |
--------------------------------------------------------------------------------