content: /*******************************************************************************
   * Copyright (c) 2011, J.W. Janssen
   * 
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *     J.W. Janssen - Cleanup and make API more OO-oriented.
   *******************************************************************************/
  package org.flashtool.binutils.hex.util;
  
  
  import java.nio.*;
  
  
  /**
   * In computing, endianness is the byte (and sometimes bit) ordering used to
   * represent some kind of data. Typical cases are the order in which integer
   * values are stored as bytes in computer memory (relative to a given memory
   * addressing scheme) and the transmission order over a network or other medium.
   * When specifically talking about bytes, endianness is also referred to simply
   * as byte order.
   */
  public class ByteOrderUtils
  {
    // CONSTRUCTORS
  
    private ByteOrderUtils()
    {
      // NO-op
    }
  
    // METHODS
  
    /**
     * Creates a (16-bit) word value with the correct byte order.
     * 
     * @param aMSB
     *          the most significant byte;
     * @param aLSB
     *          the least significant byte.
     * @return the 16-bit combination of both given bytes in the order of
     *         endianness.
     */
    public static int createWord(final ByteOrder aByteOrder, final int aMSB, final int aLSB)
    {
      if (aByteOrder == ByteOrder.BIG_ENDIAN)
      {
        return ((aMSB << 8) & 0xFF00) | (aLSB & 0x00FF);
      }
  
      return ((aLSB << 8) & 0xFF00) | (aMSB & 0x00FF);
    }
  
    /**
     * Creates a (16-bit) word value with the correct byte order.
     * 
     * @param aMSB
     *          the most significant byte;
     * @param aLSB
     *          the least significant byte.
     * @return the 16-bit combination of both given bytes in the order of
     *         endianness.
     */
    public static int createWord(final int aMSB, final int aLSB)
    {
      return createWord(ByteOrder.nativeOrder(), aMSB, aLSB);
    }
  
    /**
     * Convenience method to create a single value using the given byte values in
     * a given byte order.
     * 
     * @param aExpectedByteOrder
     *          the expected byte order;
     * @param aBytes
     *          the bytes to decode into a single value, their order depends!
     * @return the word in the expected byte order.
     */
    public static long decode(final ByteOrder aExpectedByteOrder, final byte... aBytes)
    {
      final int byteCount = aBytes.length;
      final int lastByteIdx = byteCount - 1;
  
      long result = 0L;
  
      if (aExpectedByteOrder == ByteOrder.BIG_ENDIAN)
      {
        for (int i = 0; i < byteCount; i++)
        {
          result <<= 8;
          result |= (aBytes[i] & 0xFF);
        }
      }
      else if (aExpectedByteOrder == ByteOrder.LITTLE_ENDIAN)
      {
        for (int i = lastByteIdx; i >= 0; i--)
        {
          result <<= 8;
          result |= (aBytes[i] & 0xFF);
        }
      }
  
      return result;
    }
  
    /**
     * Switches the order of bytes of the given (16-bit) word value.
     * <p>
     * In effect, this method casts a little-endian value to a big-endian value
     * and the other way around.
     * </p>
     * 
     * @param aValue
     *          the (16-bit) word value to switch the byte order for.
     * @return the given value with the MSB & LSB switched.
     */
    public static int swap16(final int aValue)
    {
      return (((aValue & 0x00ff) << 8) | ((aValue & 0xff00) >> 8));
    }
  
    /**
     * Switches the order of bytes of the given (32-bit) long word value.
     * <p>
     * In effect, this method casts a little-endian value to a big-endian value
     * and the other way around.
     * </p>
     * 
     * @param aValue
     *          the (32-bit) long word value to switch the byte order for.
     * @return the given value with the MSB & LSB switched.
     */
    public static int swap32(final int aValue)
    {
      return ((aValue & 0x000000FF) << 24) | ((aValue & 0x0000FF00) << 8) //
          | ((aValue & 0xFF000000) >>> 24) | ((aValue & 0x00FF0000) >>> 8);
    }
  
  }
  