• 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 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