/* * [The "BSD licence"] * Copyright (c) 2010 Ben Gruver (JesusFreke) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jf.smali; public class literalTools { public static byte parseByte(String byteLiteral) throws NumberFormatException { if (byteLiteral == null) { throw new NumberFormatException("string is null"); } if (byteLiteral.length() == 0) { throw new NumberFormatException("string is blank"); } char[] byteChars; if (byteLiteral.toUpperCase().endsWith("T")) { byteChars = byteLiteral.substring(0, byteLiteral.length()-1).toCharArray(); } else { byteChars = byteLiteral.toCharArray(); } int position = 0; int radix = 10; boolean negative = false; if (byteChars[position] == '-') { position++; negative = true; } if (byteChars[position] == '0') { position++; if (position == byteChars.length) { return 0; } else if (byteChars[position] == 'x' || byteChars[position] == 'X') { radix = 16; position++; } else if (Character.digit(byteChars[position], 8) >= 0) { radix = 8; } } byte result = 0; byte shiftedResult; int digit; byte maxValue = (byte)(Byte.MAX_VALUE / (radix / 2)); while (position < byteChars.length) { digit = Character.digit(byteChars[position], radix); if (digit < 0) { throw new NumberFormatException("The string contains invalid an digit - '" + byteChars[position] + "'"); } shiftedResult = (byte)(result * radix); if (result > maxValue) { throw new NumberFormatException(byteLiteral + " cannot fit into a byte"); } if (shiftedResult < 0 && shiftedResult >= -digit) { throw new NumberFormatException(byteLiteral + " cannot fit into a byte"); } result = (byte)(shiftedResult + digit); position++; } if (negative) { //allow -0x80, which is = 0x80 if (result == Byte.MIN_VALUE) { return result; } else if (result < 0) { throw new NumberFormatException(byteLiteral + " cannot fit into a byte"); } return (byte)(result * -1); } else { return result; } } public static short parseShort(String shortLiteral) throws NumberFormatException { if (shortLiteral == null) { throw new NumberFormatException("string is null"); } if (shortLiteral.length() == 0) { throw new NumberFormatException("string is blank"); } char[] shortChars; if (shortLiteral.toUpperCase().endsWith("S")) { shortChars = shortLiteral.substring(0, shortLiteral.length()-1).toCharArray(); } else { shortChars = shortLiteral.toCharArray(); } int position = 0; int radix = 10; boolean negative = false; if (shortChars[position] == '-') { position++; negative = true; } if (shortChars[position] == '0') { position++; if (position == shortChars.length) { return 0; } else if (shortChars[position] == 'x' || shortChars[position] == 'X') { radix = 16; position++; } else if (Character.digit(shortChars[position], 8) >= 0) { radix = 8; } } short result = 0; short shiftedResult; int digit; short maxValue = (short)(Short.MAX_VALUE / (radix / 2)); while (position < shortChars.length) { digit = Character.digit(shortChars[position], radix); if (digit < 0) { throw new NumberFormatException("The string contains invalid an digit - '" + shortChars[position] + "'"); } shiftedResult = (short)(result * radix); if (result > maxValue) { throw new NumberFormatException(shortLiteral + " cannot fit into a short"); } if (shiftedResult < 0 && shiftedResult >= -digit) { throw new NumberFormatException(shortLiteral + " cannot fit into a short"); } result = (short)(shiftedResult + digit); position++; } if (negative) { //allow -0x8000, which is = 0x8000 if (result == Short.MIN_VALUE) { return result; } else if (result < 0) { throw new NumberFormatException(shortLiteral + " cannot fit into a short"); } return (short)(result * -1); } else { return result; } } public static int parseInt(String intLiteral) throws NumberFormatException { if (intLiteral == null) { throw new NumberFormatException("string is null"); } if (intLiteral.length() == 0) { throw new NumberFormatException("string is blank"); } char[] intChars = intLiteral.toCharArray(); int position = 0; int radix = 10; boolean negative = false; if (intChars[position] == '-') { position++; negative = true; } if (intChars[position] == '0') { position++; if (position == intChars.length) { return 0; } else if (intChars[position] == 'x' || intChars[position] == 'X') { radix = 16; position++; } else if (Character.digit(intChars[position], 8) >= 0) { radix = 8; } } int result = 0; int shiftedResult; int digit; int maxValue = Integer.MAX_VALUE / (radix / 2); while (position < intChars.length) { digit = Character.digit(intChars[position], radix); if (digit < 0) { throw new NumberFormatException("The string contains an invalid digit - '" + intChars[position] + "'"); } shiftedResult = result * radix; if (result > maxValue) { throw new NumberFormatException(intLiteral + " cannot fit into an int"); } if (shiftedResult < 0 && shiftedResult >= -digit) { throw new NumberFormatException(intLiteral + " cannot fit into an int"); } result = shiftedResult + digit; position++; } if (negative) { //allow -0x80000000, which is = 0x80000000 if (result == Integer.MIN_VALUE) { return result; } else if (result < 0) { throw new NumberFormatException(intLiteral + " cannot fit into an int"); } return result * -1; } else { return result; } } public static long parseLong(String longLiteral) throws NumberFormatException { if (longLiteral == null) { throw new NumberFormatException("string is null"); } if (longLiteral.length() == 0) { throw new NumberFormatException("string is blank"); } char[] longChars; if (longLiteral.toUpperCase().endsWith("L")) { longChars = longLiteral.substring(0, longLiteral.length()-1).toCharArray(); } else { longChars = longLiteral.toCharArray(); } int position = 0; int radix = 10; boolean negative = false; if (longChars[position] == '-') { position++; negative = true; } if (longChars[position] == '0') { position++; if (position == longChars.length) { return 0; } else if (longChars[position] == 'x' || longChars[position] == 'X') { radix = 16; position++; } else if (Character.digit(longChars[position], 8) >= 0) { radix = 8; } } long result = 0; long shiftedResult; int digit; long maxValue = Long.MAX_VALUE / (radix / 2); while (position < longChars.length) { digit = Character.digit(longChars[position], radix); if (digit < 0) { throw new NumberFormatException("The string contains an invalid digit - '" + longChars[position] + "'"); } shiftedResult = result * radix; if (result > maxValue) { throw new NumberFormatException(longLiteral + " cannot fit into a long"); } if (shiftedResult < 0 && shiftedResult >= -digit) { throw new NumberFormatException(longLiteral + " cannot fit into a long"); } result = shiftedResult + digit; position++; } if (negative) { //allow -0x8000000000000000, which is = 0x8000000000000000 if (result == Long.MIN_VALUE) { return result; } else if (result < 0) { throw new NumberFormatException(longLiteral + " cannot fit into a long"); } return result * -1; } else { return result; } } public static byte[] longToBytes(long value) { byte[] bytes = new byte[8]; for (int i=0; value != 0; i++) { bytes[i] = (byte)value; value = value >>> 8; } return bytes; } public static byte[] intToBytes(int value) { byte[] bytes = new byte[4]; for (int i=0; value != 0; i++) { bytes[i] = (byte)value; value = value >>> 8; } return bytes; } public static byte[] shortToBytes(short value) { byte[] bytes = new byte[2]; bytes[0] = (byte)value; bytes[1] = (byte)(value >>> 8); return bytes; } public static byte[] floatToBytes(float value) { return intToBytes(Float.floatToRawIntBits(value)); } public static byte[] doubleToBytes(double value) { return longToBytes(Double.doubleToRawLongBits(value)); } public static byte[] charToBytes(char value) { return shortToBytes((short)value); } public static byte[] boolToBytes(boolean value) { if (value) { return new byte[] { 0x01 }; } else { return new byte[] { 0x00 }; } } public static void checkInt(long value) { if (value > 0xFFFFFFFF || value < -0x80000000) { throw new NumberFormatException(Long.toString(value) + " cannot fit into an int"); } } public static void checkShort(long value) { if (value > 0xFFFF | value < -0x8000) { throw new NumberFormatException(Long.toString(value) + " cannot fit into a short"); } } public static void checkByte(long value) { if (value > 0xFF | value < -0x80) { throw new NumberFormatException(Long.toString(value) + " cannot fit into a byte"); } } public static void checkNibble(long value) { if (value > 0x0F | value < -0x08) { throw new NumberFormatException(Long.toString(value) + " cannot fit into a nibble"); } } }