001 /* JAPI - (Yet another (hopefully) useful) Java API
002 *
003 * Copyright (C) 2004-2006 Christian Hujer
004 *
005 * This program is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU General Public License as
007 * published by the Free Software Foundation; either version 2 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but
011 * WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013 * General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018 * 02111-1307, USA.
019 */
020
021 package net.sf.japi.io;
022
023 /** A class to get nibbles from byte sequences.
024 * This class works in sequentially numbered big endian (network byte) order, which means that the first nibble (0-nibble) is the high nibble of the
025 * first byte (high byte high nibble).
026 * You may also call this "high nibble first".
027 * The long value 0x0123456789ABCDEFl reflects the nibble indices in longs.
028 * Other datatypes work similarly:
029 * The int value 0x01234567 reflects the nibble indices in ints.
030 * <p />
031 * Binary nibbles are returned as ints because the general contract of I/O-methods as in package <code>java.io</code> is to expect and return single
032 * bytes being stored in ints and it saves neither space nor performance to return bytes instead of ints.
033 * <p />
034 * When needing chars, you should invoke those methods returning chars directly (single method invocation) instead of first getting the nibble and then
035 * converting it to a char (two method invocations) because inlining compilers will give you a better performance then.
036 * <p />
037 * Everything in this class is final for performance reasons: Final methods can be sort of inlined by some compilers.
038 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
039 */
040 @SuppressWarnings({"UtilityClass", "ClassWithTooManyMethods"})
041 public final class Nibbles {
042
043 /** Lowercase nibble characters. */
044 private static final char[] LCASE_NIBBLES = "0123456789abcdef".toCharArray();
045
046 /** Uppercase nibble characters. */
047 private static final char[] UCASE_NIBBLES = "0123456789ABCDEF".toCharArray();
048
049 /** This class cannot be instanciated. */
050 private Nibbles() {}
051
052 /** Get a nibble from a byte array.
053 * @param data byte array to get nibble from
054 * @param index nibble number
055 * @return nibble value with nibble number
056 */
057 public static int getNibble(final byte[] data, final int index) {
058 return getNibble(data[index >> 1], index & 1);
059 }
060
061 /** Get all nibbles from a byte array.
062 * @param data byte array to get nibbles from
063 * @return byte array with nibbles; the length of the returned byte array is twice the length of the argument byte array
064 */
065 public static byte[] getNibbles(final byte[] data) {
066 return getNibbles(data, 0, data.length << 1);
067 }
068
069 /** Get some nibbles from a byte array.
070 * @param data byte array to get nibbles from
071 * @param startIndex first nibble index to get nibble for
072 * @param length number of nibbles to get
073 * @return byte array with nibbles
074 */
075 public static byte[] getNibbles(final byte[] data, final int startIndex, final int length) {
076 if (length < 0) { throw new IllegalArgumentException("Length may not be negative: " + length); }
077 if (startIndex < 0) { throw new IllegalArgumentException("Start index may not be negative: " + startIndex); }
078 if (startIndex >> 1 > data.length) { throw new IllegalArgumentException("Start index out of range: " + startIndex); }
079 if (startIndex + length >> 1 > data.length) { throw new IllegalArgumentException("Length out of range: " + length); }
080 final byte[] nibbles = new byte[length];
081 for (int i = 0, j = startIndex; i < length; i++, j++) {
082 nibbles[i] = (byte) (0xF & data[j >> 1] >> 4 * (1 - j & 1));
083 }
084 return nibbles;
085 }
086
087 /** Get a nibble from a byte value.
088 * @param data byte value to get nibble from
089 * @param index nibble number
090 * @return nibble value with nibble number
091 */
092 public static int getNibble(final byte data, final int index) {
093 return getNibble((long) data, index + 14);
094 }
095
096 /** Get a nibble from a short value.
097 * @param data short value to get nibble from
098 * @param index nibble number
099 * @return nibble value with nibble number
100 */
101 public static int getNibble(final short data, final int index) {
102 return getNibble((long) data, index + 12);
103 }
104
105 /** Get a nibble from an int value.
106 * @param data int value to get nibble from
107 * @param index nibble number
108 * @return nibble value with nibble number
109 */
110 public static int getNibble(final int data, final int index) {
111 return getNibble((long) data, index + 8);
112 }
113
114 /** Get a nibble from a long value.
115 * @param data int value to get nibble from
116 * @param index nibble number
117 * @return nibble value with nibble number
118 */
119 public static int getNibble(final long data, final int index) {
120 return 0xF & (int) (data >> 4 * (15 - index));
121 }
122
123 /** Get a nibble from a char value.
124 * @param data char value to get nibble from
125 * @param index nibble nubmer
126 * @return nibble value with nibble number
127 */
128 public static int getNibble(final char data, final int index) {
129 return getNibble((long) data, index + 12);
130 }
131
132 /** Get a nibble from a float value (raw format).
133 * To get the nibble from a float value in logical format, convert the float to an int yourself using {@link Float#floatToIntBits(float)}.
134 * @param data float value to get nibble from
135 * @param index nibble nubmer
136 * @return nibble value with nibble number
137 */
138 public static int getNibble(final float data, final int index) {
139 return getNibble((long) Float.floatToRawIntBits(data), index + 8);
140 }
141
142 /** Get a nibble from a double value (raw format).
143 * To get the nibble from a double value in logical format, convert the float to an int yourself using {@link Double#doubleToLongBits(double)}.
144 * @param data double value to get nibble from
145 * @param index nibble nubmer
146 * @return nibble value with nibble number
147 */
148 public static int getNibble(final double data, final int index) {
149 return getNibble(Double.doubleToRawLongBits(data), index);
150 }
151
152 /** Get a lowercase character for a nibble.
153 * @param nibble nibble to get character for
154 * @return lowercase character for <var>data</var>
155 * @throws IllegalArgumentException if <code>data</code> isn't a single nibble
156 */
157 public static char getNibbleLC(final int nibble) {
158 try {
159 return LCASE_NIBBLES[nibble];
160 } catch (final ArrayIndexOutOfBoundsException ignore) {
161 throw new IllegalArgumentException("Not a nibble: " + nibble);
162 }
163 }
164
165 /** Get a uppercase character for a nibble.
166 * @param nibble nibble to get character for
167 * @return uppercase character for <var>data</var>
168 * @throws IllegalArgumentException if <code>data</code> isn't a single nibble
169 */
170 public static char getNibbleUC(final int nibble) {
171 try {
172 return UCASE_NIBBLES[nibble];
173 } catch (final ArrayIndexOutOfBoundsException ignore) {
174 throw new IllegalArgumentException("Not a nibble: " + nibble);
175 }
176 }
177
178 /** Get a lowercase character reflecting a nibble from a byte array.
179 * Shorthand for getNibbleLC(getNibble(data, index)).
180 * @param data byte array to get nibble from
181 * @param index nibble number
182 * @return nibble character
183 */
184 public static char getNibbleLC(final byte[] data, final int index) {
185 return getNibbleLC(getNibble(data, index));
186 }
187
188 /** Get an uppercase character reflecting a nibble from a byte array.
189 * @param data byte array to get nibble from
190 * @param index nibble number
191 * @return nibble character
192 */
193 public static char getNibbleUC(final byte[] data, final int index) {
194 return getNibbleUC(getNibble(data, index));
195 }
196
197 /** Get a lowercase character reflecting a nibble from a byte.
198 * Shorthand for getNibbleLC(getNibble(data, index)).
199 * @param data byte to get nibble from
200 * @param index nibble number
201 * @return nibble character
202 */
203 public static char getNibbleLC(final byte data, final int index) {
204 return getNibbleLC(getNibble(data, index));
205 }
206
207 /** Get an uppercase character reflecting a nibble from a byte.
208 * @param data byte to get nibble from
209 * @param index nibble number
210 * @return nibble character
211 */
212 public static char getNibbleUC(final byte data, final int index) {
213 return getNibbleUC(getNibble(data, index));
214 }
215
216 /** Get a lowercase character reflecting a nibble from a short.
217 * Shorthand for getNibbleLC(getNibble(data, index)).
218 * @param data short to get nibble from
219 * @param index nibble number
220 * @return nibble character
221 */
222 public static char getNibbleLC(final short data, final int index) {
223 return getNibbleLC(getNibble(data, index));
224 }
225
226 /** Get an uppercase character reflecting a nibble from a short.
227 * @param data short to get nibble from
228 * @param index nibble number
229 * @return nibble character
230 */
231 public static char getNibbleUC(final short data, final int index) {
232 return getNibbleUC(getNibble(data, index));
233 }
234
235 /** Get a lowercase character reflecting a nibble from a int.
236 * Shorthand for getNibbleLC(getNibble(data, index)).
237 * @param data int to get nibble from
238 * @param index nibble number
239 * @return nibble character
240 */
241 public static char getNibbleLC(final int data, final int index) {
242 return getNibbleLC(getNibble(data, index));
243 }
244
245 /** Get an uppercase character reflecting a nibble from a int.
246 * @param data int to get nibble from
247 * @param index nibble number
248 * @return nibble character
249 */
250 public static char getNibbleUC(final int data, final int index) {
251 return getNibbleUC(getNibble(data, index));
252 }
253
254 /** Get a lowercase character reflecting a nibble from a long.
255 * Shorthand for getNibbleLC(getNibble(data, index)).
256 * @param data long to get nibble from
257 * @param index nibble number
258 * @return nibble character
259 */
260 public static char getNibbleLC(final long data, final int index) {
261 return getNibbleLC(getNibble(data, index));
262 }
263
264 /** Get an uppercase character reflecting a nibble from a long.
265 * @param data long to get nibble from
266 * @param index nibble number
267 * @return nibble character
268 */
269 public static char getNibbleUC(final long data, final int index) {
270 return getNibbleUC(getNibble(data, index));
271 }
272
273 /** Get a lowercase character reflecting a nibble from a char.
274 * Shorthand for getNibbleLC(getNibble(data, index)).
275 * @param data char to get nibble from
276 * @param index nibble number
277 * @return nibble character
278 */
279 public static char getNibbleLC(final char data, final int index) {
280 return getNibbleLC(getNibble(data, index));
281 }
282
283 /** Get an uppercase character reflecting a nibble from a char.
284 * @param data char to get nibble from
285 * @param index nibble number
286 * @return nibble character
287 */
288 public static char getNibbleUC(final char data, final int index) {
289 return getNibbleUC(getNibble(data, index));
290 }
291
292 /** Get a lowercase character reflecting a nibble from a float.
293 * Shorthand for getNibbleLC(getNibble(data, index)).
294 * @param data float to get nibble from
295 * @param index nibble number
296 * @return nibble character
297 */
298 public static char getNibbleLC(final float data, final int index) {
299 return getNibbleLC(getNibble(data, index));
300 }
301
302 /** Get an uppercase character reflecting a nibble from a float.
303 * @param data float to get nibble from
304 * @param index nibble number
305 * @return nibble character
306 */
307 public static char getNibbleUC(final float data, final int index) {
308 return getNibbleUC(getNibble(data, index));
309 }
310
311 /** Get a lowercase character reflecting a nibble from a double.
312 * Shorthand for getNibbleLC(getNibble(data, index)).
313 * @param data double to get nibble from
314 * @param index nibble number
315 * @return nibble character
316 */
317 public static char getNibbleLC(final double data, final int index) {
318 return getNibbleLC(getNibble(data, index));
319 }
320
321 /** Get an uppercase character reflecting a nibble from a double.
322 * @param data double to get nibble from
323 * @param index nibble number
324 * @return nibble character
325 */
326 public static char getNibbleUC(final double data, final int index) {
327 return getNibbleUC(getNibble(data, index));
328 }
329
330 } // class Nibbles