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