content: /**
   * Copyright 2000-2009 DFKI GmbH.
   * All Rights Reserved.  Use is subject to license terms.
   * <p/>
   * This file is part of MARY TTS.
   * <p/>
   * MARY TTS is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as published by
   * the Free Software Foundation, version 3 of the License.
   * <p/>
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Lesser General Public License for more details.
   * <p/>
   * You should have received a copy of the GNU Lesser General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package marytts.util.io;
  
  /**
   * LEDataInputStream.java
   * copyright (c) 1998-2007 Roedy Green, Canadian Mind* Products
   * Very similar to DataInputStream except it reads
   * little-endian instead of big-endian binary data. We can't extend
   * DataInputStream directly since it has only final methods, though
   * DataInputStream itself is not final. This forces us implement
   * LEDataInputStream with a DataInputStream object, and use wrapper methods.
   */
  
  import java.io.DataInput;
  import java.io.DataInputStream;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.io.InputStream;
  
  /**
   * reads little endian binary data .
   */
  public class LEDataInputStream implements DataInput {
  
      // ------------------------------ FIELDS ------------------------------
  
      /**
       * undisplayed copyright notice.
       *
       * @noinspection UnusedDeclaration
       */
      private static final String EMBEDDEDCOPYRIGHT =
              "copyright (c) 1999-2007 Roedy Green, Canadian Mind Products, http://mindprod.com";
  
      /**
       * to get at the big-Endian methods of a basic DataInputStream
       *
       * @noinspection WeakerAccess
       */
      protected final DataInputStream dis;
  
      /**
       * to get at the a basic readBytes method.
       *
       * @noinspection WeakerAccess
       */
      protected final InputStream is;
  
      /**
       * work array for buffering input.
       *
       * @noinspection WeakerAccess
       */
      protected final byte[] work;
  
      // -------------------------- PUBLIC STATIC METHODS --------------------------
  
      /**
       * constructor.
       *
       * @param in binary inputstream of little-endian data.
       */
      public LEDataInputStream(InputStream in) {
          this.is = in;
          this.dis = new DataInputStream(in);
          work = new byte[8];
      }
  
      // -------------------------- PUBLIC INSTANCE  METHODS --------------------------
  
      public LEDataInputStream(String filename) throws FileNotFoundException {
          this(new FileInputStream(filename));
      }
  
      /**
       * Note. This is a STATIC method!
       *
       * @param in stream to read UTF chars from (endian irrelevant)
       * @return string from stream
       * @throws IOException if read fails.
       */
      public static String readUTF(DataInput in) throws IOException {
          return DataInputStream.readUTF(in);
      }
  
      /**
       * close.
       *
       * @throws IOException if close fails.
       */
      public final void close() throws IOException {
          dis.close();
      }
  
      /**
       * Read bytes. Watch out, read may return fewer bytes than requested.
       *
       * @param ba  where the bytes go.
       * @param off offset in buffer, not offset in file.
       * @param len count of bytes to read.
       * @return how many bytes read.
       * @throws IOException if read fails.
       */
      public final int read(byte ba[], int off, int len) throws IOException {
          // For efficiency, we avoid one layer of wrapper
          return is.read(ba, off, len);
      }
  
      /**
       * read only a one-byte boolean.
       *
       * @return true or false.
       * @throws IOException if read fails.
       * @see java.io.DataInput#readBoolean()
       */
      @Override
      public final boolean readBoolean() throws IOException {
          return dis.readBoolean();
      }
  
      public final boolean[] readBoolean(int len) throws IOException {
          boolean[] ret = new boolean[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readBoolean();
  
          return ret;
      }
  
      /**
       * read byte.
       *
       * @return the byte read.
       * @throws IOException if read fails.
       * @see java.io.DataInput#readByte()
       */
      @Override
      public final byte readByte() throws IOException {
          return dis.readByte();
      }
  
      public final byte[] readByte(int len) throws IOException {
          byte[] ret = new byte[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readByte();
  
          return ret;
      }
  
      /**
       * Read on char. like DataInputStream.readChar except little endian.
       *
       * @return little endian 16-bit unicode char from the stream.
       * @throws IOException if read fails.
       */
      @Override
      public final char readChar() throws IOException {
          dis.readFully(work, 0, 2);
          return (char) ((work[1] & 0xff) << 8 | (work[0] & 0xff));
      }
  
      public final char[] readChar(int len) throws IOException {
          char[] ret = new char[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readChar();
  
          return ret;
      }
  
      /**
       * Read a double. like DataInputStream.readDouble except little endian.
       *
       * @return little endian IEEE double from the datastream.
       * @throws IOException
       */
      @Override
      public final double readDouble() throws IOException {
          return Double.longBitsToDouble(readLong());
      }
  
      public final double[] readDouble(int len) throws IOException {
          double[] ret = new double[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readDouble();
  
          return ret;
      }
  
      public final int[] readDoubleToInt(int len) throws IOException {
          int[] ret = new int[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = (int) readDouble();
  
          return ret;
      }
  
      /**
       * Read one float. Like DataInputStream.readFloat except little endian.
       *
       * @return little endian IEEE float from the datastream.
       * @throws IOException if read fails.
       */
      @Override
      public final float readFloat() throws IOException {
          return Float.intBitsToFloat(readInt());
      }
  
      public final float[] readFloat(int len) throws IOException {
          float[] ret = new float[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readFloat();
  
          return ret;
      }
  
      /**
       * Read bytes until the array is filled.
       *
       * @see java.io.DataInput#readFully(byte[])
       */
      @Override
      public final void readFully(byte ba[]) throws IOException {
          dis.readFully(ba, 0, ba.length);
      }
  
      /**
       * Read bytes until the count is satisfied.
       *
       * @throws IOException if read fails.
       * @see java.io.DataInput#readFully(byte[], int, int)
       */
      @Override
      public final void readFully(byte ba[],
                                  int off,
                                  int len) throws IOException {
          dis.readFully(ba, off, len);
      }
  
      /**
       * Read an int, 32-bits. Like DataInputStream.readInt except little endian.
       *
       * @return little-endian binary int from the datastream
       * @throws IOException if read fails.
       */
      @Override
      public final int readInt() throws IOException {
          dis.readFully(work, 0, 4);
          return (work[3]) << 24
                  | (work[2] & 0xff) << 16
                  | (work[1] & 0xff) << 8
                  | (work[0] & 0xff);
      }
  
      public final int[] readInt(int len) throws IOException {
          int[] ret = new int[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readInt();
  
          return ret;
      }
  
      /**
       * Read a line.
       *
       * @return a rough approximation of the 8-bit stream as a 16-bit unicode
       * string
       * @throws IOException
       * @noinspection deprecation
       * @deprecated This method does not properly convert bytes to characters.
       * Use a Reader instead with a little-endian encoding.
       */
      @Deprecated
      @Override
      public final String readLine() throws IOException {
          return dis.readLine();
      }
  
      /**
       * read a long, 64-bits.  Like DataInputStream.readLong except little
       * endian.
       *
       * @return little-endian binary long from the datastream.
       * @throws IOException
       */
      @Override
      public final long readLong() throws IOException {
          dis.readFully(work, 0, 8);
          return (long) (work[7]) << 56
                  |
                 /* long cast needed or shift done modulo 32 */
                  (long) (work[6] & 0xff) << 48
                  | (long) (work[5] & 0xff) << 40
                  | (long) (work[4] & 0xff) << 32
                  | (long) (work[3] & 0xff) << 24
                  | (long) (work[2] & 0xff) << 16
                  | (long) (work[1] & 0xff) << 8
                  | work[0] & 0xff;
      }
  
      public final long[] readLong(int len) throws IOException {
          long[] ret = new long[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readLong();
  
          return ret;
      }
  
      /**
       * Read short, 16-bits. Like DataInputStream.readShort except little
       * endian.
       *
       * @return little endian binary short from stream.
       * @throws IOException if read fails.
       */
      @Override
      public final short readShort() throws IOException {
          dis.readFully(work, 0, 2);
          return (short) ((work[1] & 0xff) << 8 | (work[0] & 0xff));
      }
  
      public final short[] readShort(int len) throws IOException {
          short[] ret = new short[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readShort();
  
          return ret;
      }
  
      /**
       * Read UTF counted string.
       *
       * @return String read.
       */
      @Override
      public final String readUTF() throws IOException {
          return dis.readUTF();
      }
  
      /**
       * Read an unsigned byte. Note: returns an int, even though says Byte
       * (non-Javadoc)
       *
       * @throws IOException if read fails.
       * @see java.io.DataInput#readUnsignedByte()
       */
      @Override
      public final int readUnsignedByte() throws IOException {
          return dis.readUnsignedByte();
      }
  
      public final int[] readUnsignedByte(int len) throws IOException {
          int[] ret = new int[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readUnsignedByte();
  
          return ret;
      }
  
      /**
       * Read an unsigned short, 16 bits. Like DataInputStream.readUnsignedShort
       * except little endian. Note, returns int even though it reads a short.
       *
       * @return little-endian int from the stream.
       * @throws IOException if read fails.
       */
      @Override
      public final int readUnsignedShort() throws IOException {
          dis.readFully(work, 0, 2);
          return ((work[1] & 0xff) << 8 | (work[0] & 0xff));
      }
  
      public final int[] readUnsignedShort(int len) throws IOException {
          int[] ret = new int[len];
  
          for (int i = 0; i < len; i++)
              ret[i] = readUnsignedShort();
  
          return ret;
      }
  
      /**
       * Skip over bytes in the stream. See the general contract of the
       * <code>skipBytes</code> method of <code>DataInput</code>.
       * <p/>
       * Bytes for this operation are read from the contained input stream.
       *
       * @param n the number of bytes to be skipped.
       * @return the actual number of bytes skipped.
       * @throws IOException if an I/O error occurs.
       */
      @Override
      public final int skipBytes(int n) throws IOException {
          return dis.skipBytes(n);
      }
  }// end class LEDataInputStream
  
  