diff options
Diffstat (limited to 'plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNumberFormat.java')
-rw-r--r-- | plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNumberFormat.java | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNumberFormat.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNumberFormat.java new file mode 100644 index 000000000..d0ebef67c --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNumberFormat.java @@ -0,0 +1,230 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. + * 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.debug.ui.model; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; + +public class TCFNumberFormat { + + public static String isValidHexNumber(String s) { + int l = s.length(); + if (l == 0) return "Need at least one digit"; + for (int i = 0; i < l; i++) { + char ch = s.charAt(i); + if (ch >= '0' && ch <= '9') continue; + if (ch >= 'A' && ch <= 'F') continue; + if (ch >= 'a' && ch <= 'f') continue; + return "Hex digit expected"; + } + return null; + } + + public static String isValidDecNumber(boolean fp, String s) { + int i = 0; + int l = s.length(); + if (l == 0) return "Need at least one digit"; + char ch = s.charAt(i++); + if (ch == '-' || ch == '+') { + if (i >= l) return "Need at least one digit"; + ch = s.charAt(i++); + } + if (fp) { + String n = s.substring(i - 1); + if (n.equals("NaN")) return null; + if (n.equals("Infinity")) return null; + } + while (ch >= '0' && ch <= '9') { + if (i >= l) return null; + ch = s.charAt(i++); + } + if (fp) { + if (ch == '.') { + if (i >= l) return null; + ch = s.charAt(i++); + while (ch >= '0' && ch <= '9') { + if (i >= l) return null; + ch = s.charAt(i++); + } + } + if (ch == 'e' || ch == 'E') { + if (i >= l) return "Invalid exponent: need at least one digit"; + ch = s.charAt(i++); + if (ch == '-' || ch == '+') { + if (i >= l) return "Invalid exponent: need at least one digit"; + ch = s.charAt(i++); + } + while (ch >= '0' && ch <= '9') { + if (i >= l) return null; + ch = s.charAt(i++); + } + return "Invalid exponent: decimal digit expected"; + } + } + return "Decimal digit expected"; + } + + public static byte[] toByteArray(String s, int radix, boolean fp, int size, boolean signed, boolean big_endian) throws Exception { + byte[] bf = null; + if (!fp) { + bf = new BigInteger(s, radix).toByteArray(); + } + else if (size == 4) { + int n = Float.floatToIntBits(Float.parseFloat(s)); + bf = new byte[size]; + for (int i = 0; i < size; i++) { + bf[i] = (byte)((n >> ((size - 1 - i) * 8)) & 0xff); + } + } + else if (size == 8) { + long n = Double.doubleToLongBits(Double.parseDouble(s)); + bf = new byte[size]; + for (int i = 0; i < size; i++) { + bf[i] = (byte)((n >> ((size - 1 - i) * 8)) & 0xff); + } + } + else { + throw new Exception("Unsupported floating point format"); + } + byte[] rs = new byte[size]; + if (signed && rs.length > bf.length && (bf[0] & 0x80) != 0) { + // Sign extension + for (int i = 0; i < rs.length; i++) rs[i] = (byte)0xff; + } + for (int i = 0; i < bf.length; i++) { + // i == 0 -> least significant byte + byte b = bf[bf.length - i - 1]; + int j = big_endian ? rs.length - i - 1 : i; + if (j >= 0 && j < rs.length) rs[j] = b; + } + return rs; + } + + public static String toFPString(byte[] data, int offs, int size, boolean big_endian) { + assert offs + size <= data.length; + byte[] arr = new byte[size]; + if (big_endian) { + System.arraycopy(data, offs, arr, 0, size); + } + else { + for (int i = 0; i < size; i++) { + arr[arr.length - i - 1] = data[offs + i]; + } + } + + boolean neg = (arr[0] & 0x80) != 0; + arr[0] &= 0x7f; + + int precision = 0; + int exponent = 0; + boolean nan = false; + switch (size) { + case 2: + precision = 3; + exponent = (arr[0] & 0x7c) >> 2; + nan = exponent == 0x1f; + arr[0] &= 0x03; + if (exponent == 0) exponent = 1; + else arr[0] |= 0x04; + exponent -= 10; // Significand + exponent -= 15; // Exponent bias + break; + case 4: + precision = 7; + exponent = ((arr[0] & 0x7f) << 1) | ((arr[1] & 0x80) >> 7); + nan = exponent == 0xff; + arr[0] = 0; + arr[1] &= 0x7f; + if (exponent == 0) exponent = 1; + else arr[1] |= 0x80; + exponent -= 23; // Significand + exponent -= 127; // Exponent bias + break; + case 8: + precision = 16; + exponent = ((arr[0] & 0x7f) << 4) | ((arr[1] & 0xf0) >> 4); + nan = exponent == 0x7ff; + arr[0] = 0; + arr[1] &= 0x0f; + if (exponent == 0) exponent = 1; + else arr[1] |= 0x10; + exponent -= 52; // Significand + exponent -= 1023; // Exponent bias + break; + case 10: + case 16: + precision = 34; + exponent = ((arr[0] & 0x7f) << 8) | (arr[1] & 0xff); + nan = exponent == 0x7fff; + arr[0] = arr[1] = 0; + if (size == 10) { + exponent -= 63; // Significand + } + else { + if (exponent == 0) exponent = 1; + else arr[1] = 1; + exponent -= 112; // Significand + } + exponent -= 16383; // Exponent bias + break; + default: + return null; + } + if (nan) { + for (int i = 0; i < arr.length; i++) { + int n = arr[i] & 0xff; + if (size == 10 && i == 2) n &= 0x7f; + if (n != 0) return neg ? "-NaN" : "+NaN"; + } + return neg ? "-Infinity" : "+Infinity"; + } + BigDecimal a = new BigDecimal(new BigInteger(arr), 0); + if (a.signum() != 0 && exponent != 0) { + BigDecimal p = new BigDecimal(BigInteger.valueOf(2), 0); + if (exponent > 0) { + a = a.multiply(p.pow(exponent)); + } + else { + BigDecimal b = p.pow(-exponent); + a = a.divide(b, b.precision(), RoundingMode.HALF_DOWN); + } + if (precision != 0 && a.precision() > precision) { + int scale = a.scale() - a.precision() + precision; + a = a.setScale(scale, RoundingMode.HALF_DOWN); + } + } + String s = a.toString(); + if (neg) s = "-" + s; + return s; + } + + public static BigInteger toBigInteger(byte[] data, int offs, int size, boolean big_endian, boolean sign_extension) { + assert offs + size <= data.length; + byte[] temp = null; + if (sign_extension) { + temp = new byte[size]; + } + else { + temp = new byte[size + 1]; + temp[0] = 0; // Extra byte to avoid sign extension by BigInteger + } + if (big_endian) { + System.arraycopy(data, offs, temp, sign_extension ? 0 : 1, size); + } + else { + for (int i = 0; i < size; i++) { + temp[temp.length - i - 1] = data[i + offs]; + } + } + return new BigInteger(temp); + } +} |