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