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