Save This Page
Home » poi-src-3.2-FINAL-20081019 » org.apache » poi » util » [javadoc | source]
    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   
    9          http://www.apache.org/licenses/LICENSE-2.0
   10   
   11      Unless required by applicable law or agreed to in writing, software
   12      distributed under the License is distributed on an "AS IS" BASIS,
   13      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14      See the License for the specific language governing permissions and
   15      limitations under the License.
   16   ==================================================================== */
   17   
   18   package org.apache.poi.util;
   19   
   20   import java.io.IOException;
   21   import java.io.InputStream;
   22   import java.util.Arrays;
   23   
   24   /**
   25    *  a utility class for handling little-endian numbers, which the 80x86 world is
   26    *  replete with. The methods are all static, and input/output is from/to byte
   27    *  arrays, or from InputStreams.
   28    *
   29    *@author     Marc Johnson (mjohnson at apache dot org)
   30    *@author     Andrew Oliver (acoliver at apache dot org)
   31    */
   32   
   33   public class LittleEndian
   34            implements LittleEndianConsts {
   35   
   36       // all methods are static, so an accessible constructor makes no
   37       // sense
   38       /**
   39        *  Constructor for the LittleEndian object
   40        */
   41       private LittleEndian() { }
   42   
   43   
   44       /**
   45        *  get a short value from a byte array
   46        *
   47        *@param  data    the byte array
   48        *@param  offset  a starting offset into the byte array
   49        *@return         the short (16-bit) value
   50        */
   51   
   52       public static short getShort(final byte[] data, final int offset) {
   53           return (short) getNumber(data, offset, SHORT_SIZE);
   54       }
   55   
   56   
   57       /**
   58        *  get an unsigned short value from a byte array
   59        *
   60        *@param  data    the byte array
   61        *@param  offset  a starting offset into the byte array
   62        *@return         the unsigned short (16-bit) value in an integer
   63        */
   64       public static int getUShort(final byte[] data, final int offset) {
   65           short num = (short) getNumber(data, offset, SHORT_SIZE);
   66           int retNum;
   67           if (num < 0) {
   68               retNum = (Short.MAX_VALUE + 1) * 2 + num;
   69           } else {
   70               retNum = num;
   71           }
   72           return retNum;
   73       }
   74   
   75   
   76       /**
   77        *  get a short array from a byte array.
   78        *
   79        *@param  data    Description of the Parameter
   80        *@param  offset  Description of the Parameter
   81        *@param  size    Description of the Parameter
   82        *@return         The simpleShortArray value
   83        */
   84       public static short[] getSimpleShortArray(final byte[] data, final int offset, final int size) {
   85           short[] results = new short[size];
   86           for (int i = 0; i < size; i++) {
   87               results[i] = getShort(data, offset + 2 + (i * 2));
   88           }
   89           return results;
   90       }
   91   
   92   
   93       /**
   94        *  get a short array from a byte array. The short array is assumed to start
   95        *  with a word describing the length of the array.
   96        *
   97        *@param  data    Description of the Parameter
   98        *@param  offset  Description of the Parameter
   99        *@return         The shortArray value
  100        */
  101       public static short[] getShortArray(final byte[] data, final int offset) {
  102           int size = (int) getNumber(data, offset, SHORT_SIZE);
  103           short[] results = getSimpleShortArray(data, offset, size);
  104           return results;
  105       }
  106   
  107   
  108       /**
  109        *  get a short value from the beginning of a byte array
  110        *
  111        *@param  data  the byte array
  112        *@return       the short (16-bit) value
  113        */
  114   
  115       public static short getShort(final byte[] data) {
  116           return getShort(data, 0);
  117       }
  118   
  119   
  120       /**
  121        *  get an unsigned short value from the beginning of a byte array
  122        *
  123        *@param  data  the byte array
  124        *@return       the unsigned short (16-bit) value in an int
  125        */
  126       public static int getUShort(final byte[] data) {
  127           return getUShort(data, 0);
  128       }
  129   
  130   
  131       /**
  132        *  get an int value from a byte array
  133        *
  134        *@param  data    the byte array
  135        *@param  offset  a starting offset into the byte array
  136        *@return         the int (32-bit) value
  137        */
  138   
  139       public static int getInt(final byte[] data, final int offset) {
  140           return (int) getNumber(data, offset, INT_SIZE);
  141       }
  142   
  143   
  144       /**
  145        *  get an int value from the beginning of a byte array
  146        *
  147        *@param  data  the byte array
  148        *@return       the int (32-bit) value
  149        */
  150   
  151       public static int getInt(final byte[] data) {
  152           return getInt(data, 0);
  153       }
  154   
  155   
  156       /**
  157        *  get an unsigned int value from a byte array
  158        *
  159        *@param  data    the byte array
  160        *@param  offset  a starting offset into the byte array
  161        *@return         the unsigned int (32-bit) value in a long
  162        */
  163       public static long getUInt(final byte[] data, final int offset) {
  164           int num = (int) getNumber(data, offset, INT_SIZE);
  165           long retNum;
  166           if (num < 0) {
  167               retNum = ((long) Integer.MAX_VALUE + 1) * 2 + num;
  168           } else {
  169               retNum = num;
  170           }
  171           return retNum;
  172       }
  173   
  174       /**
  175        *  get an unsigned int value from a byte array
  176        *
  177        *@param  data    the byte array
  178        *@return         the unsigned int (32-bit) value in a long
  179        */
  180       public static long getUInt(final byte[] data) {
  181   	return getUInt(data,0);
  182       }
  183   
  184       /**
  185        *  get a long value from a byte array
  186        *
  187        *@param  data    the byte array
  188        *@param  offset  a starting offset into the byte array
  189        *@return         the long (64-bit) value
  190        */
  191   
  192       public static long getLong(final byte[] data, final int offset) {
  193           return getNumber(data, offset, LONG_SIZE);
  194       }
  195   
  196   
  197       /**
  198        *  get a long value from the beginning of a byte array
  199        *
  200        *@param  data  the byte array
  201        *@return       the long (64-bit) value
  202        */
  203   
  204       public static long getLong(final byte[] data) {
  205           return getLong(data, 0);
  206       }
  207   
  208   
  209       /**
  210        *  get a double value from a byte array, reads it in little endian format
  211        *  then converts the resulting revolting IEEE 754 (curse them) floating
  212        *  point number to a happy java double
  213        *
  214        *@param  data    the byte array
  215        *@param  offset  a starting offset into the byte array
  216        *@return         the double (64-bit) value
  217        */
  218   
  219       public static double getDouble(final byte[] data, final int offset) {
  220           return Double.longBitsToDouble(getNumber(data, offset, DOUBLE_SIZE));
  221       }
  222   
  223   
  224       /**
  225        *  get a double value from the beginning of a byte array
  226        *
  227        *@param  data  the byte array
  228        *@return       the double (64-bit) value
  229        */
  230   
  231       public static double getDouble(final byte[] data) {
  232           return getDouble(data, 0);
  233       }
  234   
  235   
  236       /**
  237        *  put a short value into a byte array
  238        *
  239        *@param  data    the byte array
  240        *@param  offset  a starting offset into the byte array
  241        *@param  value   the short (16-bit) value
  242        */
  243       public static void putShort(final byte[] data, final int offset,
  244               final short value) {
  245           putNumber(data, offset, value, SHORT_SIZE);
  246       }
  247   
  248       /**
  249        * executes:<p/>
  250        * <code>
  251        * data[offset] = (byte)value;
  252        * </code></p>
  253        * Added for consistency with other put~() methods
  254        */
  255       public static void putByte(byte[] data, int offset, int value) {
  256           putNumber(data, offset, value, LittleEndianConsts.BYTE_SIZE);
  257       }
  258   
  259       /**
  260        *  put a array of shorts into a byte array
  261        *
  262        *@param  data    the byte array
  263        *@param  offset  a starting offset into the byte array
  264        *@param  value   the short array
  265        */
  266       public static void putShortArray(final byte[] data, final int offset, final short[] value) {
  267           putNumber(data, offset, value.length, SHORT_SIZE);
  268           for (int i = 0; i < value.length; i++) {
  269               putNumber(data, offset + 2 + (i * 2), value[i], SHORT_SIZE);
  270           }
  271       }
  272   
  273       /**
  274        * put an unsigned 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        * @exception ArrayIndexOutOfBoundsException may be thrown
  281        */
  282       public static void putUShort(final byte[] data, final int offset,
  283                                   final int value)
  284       {
  285           putNumber(data, offset, value, SHORT_SIZE);
  286       }
  287   
  288       /**
  289        *  put a short value into beginning of a byte array
  290        *
  291        *@param  data   the byte array
  292        *@param  value  the short (16-bit) value
  293        */
  294   
  295       public static void putShort(final byte[] data, final short value) {
  296           putShort(data, 0, value);
  297       }
  298   
  299   
  300       /**
  301        *  put an int 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 int (32-bit) value
  306        */
  307   
  308       public static void putInt(final byte[] data, final int offset,
  309               final int value) {
  310           putNumber(data, offset, value, INT_SIZE);
  311       }
  312   
  313   
  314       /**
  315        *  put an int value into beginning of a byte array
  316        *
  317        *@param  data   the byte array
  318        *@param  value  the int (32-bit) value
  319        */
  320   
  321       public static void putInt(final byte[] data, final int value) {
  322           putInt(data, 0, value);
  323       }
  324   
  325   
  326       /**
  327        *  put a long value into a byte array
  328        *
  329        *@param  data    the byte array
  330        *@param  offset  a starting offset into the byte array
  331        *@param  value   the long (64-bit) value
  332        */
  333   
  334       public static void putLong(final byte[] data, final int offset,
  335               final long value) {
  336           putNumber(data, offset, value, LONG_SIZE);
  337       }
  338   
  339   
  340       /**
  341        *  put a long value into beginning of a byte array
  342        *
  343        *@param  data   the byte array
  344        *@param  value  the long (64-bit) value
  345        */
  346   
  347       public static void putLong(final byte[] data, final long value) {
  348           putLong(data, 0, value);
  349       }
  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   
  360       public static void putDouble(final byte[] data, final int offset,
  361               final double value) {
  362           // Excel likes NaN to be a specific value.
  363           if (Double.isNaN(value))
  364               putNumber(data, offset, -276939487313920L, DOUBLE_SIZE);
  365           else
  366               putNumber(data, offset, Double.doubleToLongBits(value), DOUBLE_SIZE);
  367       }
  368   
  369   
  370       /**
  371        *  put a double value into beginning of a byte array
  372        *
  373        *@param  data   the byte array
  374        *@param  value  the double (64-bit) value
  375        */
  376   
  377       public static void putDouble(final byte[] data, final double value) {
  378           putDouble(data, 0, value);
  379       }
  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            *  simple constructor
  393            */
  394   
  395           BufferUnderrunException() {
  396               super("buffer underrun");
  397           }
  398       }
  399   
  400   
  401       /**
  402        *  get a short value from an InputStream
  403        *
  404        *@param  stream                       the InputStream from which the short
  405        *      is to be read
  406        *@return                              the short (16-bit) value
  407        *@exception  IOException              will be propagated back to the caller
  408        *@exception  BufferUnderrunException  if the stream cannot provide enough
  409        *      bytes
  410        */
  411   
  412       public static short readShort(final InputStream stream)
  413                throws IOException, BufferUnderrunException {
  414           return getShort(readFromStream(stream, SHORT_SIZE));
  415       }
  416   
  417   
  418       /**
  419        *  get an int value from an InputStream
  420        *
  421        *@param  stream                       the InputStream from which the int is
  422        *      to be read
  423        *@return                              the int (32-bit) value
  424        *@exception  IOException              will be propagated back to the caller
  425        *@exception  BufferUnderrunException  if the stream cannot provide enough
  426        *      bytes
  427        */
  428   
  429       public static int readInt(final InputStream stream)
  430                throws IOException, BufferUnderrunException {
  431           return getInt(readFromStream(stream, INT_SIZE));
  432       }
  433   
  434   
  435       /**
  436        *  get a long value from an InputStream
  437        *
  438        *@param  stream                       the InputStream from which the long
  439        *      is to be read
  440        *@return                              the long (64-bit) value
  441        *@exception  IOException              will be propagated back to the caller
  442        *@exception  BufferUnderrunException  if the stream cannot provide enough
  443        *      bytes
  444        */
  445   
  446       public static long readLong(final InputStream stream)
  447                throws IOException, BufferUnderrunException {
  448           return getLong(readFromStream(stream, LONG_SIZE));
  449       }
  450   
  451       /**
  452        *  Read the appropriate number of bytes from the stream and return them to
  453        *  the caller. <p>
  454        *
  455        *  However, for the purposes of the POI project, this risk is deemed
  456        *  negligible. It is, however, so noted.
  457        *
  458        *@param  stream                       the InputStream we're reading from
  459        *@param  size                         the number of bytes to read; in
  460        *      99.99% of cases, this will be SHORT_SIZE, INT_SIZE, or LONG_SIZE --
  461        *      but it doesn't have to be.
  462        *@return                              the byte array containing the
  463        *      required number of bytes. The array will contain all zero's on end
  464        *      of stream
  465        *@exception  IOException              will be propagated back to the caller
  466        *@exception  BufferUnderrunException  if the stream cannot provide enough
  467        *      bytes
  468        */
  469   
  470       public static byte[] readFromStream(final InputStream stream,
  471               final int size)
  472                throws IOException, BufferUnderrunException {
  473           byte[] buffer = new byte[size];
  474   
  475           int count = stream.read(buffer);
  476   
  477           if (count == -1) {
  478   
  479               // return a zero-filled buffer
  480               Arrays.fill(buffer, (byte) 0);
  481           } else if (count != size) {
  482               throw new BufferUnderrunException();
  483           }
  484           return buffer;
  485       }
  486   
  487   
  488       /**
  489        *  Gets the number attribute of the LittleEndian class
  490        *
  491        *@param  data    Description of the Parameter
  492        *@param  offset  Description of the Parameter
  493        *@param  size    Description of the Parameter
  494        *@return         The number value
  495        */
  496       private static long getNumber(final byte[] data, final int offset,
  497               final int size) {
  498           long result = 0;
  499   
  500           for (int j = offset + size - 1; j >= offset; j--) {
  501               result <<= 8;
  502               result |= 0xff & data[j];
  503           }
  504           return result;
  505       }
  506   
  507   
  508       /**
  509        *  Description of the Method
  510        *
  511        *@param  data    Description of the Parameter
  512        *@param  offset  Description of the Parameter
  513        *@param  value   Description of the Parameter
  514        *@param  size    Description of the Parameter
  515        */
  516       private static void putNumber(final byte[] data, final int offset,
  517               final long value, final int size) {
  518           int limit = size + offset;
  519           long v = value;
  520   
  521           for (int j = offset; j < limit; j++) {
  522               data[j] = (byte) (v & 0xFF);
  523               v >>= 8;
  524           }
  525       }
  526   
  527   
  528       /**
  529        *  Convert an 'unsigned' byte to an integer. ie, don't carry across the
  530        *  sign.
  531        *
  532        *@param  b  Description of the Parameter
  533        *@return    Description of the Return Value
  534        */
  535       public static int ubyteToInt(byte b) {
  536           return ((b & 0x80) == 0 ? (int) b : (b & (byte) 0x7f) + 0x80);
  537       }
  538   
  539   
  540       /**
  541        *  get the unsigned value of a byte.
  542        *
  543        *@param  data    the byte array.
  544        *@param  offset  a starting offset into the byte array.
  545        *@return         the unsigned value of the byte as a 32 bit integer
  546        */
  547       public static int getUnsignedByte(final byte[] data, final int offset) {
  548           return (int) getNumber(data, offset, BYTE_SIZE);
  549       }
  550   
  551   
  552       /**
  553        *  get the unsigned value of a byte.
  554        *
  555        *@param  data  the byte array
  556        *@return       the unsigned value of the byte as a 32 bit integer
  557        */
  558       public static int getUnsignedByte(final byte[] data) {
  559           return getUnsignedByte(data, 0);
  560       }
  561   
  562   
  563       /**
  564        *  Copy a portion of a byte array
  565        *
  566        *@param  data                        the original byte array
  567        *@param  offset                      Where to start copying from.
  568        *@param  size                        Number of bytes to copy.
  569        *@return                             The byteArray value
  570        *@throws  IndexOutOfBoundsException  - if copying would cause access of
  571        *      data outside array bounds.
  572        */
  573       public static byte[] getByteArray(final byte[] data, int offset, int size) {
  574           byte[] copy = new byte[size];
  575           System.arraycopy(data, offset, copy, 0, size);
  576   
  577           return copy;
  578       }
  579   
  580       /**
  581        * <p>Gets an unsigned int value (8 bytes) from a byte array.</p>
  582        * 
  583        * @param data the byte array
  584        * @param offset a starting offset into the byte array
  585        * @return the unsigned int (32-bit) value in a long
  586        */
  587       public static long getULong(final byte[] data, final int offset)
  588       {
  589           int num = (int) getNumber(data, offset, LONG_SIZE);
  590           long retNum;
  591           if (num < 0)
  592               retNum = ((long) Integer.MAX_VALUE + 1) * 2 + num;
  593           else
  594               retNum = num;
  595           return retNum;
  596       }
  597   
  598   }

Save This Page
Home » poi-src-3.2-FINAL-20081019 » org.apache » poi » util » [javadoc | source]