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; 018 019import static org.apache.commons.io.IOUtils.EOF; 020 021import java.io.EOFException; 022import java.io.IOException; 023import java.io.InputStream; 024import java.io.OutputStream; 025 026/** 027 * Helps with different endian systems. 028 * <p> 029 * Different computer architectures adopt different conventions for 030 * byte ordering. In so-called "Little Endian" architectures (eg Intel), 031 * the low-order byte is stored in memory at the lowest address, and 032 * subsequent bytes at higher addresses. For "Big Endian" architectures 033 * (eg Motorola), the situation is reversed. 034 * This class helps you solve this incompatibility. 035 * </p> 036 * <p> 037 * Origin of code: Excalibur 038 * </p> 039 * 040 * @see org.apache.commons.io.input.SwappedDataInputStream 041 */ 042public class EndianUtils { 043 044 /** 045 * Reads the next byte from the input stream. 046 * @param input the stream 047 * @return the byte 048 * @throws IOException if the end of file is reached 049 */ 050 private static int read(final InputStream input) throws IOException { 051 final int value = input.read(); 052 if (EOF == value) { 053 throw new EOFException("Unexpected EOF reached"); 054 } 055 return value; 056 } 057 058 /** 059 * Reads a "double" value from a byte array at a given offset. The value is 060 * converted to the opposed endian system while reading. 061 * @param data source byte array 062 * @param offset starting offset in the byte array 063 * @return the value read 064 */ 065 public static double readSwappedDouble(final byte[] data, final int offset) { 066 return Double.longBitsToDouble(readSwappedLong(data, offset)); 067 } 068 069 /** 070 * Reads a "double" value from an InputStream. The value is 071 * converted to the opposed endian system while reading. 072 * @param input source InputStream 073 * @return the value just read 074 * @throws IOException in case of an I/O problem 075 */ 076 public static double readSwappedDouble(final InputStream input) throws IOException { 077 return Double.longBitsToDouble(readSwappedLong(input)); 078 } 079 080 /** 081 * Reads a "float" value from a byte array at a given offset. The value is 082 * converted to the opposed endian system while reading. 083 * @param data source byte array 084 * @param offset starting offset in the byte array 085 * @return the value read 086 */ 087 public static float readSwappedFloat(final byte[] data, final int offset) { 088 return Float.intBitsToFloat(readSwappedInteger(data, offset)); 089 } 090 091 /** 092 * Reads a "float" value from an InputStream. The value is 093 * converted to the opposed endian system while reading. 094 * @param input source InputStream 095 * @return the value just read 096 * @throws IOException in case of an I/O problem 097 */ 098 public static float readSwappedFloat(final InputStream input) throws IOException { 099 return Float.intBitsToFloat(readSwappedInteger(input)); 100 } 101 102 /** 103 * Reads an "int" value from a byte array at a given offset. The value is 104 * converted to the opposed endian system while reading. 105 * @param data source byte array 106 * @param offset starting offset in the byte array 107 * @return the value read 108 */ 109 public static int readSwappedInteger(final byte[] data, final int offset) { 110 return ((data[offset + 0] & 0xff) << 0) + 111 ((data[offset + 1] & 0xff) << 8) + 112 ((data[offset + 2] & 0xff) << 16) + 113 ((data[offset + 3] & 0xff) << 24); 114 } 115 116 /** 117 * Reads an "int" value from an InputStream. The value is 118 * converted to the opposed endian system while reading. 119 * @param input source InputStream 120 * @return the value just read 121 * @throws IOException in case of an I/O problem 122 */ 123 public static int readSwappedInteger(final InputStream input) throws IOException { 124 final int value1 = read(input); 125 final int value2 = read(input); 126 final int value3 = read(input); 127 final int value4 = read(input); 128 return ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8) + ((value3 & 0xff) << 16) + ((value4 & 0xff) << 24); 129 } 130 131 /** 132 * Reads a "long" value from a byte array at a given offset. The value is 133 * converted to the opposed endian system while reading. 134 * @param data source byte array 135 * @param offset starting offset in the byte array 136 * @return the value read 137 */ 138 public static long readSwappedLong(final byte[] data, final int offset) { 139 final long low = readSwappedInteger(data, offset); 140 final long high = readSwappedInteger(data, offset + 4); 141 return (high << 32) + (0xffffffffL & low); 142 } 143 144 /** 145 * Reads a "long" value from an InputStream. The value is 146 * converted to the opposed endian system while reading. 147 * @param input source InputStream 148 * @return the value just read 149 * @throws IOException in case of an I/O problem 150 */ 151 public static long readSwappedLong(final InputStream input) throws IOException { 152 final byte[] bytes = new byte[8]; 153 for (int i = 0; i < 8; i++) { 154 bytes[i] = (byte) read(input); 155 } 156 return readSwappedLong(bytes, 0); 157 } 158 159 /** 160 * Reads a "short" value from a byte array at a given offset. The value is 161 * converted to the opposed endian system while reading. 162 * @param data source byte array 163 * @param offset starting offset in the byte array 164 * @return the value read 165 */ 166 public static short readSwappedShort(final byte[] data, final int offset) { 167 return (short)(((data[offset + 0] & 0xff) << 0) + 168 ((data[offset + 1] & 0xff) << 8)); 169 } 170 171 /** 172 * Reads a "short" value from an InputStream. The value is 173 * converted to the opposed endian system while reading. 174 * @param input source InputStream 175 * @return the value just read 176 * @throws IOException in case of an I/O problem 177 */ 178 public static short readSwappedShort(final InputStream input) throws IOException { 179 return (short) (((read(input) & 0xff) << 0) + ((read(input) & 0xff) << 8)); 180 } 181 182 /** 183 * Reads an unsigned integer (32-bit) value from a byte array at a given 184 * offset. The value is converted to the opposed endian system while 185 * reading. 186 * @param data source byte array 187 * @param offset starting offset in the byte array 188 * @return the value read 189 */ 190 public static long readSwappedUnsignedInteger(final byte[] data, final int offset) { 191 final long low = ((data[offset + 0] & 0xff) << 0) + 192 ((data[offset + 1] & 0xff) << 8) + 193 ((data[offset + 2] & 0xff) << 16); 194 final long high = data[offset + 3] & 0xff; 195 return (high << 24) + (0xffffffffL & low); 196 } 197 198 /** 199 * Reads an unsigned integer (32-bit) from an InputStream. The value is 200 * converted to the opposed endian system while reading. 201 * @param input source InputStream 202 * @return the value just read 203 * @throws IOException in case of an I/O problem 204 */ 205 public static long readSwappedUnsignedInteger(final InputStream input) throws IOException { 206 final int value1 = read(input); 207 final int value2 = read(input); 208 final int value3 = read(input); 209 final int value4 = read(input); 210 final long low = ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8) + ((value3 & 0xff) << 16); 211 final long high = value4 & 0xff; 212 return (high << 24) + (0xffffffffL & low); 213 } 214 215 /** 216 * Reads an unsigned short (16-bit) value from a byte array at a given 217 * offset. The value is converted to the opposed endian system while 218 * reading. 219 * @param data source byte array 220 * @param offset starting offset in the byte array 221 * @return the value read 222 */ 223 public static int readSwappedUnsignedShort(final byte[] data, final int offset) { 224 return ((data[offset + 0] & 0xff) << 0) + 225 ((data[offset + 1] & 0xff) << 8); 226 } 227 228 /** 229 * Reads an unsigned short (16-bit) from an InputStream. The value is 230 * converted to the opposed endian system while reading. 231 * @param input source InputStream 232 * @return the value just read 233 * @throws IOException in case of an I/O problem 234 */ 235 public static int readSwappedUnsignedShort(final InputStream input) throws IOException { 236 final int value1 = read(input); 237 final int value2 = read(input); 238 239 return ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8); 240 } 241 242 /** 243 * Converts a "double" value between endian systems. 244 * @param value value to convert 245 * @return the converted value 246 */ 247 public static double swapDouble(final double value) { 248 return Double.longBitsToDouble(swapLong(Double.doubleToLongBits(value))); 249 } 250 251 /** 252 * Converts a "float" value between endian systems. 253 * @param value value to convert 254 * @return the converted value 255 */ 256 public static float swapFloat(final float value) { 257 return Float.intBitsToFloat(swapInteger(Float.floatToIntBits(value))); 258 } 259 260 /** 261 * Converts an "int" value between endian systems. 262 * @param value value to convert 263 * @return the converted value 264 */ 265 public static int swapInteger(final int value) { 266 return 267 ((value >> 0 & 0xff) << 24) + 268 ((value >> 8 & 0xff) << 16) + 269 ((value >> 16 & 0xff) << 8) + 270 ((value >> 24 & 0xff) << 0); 271 } 272 273 /** 274 * Converts a "long" value between endian systems. 275 * @param value value to convert 276 * @return the converted value 277 */ 278 public static long swapLong(final long value) { 279 return 280 ((value >> 0 & 0xff) << 56) + 281 ((value >> 8 & 0xff) << 48) + 282 ((value >> 16 & 0xff) << 40) + 283 ((value >> 24 & 0xff) << 32) + 284 ((value >> 32 & 0xff) << 24) + 285 ((value >> 40 & 0xff) << 16) + 286 ((value >> 48 & 0xff) << 8) + 287 ((value >> 56 & 0xff) << 0); 288 } 289 290 /** 291 * Converts a "short" value between endian systems. 292 * @param value value to convert 293 * @return the converted value 294 */ 295 public static short swapShort(final short value) { 296 return (short) (((value >> 0 & 0xff) << 8) + 297 ((value >> 8 & 0xff) << 0)); 298 } 299 300 /** 301 * Writes a "double" value to a byte array at a given offset. The value is 302 * converted to the opposed endian system while writing. 303 * @param data target byte array 304 * @param offset starting offset in the byte array 305 * @param value value to write 306 */ 307 public static void writeSwappedDouble(final byte[] data, final int offset, final double value) { 308 writeSwappedLong(data, offset, Double.doubleToLongBits(value)); 309 } 310 311 /** 312 * Writes a "double" value to an OutputStream. The value is 313 * converted to the opposed endian system while writing. 314 * @param output target OutputStream 315 * @param value value to write 316 * @throws IOException in case of an I/O problem 317 */ 318 public static void writeSwappedDouble(final OutputStream output, final double value) throws IOException { 319 writeSwappedLong(output, Double.doubleToLongBits(value)); 320 } 321 322 /** 323 * Writes a "float" value to a byte array at a given offset. The value is 324 * converted to the opposed endian system while writing. 325 * @param data target byte array 326 * @param offset starting offset in the byte array 327 * @param value value to write 328 */ 329 public static void writeSwappedFloat(final byte[] data, final int offset, final float value) { 330 writeSwappedInteger(data, offset, Float.floatToIntBits(value)); 331 } 332 333 /** 334 * Writes a "float" value to an OutputStream. The value is 335 * converted to the opposed endian system while writing. 336 * @param output target OutputStream 337 * @param value value to write 338 * @throws IOException in case of an I/O problem 339 */ 340 public static void writeSwappedFloat(final OutputStream output, final float value) throws IOException { 341 writeSwappedInteger(output, Float.floatToIntBits(value)); 342 } 343 344 /** 345 * Writes an "int" value to a byte array at a given offset. The value is 346 * converted to the opposed endian system while writing. 347 * @param data target byte array 348 * @param offset starting offset in the byte array 349 * @param value value to write 350 */ 351 public static void writeSwappedInteger(final byte[] data, final int offset, final int value) { 352 data[offset + 0] = (byte) (value >> 0 & 0xff); 353 data[offset + 1] = (byte) (value >> 8 & 0xff); 354 data[offset + 2] = (byte) (value >> 16 & 0xff); 355 data[offset + 3] = (byte) (value >> 24 & 0xff); 356 } 357 358 /** 359 * Writes an "int" value to an OutputStream. The value is converted to the opposed endian system while writing. 360 * 361 * @param output target OutputStream 362 * @param value value to write 363 * @throws IOException in case of an I/O problem 364 */ 365 public static void writeSwappedInteger(final OutputStream output, final int value) throws IOException { 366 output.write((byte) (value >> 0 & 0xff)); 367 output.write((byte) (value >> 8 & 0xff)); 368 output.write((byte) (value >> 16 & 0xff)); 369 output.write((byte) (value >> 24 & 0xff)); 370 } 371 372 /** 373 * Writes a "long" value to a byte array at a given offset. The value is 374 * converted to the opposed endian system while writing. 375 * @param data target byte array 376 * @param offset starting offset in the byte array 377 * @param value value to write 378 */ 379 public static void writeSwappedLong(final byte[] data, final int offset, final long value) { 380 data[offset + 0] = (byte) (value >> 0 & 0xff); 381 data[offset + 1] = (byte) (value >> 8 & 0xff); 382 data[offset + 2] = (byte) (value >> 16 & 0xff); 383 data[offset + 3] = (byte) (value >> 24 & 0xff); 384 data[offset + 4] = (byte) (value >> 32 & 0xff); 385 data[offset + 5] = (byte) (value >> 40 & 0xff); 386 data[offset + 6] = (byte) (value >> 48 & 0xff); 387 data[offset + 7] = (byte) (value >> 56 & 0xff); 388 } 389 390 /** 391 * Writes a "long" value to an OutputStream. The value is 392 * converted to the opposed endian system while writing. 393 * @param output target OutputStream 394 * @param value value to write 395 * @throws IOException in case of an I/O problem 396 */ 397 public static void writeSwappedLong(final OutputStream output, final long value) throws IOException { 398 output.write((byte) (value >> 0 & 0xff)); 399 output.write((byte) (value >> 8 & 0xff)); 400 output.write((byte) (value >> 16 & 0xff)); 401 output.write((byte) (value >> 24 & 0xff)); 402 output.write((byte) (value >> 32 & 0xff)); 403 output.write((byte) (value >> 40 & 0xff)); 404 output.write((byte) (value >> 48 & 0xff)); 405 output.write((byte) (value >> 56 & 0xff)); 406 } 407 408 /** 409 * Writes a "short" value to a byte array at a given offset. The value is 410 * converted to the opposed endian system while writing. 411 * @param data target byte array 412 * @param offset starting offset in the byte array 413 * @param value value to write 414 */ 415 public static void writeSwappedShort(final byte[] data, final int offset, final short value) { 416 data[offset + 0] = (byte)(value >> 0 & 0xff); 417 data[offset + 1] = (byte)(value >> 8 & 0xff); 418 } 419 420 /** 421 * Writes a "short" value to an OutputStream. The value is 422 * converted to the opposed endian system while writing. 423 * @param output target OutputStream 424 * @param value value to write 425 * @throws IOException in case of an I/O problem 426 */ 427 public static void writeSwappedShort(final OutputStream output, final short value) throws IOException { 428 output.write((byte) (value >> 0 & 0xff)); 429 output.write((byte) (value >> 8 & 0xff)); 430 } 431 432 /** 433 * Instances should NOT be constructed in standard programming. 434 */ 435 public EndianUtils() { 436 } 437}