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