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 character delegating to {@link #readShort()}.
072     *
073     * @return the byte 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     * Delegates to {@link EndianUtils#readSwappedDouble(InputStream)}.
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     * Delegates to {@link EndianUtils#readSwappedFloat(InputStream)}.
096     *
097     * @return the read long
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     * Delegates to {@link EndianUtils#readSwappedInteger(InputStream)}.
145     *
146     * @return the read long
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     */
162    @Override
163    public String readLine() throws IOException, EOFException {
164        throw UnsupportedOperationExceptions.method("readLine");
165    }
166
167    /**
168     * Delegates to {@link EndianUtils#readSwappedLong(InputStream)}.
169     *
170     * @return the read long
171     * @throws EOFException if an end of file is reached unexpectedly
172     * @throws IOException if an I/O error occurs.
173     */
174    @Override
175    public long readLong() throws IOException, EOFException {
176        return EndianUtils.readSwappedLong(in);
177    }
178
179    /**
180     * Delegates to {@link EndianUtils#readSwappedShort(InputStream)}.
181     *
182     * @return the read long
183     * @throws EOFException if an end of file is reached unexpectedly
184     * @throws IOException if an I/O error occurs.
185     */
186    @Override
187    public short readShort() throws IOException, EOFException {
188        return EndianUtils.readSwappedShort(in);
189    }
190
191    /**
192     * Invokes the delegate's {@code read()} method.
193     *
194     * @return the byte read or -1 if the end of stream
195     * @throws EOFException if an end of file is reached unexpectedly
196     * @throws IOException if an I/O error occurs.
197     */
198    @Override
199    public int readUnsignedByte() throws IOException, EOFException {
200        return in.read();
201    }
202
203    /**
204     * Delegates to {@link EndianUtils#readSwappedUnsignedShort(InputStream)}.
205     *
206     * @return the read long
207     * @throws EOFException if an end of file is reached unexpectedly
208     * @throws IOException if an I/O error occurs.
209     */
210    @Override
211    public int readUnsignedShort() throws IOException, EOFException {
212        return EndianUtils.readSwappedUnsignedShort(in);
213    }
214
215    /**
216     * Not currently supported - throws {@link UnsupportedOperationException}.
217     *
218     * @return UTF String read
219     * @throws EOFException if an end of file is reached unexpectedly
220     * @throws IOException if an I/O error occurs.
221     */
222    @Override
223    public String readUTF() throws IOException, EOFException {
224        throw UnsupportedOperationExceptions.method("readUTF");
225    }
226
227    /**
228     * Invokes the delegate's {@code skip(int)} method.
229     *
230     * @param count the number of bytes to skip
231     * @return the number of bytes to skipped or -1 if the end of stream
232     * @throws EOFException if an end of file is reached unexpectedly
233     * @throws IOException if an I/O error occurs.
234     */
235    @Override
236    public int skipBytes(final int count) throws IOException, EOFException {
237        return (int) in.skip(count);
238    }
239
240}