001/* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.io; 016 017import com.google.common.annotations.GwtIncompatible; 018import com.google.common.annotations.J2ktIncompatible; 019import com.google.common.base.Preconditions; 020import com.google.common.primitives.Ints; 021import com.google.common.primitives.Longs; 022import com.google.errorprone.annotations.CanIgnoreReturnValue; 023import com.google.errorprone.annotations.DoNotCall; 024import java.io.DataInput; 025import java.io.DataInputStream; 026import java.io.EOFException; 027import java.io.FilterInputStream; 028import java.io.IOException; 029import java.io.InputStream; 030 031/** 032 * An implementation of {@link DataInput} that uses little-endian byte ordering for reading {@code 033 * short}, {@code int}, {@code float}, {@code double}, and {@code long} values. 034 * 035 * <p><b>Note:</b> This class intentionally violates the specification of its supertype {@code 036 * DataInput}, which explicitly requires big-endian byte order. 037 * 038 * @author Chris Nokleberg 039 * @author Keith Bottner 040 * @since 8.0 041 */ 042@J2ktIncompatible 043@GwtIncompatible 044public final class LittleEndianDataInputStream extends FilterInputStream implements DataInput { 045 046 /** 047 * Creates a {@code LittleEndianDataInputStream} that wraps the given stream. 048 * 049 * @param in the stream to delegate to 050 */ 051 public LittleEndianDataInputStream(InputStream in) { 052 super(Preconditions.checkNotNull(in)); 053 } 054 055 /** This method will throw an {@link UnsupportedOperationException}. */ 056 @CanIgnoreReturnValue // to skip a line 057 @Override 058 @DoNotCall("Always throws UnsupportedOperationException") 059 public String readLine() { 060 throw new UnsupportedOperationException("readLine is not supported"); 061 } 062 063 @Override 064 public void readFully(byte[] b) throws IOException { 065 ByteStreams.readFully(this, b); 066 } 067 068 @Override 069 public void readFully(byte[] b, int off, int len) throws IOException { 070 ByteStreams.readFully(this, b, off, len); 071 } 072 073 @Override 074 public int skipBytes(int n) throws IOException { 075 return (int) in.skip(n); 076 } 077 078 @CanIgnoreReturnValue // to skip a byte 079 @Override 080 public int readUnsignedByte() throws IOException { 081 int b1 = in.read(); 082 if (0 > b1) { 083 throw new EOFException(); 084 } 085 086 return b1; 087 } 088 089 /** 090 * Reads an unsigned {@code short} as specified by {@link DataInputStream#readUnsignedShort()}, 091 * except using little-endian byte order. 092 * 093 * @return the next two bytes of the input stream, interpreted as an unsigned 16-bit integer in 094 * little-endian byte order 095 * @throws IOException if an I/O error occurs 096 */ 097 @CanIgnoreReturnValue // to skip some bytes 098 @Override 099 public int readUnsignedShort() throws IOException { 100 byte b1 = readAndCheckByte(); 101 byte b2 = readAndCheckByte(); 102 103 return Ints.fromBytes((byte) 0, (byte) 0, b2, b1); 104 } 105 106 /** 107 * Reads an integer as specified by {@link DataInputStream#readInt()}, except using little-endian 108 * byte order. 109 * 110 * @return the next four bytes of the input stream, interpreted as an {@code int} in little-endian 111 * byte order 112 * @throws IOException if an I/O error occurs 113 */ 114 @CanIgnoreReturnValue // to skip some bytes 115 @Override 116 public int readInt() throws IOException { 117 byte b1 = readAndCheckByte(); 118 byte b2 = readAndCheckByte(); 119 byte b3 = readAndCheckByte(); 120 byte b4 = readAndCheckByte(); 121 122 return Ints.fromBytes(b4, b3, b2, b1); 123 } 124 125 /** 126 * Reads a {@code long} as specified by {@link DataInputStream#readLong()}, except using 127 * little-endian byte order. 128 * 129 * @return the next eight bytes of the input stream, interpreted as a {@code long} in 130 * little-endian byte order 131 * @throws IOException if an I/O error occurs 132 */ 133 @CanIgnoreReturnValue // to skip some bytes 134 @Override 135 public long readLong() throws IOException { 136 byte b1 = readAndCheckByte(); 137 byte b2 = readAndCheckByte(); 138 byte b3 = readAndCheckByte(); 139 byte b4 = readAndCheckByte(); 140 byte b5 = readAndCheckByte(); 141 byte b6 = readAndCheckByte(); 142 byte b7 = readAndCheckByte(); 143 byte b8 = readAndCheckByte(); 144 145 return Longs.fromBytes(b8, b7, b6, b5, b4, b3, b2, b1); 146 } 147 148 /** 149 * Reads a {@code float} as specified by {@link DataInputStream#readFloat()}, except using 150 * little-endian byte order. 151 * 152 * @return the next four bytes of the input stream, interpreted as a {@code float} in 153 * little-endian byte order 154 * @throws IOException if an I/O error occurs 155 */ 156 @CanIgnoreReturnValue // to skip some bytes 157 @Override 158 public float readFloat() throws IOException { 159 return Float.intBitsToFloat(readInt()); 160 } 161 162 /** 163 * Reads a {@code double} as specified by {@link DataInputStream#readDouble()}, except using 164 * little-endian byte order. 165 * 166 * @return the next eight bytes of the input stream, interpreted as a {@code double} in 167 * little-endian byte order 168 * @throws IOException if an I/O error occurs 169 */ 170 @CanIgnoreReturnValue // to skip some bytes 171 @Override 172 public double readDouble() throws IOException { 173 return Double.longBitsToDouble(readLong()); 174 } 175 176 @CanIgnoreReturnValue // to skip a field 177 @Override 178 public String readUTF() throws IOException { 179 return new DataInputStream(in).readUTF(); 180 } 181 182 /** 183 * Reads a {@code short} as specified by {@link DataInputStream#readShort()}, except using 184 * little-endian byte order. 185 * 186 * @return the next two bytes of the input stream, interpreted as a {@code short} in little-endian 187 * byte order. 188 * @throws IOException if an I/O error occurs. 189 */ 190 @CanIgnoreReturnValue // to skip some bytes 191 @Override 192 public short readShort() throws IOException { 193 return (short) readUnsignedShort(); 194 } 195 196 /** 197 * Reads a char as specified by {@link DataInputStream#readChar()}, except using little-endian 198 * byte order. 199 * 200 * @return the next two bytes of the input stream, interpreted as a {@code char} in little-endian 201 * byte order 202 * @throws IOException if an I/O error occurs 203 */ 204 @CanIgnoreReturnValue // to skip some bytes 205 @Override 206 public char readChar() throws IOException { 207 return (char) readUnsignedShort(); 208 } 209 210 @CanIgnoreReturnValue // to skip a byte 211 @Override 212 public byte readByte() throws IOException { 213 return (byte) readUnsignedByte(); 214 } 215 216 @CanIgnoreReturnValue // to skip a byte 217 @Override 218 public boolean readBoolean() throws IOException { 219 return readUnsignedByte() != 0; 220 } 221 222 /** 223 * Reads a byte from the input stream checking that the end of file (EOF) has not been 224 * encountered. 225 * 226 * @return byte read from input 227 * @throws IOException if an error is encountered while reading 228 * @throws EOFException if the end of file (EOF) is encountered. 229 */ 230 private byte readAndCheckByte() throws IOException, EOFException { 231 int b1 = in.read(); 232 233 if (-1 == b1) { 234 throw new EOFException(); 235 } 236 237 return (byte) b1; 238 } 239}