-
Notifications
You must be signed in to change notification settings - Fork 40
/
BinaryUtils.java
168 lines (151 loc) · 5.55 KB
/
BinaryUtils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// ============================================================================
// Copyright 2006-2012 Daniel W. Dyer
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ============================================================================
package org.uncommons.maths.binary;
/**
* Utility methods for working with binary and hex data.
* @author Daniel Dyer
*/
public final class BinaryUtils
{
// Mask for casting a byte to an int, bit-by-bit (with
// bitwise AND) with no special consideration for the sign bit.
private static final int BITWISE_BYTE_TO_INT = 0x000000FF;
private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
private BinaryUtils()
{
// Prevents instantiation of utility class.
}
/**
* Converts an array of bytes in to a String of hexadecimal characters (0 - F).
* @param data An array of bytes to convert to a String.
* @return A hexadecimal String representation of the data.
*/
public static String convertBytesToHexString(byte[] data)
{
StringBuilder buffer = new StringBuilder(data.length * 2);
for (byte b : data)
{
buffer.append(HEX_CHARS[(b >>> 4) & 0x0F]);
buffer.append(HEX_CHARS[b & 0x0F]);
}
return buffer.toString();
}
/**
* Converts a hexadecimal String (such as one generated by the
* {@link #convertBytesToHexString(byte[])} method) into an array of bytes.
* @param hex The hexadecimal String to be converted into an array of bytes.
* @return An array of bytes that.
*/
public static byte[] convertHexStringToBytes(String hex)
{
if (hex.length() % 2 != 0)
{
throw new IllegalArgumentException("Hex string must have even number of characters.");
}
byte[] seed = new byte[hex.length() / 2];
for (int i = 0; i < seed.length; i++)
{
int index = i * 2;
seed[i] = (byte) Integer.parseInt(hex.substring(index, index + 2), 16);
}
return seed;
}
/**
* Take four bytes from the specified position in the specified
* block and convert them into a 32-bit int, using the big-endian
* convention.
* @param bytes The data to read from.
* @param offset The position to start reading the 4-byte int from.
* @return The 32-bit integer represented by the four bytes.
*/
public static int convertBytesToInt(byte[] bytes, int offset)
{
return (BITWISE_BYTE_TO_INT & bytes[offset + 3])
| ((BITWISE_BYTE_TO_INT & bytes[offset + 2]) << 8)
| ((BITWISE_BYTE_TO_INT & bytes[offset + 1]) << 16)
| ((BITWISE_BYTE_TO_INT & bytes[offset]) << 24);
}
/**
* Convert an array of bytes into an array of ints. 4 bytes from the
* input data map to a single int in the output data.
* @param bytes The data to read from.
* @return An array of 32-bit integers constructed from the data.
* @since 1.1
*/
public static int[] convertBytesToInts(byte[] bytes)
{
if (bytes.length % 4 != 0)
{
throw new IllegalArgumentException("Number of input bytes must be a multiple of 4.");
}
int[] ints = new int[bytes.length / 4];
for (int i = 0; i < ints.length; i++)
{
ints[i] = convertBytesToInt(bytes, i * 4);
}
return ints;
}
/**
* Utility method to convert an array of bytes into a long. Byte ordered is
* assumed to be big-endian.
* @param bytes The data to read from.
* @param offset The position to start reading the 8-byte long from.
* @return The 64-bit integer represented by the eight bytes.
* @since 1.1
*/
public static long convertBytesToLong(byte[] bytes, int offset)
{
long value = 0;
for (int i = offset; i < offset + 8; i++)
{
byte b = bytes[i];
value <<= 8;
value |= b;
}
return value;
}
/**
* Converts a floating point value in the range 0 - 1 into a fixed
* point bit string (where the most significant bit has a value of 0.5).
* @param value The value to convert (must be between zero and one).
* @return A bit string representing the value in fixed-point format.
*/
public static BitString convertDoubleToFixedPointBits(double value)
{
if (value < 0.0d || value >= 1.0d)
{
throw new IllegalArgumentException("Value must be between 0 and 1.");
}
StringBuilder bits = new StringBuilder(64);
double bitValue = 0.5d;
double d = value;
while (d > 0)
{
if (d >= bitValue)
{
bits.append('1');
d -= bitValue;
}
else
{
bits.append('0');
}
bitValue /= 2;
}
return new BitString(bits.toString());
}
}