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}