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