Coverage Report - org.apache.commons.io.EndianUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
EndianUtils
100%
86/86
100%
4/4
1.097
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.io;
 18  
 
 19  
 import static org.apache.commons.io.IOUtils.EOF;
 20  
 
 21  
 import java.io.EOFException;
 22  
 import java.io.IOException;
 23  
 import java.io.InputStream;
 24  
 import java.io.OutputStream;
 25  
 
 26  
 /**
 27  
  * Utility code for dealing with different endian systems.
 28  
  * <p>
 29  
  * Different computer architectures adopt different conventions for
 30  
  * byte ordering. In so-called "Little Endian" architectures (eg Intel),
 31  
  * the low-order byte is stored in memory at the lowest address, and
 32  
  * subsequent bytes at higher addresses. For "Big Endian" architectures
 33  
  * (eg Motorola), the situation is reversed.
 34  
  * This class helps you solve this incompatibility.
 35  
  * <p>
 36  
  * Origin of code: Excalibur
 37  
  *
 38  
  * @version $Id: EndianUtils.java 1686450 2015-06-19 16:43:48Z krosenvold $
 39  
  * @see org.apache.commons.io.input.SwappedDataInputStream
 40  
  */
 41  
 public class EndianUtils {
 42  
 
 43  
     /**
 44  
      * Instances should NOT be constructed in standard programming.
 45  
      */
 46  
     public EndianUtils() {
 47  1
         super();
 48  1
     }
 49  
 
 50  
     // ========================================== Swapping routines
 51  
 
 52  
     /**
 53  
      * Converts a "short" value between endian systems.
 54  
      * @param value value to convert
 55  
      * @return the converted value
 56  
      */
 57  
     public static short swapShort(final short value) {
 58  6
         return (short) ( ( ( ( value >> 0 ) & 0xff ) << 8 ) +
 59  
             ( ( ( value >> 8 ) & 0xff ) << 0 ) );
 60  
     }
 61  
 
 62  
     /**
 63  
      * Converts a "int" value between endian systems.
 64  
      * @param value value to convert
 65  
      * @return the converted value
 66  
      */
 67  
     public static int swapInteger(final int value) {
 68  13
         return
 69  
             ( ( ( value >> 0 ) & 0xff ) << 24 ) +
 70  
             ( ( ( value >> 8 ) & 0xff ) << 16 ) +
 71  
             ( ( ( value >> 16 ) & 0xff ) << 8 ) +
 72  
             ( ( ( value >> 24 ) & 0xff ) << 0 );
 73  
     }
 74  
 
 75  
     /**
 76  
      * Converts a "long" value between endian systems.
 77  
      * @param value value to convert
 78  
      * @return the converted value
 79  
      */
 80  
     public static long swapLong(final long value) {
 81  10
         return
 82  
             ( ( ( value >> 0 ) & 0xff ) << 56 ) +
 83  
             ( ( ( value >> 8 ) & 0xff ) << 48 ) +
 84  
             ( ( ( value >> 16 ) & 0xff ) << 40 ) +
 85  
             ( ( ( value >> 24 ) & 0xff ) << 32 ) +
 86  
             ( ( ( value >> 32 ) & 0xff ) << 24 ) +
 87  
             ( ( ( value >> 40 ) & 0xff ) << 16 ) +
 88  
             ( ( ( value >> 48 ) & 0xff ) << 8 ) +
 89  
             ( ( ( value >> 56 ) & 0xff ) << 0 );
 90  
     }
 91  
 
 92  
     /**
 93  
      * Converts a "float" value between endian systems.
 94  
      * @param value value to convert
 95  
      * @return the converted value
 96  
      */
 97  
     public static float swapFloat(final float value) {
 98  4
         return Float.intBitsToFloat( swapInteger( Float.floatToIntBits( value ) ) );
 99  
     }
 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  4
         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  1
         data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff );
 121  1
         data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff );
 122  1
     }
 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  1
         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  1
         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  2
         data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff );
 158  2
         data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff );
 159  2
         data[ offset + 2 ] = (byte)( ( value >> 16 ) & 0xff );
 160  2
         data[ offset + 3 ] = (byte)( ( value >> 24 ) & 0xff );
 161  2
     }
 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  34
         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  2
         final long low = ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
 187  
                      ( ( data[ offset + 1 ] & 0xff ) << 8 ) +
 188  
                      ( ( data[ offset + 2 ] & 0xff ) << 16 ) );
 189  
 
 190  2
         final long high = data[ offset + 3 ] & 0xff;
 191  
 
 192  2
         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  12
         data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff );
 204  12
         data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff );
 205  12
         data[ offset + 2 ] = (byte)( ( value >> 16 ) & 0xff );
 206  12
         data[ offset + 3 ] = (byte)( ( value >> 24 ) & 0xff );
 207  12
         data[ offset + 4 ] = (byte)( ( value >> 32 ) & 0xff );
 208  12
         data[ offset + 5 ] = (byte)( ( value >> 40 ) & 0xff );
 209  12
         data[ offset + 6 ] = (byte)( ( value >> 48 ) & 0xff );
 210  12
         data[ offset + 7 ] = (byte)( ( value >> 56 ) & 0xff );
 211  12
     }
 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  16
         final long low = readSwappedInteger(data, offset);
 222  16
         final long high = readSwappedInteger(data, offset + 4);
 223  16
         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  1
         writeSwappedInteger( data, offset, Float.floatToIntBits( value ) );
 235  1
     }
 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  1
         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  6
         writeSwappedLong( data, offset, Double.doubleToLongBits( value ) );
 257  6
     }
 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  6
         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  1
         output.write( (byte)( ( value >> 0 ) & 0xff ) );
 281  1
         output.write( (byte)( ( value >> 8 ) & 0xff ) );
 282  1
     }
 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  3
         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  2
         final int value1 = read( input );
 309  2
         final int value2 = read( input );
 310  
 
 311  2
         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  2
         output.write( (byte)( ( value >> 0 ) & 0xff ) );
 326  2
         output.write( (byte)( ( value >> 8 ) & 0xff ) );
 327  2
         output.write( (byte)( ( value >> 16 ) & 0xff ) );
 328  2
         output.write( (byte)( ( value >> 24 ) & 0xff ) );
 329  2
     }
 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  5
         final int value1 = read( input );
 342  5
         final int value2 = read( input );
 343  5
         final int value3 = read( input );
 344  5
         final int value4 = read( input );
 345  
 
 346  5
         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  2
         final int value1 = read( input );
 363  2
         final int value2 = read( input );
 364  2
         final int value3 = read( input );
 365  2
         final int value4 = read( input );
 366  
 
 367  2
         final long low = ( ( ( value1 & 0xff ) << 0 ) +
 368  
                      ( ( value2 & 0xff ) << 8 ) +
 369  
                      ( ( value3 & 0xff ) << 16 ) );
 370  
 
 371  2
         final long high = value4 & 0xff;
 372  
 
 373  2
         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  2
         output.write( (byte)( ( value >> 0 ) & 0xff ) );
 387  2
         output.write( (byte)( ( value >> 8 ) & 0xff ) );
 388  2
         output.write( (byte)( ( value >> 16 ) & 0xff ) );
 389  2
         output.write( (byte)( ( value >> 24 ) & 0xff ) );
 390  2
         output.write( (byte)( ( value >> 32 ) & 0xff ) );
 391  2
         output.write( (byte)( ( value >> 40 ) & 0xff ) );
 392  2
         output.write( (byte)( ( value >> 48 ) & 0xff ) );
 393  2
         output.write( (byte)( ( value >> 56 ) & 0xff ) );
 394  2
     }
 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  5
         final byte[] bytes = new byte[8];
 407  37
         for ( int i=0; i<8; i++ ) {
 408  33
             bytes[i] = (byte) read( input );
 409  
         }
 410  4
         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  1
         writeSwappedInteger( output, Float.floatToIntBits( value ) );
 424  1
     }
 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  2
         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  1
         writeSwappedLong( output, Double.doubleToLongBits( value ) );
 450  1
     }
 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  3
         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  71
         final int value = input.read();
 475  
 
 476  71
         if( EOF == value ) {
 477  1
             throw new EOFException( "Unexpected EOF reached" );
 478  
         }
 479  
 
 480  70
         return value;
 481  
     }
 482  
 }