1 /* 2 * [The "BSD licence"] 3 * Copyright (c) 2010 Ben Gruver (JesusFreke) 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 package org.jf.smali; 30 31 public class LiteralTools 32 { parseByte(String byteLiteral)33 public static byte parseByte(String byteLiteral) 34 throws NumberFormatException { 35 if (byteLiteral == null) { 36 throw new NumberFormatException("string is null"); 37 } 38 if (byteLiteral.length() == 0) { 39 throw new NumberFormatException("string is blank"); 40 } 41 42 char[] byteChars; 43 if (byteLiteral.toUpperCase().endsWith("T")) { 44 byteChars = byteLiteral.substring(0, byteLiteral.length()-1).toCharArray(); 45 } else { 46 byteChars = byteLiteral.toCharArray(); 47 } 48 49 int position = 0; 50 int radix = 10; 51 boolean negative = false; 52 if (byteChars[position] == '-') { 53 position++; 54 negative = true; 55 } 56 57 if (byteChars[position] == '0') { 58 position++; 59 if (position == byteChars.length) { 60 return 0; 61 } else if (byteChars[position] == 'x' || byteChars[position] == 'X') { 62 radix = 16; 63 position++; 64 } else if (Character.digit(byteChars[position], 8) >= 0) { 65 radix = 8; 66 } 67 } 68 69 byte result = 0; 70 byte shiftedResult; 71 int digit; 72 byte maxValue = (byte)(Byte.MAX_VALUE / (radix / 2)); 73 74 while (position < byteChars.length) { 75 digit = Character.digit(byteChars[position], radix); 76 if (digit < 0) { 77 throw new NumberFormatException("The string contains invalid an digit - '" + byteChars[position] + "'"); 78 } 79 shiftedResult = (byte)(result * radix); 80 if (result > maxValue) { 81 throw new NumberFormatException(byteLiteral + " cannot fit into a byte"); 82 } 83 if (shiftedResult < 0 && shiftedResult >= -digit) { 84 throw new NumberFormatException(byteLiteral + " cannot fit into a byte"); 85 } 86 result = (byte)(shiftedResult + digit); 87 position++; 88 } 89 90 if (negative) { 91 //allow -0x80, which is = 0x80 92 if (result == Byte.MIN_VALUE) { 93 return result; 94 } else if (result < 0) { 95 throw new NumberFormatException(byteLiteral + " cannot fit into a byte"); 96 } 97 return (byte)(result * -1); 98 } else { 99 return result; 100 } 101 } 102 parseShort(String shortLiteral)103 public static short parseShort(String shortLiteral) 104 throws NumberFormatException { 105 if (shortLiteral == null) { 106 throw new NumberFormatException("string is null"); 107 } 108 if (shortLiteral.length() == 0) { 109 throw new NumberFormatException("string is blank"); 110 } 111 112 char[] shortChars; 113 if (shortLiteral.toUpperCase().endsWith("S")) { 114 shortChars = shortLiteral.substring(0, shortLiteral.length()-1).toCharArray(); 115 } else { 116 shortChars = shortLiteral.toCharArray(); 117 } 118 119 int position = 0; 120 int radix = 10; 121 boolean negative = false; 122 if (shortChars[position] == '-') { 123 position++; 124 negative = true; 125 } 126 127 if (shortChars[position] == '0') { 128 position++; 129 if (position == shortChars.length) { 130 return 0; 131 } else if (shortChars[position] == 'x' || shortChars[position] == 'X') { 132 radix = 16; 133 position++; 134 } else if (Character.digit(shortChars[position], 8) >= 0) { 135 radix = 8; 136 } 137 } 138 139 short result = 0; 140 short shiftedResult; 141 int digit; 142 short maxValue = (short)(Short.MAX_VALUE / (radix / 2)); 143 144 while (position < shortChars.length) { 145 digit = Character.digit(shortChars[position], radix); 146 if (digit < 0) { 147 throw new NumberFormatException("The string contains invalid an digit - '" + shortChars[position] + "'"); 148 } 149 shiftedResult = (short)(result * radix); 150 if (result > maxValue) { 151 throw new NumberFormatException(shortLiteral + " cannot fit into a short"); 152 } 153 if (shiftedResult < 0 && shiftedResult >= -digit) { 154 throw new NumberFormatException(shortLiteral + " cannot fit into a short"); 155 } 156 result = (short)(shiftedResult + digit); 157 position++; 158 } 159 160 if (negative) { 161 //allow -0x8000, which is = 0x8000 162 if (result == Short.MIN_VALUE) { 163 return result; 164 } else if (result < 0) { 165 throw new NumberFormatException(shortLiteral + " cannot fit into a short"); 166 } 167 return (short)(result * -1); 168 } else { 169 return result; 170 } 171 } 172 parseInt(String intLiteral)173 public static int parseInt(String intLiteral) 174 throws NumberFormatException { 175 if (intLiteral == null) { 176 throw new NumberFormatException("string is null"); 177 } 178 if (intLiteral.length() == 0) { 179 throw new NumberFormatException("string is blank"); 180 } 181 182 char[] intChars = intLiteral.toCharArray(); 183 int position = 0; 184 int radix = 10; 185 boolean negative = false; 186 if (intChars[position] == '-') { 187 position++; 188 negative = true; 189 } 190 191 if (intChars[position] == '0') { 192 position++; 193 if (position == intChars.length) { 194 return 0; 195 } else if (intChars[position] == 'x' || intChars[position] == 'X') { 196 radix = 16; 197 position++; 198 } else if (Character.digit(intChars[position], 8) >= 0) { 199 radix = 8; 200 } 201 } 202 203 int result = 0; 204 int shiftedResult; 205 int digit; 206 int maxValue = Integer.MAX_VALUE / (radix / 2); 207 208 while (position < intChars.length) { 209 digit = Character.digit(intChars[position], radix); 210 if (digit < 0) { 211 throw new NumberFormatException("The string contains an invalid digit - '" + intChars[position] + "'"); 212 } 213 shiftedResult = result * radix; 214 if (result > maxValue) { 215 throw new NumberFormatException(intLiteral + " cannot fit into an int"); 216 } 217 if (shiftedResult < 0 && shiftedResult >= -digit) { 218 throw new NumberFormatException(intLiteral + " cannot fit into an int"); 219 } 220 result = shiftedResult + digit; 221 position++; 222 } 223 224 if (negative) { 225 //allow -0x80000000, which is = 0x80000000 226 if (result == Integer.MIN_VALUE) { 227 return result; 228 } else if (result < 0) { 229 throw new NumberFormatException(intLiteral + " cannot fit into an int"); 230 } 231 return result * -1; 232 } else { 233 return result; 234 } 235 } 236 parseLong(String longLiteral)237 public static long parseLong(String longLiteral) 238 throws NumberFormatException { 239 if (longLiteral == null) { 240 throw new NumberFormatException("string is null"); 241 } 242 if (longLiteral.length() == 0) { 243 throw new NumberFormatException("string is blank"); 244 } 245 246 char[] longChars; 247 if (longLiteral.toUpperCase().endsWith("L")) { 248 longChars = longLiteral.substring(0, longLiteral.length()-1).toCharArray(); 249 } else { 250 longChars = longLiteral.toCharArray(); 251 } 252 253 int position = 0; 254 int radix = 10; 255 boolean negative = false; 256 if (longChars[position] == '-') { 257 position++; 258 negative = true; 259 } 260 261 if (longChars[position] == '0') { 262 position++; 263 if (position == longChars.length) { 264 return 0; 265 } else if (longChars[position] == 'x' || longChars[position] == 'X') { 266 radix = 16; 267 position++; 268 } else if (Character.digit(longChars[position], 8) >= 0) { 269 radix = 8; 270 } 271 } 272 273 long result = 0; 274 long shiftedResult; 275 int digit; 276 long maxValue = Long.MAX_VALUE / (radix / 2); 277 278 while (position < longChars.length) { 279 digit = Character.digit(longChars[position], radix); 280 if (digit < 0) { 281 throw new NumberFormatException("The string contains an invalid digit - '" + longChars[position] + "'"); 282 } 283 shiftedResult = result * radix; 284 if (result > maxValue) { 285 throw new NumberFormatException(longLiteral + " cannot fit into a long"); 286 } 287 if (shiftedResult < 0 && shiftedResult >= -digit) { 288 throw new NumberFormatException(longLiteral + " cannot fit into a long"); 289 } 290 result = shiftedResult + digit; 291 position++; 292 } 293 294 if (negative) { 295 //allow -0x8000000000000000, which is = 0x8000000000000000 296 if (result == Long.MIN_VALUE) { 297 return result; 298 } else if (result < 0) { 299 throw new NumberFormatException(longLiteral + " cannot fit into a long"); 300 } 301 return result * -1; 302 } else { 303 return result; 304 } 305 } 306 longToBytes(long value)307 public static byte[] longToBytes(long value) { 308 byte[] bytes = new byte[8]; 309 310 for (int i=0; value != 0; i++) { 311 bytes[i] = (byte)value; 312 value = value >>> 8; 313 } 314 return bytes; 315 } 316 intToBytes(int value)317 public static byte[] intToBytes(int value) { 318 byte[] bytes = new byte[4]; 319 320 for (int i=0; value != 0; i++) { 321 bytes[i] = (byte)value; 322 value = value >>> 8; 323 } 324 return bytes; 325 } 326 shortToBytes(short value)327 public static byte[] shortToBytes(short value) { 328 byte[] bytes = new byte[2]; 329 330 bytes[0] = (byte)value; 331 bytes[1] = (byte)(value >>> 8); 332 return bytes; 333 } 334 floatToBytes(float value)335 public static byte[] floatToBytes(float value) { 336 return intToBytes(Float.floatToRawIntBits(value)); 337 } 338 doubleToBytes(double value)339 public static byte[] doubleToBytes(double value) { 340 return longToBytes(Double.doubleToRawLongBits(value)); 341 } 342 charToBytes(char value)343 public static byte[] charToBytes(char value) { 344 return shortToBytes((short)value); 345 } 346 boolToBytes(boolean value)347 public static byte[] boolToBytes(boolean value) { 348 if (value) { 349 return new byte[] { 0x01 }; 350 } else { 351 return new byte[] { 0x00 }; 352 } 353 } 354 checkInt(long value)355 public static void checkInt(long value) { 356 if (value > 0xFFFFFFFF || value < -0x80000000) { 357 throw new NumberFormatException(Long.toString(value) + " cannot fit into an int"); 358 } 359 } 360 checkShort(long value)361 public static void checkShort(long value) { 362 if (value > 0xFFFF | value < -0x8000) { 363 throw new NumberFormatException(Long.toString(value) + " cannot fit into a short"); 364 } 365 } 366 checkByte(long value)367 public static void checkByte(long value) { 368 if (value > 0xFF | value < -0x80) { 369 throw new NumberFormatException(Long.toString(value) + " cannot fit into a byte"); 370 } 371 } 372 checkNibble(long value)373 public static void checkNibble(long value) { 374 if (value > 0x0F | value < -0x08) { 375 throw new NumberFormatException(Long.toString(value) + " cannot fit into a nibble"); 376 } 377 } 378 } 379