Coverage Report - com.healthmarketscience.jackcess.ByteUtil
 
Classes in this File Line Coverage Branch Coverage Complexity
ByteUtil
86%
89/103
77%
17/22
1.5
 
 1  
 /*
 2  
 Copyright (c) 2005 Health Market Science, Inc.
 3  
 
 4  
 This library is free software; you can redistribute it and/or
 5  
 modify it under the terms of the GNU Lesser General Public
 6  
 License as published by the Free Software Foundation; either
 7  
 version 2.1 of the License, or (at your option) any later version.
 8  
 
 9  
 This library is distributed in the hope that it will be useful,
 10  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  
 Lesser General Public License for more details.
 13  
 
 14  
 You should have received a copy of the GNU Lesser General Public
 15  
 License along with this library; if not, write to the Free Software
 16  
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 17  
 USA
 18  
 
 19  
 You can contact Health Market Science at info@healthmarketscience.com
 20  
 or at the following address:
 21  
 
 22  
 Health Market Science
 23  
 2700 Horizon Drive
 24  
 Suite 200
 25  
 King of Prussia, PA 19406
 26  
 */
 27  
 
 28  
 package com.healthmarketscience.jackcess;
 29  
 
 30  
 import java.io.FileWriter;
 31  
 import java.io.IOException;
 32  
 import java.io.PrintWriter;
 33  
 import java.nio.ByteBuffer;
 34  
 import java.nio.ByteOrder;
 35  
 
 36  
 /**
 37  
  * Byte manipulation and display utilities
 38  
  * @author Tim McCune
 39  
  */
 40  
 public final class ByteUtil {
 41  
   
 42  1
   private static final String[] HEX_CHARS = new String[] {
 43  
       "0", "1", "2", "3", "4", "5", "6", "7",
 44  
       "8", "9", "A", "B", "C", "D", "E", "F"};
 45  
       
 46  0
   private ByteUtil() {}
 47  
 
 48  
   /**
 49  
    * Put an integer into the given buffer at the given offset as a 3-byte
 50  
    * integer.
 51  
    * @param buffer buffer into which to insert the int
 52  
    * @param val Int to convert
 53  
    */    
 54  
   public static void put3ByteInt(ByteBuffer buffer, int val)
 55  
   {
 56  1358
     put3ByteInt(buffer, val, buffer.order());
 57  1358
   }
 58  
   
 59  
   /**
 60  
    * Put an integer into the given buffer at the given offset as a 3-byte
 61  
    * integer.
 62  
    * @param buffer buffer into which to insert the int
 63  
    * @param val Int to convert
 64  
    * @param order  the order to insert the bytes of the int
 65  
    */    
 66  
   public static void put3ByteInt(ByteBuffer buffer, int val, ByteOrder order)
 67  
   {
 68  46874
     int pos = buffer.position();
 69  46874
     put3ByteInt(buffer, val, pos, order);
 70  46874
     buffer.position(pos + 3);
 71  46874
   }
 72  
   
 73  
   /**
 74  
    * Put an integer into the given buffer at the given offset as a 3-byte
 75  
    * integer.
 76  
    * @param buffer buffer into which to insert the int
 77  
    * @param val Int to convert
 78  
    * @param offset offset at which to insert the int
 79  
    * @param order  the order to insert the bytes of the int
 80  
    */    
 81  
   public static void put3ByteInt(ByteBuffer buffer, int val, int offset,
 82  
                                  ByteOrder order) {
 83  
 
 84  46874
     int offInc = 1;
 85  46874
     if(order == ByteOrder.BIG_ENDIAN) {
 86  45516
       offInc = -1;
 87  45516
       offset += 2;
 88  
     }
 89  
 
 90  46874
     buffer.put(offset, (byte) (val & 0xFF));
 91  46874
     buffer.put(offset + (1 * offInc), (byte) ((val >>> 8) & 0xFF));
 92  46874
     buffer.put(offset + (2 * offInc), (byte) ((val >>> 16) & 0xFF));
 93  46874
   }
 94  
 
 95  
   /**
 96  
    * Read a 3 byte int from a buffer
 97  
    * @param buffer Buffer containing the bytes
 98  
    * @return The int
 99  
    */
 100  
   public static int get3ByteInt(ByteBuffer buffer) {
 101  1180
     return get3ByteInt(buffer, buffer.order());
 102  
   }
 103  
 
 104  
   /**
 105  
    * Read a 3 byte int from a buffer
 106  
    * @param buffer Buffer containing the bytes
 107  
    * @param order  the order of the bytes of the int
 108  
    * @return The int
 109  
    */
 110  
   public static int get3ByteInt(ByteBuffer buffer, ByteOrder order) {  
 111  9010
     int pos = buffer.position();
 112  9010
     int rtn = get3ByteInt(buffer, pos, order);
 113  9010
     buffer.position(pos + 3);
 114  9010
     return rtn;
 115  
   }
 116  
 
 117  
   /**
 118  
    * Read a 3 byte int from a buffer
 119  
    * @param buffer Buffer containing the bytes
 120  
    * @param offset Offset at which to start reading the int
 121  
    * @return The int
 122  
    */
 123  
   public static int get3ByteInt(ByteBuffer buffer, int offset) {
 124  814
     return get3ByteInt(buffer, offset, buffer.order());
 125  
   }
 126  
   
 127  
   /**
 128  
    * Read a 3 byte int from a buffer
 129  
    * @param buffer Buffer containing the bytes
 130  
    * @param offset Offset at which to start reading the int
 131  
    * @param order  the order of the bytes of the int
 132  
    * @return The int
 133  
    */
 134  
   public static int get3ByteInt(ByteBuffer buffer, int offset,
 135  
                                 ByteOrder order) {
 136  
 
 137  9824
     int offInc = 1;
 138  9824
     if(order == ByteOrder.BIG_ENDIAN) {
 139  7830
       offInc = -1;
 140  7830
       offset += 2;
 141  
     }
 142  
     
 143  9824
     int rtn = getUnsignedByte(buffer, offset);
 144  9824
     rtn += (getUnsignedByte(buffer, offset + (1 * offInc)) << 8);
 145  9824
     rtn += (getUnsignedByte(buffer, offset + (2 * offInc)) << 16);
 146  9824
     return rtn;
 147  
   }
 148  
 
 149  
   /**
 150  
    * Read an unsigned byte from a buffer
 151  
    * @param buffer Buffer containing the bytes
 152  
    * @return The unsigned byte as an int
 153  
    */
 154  
   public static int getUnsignedByte(ByteBuffer buffer) {
 155  8409
     int pos = buffer.position();
 156  8409
     int rtn = getUnsignedByte(buffer, pos);
 157  8409
     buffer.position(pos + 1);
 158  8409
     return rtn;
 159  
   }
 160  
 
 161  
   /**
 162  
    * Read an unsigned byte from a buffer
 163  
    * @param buffer Buffer containing the bytes
 164  
    * @param offset Offset at which to read the byte
 165  
    * @return The unsigned byte as an int
 166  
    */
 167  
   public static int getUnsignedByte(ByteBuffer buffer, int offset) {  
 168  38428
     return asUnsignedByte(buffer.get(offset));
 169  
   }
 170  
   
 171  
   /**
 172  
    * Read an unsigned short from a buffer
 173  
    * @param buffer Buffer containing the short
 174  
    * @return The unsigned short as an int
 175  
    */
 176  
   public static int getUnsignedShort(ByteBuffer buffer) {
 177  2565
     int pos = buffer.position();
 178  2565
     int rtn = getUnsignedShort(buffer, pos);
 179  2565
     buffer.position(pos + 2);
 180  2565
     return rtn;
 181  
   }
 182  
 
 183  
   /**
 184  
    * Read an unsigned short from a buffer
 185  
    * @param buffer Buffer containing the short
 186  
    * @param offset Offset at which to read the short
 187  
    * @return The unsigned short as an int
 188  
    */
 189  
   public static int getUnsignedShort(ByteBuffer buffer, int offset) {  
 190  2994
     return asUnsignedShort(buffer.getShort(offset));
 191  
   }
 192  
 
 193  
   
 194  
   /**
 195  
    * @param buffer Buffer containing the bytes
 196  
    * @param order  the order of the bytes of the int
 197  
    * @return an int from the current position in the given buffer, read using
 198  
    *         the given ByteOrder
 199  
    */
 200  
   public static int getInt(ByteBuffer buffer, ByteOrder order) {
 201  209
     int offset = buffer.position();
 202  209
     int rtn = getInt(buffer, offset, order);
 203  209
     buffer.position(offset + 4);
 204  209
     return rtn;
 205  
   }
 206  
   
 207  
   /**
 208  
    * @param buffer Buffer containing the bytes
 209  
    * @param offset Offset at which to start reading the int
 210  
    * @param order  the order of the bytes of the int
 211  
    * @return an int from the given position in the given buffer, read using
 212  
    *         the given ByteOrder
 213  
    */
 214  
   public static int getInt(ByteBuffer buffer, int offset, ByteOrder order) {
 215  209
     ByteOrder origOrder = buffer.order();
 216  
     try {
 217  209
       return buffer.order(order).getInt(offset);
 218  
     } finally {
 219  209
       buffer.order(origOrder);
 220  
     }
 221  
   }
 222  
   
 223  
   /**
 224  
    * Writes an int at the current position in the given buffer, using the
 225  
    * given ByteOrder
 226  
    * @param buffer buffer into which to insert the int
 227  
    * @param val Int to insert
 228  
    * @param order the order to insert the bytes of the int
 229  
    */
 230  
   public static void putInt(ByteBuffer buffer, int val, ByteOrder order) {
 231  4945
     int offset = buffer.position();
 232  4945
     putInt(buffer, val, offset, order);
 233  4945
     buffer.position(offset + 4);
 234  4945
   }
 235  
   
 236  
   /**
 237  
    * Writes an int at the given position in the given buffer, using the
 238  
    * given ByteOrder
 239  
    * @param buffer buffer into which to insert the int
 240  
    * @param val Int to insert
 241  
    * @param offset offset at which to insert the int
 242  
    * @param order the order to insert the bytes of the int
 243  
    */
 244  
   public static void putInt(ByteBuffer buffer, int val, int offset,
 245  
                            ByteOrder order)
 246  
   {
 247  4945
     ByteOrder origOrder = buffer.order();
 248  
     try {
 249  4945
       buffer.order(order).putInt(offset, val);
 250  
     } finally {
 251  4945
       buffer.order(origOrder);
 252  4945
     }
 253  4945
   }
 254  
 
 255  
   /**
 256  
    * Sets all bits in the given byte range to 0.
 257  
    */
 258  
   public static void clearRange(ByteBuffer buffer, int start,
 259  
                                 int end)
 260  
   {
 261  5
     putRange(buffer, start, end, (byte)0x00);
 262  5
   }
 263  
 
 264  
   /**
 265  
    * Sets all bits in the given byte range to 1.
 266  
    */
 267  
   public static void fillRange(ByteBuffer buffer, int start,
 268  
                                int end)
 269  
   {
 270  0
     putRange(buffer, start, end, (byte)0xff);
 271  0
   }
 272  
   
 273  
   /**
 274  
    * Sets all bytes in the given byte range to the given byte value.
 275  
    */
 276  
   public static void putRange(ByteBuffer buffer, int start,
 277  
                               int end, byte b)
 278  
   {
 279  345
     for(int i = start; i < end; ++i) {
 280  340
       buffer.put(i, b);
 281  
     }
 282  5
   }
 283  
 
 284  
   /**
 285  
    * Matches a pattern of bytes against the given buffer starting at the given
 286  
    * offset.
 287  
    */
 288  
   public static boolean matchesRange(ByteBuffer buffer, int start,
 289  
                                      byte[] pattern)
 290  
   {
 291  0
     for(int i = 0; i < pattern.length; ++i) {
 292  0
       if(pattern[i] != buffer.get(start + i)) {
 293  0
         return false;
 294  
       }
 295  
     }
 296  0
     return true;
 297  
   }
 298  
   
 299  
   /**
 300  
    * Convert a byte buffer to a hexadecimal string for display
 301  
    * @param buffer Buffer to display, starting at offset 0
 302  
    * @param size Number of bytes to read from the buffer
 303  
    * @return The display String
 304  
    */
 305  
   public static String toHexString(ByteBuffer buffer, int size) {
 306  3608
     return toHexString(buffer, 0, size);
 307  
   }
 308  
   
 309  
   /**
 310  
    * Convert a byte array to a hexadecimal string for display
 311  
    * @param array byte array to display, starting at offset 0
 312  
    * @return The display String
 313  
    */
 314  
   public static String toHexString(byte[] array) {
 315  0
     return toHexString(ByteBuffer.wrap(array), 0, array.length);
 316  
   }
 317  
   
 318  
   /**
 319  
    * Convert a byte buffer to a hexadecimal string for display
 320  
    * @param buffer Buffer to display, starting at offset 0
 321  
    * @param offset Offset at which to start reading the buffer
 322  
    * @param size Number of bytes to read from the buffer
 323  
    * @return The display String
 324  
    */
 325  
   public static String toHexString(ByteBuffer buffer, int offset, int size) {
 326  3608
     return toHexString(buffer, offset, size, true);
 327  
   }    
 328  
 
 329  
   /**
 330  
    * Convert a byte buffer to a hexadecimal string for display
 331  
    * @param buffer Buffer to display, starting at offset 0
 332  
    * @param offset Offset at which to start reading the buffer
 333  
    * @param size Number of bytes to read from the buffer
 334  
    * @param formatted flag indicating if formatting is required
 335  
    * @return The display String
 336  
    */
 337  
   public static String toHexString(ByteBuffer buffer,
 338  
                                    int offset, int size, boolean formatted) {
 339  
     
 340  3633
     StringBuilder rtn = new StringBuilder();
 341  3633
     int position = buffer.position();
 342  3633
     buffer.position(offset);
 343  
 
 344  39821
     for (int i = 0; i < size; i++) {
 345  36188
       byte b = buffer.get();
 346  36188
       byte h = (byte) (b & 0xF0);
 347  36188
       h = (byte) (h >>> 4);
 348  36188
       h = (byte) (h & 0x0F);
 349  36188
       rtn.append(HEX_CHARS[h]);
 350  36188
       h = (byte) (b & 0x0F);
 351  36188
       rtn.append(HEX_CHARS[h]);
 352  
 
 353  36188
       if (formatted == true)
 354  
       {
 355  36108
         rtn.append(" ");
 356  
 
 357  36108
         if ((i + 1) % 4 == 0) {
 358  7834
           rtn.append(" ");
 359  
         }
 360  36108
         if ((i + 1) % 24 == 0) {
 361  148
           rtn.append("\n");
 362  
         }
 363  
       }
 364  
     }
 365  
 
 366  3633
     buffer.position(position);
 367  3633
     return rtn.toString();
 368  
   }
 369  
 
 370  
   /**
 371  
    * Writes a sequence of hexidecimal values into the given buffer, where
 372  
    * every two characters represent one byte value.
 373  
    */
 374  
   public static void writeHexString(ByteBuffer buffer,
 375  
                                     String hexStr)
 376  
     throws IOException
 377  
   {
 378  25
     char[] hexChars = hexStr.toCharArray();
 379  25
     if((hexChars.length % 2) != 0) {
 380  0
       throw new IOException("Hex string length must be even");
 381  
     }
 382  105
     for(int i = 0; i < hexChars.length; i += 2) {
 383  80
       String tmpStr = new String(hexChars, i, 2);
 384  80
       buffer.put((byte)Long.parseLong(tmpStr, 16));
 385  
     }
 386  25
   }
 387  
 
 388  
   /**
 389  
    * Writes a chunk of data to a file in pretty printed hexidecimal.
 390  
    */
 391  
   public static void toHexFile(
 392  
       String fileName,
 393  
       ByteBuffer buffer, 
 394  
       int offset, int size)
 395  
     throws IOException
 396  
   {
 397  0
     PrintWriter writer = new PrintWriter(
 398  
         new FileWriter(fileName));
 399  
     try {
 400  0
       writer.println(toHexString(buffer, offset, size));
 401  
     } finally {
 402  0
       writer.close();
 403  0
     }
 404  0
   }
 405  
 
 406  
   /**
 407  
    * @return the byte value converted to an unsigned int value
 408  
    */
 409  
   public static int asUnsignedByte(byte b) { 
 410  290846
     return b & 0xFF;
 411  
   }
 412  
   
 413  
   /**
 414  
    * @return the short value converted to an unsigned int value
 415  
    */
 416  
   public static int asUnsignedShort(short s) { 
 417  2994
     return s & 0xFFFF;
 418  
   }
 419  
   
 420  
 }