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 240 public static void putShort(final byte[] data, final int offset, 241 final short value) 242 { 243 putNumber(data, offset, value, SHORT_SIZE); 244 } 245 246 /** 247 * put a array of shorts into a byte array 248 * 249 * @param data the byte array 250 * @param offset a starting offset into the byte array 251 * @param value the short array 252 * 253 * @exception ArrayIndexOutOfBoundsException may be thrown 254 */ 255 public static void putShortArray(final byte[] data, final int offset, final short[] value) 256 { 257 putNumber(data, offset, value.length, SHORT_SIZE); 258 for (int i = 0; i < value.length; i++) 259 { 260 putNumber(data, offset + 2 + (i * 2), value[i], SHORT_SIZE); 261 } 262 } 263 264 /** 265 * put a short value into beginning of a byte array 266 * 267 * @param data the byte array 268 * @param value the short (16-bit) value 269 * 270 * @exception ArrayIndexOutOfBoundsException may be thrown 271 */ 272 273 public static void putShort(final byte[] data, final short value) 274 { 275 putShort(data, 0, value); 276 } 277 278 /** 279 * put an int value into a byte array 280 * 281 * @param data the byte array 282 * @param offset a starting offset into the byte array 283 * @param value the int (32-bit) value 284 * 285 * @exception ArrayIndexOutOfBoundsException may be thrown 286 */ 287 288 public static void putInt(final byte[] data, final int offset, 289 final int value) 290 { 291 putNumber(data, offset, value, INT_SIZE); 292 } 293 294 /** 295 * put an int value into beginning of a byte array 296 * 297 * @param data the byte array 298 * @param value the int (32-bit) value 299 * 300 * @exception ArrayIndexOutOfBoundsException may be thrown 301 */ 302 303 public static void putInt(final byte[] data, final int value) 304 { 305 putInt(data, 0, value); 306 } 307 308 /** 309 * put a long value into a byte array 310 * 311 * @param data the byte array 312 * @param offset a starting offset into the byte array 313 * @param value the long (64-bit) value 314 * 315 * @exception ArrayIndexOutOfBoundsException may be thrown 316 */ 317 318 public static void putLong(final byte[] data, final int offset, 319 final long value) 320 { 321 putNumber(data, offset, value, LONG_SIZE); 322 } 323 324 /** 325 * put a long value into beginning of a byte array 326 * 327 * @param data the byte array 328 * @param value the long (64-bit) value 329 * 330 * @exception ArrayIndexOutOfBoundsException may be thrown 331 */ 332 333 public static void putLong(final byte[] data, final long value) 334 { 335 putLong(data, 0, value); 336 } 337 338 /** 339 * put a double value into a byte array 340 * 341 * @param data the byte array 342 * @param offset a starting offset into the byte array 343 * @param value the double (64-bit) value 344 * 345 * @exception ArrayIndexOutOfBoundsException may be thrown 346 */ 347 348 public static void putDouble(final byte[] data, final int offset, 349 final double value) 350 { 351 putNumber(data, offset, Double.doubleToLongBits(value), DOUBLE_SIZE); 352 } 353 354 /** 355 * put a double value into beginning of a byte array 356 * 357 * @param data the byte array 358 * @param value the double (64-bit) value 359 * 360 * @exception ArrayIndexOutOfBoundsException may be thrown 361 */ 362 363 public static void putDouble(final byte[] data, final double value) 364 { 365 putDouble(data, 0, value); 366 } 367 368 /** 369 * Exception to handle buffer underruns 370 * 371 * @author Marc Johnson (mjohnson at apache dot org) 372 */ 373 374 public static class BufferUnderrunException 375 extends IOException 376 { 377 378 /** 379 * simple constructor 380 */ 381 382 BufferUnderrunException() 383 { 384 super("buffer underrun"); 385 } 386 } 387 388 /** 389 * get a short value from an InputStream 390 * 391 * @param stream the InputStream from which the short is to be 392 * read 393 * 394 * @return the short (16-bit) value 395 * 396 * @exception IOException will be propagated back to the caller 397 * @exception BufferUnderrunException if the stream cannot provide 398 * enough bytes 399 */ 400 401 public static short readShort(final InputStream stream) 402 throws IOException, BufferUnderrunException 403 { 404 return getShort(readFromStream(stream, SHORT_SIZE)); 405 } 406 407 /** 408 * get an int value from an InputStream 409 * 410 * @param stream the InputStream from which the int is to be read 411 * 412 * @return the int (32-bit) value 413 * 414 * @exception IOException will be propagated back to the caller 415 * @exception BufferUnderrunException if the stream cannot provide 416 * enough bytes 417 */ 418 419 public static int readInt(final InputStream stream) 420 throws IOException, BufferUnderrunException 421 { 422 return getInt(readFromStream(stream, INT_SIZE)); 423 } 424 425 /** 426 * get a long value from an InputStream 427 * 428 * @param stream the InputStream from which the long is to be read 429 * 430 * @return the long (64-bit) value 431 * 432 * @exception IOException will be propagated back to the caller 433 * @exception BufferUnderrunException if the stream cannot provide 434 * enough bytes 435 */ 436 437 public static long readLong(final InputStream stream) 438 throws IOException, BufferUnderrunException 439 { 440 return getLong(readFromStream(stream, LONG_SIZE)); 441 } 442 443 private static final byte[] _short_buffer = new byte[SHORT_SIZE]; 444 private static final byte[] _int_buffer = new byte[INT_SIZE]; 445 private static final byte[] _long_buffer = new byte[LONG_SIZE]; 446 447 /** 448 * Read the appropriate number of bytes from the stream and return 449 * them to the caller. 450 * <p> 451 * It should be noted that, in an attempt to improve system 452 * performance and to prevent a transient explosion of discarded 453 * byte arrays to be garbage collected, static byte arrays are 454 * employed for the standard cases of reading a short, an int, or 455 * a long. 456 * <p> 457 * <b>THIS INTRODUCES A RISK FOR THREADED OPERATIONS!</b> 458 * <p> 459 * However, for the purposes of the POI project, this risk is 460 * deemed negligible. It is, however, so noted. 461 * 462 * @param stream the InputStream we're reading from 463 * @param size the number of bytes to read; in 99.99% of cases, 464 * this will be SHORT_SIZE, INT_SIZE, or LONG_SIZE -- 465 * but it doesn't have to be. 466 * 467 * @return the byte array containing the required number of 468 * bytes. The array will contain all zero's on end of 469 * stream 470 * 471 * @exception IOException will be propagated back to the caller 472 * @exception BufferUnderrunException if the stream cannot provide 473 * enough bytes 474 */ 475 476 public static byte[] readFromStream(final InputStream stream, 477 final int size) 478 throws IOException, BufferUnderrunException 479 { 480 byte[] buffer = null; 481 482 switch (size) 483 { 484 485 case SHORT_SIZE: 486 buffer = _short_buffer; 487 break; 488 489 case INT_SIZE: 490 buffer = _int_buffer; 491 break; 492 493 case LONG_SIZE: 494 buffer = _long_buffer; 495 break; 496 497 default : 498 buffer = new byte[size]; 499 break; 500 } 501 int count = stream.read(buffer); 502 503 if (count == -1) 504 { 505 506 // return a zero-filled buffer 507 Arrays.fill(buffer, (byte) 0); 508 } else if (count != size) 509 { 510 throw new BufferUnderrunException(); 511 } 512 return buffer; 513 } 514 515 private static long getNumber(final byte[] data, final int offset, 516 final int size) 517 { 518 long result = 0; 519 520 for (int j = offset + size - 1; j >= offset; j--) 521 { 522 result <<= 8; 523 result |= 0xff & data[j]; 524 } 525 return result; 526 } 527 528 private static void putNumber(final byte[] data, final int offset, 529 final long value, final int size) 530 { 531 int limit = size + offset; 532 long v = value; 533 534 for (int j = offset; j < limit; j++) 535 { 536 data[j] = (byte) (v & 0xFF); 537 v >>= 8; 538 } 539 } 540 541 /** 542 * Convert an 'unsigned' byte to an integer. ie, don't carry across the sign. 543 */ 544 public static int ubyteToInt(byte b) 545 { 546 return ((b & 0x80) == 0 ? (int) b : (int) (b & (byte) 0x7f) + 0x80); 547 } 548 549 /** 550 * get the unsigned value of a byte. 551 * 552 * @param data the byte array. 553 * @param offset a starting offset into the byte array. 554 * 555 * @return the unsigned value of the byte as a 32 bit integer 556 * 557 * @exception ArrayIndexOutOfBoundsException may be thrown 558 */ 559 public static int getUnsignedByte(final byte[] data, final int offset) 560 { 561 return (int) getNumber(data, offset, BYTE_SIZE); 562 } 563 564 /** 565 * get the unsigned value of a byte. 566 * 567 * @param data 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) 574 { 575 return getUnsignedByte(data, 0); 576 } 577 /** 578 * Copy a portion of a byte array 579 * 580 * @param data the original byte array 581 * @param offset Where to start copying from. 582 * @param size Number of bytes to copy. 583 * 584 * @throws IndexOutOfBoundsException - if copying would cause access of data 585 * outside array bounds. 586 */ 587 public static byte[] getByteArray(final byte[] data, int offset, int size) 588 { 589 byte[] copy = new byte[size]; 590 System.arraycopy(data, offset, copy, 0, size); 591 592 return copy; 593 } 594 595 } 596