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