    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.
    030 * When read, values will be changed from little endian to big
    031 * endian formats for internal usage.
    032 * <p>
    033 * <b>Origin of code: </b>Avalon Excalibur (IO)
    034 * </p>
    035 *
    036 */
    037public class SwappedDataInputStream extends ProxyInputStream
    038    implements DataInput
    039{
    040
    041    /**
    042     * Constructs a SwappedDataInputStream.
    043     *
    044     * @param input InputStream to read from
    045     */
    046    public SwappedDataInputStream( final InputStream input )
    047    {
    048        super( input );
    049    }
    050
    051    /**
    052     * Return <code>{@link #readByte()} != 0</code>
    053     * @return false if the byte read is zero, otherwise true
    054     * @throws IOException if an I/O error occurs
    055     * @throws EOFException if an end of file is reached unexpectedly
    056     */
    057    @Override
    058    public boolean readBoolean()
    059        throws IOException, EOFException
    060    {
    061        return 0 != readByte();
    062    }
    063
    064    /**
    065     * Invokes the delegate's <code>read()</code> method.
    066     * @return the byte read or -1 if the end of stream
    067     * @throws IOException if an I/O error occurs
    068     * @throws EOFException if an end of file is reached unexpectedly
    069     */
    070    @Override
    071    public byte readByte()
    072        throws IOException, EOFException
    073    {
    074        return (byte)in.read();
    075    }
    076
    077    /**
    078     * Reads a character delegating to {@link #readShort()}.
    079     * @return the byte read or -1 if the end of stream
    080     * @throws IOException if an I/O error occurs
    081     * @throws EOFException if an end of file is reached unexpectedly
    082     */
    083    @Override
    084    public char readChar()
    085        throws IOException, EOFException
    086    {
    087        return (char)readShort();
    088    }
    089
    090    /**
    091     * Delegates to {@link EndianUtils#readSwappedDouble(InputStream)}.
    092     * @return the read long
    093     * @throws IOException if an I/O error occurs
    094     * @throws EOFException if an end of file is reached unexpectedly
    095     */
    096    @Override
    097    public double readDouble()
    098        throws IOException, EOFException
    099    {
    100        return EndianUtils.readSwappedDouble( in );
    101    }
    102
    103    /**
    104     * Delegates to {@link EndianUtils#readSwappedFloat(InputStream)}.
    105     * @return the read long
    106     * @throws IOException if an I/O error occurs
    107     * @throws EOFException if an end of file is reached unexpectedly
    108     */
    109    @Override
    110    public float readFloat()
    111        throws IOException, EOFException
    112    {
    113        return EndianUtils.readSwappedFloat( in );
    114    }
    115
    116    /**
    117     * Invokes the delegate's <code>read(byte[] data, int, int)</code> method.
    118     *
    119     * @param data the buffer to read the bytes into
    120     * @throws EOFException if an end of file is reached unexpectedly
    121     * @throws IOException if an I/O error occurs
    122     */
    123    @Override
    124    public void readFully( final byte[] data )
    125        throws IOException, EOFException
    126    {
    127        readFully( data, 0, data.length );
    128    }
    129
    130
    131    /**
    132     * Invokes the delegate's <code>read(byte[] data, int, int)</code> method.
    133     *
    134     * @param data the buffer to read the bytes into
    135     * @param offset The start offset
    136     * @param length The number of bytes to read
    137     * @throws EOFException if an end of file is reached unexpectedly
    138     * @throws IOException if an I/O error occurs
    139     */
    140    @Override
    141    public void readFully( final byte[] data, final int offset, final int length )
    142        throws IOException, EOFException
    143    {
    144        int remaining = length;
    145
    146        while( remaining > 0 )
    147        {
    148            final int location = offset + length - remaining;
    149            final int count = read( data, location, remaining );
    150
    151            if (EOF == count)
    152            {
    153                throw new EOFException();
    154            }
    155
    156            remaining -= count;
    157        }
    158    }
    159
    160    /**
    161     * Delegates to {@link EndianUtils#readSwappedInteger(InputStream)}.
    162     * @return the read long
    163     * @throws EOFException if an end of file is reached unexpectedly
    164     * @throws IOException if an I/O error occurs
    165     */
    166    @Override
    167    public int readInt()
    168        throws IOException, EOFException
    169    {
    170        return EndianUtils.readSwappedInteger( in );
    171    }
    172
    173    /**
    174     * Not currently supported - throws {@link UnsupportedOperationException}.
    175     * @return the line read
    176     * @throws EOFException if an end of file is reached unexpectedly
    177     * @throws IOException if an I/O error occurs
    178     */
    179    @Override
    180    public String readLine()
    181        throws IOException, EOFException
    182    {
    183        throw new UnsupportedOperationException(
    184                "Operation not supported: readLine()" );
    185    }
    186
    187    /**
    188     * Delegates to {@link EndianUtils#readSwappedLong(InputStream)}.
    189     * @return the read long
    190     * @throws EOFException if an end of file is reached unexpectedly
    191     * @throws IOException if an I/O error occurs
    192     */
    193    @Override
    194    public long readLong()
    195        throws IOException, EOFException
    196    {
    197        return EndianUtils.readSwappedLong( in );
    198    }
    199
    200    /**
    201     * Delegates to {@link EndianUtils#readSwappedShort(InputStream)}.
    202     * @return the read long
    203     * @throws EOFException if an end of file is reached unexpectedly
    204     * @throws IOException if an I/O error occurs
    205     */
    206    @Override
    207    public short readShort()
    208        throws IOException, EOFException
    209    {
    210        return EndianUtils.readSwappedShort( in );
    211    }
    212
    213    /**
    214     * Invokes the delegate's <code>read()</code> method.
    215     * @return the byte read or -1 if the end of stream
    216     * @throws EOFException if an end of file is reached unexpectedly
    217     * @throws IOException if an I/O error occurs
    218     */
    219    @Override
    220    public int readUnsignedByte()
    221        throws IOException, EOFException
    222    {
    223        return in.read();
    224    }
    225
    226    /**
    227     * Delegates to {@link EndianUtils#readSwappedUnsignedShort(InputStream)}.
    228     * @return the read long
    229     * @throws EOFException if an end of file is reached unexpectedly
    230     * @throws IOException if an I/O error occurs
    231     */
    232    @Override
    233    public int readUnsignedShort()
    234        throws IOException, EOFException
    235    {
    236        return EndianUtils.readSwappedUnsignedShort( in );
    237    }
    238
    239    /**
    240     * Not currently supported - throws {@link UnsupportedOperationException}.
    241     * @return UTF String read
    242     * @throws EOFException if an end of file is reached unexpectedly
    243     * @throws IOException if an I/O error occurs
    244     */
    245    @Override
    246    public String readUTF()
    247        throws IOException, EOFException
    248    {
    249        throw new UnsupportedOperationException(
    250                "Operation not supported: readUTF()" );
    251    }
    252
    253    /**
    254     * Invokes the delegate's <code>skip(int)</code> method.
    255     * @param count the number of bytes to skip
    256     * @return the number of bytes to skipped or -1 if the end of stream
    257     * @throws EOFException if an end of file is reached unexpectedly
    258     * @throws IOException if an I/O error occurs
    259     */
    260    @Override
    261    public int skipBytes( final int count )
    262        throws IOException, EOFException
    263    {
    264        return (int)in.skip( count );
    265    }
    266
    267}