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