1 /* ==================================================================== 2 * The Apache Software License, Version 1.1 3 * 4 * Copyright (c) 2002 The Apache Software Foundation. All rights 5 * reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * 3. The end-user documentation included with the redistribution, 20 * if any, must include the following acknowledgment: 21 * "This product includes software developed by the 22 * Apache Software Foundation (http://www.apache.org/)." 23 * Alternately, this acknowledgment may appear in the software itself, 24 * if and wherever such third-party acknowledgments normally appear. 25 * 26 * 4. The names "Apache" and "Apache Software Foundation" and 27 * "Apache POI" must not be used to endorse or promote products 28 * derived from this software without prior written permission. For 29 * written permission, please contact apache@apache.org. 30 * 31 * 5. Products derived from this software may not be called "Apache", 32 * "Apache POI", nor may "Apache" appear in their name, without 33 * prior written permission of the Apache Software Foundation. 34 * 35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 46 * SUCH DAMAGE. 47 * ==================================================================== 48 * 49 * This software consists of voluntary contributions made by many 50 * individuals on behalf of the Apache Software Foundation. For more 51 * information on the Apache Software Foundation, please see 52 * <http://www.apache.org/>. 53 */ 54 55 package org.apache.poi.util; 56 57 import java.io.IOException; 58 import java.io.InputStream; 59 import java.util.Arrays; 60 61 /** 62 * a utility class for handling little-endian numbers, which the 80x86 63 * world is replete with. The methods are all static, and input/output 64 * is from/to byte arrays, or from InputStreams. 65 * 66 * @author Marc Johnson (mjohnson at apache dot org) 67 * @author Andrew Oliver (acoliver at apache dot org) 68 * 69 */ 70 71 public class LittleEndian 72 implements LittleEndianConsts 73 { 74 75 // all methods are static, so an accessible constructor makes no 76 // sense 77 private LittleEndian() 78 { 79 } 80 81 /** 82 * get a short value from a byte array 83 * 84 * @param data the byte array 85 * @param offset a starting offset into the byte array 86 * 87 * @return the short (16-bit) value 88 * 89 * @exception ArrayIndexOutOfBoundsException may be thrown 90 */ 91 92 public static short getShort(final byte[] data, final int offset) 93 { 94 return (short) getNumber(data, offset, SHORT_SIZE); 95 } 96 97 /** 98 * get a short array from a byte array. 99 */ 100 public static short[] getSimpleShortArray(final byte[] data, final int offset, final int size) 101 { 102 short[] results = new short[size]; 103 for (int i = 0; i < size; i++) 104 { 105 results[i] = getShort(data, offset + 2 + (i * 2)); 106 } 107 return results; 108 } 109 /** 110 * get a short array from a byte array. The short array is assumed 111 * to start with a word describing the length of the array. 112 */ 113 public static short[] getShortArray(final byte[] data, final int offset) 114 { 115 int size = (short) getNumber(data, offset, SHORT_SIZE); 116 short[] results = getSimpleShortArray(data, offset, size); 117 return results; 118 } 119 120 /** 121 * get a short value from the beginning of a byte array 122 * 123 * @param data the byte array 124 * 125 * @return the short (16-bit) value 126 * 127 * @exception ArrayIndexOutOfBoundsException may be thrown 128 */ 129 130 public static short getShort(final byte[] data) 131 { 132 return getShort(data, 0); 133 } 134 135 /** 136 * get an int value from a byte array 137 * 138 * @param data the byte array 139 * @param offset a starting offset into the byte array 140 * 141 * @return the int (32-bit) value 142 * 143 * @exception ArrayIndexOutOfBoundsException may be thrown 144 */ 145 146 public static int getInt(final byte[] data, final int offset) 147 { 148 return (int) getNumber(data, offset, INT_SIZE); 149 } 150 151 /** 152 * get an int value from the beginning of a byte array 153 * 154 * @param data the byte array 155 * 156 * @return the int (32-bit) value 157 * 158 * @exception ArrayIndexOutOfBoundsException may be thrown 159 */ 160 161 public static int getInt(final byte[] data) 162 { 163 return getInt(data, 0); 164 } 165 166 /** 167 * get a long value from a byte array 168 * 169 * @param data the byte array 170 * @param offset a starting offset into the byte array 171 * 172 * @return the long (64-bit) value 173 * 174 * @exception ArrayIndexOutOfBoundsException may be thrown 175 */ 176 177 public static long getLong(final byte[] data, final int offset) 178 { 179 return getNumber(data, offset, LONG_SIZE); 180 } 181 182 /** 183 * get a long value from the beginning of a byte array 184 * 185 * @param data the byte array 186 * 187 * @return the long (64-bit) value 188 * 189 * @exception ArrayIndexOutOfBoundsException may be thrown 190 */ 191 192 public static long getLong(final byte[] data) 193 { 194 return getLong(data, 0); 195 } 196 197 /** 198 * get a double value from a byte array, reads it in little endian format 199 * then converts the resulting revolting IEEE 754 (curse them) floating 200 * point number to a happy java double 201 * 202 * @param data the byte array 203 * @param offset a starting offset into the byte array 204 * 205 * @return the double (64-bit) value 206 * 207 * @exception ArrayIndexOutOfBoundsException may be thrown 208 */ 209 210 public static double getDouble(final byte[] data, final int offset) 211 { 212 return Double.longBitsToDouble(getNumber(data, offset, DOUBLE_SIZE)); 213 } 214 215 /** 216 * get a double value from the beginning of a byte array 217 * 218 * @param data the byte array 219 * 220 * @return the double (64-bit) value 221 * 222 * @exception ArrayIndexOutOfBoundsException may be thrown 223 */ 224 225 public static double getDouble(final byte[] data) 226 { 227 return getDouble(data, 0); 228 } 229 230 /** 231 * put a short value into a byte array 232 * 233 * @param data the byte array 234 * @param offset a starting offset into the byte array 235 * @param value the short (16-bit) value 236 * 237 * @exception ArrayIndexOutOfBoundsException may be thrown 238 */ 239 public static void putShort(final byte[] data, final int offset, 240 final short value) 241 { 242 putNumber(data, offset, value, SHORT_SIZE); 243 } 244 245 /** 246 * put an unsigned short value into a byte array 247 * 248 * @param data the byte array 249 * @param offset a starting offset into the byte array 250 * @param value the short (16-bit) value 251 * 252 * @exception ArrayIndexOutOfBoundsException may be thrown 253 */ 254 public static void putUShort(final byte[] data, final int offset, 255 final int value) 256 { 257 putNumber(data, offset, value, SHORT_SIZE); 258 } 259 260 /** 261 * put a array of shorts into a byte array 262 * 263 * @param data the byte array 264 * @param offset a starting offset into the byte array 265 * @param value the short array 266 * 267 * @exception ArrayIndexOutOfBoundsException may be thrown 268 */ 269 public static void putShortArray(final byte[] data, final int offset, final short[] value) 270 { 271 putNumber(data, offset, value.length, SHORT_SIZE); 272 for (int i = 0; i < value.length; i++) 273 { 274 putNumber(data, offset + 2 + (i * 2), value[i], SHORT_SIZE); 275 } 276 } 277 278 /** 279 * put a short value into beginning of a byte array 280 * 281 * @param data the byte array 282 * @param value the short (16-bit) value 283 * 284 * @exception ArrayIndexOutOfBoundsException may be thrown 285 */ 286 287 public static void putShort(final byte[] data, final short value) 288 { 289 putShort(data, 0, value); 290 } 291 292 /** 293 * put an int value into a byte array 294 * 295 * @param data the byte array 296 * @param offset a starting offset into the byte array 297 * @param value the int (32-bit) value 298 * 299 * @exception ArrayIndexOutOfBoundsException may be thrown 300 */ 301 302 public static void putInt(final byte[] data, final int offset, 303 final int value) 304 { 305 putNumber(data, offset, value, INT_SIZE); 306 } 307 308 /** 309 * put an int value into beginning of a byte array 310 * 311 * @param data the byte array 312 * @param value the int (32-bit) value 313 * 314 * @exception ArrayIndexOutOfBoundsException may be thrown 315 */ 316 317 public static void putInt(final byte[] data, final int value) 318 { 319 putInt(data, 0, value); 320 } 321 322 /** 323 * put a long value into a byte array 324 * 325 * @param data the byte array 326 * @param offset a starting offset into the byte array 327 * @param value the long (64-bit) value 328 * 329 * @exception ArrayIndexOutOfBoundsException may be thrown 330 */ 331 332 public static void putLong(final byte[] data, final int offset, 333 final long value) 334 { 335 putNumber(data, offset, value, LONG_SIZE); 336 } 337 338 /** 339 * put a long value into beginning of a byte array 340 * 341 * @param data the byte array 342 * @param value the long (64-bit) value 343 * 344 * @exception ArrayIndexOutOfBoundsException may be thrown 345 */ 346 347 public static void putLong(final byte[] data, final long value) 348 { 349 putLong(data, 0, value); 350 } 351 352 /** 353 * put a double value into a byte array 354 * 355 * @param data the byte array 356 * @param offset a starting offset into the byte array 357 * @param value the double (64-bit) value 358 * 359 * @exception ArrayIndexOutOfBoundsException may be thrown 360 */ 361 362 public static void putDouble(final byte[] data, final int offset, 363 final double value) 364 { 365 putNumber(data, offset, Double.doubleToLongBits(value), DOUBLE_SIZE); 366 } 367 368 /** 369 * put a double value into beginning of a byte array 370 * 371 * @param data the byte array 372 * @param value the double (64-bit) value 373 * 374 * @exception ArrayIndexOutOfBoundsException may be thrown 375 */ 376 377 public static void putDouble(final byte[] data, final double value) 378 { 379 putDouble(data, 0, value); 380 } 381 382 /** 383 * Exception to handle buffer underruns 384 * 385 * @author Marc Johnson (mjohnson at apache dot org) 386 */ 387 388 public static class BufferUnderrunException 389 extends IOException 390 { 391 392 /** 393 * simple constructor 394 */ 395 396 BufferUnderrunException() 397 { 398 super("buffer underrun"); 399 } 400 } 401 402 /** 403 * get a short value from an InputStream 404 * 405 * @param stream the InputStream from which the short is to be 406 * read 407 * 408 * @return the short (16-bit) value 409 * 410 * @exception IOException will be propagated back to the caller 411 * @exception BufferUnderrunException if the stream cannot provide 412 * enough bytes 413 */ 414 415 public static short readShort(final InputStream stream) 416 throws IOException, BufferUnderrunException 417 { 418 return getShort(readFromStream(stream, SHORT_SIZE)); 419 } 420 421 /** 422 * get an int value from an InputStream 423 * 424 * @param stream the InputStream from which the int is to be read 425 * 426 * @return the int (32-bit) value 427 * 428 * @exception IOException will be propagated back to the caller 429 * @exception BufferUnderrunException if the stream cannot provide 430 * enough bytes 431 */ 432 433 public static int readInt(final InputStream stream) 434 throws IOException, BufferUnderrunException 435 { 436 return getInt(readFromStream(stream, INT_SIZE)); 437 } 438 439 /** 440 * get a long value from an InputStream 441 * 442 * @param stream the InputStream from which the long is to be read 443 * 444 * @return the long (64-bit) value 445 * 446 * @exception IOException will be propagated back to the caller 447 * @exception BufferUnderrunException if the stream cannot provide 448 * enough bytes 449 */ 450 451 public static long readLong(final InputStream stream) 452 throws IOException, BufferUnderrunException 453 { 454 return getLong(readFromStream(stream, LONG_SIZE)); 455 } 456 457 private static final byte[] _short_buffer = new byte[SHORT_SIZE]; 458 private static final byte[] _int_buffer = new byte[INT_SIZE]; 459 private static final byte[] _long_buffer = new byte[LONG_SIZE]; 460 461 /** 462 * Read the appropriate number of bytes from the stream and return 463 * them to the caller. 464 * <p> 465 * It should be noted that, in an attempt to improve system 466 * performance and to prevent a transient explosion of discarded 467 * byte arrays to be garbage collected, static byte arrays are 468 * employed for the standard cases of reading a short, an int, or 469 * a long. 470 * <p> 471 * <b>THIS INTRODUCES A RISK FOR THREADED OPERATIONS!</b> 472 * <p> 473 * However, for the purposes of the POI project, this risk is 474 * deemed negligible. It is, however, so noted. 475 * 476 * @param stream the InputStream we're reading from 477 * @param size the number of bytes to read; in 99.99% of cases, 478 * this will be SHORT_SIZE, INT_SIZE, or LONG_SIZE -- 479 * but it doesn't have to be. 480 * 481 * @return the byte array containing the required number of 482 * bytes. The array will contain all zero's on end of 483 * stream 484 * 485 * @exception IOException will be propagated back to the caller 486 * @exception BufferUnderrunException if the stream cannot provide 487 * enough bytes 488 */ 489 490 public static byte[] readFromStream(final InputStream stream, 491 final int size) 492 throws IOException, BufferUnderrunException 493 { 494 byte[] buffer = null; 495 496 switch (size) 497 { 498 499 case SHORT_SIZE: 500 buffer = _short_buffer; 501 break; 502 503 case INT_SIZE: 504 buffer = _int_buffer; 505 break; 506 507 case LONG_SIZE: 508 buffer = _long_buffer; 509 break; 510 511 default : 512 buffer = new byte[size]; 513 break; 514 } 515 int count = stream.read(buffer); 516 517 if (count == -1) 518 { 519 520 // return a zero-filled buffer 521 Arrays.fill(buffer, (byte) 0); 522 } else if (count != size) 523 { 524 throw new BufferUnderrunException(); 525 } 526 return buffer; 527 } 528 529 private static long getNumber(final byte[] data, final int offset, 530 final int size) 531 { 532 long result = 0; 533 534 for (int j = offset + size - 1; j >= offset; j--) 535 { 536 result <<= 8; 537 result |= 0xff & data[j]; 538 } 539 return result; 540 } 541 542 private static void putNumber(final byte[] data, final int offset, 543 final long value, final int size) 544 { 545 int limit = size + offset; 546 long v = value; 547 548 for (int j = offset; j < limit; j++) 549 { 550 data[j] = (byte) (v & 0xFF); 551 v >>= 8; 552 } 553 } 554 555 /** 556 * Convert an 'unsigned' byte to an integer. ie, don't carry across the sign. 557 */ 558 public static int ubyteToInt(byte b) 559 { 560 return ((b & 0x80) == 0 ? (int) b : (int) (b & (byte) 0x7f) + 0x80); 561 } 562 563 /** 564 * get the unsigned value of a byte. 565 * 566 * @param data the byte array. 567 * @param offset a starting offset into the byte array. 568 * 569 * @return the unsigned value of the byte as a 32 bit integer 570 * 571 * @exception ArrayIndexOutOfBoundsException may be thrown 572 */ 573 public static int getUnsignedByte(final byte[] data, final int offset) 574 { 575 return (int) getNumber(data, offset, BYTE_SIZE); 576 } 577 578 /** 579 * get the unsigned value of a byte. 580 * 581 * @param data the byte array 582 * 583 * @return the unsigned value of the byte as a 32 bit integer 584 * 585 * @exception ArrayIndexOutOfBoundsException may be thrown 586 */ 587 public static int getUnsignedByte(final byte[] data) 588 { 589 return getUnsignedByte(data, 0); 590 } 591 /** 592 * Copy a portion of a byte array 593 * 594 * @param data the original byte array 595 * @param offset Where to start copying from. 596 * @param size Number of bytes to copy. 597 * 598 * @throws IndexOutOfBoundsException - if copying would cause access of data 599 * outside array bounds. 600 */ 601 public static byte[] getByteArray(final byte[] data, int offset, int size) 602 { 603 byte[] copy = new byte[size]; 604 System.arraycopy(data, offset, copy, 0, size); 605 606 return copy; 607 } 608 609 /** 610 * Retrieves and unsigned short. This is converted UP to a int 611 * so it can fit. 612 * 613 * @param data The data to read 614 * @param offset The offset to read the short from 615 * @return An integer representation of the short. 616 */ 617 public static int getUShort( byte[] data, int offset ) 618 { 619 return (int)getNumber(data, offset, SHORT_SIZE); 620 } 621 622 } 623