# HG changeset patch # User Michael Starzinger # Date 1301951475 -7200 # Node ID 56844aab0e5c1edc64dce3aa211815e87dc9546f # Parent b375045a6197f79810b2b34d128cef44d5ee6c90 Fixed parsing of encoded float and double values. * dex/EncodedValue.java (parse): Implemented for float and double values. * (readS64, readU64): Fixed casting bug. * (readL64): Added new helper method. * dex/EncodedValueTest.java: Fixed broken test, never trust the implementation. * rewriter/FieldConstantTest.java: New regression test for above changes. diff -r b375045a6197 -r 56844aab0e5c src/main/java/org/icedrobot/daneel/dex/EncodedValue.java --- a/src/main/java/org/icedrobot/daneel/dex/EncodedValue.java Mon Apr 04 18:59:04 2011 +0200 +++ b/src/main/java/org/icedrobot/daneel/dex/EncodedValue.java Mon Apr 04 23:11:15 2011 +0200 @@ -96,6 +96,12 @@ case VALUE_LONG: assertValueArg(arg, 7); return Long.valueOf(readS64(buffer, arg)); + case VALUE_FLOAT: + assertValueArg(arg, 3); + return Float.intBitsToFloat((int) readL64(buffer, arg, 32)); + case VALUE_DOUBLE: + assertValueArg(arg, 7); + return Double.longBitsToDouble(readL64(buffer, arg, 64)); case VALUE_STRING: assertValueArg(arg, 3); return dex.getString((int) readU64(buffer, arg)); @@ -181,8 +187,8 @@ private static long readS64(ByteBuffer buffer, int size) { long result = 0; for (int i = 0; i < size; i++) - result |= (buffer.get() & 0xff) << (i * 8); - result |= buffer.get() << (size * 8); + result |= ((long) buffer.get() & 0xff) << (i * 8); + result |= ((long) buffer.get()) << (size * 8); return result; } @@ -196,7 +202,22 @@ private static long readU64(ByteBuffer buffer, int size) { long result = 0; for (int i = 0; i <= size; i++) - result |= (buffer.get() & 0xff) << (i * 8); + result |= ((long) buffer.get() & 0xff) << (i * 8); + return result; + } + + /** + * Helper method decoding a left-aligned (zero-extended to the right) + * {@code value} array. Used to encode floating point values. + * + * @param buffer The buffer positioned at the {@code value} array. + * @param size The number of bytes in the array minus 1. + * @param bits The expected number of bits in the decoded value. + * @return The decoded value. + */ + private static long readL64(ByteBuffer buffer, int size, int bits) { + long result = readU64(buffer, size); + result <<= (bits - (size + 1) * 8); return result; } diff -r b375045a6197 -r 56844aab0e5c src/test/java/org/icedrobot/daneel/dex/EncodedValueTest.java --- a/src/test/java/org/icedrobot/daneel/dex/EncodedValueTest.java Mon Apr 04 18:59:04 2011 +0200 +++ b/src/test/java/org/icedrobot/daneel/dex/EncodedValueTest.java Mon Apr 04 23:11:15 2011 +0200 @@ -71,8 +71,8 @@ assertEquals(Short.valueOf((short) 511), parse(SEQ_SHORT2)); assertEquals(Short.valueOf((short) 256), parse(SEQ_SHORT3)); assertEquals(Short.valueOf(Short.MAX_VALUE), parse(SEQ_SHORT4)); - assertEquals(Integer.valueOf((byte) -5), parse(SEQ_INT)); - assertEquals(Long.valueOf((byte) -1), parse(SEQ_LONG)); + assertEquals(Integer.valueOf(-5), parse(SEQ_INT)); + assertEquals(Long.valueOf(-129l), parse(SEQ_LONG)); assertEquals(Character.valueOf((char) 255), parse(SEQ_CHAR1)); assertEquals(Character.valueOf((char) 511), parse(SEQ_CHAR2)); assertEquals(Character.valueOf((char) 256), parse(SEQ_CHAR3)); diff -r b375045a6197 -r 56844aab0e5c src/test/java/org/icedrobot/daneel/rewriter/FieldConstantTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/java/org/icedrobot/daneel/rewriter/FieldConstantTest.java Mon Apr 04 23:11:15 2011 +0200 @@ -0,0 +1,87 @@ +/* + * Daneel - Dalvik to Java bytecode compiler + * Copyright (C) 2011 IcedRobot team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file is subject to the "Classpath" exception: + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under terms + * of your choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. An + * independent module is a module which is not derived from or based on + * this library. If you modify this library, you may extend this exception + * to your version of the library, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ + +package org.icedrobot.daneel.rewriter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.lang.reflect.Field; + +import org.icedrobot.daneel.DexifyingRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(DexifyingRunner.class) +public class FieldConstantTest { + + @Test + public void testConstLong() throws Exception { + Field f = DEXCode.class.getField("CONST_LONG"); + assertSame(long.class, f.getType()); + assertEquals(Long.MAX_VALUE, f.getLong(null)); + } + + @Test + public void testConstFloat1() throws Exception { + Field f = DEXCode.class.getField("CONST_FLOAT1"); + assertSame(float.class, f.getType()); + assertEquals(0.5f, f.getFloat(null), 0); + } + + @Test + public void testConstFloat2() throws Exception { + Field f = DEXCode.class.getField("CONST_FLOAT2"); + assertSame(float.class, f.getType()); + assertEquals(0.23f, f.getFloat(null), 0); + } + + @Test + public void testConstDouble() throws Exception { + Field f = DEXCode.class.getField("CONST_DOUBLE"); + assertSame(double.class, f.getType()); + assertEquals(0.42, f.getDouble(null), 0); + } + + // Keep this class named "DEXCode" to push it through Daneel. + public static class DEXCode { + public static final long CONST_LONG = Long.MAX_VALUE; + public static final float CONST_FLOAT1 = 0.5f; + public static final float CONST_FLOAT2 = 0.23f; + public static final double CONST_DOUBLE = 0.42; + }; +}