You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LittleEndian.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.util;
  16. import java.io.IOException;
  17. import java.io.InputStream;
  18. import java.io.OutputStream;
  19. import java.io.Serializable;
  20. /**
  21. * a utility class for handling little-endian numbers, which the 80x86 world is
  22. * replete with. The methods are all static, and input/output is from/to byte
  23. * arrays, or from InputStreams.
  24. */
  25. @Internal
  26. public final class LittleEndian implements LittleEndianConsts {
  27. /**
  28. * Exception to handle buffer underruns
  29. */
  30. public static final class BufferUnderrunException extends IOException {
  31. /**
  32. * Serial version UID
  33. *
  34. * @see Serializable
  35. */
  36. private static final long serialVersionUID = 8736973884877006145L;
  37. BufferUnderrunException() {
  38. super( "buffer underrun" );
  39. }
  40. }
  41. /**
  42. * get a double value from a byte array, reads it in little endian format
  43. * then converts the resulting revolting IEEE 754 (curse them) floating
  44. * point number to a happy java double
  45. *
  46. * @param data
  47. * the byte array
  48. * @return the double (64-bit) value
  49. */
  50. public static double getDouble( byte[] data ) {
  51. return Double.longBitsToDouble( getLong( data, 0 ) );
  52. }
  53. /**
  54. * get a double value from a byte array, reads it in little endian format
  55. * then converts the resulting revolting IEEE 754 (curse them) floating
  56. * point number to a happy java double
  57. *
  58. * @param data
  59. * the byte array
  60. * @param offset
  61. * a starting offset into the byte array
  62. * @return the double (64-bit) value
  63. */
  64. public static double getDouble( byte[] data, int offset ) {
  65. return Double.longBitsToDouble( getLong( data, offset ) );
  66. }
  67. /**
  68. * get a float value from a byte array, reads it in little endian format
  69. * then converts the resulting revolting IEEE 754 (curse them) floating
  70. * point number to a happy java float
  71. *
  72. * @param data
  73. * the byte array
  74. * @return the double (64-bit) value
  75. */
  76. public static float getFloat( byte[] data ) {
  77. return getFloat( data, 0 );
  78. }
  79. /**
  80. * get a float value from a byte array, reads it in little endian format
  81. * then converts the resulting revolting IEEE 754 (curse them) floating
  82. * point number to a happy java float
  83. *
  84. * @param data
  85. * the byte array
  86. * @param offset
  87. * a starting offset into the byte array
  88. * @return the double (64-bit) value
  89. */
  90. public static float getFloat( byte[] data, int offset ) {
  91. return Float.intBitsToFloat( getInt( data, offset ) );
  92. }
  93. /**
  94. * get an int value from the beginning of a byte array
  95. *
  96. * @param data
  97. * the byte array
  98. * @return the int (32-bit) value
  99. */
  100. public static int getInt( byte[] data ) {
  101. return getInt( data, 0 );
  102. }
  103. /**
  104. * get an int value from a byte array
  105. *
  106. * @param data
  107. * the byte array
  108. * @param offset
  109. * a starting offset into the byte array
  110. * @return the int (32-bit) value
  111. */
  112. public static int getInt( byte[] data, int offset ) {
  113. int i = offset;
  114. int b0 = data[i++] & 0xFF;
  115. int b1 = data[i++] & 0xFF;
  116. int b2 = data[i++] & 0xFF;
  117. int b3 = data[i ] & 0xFF;
  118. return ( b3 << 24 ) + ( b2 << 16 ) + ( b1 << 8 ) + (b0);
  119. }
  120. /**
  121. * get a long value from a byte array
  122. *
  123. * @param data
  124. * the byte array
  125. * @return the long (64-bit) value
  126. */
  127. public static long getLong( byte[] data ) {
  128. return getLong( data, 0 );
  129. }
  130. /**
  131. * get a long value from a byte array
  132. *
  133. * @param data
  134. * the byte array
  135. * @param offset
  136. * a starting offset into the byte array
  137. * @return the long (64-bit) value
  138. */
  139. public static long getLong( byte[] data, int offset ) {
  140. long result = 0xff & data[offset + 7];
  141. for ( int j = offset + LONG_SIZE - 1; j >= offset; j-- )
  142. {
  143. result <<= 8;
  144. result |= 0xff & data[j];
  145. }
  146. return result;
  147. }
  148. /**
  149. * get a short value from the beginning of a byte array
  150. *
  151. * @param data
  152. * the byte array
  153. * @return the short (16-bit) value
  154. */
  155. public static short getShort( byte[] data ) {
  156. return getShort( data, 0 );
  157. }
  158. /**
  159. * get a short value from a byte array
  160. *
  161. * @param data
  162. * the byte array
  163. * @param offset
  164. * a starting offset into the byte array
  165. * @return the short (16-bit) value
  166. */
  167. public static short getShort( byte[] data, int offset ) {
  168. int b0 = data[offset] & 0xFF;
  169. int b1 = data[offset + 1] & 0xFF;
  170. return (short) ( ( b1 << 8 ) + (b0) );
  171. }
  172. /**
  173. * Read short array
  174. *
  175. * @param data
  176. * the original byte array
  177. * @param offset
  178. * Where to start copying from.
  179. * @param size
  180. * Number of bytes to copy.
  181. * @throws IndexOutOfBoundsException
  182. * - if read would cause access of data outside array bounds.
  183. */
  184. public static short[] getShortArray( byte[] data, int offset, int size ) {
  185. short[] result = new short[size / SHORT_SIZE];
  186. for ( int i = 0; i < result.length; i++ )
  187. {
  188. result[i] = getShort( data, offset + i * SHORT_SIZE );
  189. }
  190. return result;
  191. }
  192. /**
  193. * get the unsigned value of a byte.
  194. *
  195. * @param data
  196. * the byte array.
  197. * @return the unsigned value of the byte as a 16 bit short
  198. */
  199. public static short getUByte( byte[] data ) {
  200. return (short) ( data[0] & 0xFF );
  201. }
  202. /**
  203. * get the unsigned value of a byte.
  204. *
  205. * @param data
  206. * the byte array.
  207. * @param offset
  208. * a starting offset into the byte array.
  209. * @return the unsigned value of the byte as a 16 bit short
  210. */
  211. public static short getUByte( byte[] data, int offset ) {
  212. return (short) ( data[offset] & 0xFF );
  213. }
  214. /**
  215. * get an unsigned int value from a byte array
  216. *
  217. * @param data
  218. * the byte array
  219. * @return the unsigned int (32-bit) value in a long
  220. */
  221. public static long getUInt( byte[] data ) {
  222. return getUInt( data, 0 );
  223. }
  224. /**
  225. * get an unsigned int value from a byte array
  226. *
  227. * @param data
  228. * the byte array
  229. * @param offset
  230. * a starting offset into the byte array
  231. * @return the unsigned int (32-bit) value in a long
  232. */
  233. public static long getUInt( byte[] data, int offset ) {
  234. long retNum = getInt( data, offset );
  235. return retNum & 0x00FFFFFFFFL;
  236. }
  237. /**
  238. * get an unsigned short value from the beginning of a byte array
  239. *
  240. * @param data
  241. * the byte array
  242. * @return the unsigned short (16-bit) value in an int
  243. */
  244. public static int getUShort( byte[] data ) {
  245. return getUShort( data, 0 );
  246. }
  247. /**
  248. * get an unsigned short value from a byte array
  249. *
  250. * @param data
  251. * the byte array
  252. * @param offset
  253. * a starting offset into the byte array
  254. * @return the unsigned short (16-bit) value in an integer
  255. */
  256. public static int getUShort( byte[] data, int offset ) {
  257. int b0 = data[offset] & 0xFF;
  258. int b1 = data[offset + 1] & 0xFF;
  259. return ( b1 << 8 ) + (b0);
  260. }
  261. /**
  262. * executes:
  263. * <p>
  264. * <code>
  265. * data[offset] = (byte)value;
  266. * </code>
  267. * </p>
  268. * Added for consistency with other put~() methods
  269. */
  270. public static void putByte( byte[] data, int offset, int value ) {
  271. data[offset] = (byte) value;
  272. }
  273. /**
  274. * put a double value into a byte array
  275. *
  276. * @param data
  277. * the byte array
  278. * @param offset
  279. * a starting offset into the byte array
  280. * @param value
  281. * the double (64-bit) value
  282. */
  283. public static void putDouble( byte[] data, int offset, double value ) {
  284. putLong( data, offset, Double.doubleToLongBits( value ) );
  285. }
  286. /**
  287. * put a double value into a byte array
  288. *
  289. * @param value
  290. * the double (64-bit) value
  291. * @param outputStream
  292. * output stream
  293. * @throws IOException
  294. * if an I/O error occurs
  295. */
  296. public static void putDouble( double value, OutputStream outputStream ) throws IOException {
  297. putLong( Double.doubleToLongBits( value ), outputStream );
  298. }
  299. /**
  300. * put a float value into a byte array
  301. *
  302. * @param data
  303. * the byte array
  304. * @param offset
  305. * a starting offset into the byte array
  306. * @param value
  307. * the float (32-bit) value
  308. */
  309. public static void putFloat( byte[] data, int offset, float value ) {
  310. putInt( data, offset, Float.floatToIntBits( value ) );
  311. }
  312. /**
  313. * put a float value into a byte array
  314. *
  315. * @param value
  316. * the float (32-bit) value
  317. * @param outputStream
  318. * output stream
  319. * @throws IOException
  320. * if an I/O error occurs
  321. */
  322. @SuppressWarnings("unused")
  323. public static void putFloat(float value, OutputStream outputStream ) throws IOException {
  324. putInt( Float.floatToIntBits( value ), outputStream );
  325. }
  326. /**
  327. * put an int value into a byte array
  328. *
  329. * @param data
  330. * the byte array
  331. * @param offset
  332. * a starting offset into the byte array
  333. * @param value
  334. * the int (32-bit) value
  335. */
  336. public static void putInt( byte[] data, int offset, int value ) {
  337. int i = offset;
  338. data[i++] = (byte) ( ( value ) & 0xFF );
  339. data[i++] = (byte) ( ( value >>> 8 ) & 0xFF );
  340. data[i++] = (byte) ( ( value >>> 16 ) & 0xFF );
  341. data[i] = (byte) ( ( value >>> 24 ) & 0xFF );
  342. }
  343. /**
  344. * Put int into output stream
  345. *
  346. * @param value
  347. * the int (32-bit) value
  348. * @param outputStream
  349. * output stream
  350. * @throws IOException
  351. * if an I/O error occurs
  352. */
  353. public static void putInt( int value, OutputStream outputStream ) throws IOException {
  354. outputStream.write( (byte) ( ( value ) & 0xFF ) );
  355. outputStream.write( (byte) ( ( value >>> 8 ) & 0xFF ) );
  356. outputStream.write( (byte) ( ( value >>> 16 ) & 0xFF ) );
  357. outputStream.write( (byte) ( ( value >>> 24 ) & 0xFF ) );
  358. }
  359. /**
  360. * put a long value into a byte array
  361. *
  362. * @param data
  363. * the byte array
  364. * @param offset
  365. * a starting offset into the byte array
  366. * @param value
  367. * the long (64-bit) value
  368. */
  369. public static void putLong( byte[] data, int offset, long value ) {
  370. data[offset ] = (byte) ( ( value ) & 0xFF );
  371. data[offset + 1] = (byte) ( ( value >>> 8 ) & 0xFF );
  372. data[offset + 2] = (byte) ( ( value >>> 16 ) & 0xFF );
  373. data[offset + 3] = (byte) ( ( value >>> 24 ) & 0xFF );
  374. data[offset + 4] = (byte) ( ( value >>> 32 ) & 0xFF );
  375. data[offset + 5] = (byte) ( ( value >>> 40 ) & 0xFF );
  376. data[offset + 6] = (byte) ( ( value >>> 48 ) & 0xFF );
  377. data[offset + 7] = (byte) ( ( value >>> 56 ) & 0xFF );
  378. }
  379. /**
  380. * Put long into output stream
  381. *
  382. * @param value
  383. * the long (64-bit) value
  384. * @param outputStream
  385. * output stream
  386. * @throws IOException
  387. * if an I/O error occurs
  388. */
  389. public static void putLong( long value, OutputStream outputStream ) throws IOException {
  390. outputStream.write( (byte) ( ( value ) & 0xFF ) );
  391. outputStream.write( (byte) ( ( value >>> 8 ) & 0xFF ) );
  392. outputStream.write( (byte) ( ( value >>> 16 ) & 0xFF ) );
  393. outputStream.write( (byte) ( ( value >>> 24 ) & 0xFF ) );
  394. outputStream.write( (byte) ( ( value >>> 32 ) & 0xFF ) );
  395. outputStream.write( (byte) ( ( value >>> 40 ) & 0xFF ) );
  396. outputStream.write( (byte) ( ( value >>> 48 ) & 0xFF ) );
  397. outputStream.write( (byte) ( ( value >>> 56 ) & 0xFF ) );
  398. }
  399. /**
  400. * put a short value into a byte array
  401. *
  402. * @param data
  403. * the byte array
  404. * @param offset
  405. * a starting offset into the byte array
  406. * @param value
  407. * the short (16-bit) value
  408. */
  409. public static void putShort( byte[] data, int offset, short value ) {
  410. int i = offset;
  411. data[i++] = (byte) ( ( value ) & 0xFF );
  412. data[i ] = (byte) ( ( value >>> 8 ) & 0xFF );
  413. }
  414. /**
  415. * Put signed short into output stream
  416. *
  417. * @param value
  418. * the short (16-bit) value
  419. * @param outputStream
  420. * output stream
  421. * @throws IOException
  422. * if an I/O error occurs
  423. */
  424. public static void putShort( OutputStream outputStream, short value ) throws IOException {
  425. outputStream.write( (byte) ( ( value ) & 0xFF ) );
  426. outputStream.write( (byte) ( ( value >>> 8 ) & 0xFF ) );
  427. }
  428. /**
  429. * Stores short array in buffer
  430. *
  431. * @param data
  432. * the byte array
  433. * @param startOffset
  434. * a starting offset into the byte array
  435. * @param value
  436. * the short (16-bit) values
  437. */
  438. public static void putShortArray( byte[] data, int startOffset, short[] value ) {
  439. int offset = startOffset;
  440. for ( short s : value )
  441. {
  442. putShort( data, offset, s );
  443. offset += SHORT_SIZE;
  444. }
  445. }
  446. /**
  447. * put an unsigned byte value into a byte array
  448. *
  449. * @param data
  450. * the byte array
  451. * @param offset
  452. * a starting offset into the byte array
  453. * @param value
  454. * the short (16-bit) value
  455. *
  456. * @throws ArrayIndexOutOfBoundsException
  457. * may be thrown
  458. */
  459. public static void putUByte( byte[] data, int offset, short value ) {
  460. data[offset] = (byte) ( value & 0xFF );
  461. }
  462. /**
  463. * put an unsigned int value into a byte array
  464. *
  465. * @param data
  466. * the byte array
  467. * @param offset
  468. * a starting offset into the byte array
  469. * @param value
  470. * the int (32-bit) value
  471. *
  472. * @throws ArrayIndexOutOfBoundsException
  473. * may be thrown
  474. */
  475. public static void putUInt( byte[] data, int offset, long value ) {
  476. int i = offset;
  477. data[i++] = (byte) ( ( value ) & 0xFF );
  478. data[i++] = (byte) ( ( value >>> 8 ) & 0xFF );
  479. data[i++] = (byte) ( ( value >>> 16 ) & 0xFF );
  480. data[i ] = (byte) ( ( value >>> 24 ) & 0xFF );
  481. }
  482. /**
  483. * Put unsigned int into output stream
  484. *
  485. * @param value
  486. * the int (32-bit) value
  487. * @param outputStream
  488. * output stream
  489. * @throws IOException
  490. * if an I/O error occurs
  491. */
  492. public static void putUInt( long value, OutputStream outputStream ) throws IOException {
  493. outputStream.write( (byte) ( ( value ) & 0xFF ) );
  494. outputStream.write( (byte) ( ( value >>> 8 ) & 0xFF ) );
  495. outputStream.write( (byte) ( ( value >>> 16 ) & 0xFF ) );
  496. outputStream.write( (byte) ( ( value >>> 24 ) & 0xFF ) );
  497. }
  498. /**
  499. * put an unsigned short value into a byte array
  500. *
  501. * @param data
  502. * the byte array
  503. * @param offset
  504. * a starting offset into the byte array
  505. * @param value
  506. * the short (16-bit) value
  507. *
  508. * @throws ArrayIndexOutOfBoundsException
  509. * may be thrown
  510. */
  511. public static void putUShort( byte[] data, int offset, int value ) {
  512. int i = offset;
  513. data[i++] = (byte) ( ( value ) & 0xFF );
  514. data[i ] = (byte) ( ( value >>> 8 ) & 0xFF );
  515. }
  516. /**
  517. * Put unsigned short into output stream
  518. *
  519. * @param value
  520. * the unsigned short (16-bit) value
  521. * @param outputStream
  522. * output stream
  523. * @throws IOException
  524. * if an I/O error occurs
  525. */
  526. public static void putUShort( int value, OutputStream outputStream ) throws IOException {
  527. outputStream.write( (byte) ( ( value ) & 0xFF ) );
  528. outputStream.write( (byte) ( ( value >>> 8 ) & 0xFF ) );
  529. }
  530. /**
  531. * get an int value from an InputStream
  532. *
  533. * @param stream
  534. * the InputStream from which the int is to be read
  535. * @return the int (32-bit) value
  536. * @throws IOException
  537. * will be propagated back to the caller
  538. * @throws BufferUnderrunException
  539. * if the stream cannot provide enough bytes
  540. */
  541. public static int readInt( InputStream stream ) throws IOException {
  542. int ch1 = stream.read();
  543. int ch2 = stream.read();
  544. int ch3 = stream.read();
  545. int ch4 = stream.read();
  546. if ( ( ch1 | ch2 | ch3 | ch4 ) < 0 )
  547. {
  548. throw new BufferUnderrunException();
  549. }
  550. return ( ch4 << 24 ) + ( ch3 << 16 ) + ( ch2 << 8 ) + ( ch1 );
  551. }
  552. /**
  553. * get an unsigned int value from an InputStream
  554. *
  555. * @param stream
  556. * the InputStream from which the int is to be read
  557. * @return the unsigned int (32-bit) value
  558. * @throws IOException
  559. * will be propagated back to the caller
  560. * @throws BufferUnderrunException
  561. * if the stream cannot provide enough bytes
  562. */
  563. public static long readUInt( InputStream stream ) throws IOException {
  564. long retNum = readInt(stream);
  565. return retNum & 0x00FFFFFFFFL;
  566. }
  567. /**
  568. * get a long value from an InputStream
  569. *
  570. * @param stream
  571. * the InputStream from which the long is to be read
  572. * @return the long (64-bit) value
  573. * @throws IOException
  574. * will be propagated back to the caller
  575. * @throws BufferUnderrunException
  576. * if the stream cannot provide enough bytes
  577. */
  578. public static long readLong( InputStream stream ) throws IOException {
  579. int ch1 = stream.read();
  580. int ch2 = stream.read();
  581. int ch3 = stream.read();
  582. int ch4 = stream.read();
  583. int ch5 = stream.read();
  584. int ch6 = stream.read();
  585. int ch7 = stream.read();
  586. int ch8 = stream.read();
  587. if ( ( ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8 ) < 0 ) {
  588. throw new BufferUnderrunException();
  589. }
  590. return ( (long) ch8 << 56 ) + ( (long) ch7 << 48 )
  591. + ( (long) ch6 << 40 ) + ( (long) ch5 << 32 )
  592. + ( (long) ch4 << 24 ) + // cast to long to preserve bit 31
  593. // (sign bit for ints)
  594. ( ch3 << 16 ) + ( ch2 << 8 ) + ( ch1 );
  595. }
  596. /**
  597. * get a short value from an InputStream
  598. *
  599. * @param stream
  600. * the InputStream from which the short is to be read
  601. * @return the short (16-bit) value
  602. * @throws IOException
  603. * will be propagated back to the caller
  604. * @throws BufferUnderrunException
  605. * if the stream cannot provide enough bytes
  606. */
  607. public static short readShort( InputStream stream ) throws IOException {
  608. return (short) readUShort( stream );
  609. }
  610. public static int readUShort( InputStream stream ) throws IOException {
  611. int ch1 = stream.read();
  612. int ch2 = stream.read();
  613. if ( ( ch1 | ch2 ) < 0 ) {
  614. throw new BufferUnderrunException();
  615. }
  616. return ( ch2 << 8 ) + ( ch1 );
  617. }
  618. /**
  619. * Convert an 'unsigned' byte to an integer. ie, don't carry across the
  620. * sign.
  621. *
  622. * @param b
  623. * Description of the Parameter
  624. * @return Description of the Return Value
  625. */
  626. public static int ubyteToInt( byte b ) {
  627. return b & 0xFF;
  628. }
  629. private LittleEndian() {
  630. // no instances of this class
  631. }
  632. }