001: /***
002: * Retrotranslator: a Java bytecode transformer that translates Java classes
003: * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
004: *
005: * Copyright (c) 2005 - 2008 Taras Puchko
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * 3. Neither the name of the copyright holders nor the names of its
017: * contributors may be used to endorse or promote products derived from
018: * this software without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
022: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
023: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
024: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
025: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
026: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
027: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
028: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
029: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
030: * THE POSSIBILITY OF SUCH DAMAGE.
031: */package net.sf.retrotranslator.runtime.format;
032:
033: /**
034: * @author Taras Puchko
035: */
036: class HexadecimalExponentialConversion extends NumericConversion {
037:
038: public void format(FormatContext context) {
039: context.checkFlags();
040: context.assertNoFlag('(');
041: context.assertNoFlag(',');
042: Object argument = context.getArgument();
043: if (argument instanceof Double) {
044: printf(context, (Double) argument);
045: } else if (argument instanceof Float) {
046: printf(context, (Float) argument);
047: } else if (argument == null) {
048: context.writeRestricted(String.valueOf(argument));
049: } else {
050: throw context.getConversionException();
051: }
052: }
053:
054: private static void printf(FormatContext context, double argument) {
055: if (!printSpecialNumber(context, argument)) {
056: context.writePadded(toHex(context, argument));
057: }
058: }
059:
060: private static String toHex(FormatContext context, double argument) {
061: StringBuilder builder = new StringBuilder();
062: long bits = Double.doubleToLongBits(argument);
063: if (bits < 0) {
064: builder.append('-');
065: } else if (context.isFlag('+')) {
066: builder.append('+');
067: }
068: int exponent = getExponent(bits);
069: int precision = context.getPrecision();
070: if (argument != 0 && precision >= 0 && precision <= 12) {
071: if (exponent == 0) {
072: bits = Double.doubleToLongBits(argument * (1L << 52));
073: exponent = getExponent(bits) - 52;
074: }
075: double value = Double
076: .longBitsToDouble(getSignificand(bits));
077: double factor = 1L << (52 - 4 * Math.max(precision, 1));
078: bits = Double.doubleToLongBits(value / factor * factor);
079: exponent += getExponent(bits) - 1;
080: }
081: builder.append(exponent == 0 ? "0x0." : "0x1.");
082: appendSignificand(builder, bits, precision);
083: return builder.append('p').append(
084: argument == 0 ? 0 : exponent == 0 ? -1022
085: : exponent - 1023).toString();
086: }
087:
088: private static int getExponent(long bits) {
089: return (int) (bits << 1 >>> 53);
090: }
091:
092: private static long getSignificand(long bits) {
093: return bits & ((1L << 52) - 1) | 1L << 52;
094: }
095:
096: private static void appendSignificand(StringBuilder builder,
097: long bits, int precision) {
098: String s = Long.toHexString(getSignificand(bits));
099: int endIndex = s.length();
100: while (endIndex > 2 && s.charAt(endIndex - 1) == '0') {
101: endIndex--;
102: }
103: builder.append(s.substring(1, endIndex));
104: for (int i = endIndex; i <= precision; i++) {
105: builder.append('0');
106: }
107: }
108:
109: }
|