/*
 * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.debugger;

/** Common routines for data conversion */

public class DebuggerUtilities {
  protected long addressSize;
  protected boolean isBigEndian;

  public DebuggerUtilities(long addressSize, boolean isBigEndian) {
    this.addressSize = addressSize;
    this.isBigEndian = isBigEndian;
  }

  public String addressValueToString(long address) {
    StringBuffer buf = new StringBuffer();
    buf.append("0x");
    String val;
    // Make negative addresses have the correct size
    if (addressSize == 8) {
      val = Long.toHexString(address);
    } else {
      val = Integer.toHexString((int) address);
    }
    for (int i = 0; i < ((2 * addressSize) - val.length()); i++) {
      buf.append('0');
    }
    buf.append(val);
    return buf.toString();
  }

  public void checkAlignment(long address, long alignment) {
    if (address % alignment != 0) {
      throw new UnalignedAddressException("Trying to read at address: " +
                                           addressValueToString(address) +
                                           " with alignment: " + alignment,
                                          address);
    }
  }

  public long scanAddress(String addrStr) throws NumberFormatException {
    String s = addrStr.trim();
    if (!s.startsWith("0x")) {
      throw new NumberFormatException(addrStr);
    }
    long l = 0;
    for (int i = 2; i < s.length(); ++i) {
      int val = charToNibble(s.charAt(i));
      l <<= 4;
      l |= val;
    }
    return l;
  }

  public int charToNibble(char ascii) throws NumberFormatException {
    if (ascii >= '0' && ascii <= '9') {
      return ascii - '0';
    } else if (ascii >= 'A' && ascii <= 'F') {
      return 10 + ascii - 'A';
    } else if (ascii >= 'a' && ascii <= 'f') {
      return 10 + ascii - 'a';
    }
    throw new NumberFormatException(new Character(ascii).toString());
  }

  public boolean dataToJBoolean(byte[] data, long jbooleanSize) {
    checkDataContents(data, jbooleanSize);

    return (data[0] != 0);
  }

  public byte dataToJByte(byte[] data, long jbyteSize) {
    checkDataContents(data, jbyteSize);

    return data[0];
  }

  public char dataToJChar(byte[] data, long jcharSize) {
    checkDataContents(data, jcharSize);

    if (!isBigEndian) {
      byteSwap(data);
    }

    return (char) (((data[0] & 0xFF) << 8) | (data[1] & 0xFF));
  }

  public double dataToJDouble(byte[] data, long jdoubleSize) {
    long longBits = dataToJLong(data, jdoubleSize);

    return Double.longBitsToDouble(longBits);
  }

  public float dataToJFloat(byte[] data, long jfloatSize) {
    int intBits = dataToJInt(data, jfloatSize);

    return Float.intBitsToFloat(intBits);
  }

  public int dataToJInt(byte[] data, long jintSize) {
    checkDataContents(data, jintSize);

    if (!isBigEndian) {
      byteSwap(data);
    }

    return (((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16) | ((data[2] & 0xFF) << 8) | (data[3] & 0xFF));
  }

  public long dataToJLong(byte[] data, long jlongSize) {
    checkDataContents(data, jlongSize);

    if (!isBigEndian) {
      byteSwap(data);
    }

    return rawDataToJLong(data);
  }

  public short dataToJShort(byte[] data, long jshortSize) {
    checkDataContents(data, jshortSize);

    if (!isBigEndian) {
      byteSwap(data);
    }

    return (short) (((data[0] & 0xFF) << 8) | (data[1] & 0xFF));
  }

  public long dataToCInteger(byte[] data, boolean isUnsigned) {
    checkDataContents(data, data.length);

    if (!isBigEndian) {
      byteSwap(data);
    }

    // By default we'll be zero-extending.
    // Therefore we need to check to see whether isUnsigned is false and
    // also the high bit of the data is set.
    if ((data.length < 8) &&
        (isUnsigned == false) &&
        ((data[0] & 0x80) != 0)) {
      // Must sign-extend and right-align the data
      byte[] newData = new byte[8];
      for (int i = 0; i < 8; ++i) {
        if ((7 - i) < data.length) {
          newData[i] = data[i + data.length - 8];
        } else {
          newData[i] = (byte) 0xFF;
        }
      }
      data = newData;
    }

    // Now just do the usual loop
    return rawDataToJLong(data);
  }

  public long dataToAddressValue(byte[] data) {
    checkDataContents(data, addressSize);

    if (!isBigEndian) {
      byteSwap(data);
    }

    return rawDataToJLong(data);
  }

  public byte[] jbooleanToData(boolean value) {
    byte[] res = new byte[1];
    res[0] = (byte) (value ? 1 : 0);
    return res;
  }

  public byte[] jbyteToData(byte value) {
    byte[] res = new byte[1];
    res[0] = value;
    return res;
  }

  public byte[] jcharToData(char value) {
    byte[] res = new byte[2];
    res[0] = (byte) ((value >> 8) & 0xFF);
    res[1] = (byte) value;
    if (!isBigEndian) {
      byteSwap(res);
    }
    return res;
  }

  public byte[] jdoubleToData(double value) {
    return jlongToData(Double.doubleToLongBits(value));
  }

  public byte[] jfloatToData(float value) {
    return jintToData(Float.floatToIntBits(value));
  }

  public byte[] jintToData(int value) {
    byte[] res = new byte[4];
    for (int i = 0; i < 4; i++) {
      res[3 - i] = (byte) (value & 0xFF);
      value >>>= 8;
    }
    if (!isBigEndian) {
      byteSwap(res);
    }
    return res;
  }

  public byte[] jlongToData(long value) {
    byte[] res = new byte[8];
    for (int i = 0; i < 8; i++) {
      res[7 - i] = (byte) (value & 0xFF);
      value >>>= 8;
    }
    if (!isBigEndian) {
      byteSwap(res);
    }
    return res;
  }

  public byte[] jshortToData(short value) {
    byte[] res = new byte[2];
    res[0] = (byte) ((value >> 8) & 0xFF);
    res[1] = (byte) value;
    if (!isBigEndian) {
      byteSwap(res);
    }
    return res;
  }

  public byte[] cIntegerToData(long longNumBytes, long value) {
    int numBytes = (int) longNumBytes;
    byte[] res = new byte[numBytes];
    for (int i = 0; i < numBytes; i++) {
      res[numBytes - i - 1] = (byte) (value & 0xFF);
      value >>>= 8;
    }
    if (!isBigEndian) {
      byteSwap(res);
    }
    return res;
  }

  //--------------------------------------------------------------------------------
  // Internals only below this point
  //

  private void checkDataContents(byte[] data, long len) {
    if (data.length != (int) len) {
      throw new InternalError("Bug in Win32Debugger");
    }
  }

  private void byteSwap(byte[] data) {
    for (int i = 0; i < (data.length / 2); ++i) {
      int altIndex = data.length - i - 1;
      byte t = data[altIndex];
      data[altIndex] = data[i];
      data[i] = t;
    }
  }

  private long rawDataToJLong(byte[] data) {
    long addr = 0;
    for (int i = 0; i < data.length; ++i) {
      addr <<= 8;
      addr |= data[i] & 0xFF;
    }

    return addr;
  }
}
