• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33 
34 public class LiteralTools
35 {
parseByte(String byteLiteral)36     public static byte parseByte(String byteLiteral)
37             throws NumberFormatException {
38         if (byteLiteral == null) {
39             throw new NumberFormatException("string is null");
40         }
41         if (byteLiteral.length() == 0) {
42             throw new NumberFormatException("string is blank");
43         }
44 
45         char[] byteChars;
46         if (byteLiteral.toUpperCase().endsWith("T")) {
47             byteChars = byteLiteral.substring(0, byteLiteral.length()-1).toCharArray();
48         } else {
49             byteChars = byteLiteral.toCharArray();
50         }
51 
52         int position = 0;
53         int radix = 10;
54         boolean negative = false;
55         if (byteChars[position] == '-') {
56             position++;
57             negative = true;
58         }
59 
60         if (byteChars[position] == '0') {
61             position++;
62             if (position == byteChars.length) {
63                 return 0;
64             } else if (byteChars[position] == 'x' || byteChars[position] == 'X') {
65                 radix = 16;
66                 position++;
67             } else if (Character.digit(byteChars[position], 8) >= 0) {
68                 radix = 8;
69             }
70         }
71 
72         byte result = 0;
73         byte shiftedResult;
74         int digit;
75         byte maxValue = (byte)(Byte.MAX_VALUE / (radix / 2));
76 
77         while (position < byteChars.length) {
78             digit = Character.digit(byteChars[position], radix);
79             if (digit < 0) {
80                 throw new NumberFormatException("The string contains invalid an digit - '" + byteChars[position] + "'");
81             }
82             shiftedResult = (byte)(result * radix);
83             if (result > maxValue) {
84                 throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
85             }
86             if (shiftedResult < 0 && shiftedResult >= -digit) {
87                 throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
88             }
89             result = (byte)(shiftedResult + digit);
90             position++;
91         }
92 
93         if (negative) {
94             //allow -0x80, which is = 0x80
95             if (result == Byte.MIN_VALUE) {
96                 return result;
97             } else if (result < 0) {
98                 throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
99             }
100             return (byte)(result * -1);
101         } else {
102             return result;
103         }
104     }
105 
parseShort(String shortLiteral)106     public static short parseShort(String shortLiteral)
107             throws NumberFormatException {
108         if (shortLiteral == null) {
109             throw new NumberFormatException("string is null");
110         }
111         if (shortLiteral.length() == 0) {
112             throw new NumberFormatException("string is blank");
113         }
114 
115         char[] shortChars;
116         if (shortLiteral.toUpperCase().endsWith("S")) {
117             shortChars = shortLiteral.substring(0, shortLiteral.length()-1).toCharArray();
118         } else {
119             shortChars = shortLiteral.toCharArray();
120         }
121 
122         int position = 0;
123         int radix = 10;
124         boolean negative = false;
125         if (shortChars[position] == '-') {
126             position++;
127             negative = true;
128         }
129 
130         if (shortChars[position] == '0') {
131             position++;
132             if (position == shortChars.length) {
133                 return 0;
134             } else if (shortChars[position] == 'x' || shortChars[position] == 'X') {
135                 radix = 16;
136                 position++;
137             } else if (Character.digit(shortChars[position], 8) >= 0) {
138                 radix = 8;
139             }
140         }
141 
142         short result = 0;
143         short shiftedResult;
144         int digit;
145         short maxValue = (short)(Short.MAX_VALUE / (radix / 2));
146 
147         while (position < shortChars.length) {
148             digit = Character.digit(shortChars[position], radix);
149             if (digit < 0) {
150                 throw new NumberFormatException("The string contains invalid an digit - '" + shortChars[position] + "'");
151             }
152             shiftedResult = (short)(result * radix);
153             if (result > maxValue) {
154                 throw new NumberFormatException(shortLiteral + " cannot fit into a short");
155             }
156             if (shiftedResult < 0 && shiftedResult >= -digit) {
157                 throw new NumberFormatException(shortLiteral + " cannot fit into a short");
158             }
159             result = (short)(shiftedResult + digit);
160             position++;
161         }
162 
163         if (negative) {
164             //allow -0x8000, which is = 0x8000
165             if (result == Short.MIN_VALUE) {
166                 return result;
167             } else if (result < 0) {
168                 throw new NumberFormatException(shortLiteral + " cannot fit into a short");
169             }
170             return (short)(result * -1);
171         } else {
172             return result;
173         }
174     }
175 
parseInt(String intLiteral)176     public static int parseInt(String intLiteral)
177             throws NumberFormatException {
178         if (intLiteral == null) {
179             throw new NumberFormatException("string is null");
180         }
181         if (intLiteral.length() == 0) {
182             throw new NumberFormatException("string is blank");
183         }
184 
185         char[] intChars = intLiteral.toCharArray();
186         int position = 0;
187         int radix = 10;
188         boolean negative = false;
189         if (intChars[position] == '-') {
190             position++;
191             negative = true;
192         }
193 
194         if (intChars[position] == '0') {
195             position++;
196             if (position == intChars.length) {
197                 return 0;
198             } else if (intChars[position] == 'x' || intChars[position] == 'X') {
199                 radix = 16;
200                 position++;
201             } else if (Character.digit(intChars[position], 8) >= 0) {
202                 radix = 8;
203             }
204         }
205 
206         int result = 0;
207         int shiftedResult;
208         int digit;
209         int maxValue = Integer.MAX_VALUE / (radix / 2);
210 
211         while (position < intChars.length) {
212             digit = Character.digit(intChars[position], radix);
213             if (digit < 0) {
214                 throw new NumberFormatException("The string contains an invalid digit - '" + intChars[position] + "'");
215             }
216             shiftedResult = result * radix;
217             if (result > maxValue) {
218                 throw new NumberFormatException(intLiteral + " cannot fit into an int");
219             }
220             if (shiftedResult < 0 && shiftedResult >= -digit) {
221                 throw new NumberFormatException(intLiteral + " cannot fit into an int");
222             }
223             result = shiftedResult + digit;
224             position++;
225         }
226 
227         if (negative) {
228             //allow -0x80000000, which is = 0x80000000
229             if (result == Integer.MIN_VALUE) {
230                 return result;
231             } else if (result < 0) {
232                 throw new NumberFormatException(intLiteral + " cannot fit into an int");
233             }
234             return result * -1;
235         } else {
236             return result;
237         }
238     }
239 
parseLong(String longLiteral)240     public static long parseLong(String longLiteral)
241             throws NumberFormatException {
242         if (longLiteral == null) {
243             throw new NumberFormatException("string is null");
244         }
245         if (longLiteral.length() == 0) {
246             throw new NumberFormatException("string is blank");
247         }
248 
249         char[] longChars;
250         if (longLiteral.toUpperCase().endsWith("L")) {
251             longChars = longLiteral.substring(0, longLiteral.length()-1).toCharArray();
252         } else {
253             longChars = longLiteral.toCharArray();
254         }
255 
256         int position = 0;
257         int radix = 10;
258         boolean negative = false;
259         if (longChars[position] == '-') {
260             position++;
261             negative = true;
262         }
263 
264         if (longChars[position] == '0') {
265             position++;
266             if (position == longChars.length) {
267                 return 0;
268             } else if (longChars[position] == 'x' || longChars[position] == 'X') {
269                 radix = 16;
270                 position++;
271             } else if (Character.digit(longChars[position], 8) >= 0) {
272                 radix = 8;
273             }
274         }
275 
276         long result = 0;
277         long shiftedResult;
278         int digit;
279         long maxValue = Long.MAX_VALUE / (radix / 2);
280 
281         while (position < longChars.length) {
282             digit = Character.digit(longChars[position], radix);
283             if (digit < 0) {
284                 throw new NumberFormatException("The string contains an invalid digit - '" + longChars[position] + "'");
285             }
286             shiftedResult = result * radix;
287             if (result > maxValue) {
288                 throw new NumberFormatException(longLiteral + " cannot fit into a long");
289             }
290             if (shiftedResult < 0 && shiftedResult >= -digit) {
291                 throw new NumberFormatException(longLiteral + " cannot fit into a long");
292             }
293             result = shiftedResult + digit;
294             position++;
295         }
296 
297         if (negative) {
298             //allow -0x8000000000000000, which is = 0x8000000000000000
299             if (result == Long.MIN_VALUE) {
300                 return result;
301             } else if (result < 0) {
302                 throw new NumberFormatException(longLiteral + " cannot fit into a long");
303             }
304             return result * -1;
305         } else {
306             return result;
307         }
308     }
309 
310     private static Pattern specialFloatRegex = Pattern.compile("((-)?infinityf)|(nanf)", Pattern.CASE_INSENSITIVE);
parseFloat(String floatString)311     public static float parseFloat(String floatString) {
312         Matcher m = specialFloatRegex.matcher(floatString);
313         if (m.matches()) {
314             //got an infinity
315             if (m.start(1) != -1) {
316                 if (m.start(2) != -1) {
317                     return Float.NEGATIVE_INFINITY;
318                 } else {
319                     return Float.POSITIVE_INFINITY;
320                 }
321             } else {
322                 return Float.NaN;
323             }
324         }
325         return Float.parseFloat(floatString);
326     }
327 
328     private static Pattern specialDoubleRegex = Pattern.compile("((-)?infinityd?)|(nand?)", Pattern.CASE_INSENSITIVE);
parseDouble(String doubleString)329     public static double parseDouble(String doubleString) {
330         Matcher m = specialDoubleRegex.matcher(doubleString);
331         if (m.matches()) {
332             //got an infinity
333             if (m.start(1) != -1) {
334                 if (m.start(2) != -1) {
335                     return Double.NEGATIVE_INFINITY;
336                 } else {
337                     return Double.POSITIVE_INFINITY;
338                 }
339             } else {
340                 return Double.NaN;
341             }
342         }
343         return Double.parseDouble(doubleString);
344     }
345 
longToBytes(long value)346     public static byte[] longToBytes(long value) {
347         byte[] bytes = new byte[8];
348 
349         for (int i=0; value != 0; i++) {
350             bytes[i] = (byte)value;
351             value = value >>> 8;
352         }
353         return bytes;
354     }
355 
intToBytes(int value)356     public static byte[] intToBytes(int value) {
357         byte[] bytes = new byte[4];
358 
359         for (int i=0; value != 0; i++) {
360             bytes[i] = (byte)value;
361             value = value >>> 8;
362         }
363         return bytes;
364     }
365 
shortToBytes(short value)366     public static byte[] shortToBytes(short value) {
367         byte[] bytes = new byte[2];
368 
369         bytes[0] = (byte)value;
370         bytes[1] = (byte)(value >>> 8);
371         return bytes;
372     }
373 
floatToBytes(float value)374     public static byte[] floatToBytes(float value) {
375         return intToBytes(Float.floatToRawIntBits(value));
376     }
377 
doubleToBytes(double value)378     public static byte[] doubleToBytes(double value) {
379         return longToBytes(Double.doubleToRawLongBits(value));
380     }
381 
charToBytes(char value)382     public static byte[] charToBytes(char value) {
383         return shortToBytes((short)value);
384     }
385 
boolToBytes(boolean value)386     public static byte[] boolToBytes(boolean value) {
387         if (value) {
388             return new byte[] { 0x01 };
389         } else {
390             return new byte[] { 0x00 };
391         }
392     }
393 
checkInt(long value)394     public static void checkInt(long value) {
395         if (value > 0xFFFFFFFF || value < -0x80000000) {
396             throw new NumberFormatException(Long.toString(value) + " cannot fit into an int");
397         }
398     }
399 
checkShort(long value)400     public static void checkShort(long value) {
401         if (value > 0xFFFF | value < -0x8000) {
402             throw new NumberFormatException(Long.toString(value) + " cannot fit into a short");
403         }
404     }
405 
checkByte(long value)406     public static void checkByte(long value) {
407         if (value > 0xFF | value < -0x80) {
408             throw new NumberFormatException(Long.toString(value) + " cannot fit into a byte");
409         }
410     }
411 
checkNibble(long value)412     public static void checkNibble(long value) {
413         if (value > 0x0F | value < -0x08) {
414             throw new NumberFormatException(Long.toString(value) + " cannot fit into a nibble");
415         }
416     }
417 }
418