    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.io.input;
    018
    019import static org.apache.commons.io.IOUtils.EOF;
    020
    021import java.io.DataInput;
    022import java.io.EOFException;
    023import java.io.IOException;
    024import java.io.InputStream;
    025
    026import org.apache.commons.io.EndianUtils;
    027
    028/**
    029 * DataInput for systems relying on little-endian data formats. When read, values will be changed from little-endian to
    030 * big-endian formats for internal usage.
    031 * <p>
    032 * Provenance: Avalon Excalibur (IO)
    033 * </p>
    034 */
    035public class SwappedDataInputStream extends ProxyInputStream implements DataInput {
    036
    037    /**
    038     * Constructs a SwappedDataInputStream.
    039     *
    040     * @param input InputStream to read from
    041     */
    042    public SwappedDataInputStream(final InputStream input) {
    043        super(input);
    044    }
    045
    046    /**
    047     * Return <code>{@link #readByte()} != 0</code>
    048     *
    049     * @return false if the byte read is zero, otherwise true
    050     * @throws IOException if an I/O error occurs.
    051     * @throws EOFException if an end of file is reached unexpectedly
    052     */
    053    @Override
    054    public boolean readBoolean() throws IOException, EOFException {
    055        return 0 != readByte();
    056    }
    057
    058    /**
    059     * Invokes the delegate's {@code read()} method.
    060     *
    061     * @return the byte read or -1 if the end of stream
    062     * @throws IOException if an I/O error occurs.
    063     * @throws EOFException if an end of file is reached unexpectedly
    064     */
    065    @Override
    066    public byte readByte() throws IOException, EOFException {
    067        return (byte) in.read();
    068    }
    069
    070    /**
    071     * Reads a 2 byte, unsigned, little endian UTF-16 code point.
    072     *
    073     * @return the UTF-16 code point read or -1 if the end of stream
    074     * @throws IOException if an I/O error occurs.
    075     * @throws EOFException if an end of file is reached unexpectedly
    076     */
    077    @Override
    078    public char readChar() throws IOException, EOFException {
    079        return (char) readShort();
    080    }
    081
    082    /**
    083     * Reads an 8 byte, two's complement, little-endian long.
    084     *
    085     * @return the read long
    086     * @throws IOException if an I/O error occurs.
    087     * @throws EOFException if an end of file is reached unexpectedly
    088     */
    089    @Override
    090    public double readDouble() throws IOException, EOFException {
    091        return EndianUtils.readSwappedDouble(in);
    092    }
    093
    094    /**
    095     * Reads a 4 byte, IEEE 754, little-endian float.
    096     *
    097     * @return the read float
    098     * @throws IOException if an I/O error occurs.
    099     * @throws EOFException if an end of file is reached unexpectedly
    100     */
    101    @Override
    102    public float readFloat() throws IOException, EOFException {
    103        return EndianUtils.readSwappedFloat(in);
    104    }
    105
    106    /**
    107     * Invokes the delegate's {@code read(byte[] data, int, int)} method.
    108     *
    109     * @param data the buffer to read the bytes into
    110     * @throws EOFException if an end of file is reached unexpectedly
    111     * @throws IOException if an I/O error occurs.
    112     */
    113    @Override
    114    public void readFully(final byte[] data) throws IOException, EOFException {
    115        readFully(data, 0, data.length);
    116    }
    117
    118    /**
    119     * Invokes the delegate's {@code read(byte[] data, int, int)} method.
    120     *
    121     * @param data the buffer to read the bytes into
    122     * @param offset The start offset
    123     * @param length The number of bytes to read
    124     * @throws EOFException if an end of file is reached unexpectedly
    125     * @throws IOException if an I/O error occurs.
    126     */
    127    @Override
    128    public void readFully(final byte[] data, final int offset, final int length) throws IOException, EOFException {
    129        int remaining = length;
    130
    131        while (remaining > 0) {
    132            final int location = offset + length - remaining;
    133            final int count = read(data, location, remaining);
    134
    135            if (EOF == count) {
    136                throw new EOFException();
    137            }
    138
    139            remaining -= count;
    140        }
    141    }
    142
    143    /**
    144     * Reads a 4 byte, two's complement little-endian integer.
    145     *
    146     * @return the read int
    147     * @throws EOFException if an end of file is reached unexpectedly
    148     * @throws IOException if an I/O error occurs.
    149     */
    150    @Override
    151    public int readInt() throws IOException, EOFException {
    152        return EndianUtils.readSwappedInteger(in);
    153    }
    154
    155    /**
    156     * Not currently supported - throws {@link UnsupportedOperationException}.
    157     *
    158     * @return the line read
    159     * @throws EOFException if an end of file is reached unexpectedly
    160     * @throws IOException if an I/O error occurs
    161     * @throws UnsupportedOperationException always
    162     */
    163    @Override
    164    public String readLine() throws IOException, EOFException {
    165        throw UnsupportedOperationExceptions.method("readLine");
    166    }
    167
    168    /**
    169     * Reads an 8 byte, two's complement little-endian integer.
    170     *
    171     * @return the read long
    172     * @throws EOFException if an end of file is reached unexpectedly
    173     * @throws IOException if an I/O error occurs.
    174     */
    175    @Override
    176    public long readLong() throws IOException, EOFException {
    177        return EndianUtils.readSwappedLong(in);
    178    }
    179
    180    /**
    181     * Reads a 2 byte, two's complement, little-endian integer.
    182     *
    183     * @return the read short
    184     * @throws EOFException if an end of file is reached unexpectedly
    185     * @throws IOException if an I/O error occurs.
    186     */
    187    @Override
    188    public short readShort() throws IOException, EOFException {
    189        return EndianUtils.readSwappedShort(in);
    190    }
    191
    192    /**
    193     * Invokes the delegate's {@code read()} method.
    194     *
    195     * @return the byte read or -1 if the end of stream
    196     * @throws EOFException if an end of file is reached unexpectedly
    197     * @throws IOException if an I/O error occurs.
    198     */
    199    @Override
    200    public int readUnsignedByte() throws IOException, EOFException {
    201        return in.read();
    202    }
    203
    204    /**
    205     * Reads a 2 byte, unsigned, little-endian integer.
    206     *
    207     * @return the read short
    208     * @throws EOFException if an end of file is reached unexpectedly
    209     * @throws IOException if an I/O error occurs.
    210     */
    211    @Override
    212    public int readUnsignedShort() throws IOException, EOFException {
    213        return EndianUtils.readSwappedUnsignedShort(in);
    214    }
    215
    216    /**
    217     * Not currently supported - throws {@link UnsupportedOperationException}.
    218     *
    219     * @return never
    220     * @throws EOFException if an end of file is reached unexpectedly
    221     * @throws IOException if an I/O error occurs
    222     * @throws UnsupportedOperationException always
    223     */
    224    @Override
    225    public String readUTF() throws IOException, EOFException {
    226        throw UnsupportedOperationExceptions.method("readUTF");
    227    }
    228
    229    /**
    230     * Invokes the delegate's {@code skip(int)} method.
    231     *
    232     * @param count the number of bytes to skip
    233     * @return the number of bytes skipped or -1 if the end of stream
    234     * @throws IOException if an I/O error occurs
    235     */
    236    @Override
    237    public int skipBytes(final int count) throws IOException {
    238        return (int) in.skip(count);
    239    }
    240
    241}