1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.tools.layoutlib.java;
18
19/**
20 * Defines the same class as the java.lang.IntegralToString which was added in
21 * Dalvik VM. This hack, provides a replacement for that class which can't be
22 * loaded in the standard JVM since it's in the java package and standard JVM
23 * doesn't have it. Since it's no longer in java.lang, access to package
24 * private methods and classes has been replaced by the closes matching public
25 * implementation.
26 * <p/>
27 * Extracted from API level 18, file:
28 * platform/libcore/luni/src/main/java/java/lang/IntegralToString.java
29 */
30public final class IntegralToString {
31    /**
32     * When appending to an AbstractStringBuilder, this thread-local char[] lets us avoid
33     * allocation of a temporary array. (We can't write straight into the AbstractStringBuilder
34     * because it's almost as expensive to work out the exact length of the result as it is to
35     * do the formatting. We could try being conservative and "delete"-ing the unused space
36     * afterwards, but then we'd need to duplicate convertInt and convertLong rather than share
37     * the code.)
38     */
39    private static final ThreadLocal<char[]> BUFFER = new ThreadLocal<char[]>() {
40        @Override protected char[] initialValue() {
41            return new char[20]; // Maximum length of a base-10 long.
42        }
43    };
44
45    /**
46     * These tables are used to special-case toString computation for
47     * small values.  This serves three purposes: it reduces memory usage;
48     * it increases performance for small values; and it decreases the
49     * number of comparisons required to do the length computation.
50     * Elements of this table are lazily initialized on first use.
51     * No locking is necessary, i.e., we use the non-volatile, racy
52     * single-check idiom.
53     */
54    private static final String[] SMALL_NONNEGATIVE_VALUES = new String[100];
55    private static final String[] SMALL_NEGATIVE_VALUES = new String[100];
56
57    /** TENS[i] contains the tens digit of the number i, 0 <= i <= 99. */
58    private static final char[] TENS = {
59        '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
60        '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
61        '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
62        '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
63        '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
64        '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
65        '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
66        '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
67        '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
68        '9', '9', '9', '9', '9', '9', '9', '9', '9', '9'
69    };
70
71    /** Ones [i] contains the tens digit of the number i, 0 <= i <= 99. */
72    private static final char[] ONES = {
73        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
74        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
75        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
76        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
77        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
78        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
79        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
80        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
81        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
82        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
83    };
84
85    /**
86     * Table for MOD / DIV 10 computation described in Section 10-21
87     * of Hank Warren's "Hacker's Delight" online addendum.
88     * http://www.hackersdelight.org/divcMore.pdf
89     */
90    private static final char[] MOD_10_TABLE = {
91        0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 0
92    };
93
94    /**
95     * The digits for every supported radix.
96     */
97    private static final char[] DIGITS = {
98        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
99        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
100        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
101        'u', 'v', 'w', 'x', 'y', 'z'
102    };
103
104    private static final char[] UPPER_CASE_DIGITS = {
105        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
106        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
107        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
108        'U', 'V', 'W', 'X', 'Y', 'Z'
109    };
110
111    private IntegralToString() {
112    }
113
114    /**
115     * Equivalent to Integer.toString(i, radix).
116     */
117    public static String intToString(int i, int radix) {
118        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
119            radix = 10;
120        }
121        if (radix == 10) {
122            return intToString(i);
123        }
124
125        /*
126         * If i is positive, negate it. This is the opposite of what one might
127         * expect. It is necessary because the range of the negative values is
128         * strictly larger than that of the positive values: there is no
129         * positive value corresponding to Integer.MIN_VALUE.
130         */
131        boolean negative = false;
132        if (i < 0) {
133            negative = true;
134        } else {
135            i = -i;
136        }
137
138        int bufLen = radix < 8 ? 33 : 12;  // Max chars in result (conservative)
139        char[] buf = new char[bufLen];
140        int cursor = bufLen;
141
142        do {
143            int q = i / radix;
144            buf[--cursor] = DIGITS[radix * q - i];
145            i = q;
146        } while (i != 0);
147
148        if (negative) {
149            buf[--cursor] = '-';
150        }
151
152        return new String(buf, cursor, bufLen - cursor);
153    }
154
155    /**
156     * Equivalent to Integer.toString(i).
157     */
158    public static String intToString(int i) {
159        return convertInt(null, i);
160    }
161
162    /**
163     * Equivalent to sb.append(Integer.toString(i)).
164     */
165    public static void appendInt(StringBuilder sb, int i) {
166        convertInt(sb, i);
167    }
168
169    /**
170     * Returns the string representation of i and leaves sb alone if sb is null.
171     * Returns null and appends the string representation of i to sb if sb is non-null.
172     */
173    private static String convertInt(StringBuilder sb, int i) {
174        boolean negative = false;
175        String quickResult = null;
176        if (i < 0) {
177            negative = true;
178            i = -i;
179            if (i < 100) {
180                if (i < 0) {
181                    // If -n is still negative, n is Integer.MIN_VALUE
182                    quickResult = "-2147483648";
183                } else {
184                    quickResult = SMALL_NEGATIVE_VALUES[i];
185                    if (quickResult == null) {
186                        SMALL_NEGATIVE_VALUES[i] = quickResult =
187                                i < 10 ? stringOf('-', ONES[i]) : stringOf('-', TENS[i], ONES[i]);
188                    }
189                }
190            }
191        } else {
192            if (i < 100) {
193                quickResult = SMALL_NONNEGATIVE_VALUES[i];
194                if (quickResult == null) {
195                    SMALL_NONNEGATIVE_VALUES[i] = quickResult =
196                            i < 10 ? stringOf(ONES[i]) : stringOf(TENS[i], ONES[i]);
197                }
198            }
199        }
200        if (quickResult != null) {
201            if (sb != null) {
202                sb.append(quickResult);
203                return null;
204            }
205            return quickResult;
206        }
207
208        int bufLen = 11; // Max number of chars in result
209        char[] buf = (sb != null) ? BUFFER.get() : new char[bufLen];
210        int cursor = bufLen;
211
212        // Calculate digits two-at-a-time till remaining digits fit in 16 bits
213        while (i >= (1 << 16)) {
214            // Compute q = n/100 and r = n % 100 as per "Hacker's Delight" 10-8
215            int q = (int) ((0x51EB851FL * i) >>> 37);
216            int r = i - 100*q;
217            buf[--cursor] = ONES[r];
218            buf[--cursor] = TENS[r];
219            i = q;
220        }
221
222        // Calculate remaining digits one-at-a-time for performance
223        while (i != 0) {
224            // Compute q = n/10 and r = n % 10 as per "Hacker's Delight" 10-8
225            int q = (0xCCCD * i) >>> 19;
226            int r = i - 10*q;
227            buf[--cursor] = DIGITS[r];
228            i = q;
229        }
230
231        if (negative) {
232            buf[--cursor] = '-';
233        }
234
235        if (sb != null) {
236            sb.append(buf, cursor, bufLen - cursor);
237            return null;
238        } else {
239            return new String(buf, cursor, bufLen - cursor);
240        }
241    }
242
243    /**
244     * Equivalent to Long.toString(v, radix).
245     */
246    public static String longToString(long v, int radix) {
247        int i = (int) v;
248        if (i == v) {
249            return intToString(i, radix);
250        }
251
252        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
253            radix = 10;
254        }
255        if (radix == 10) {
256            return longToString(v);
257        }
258
259        /*
260         * If v is positive, negate it. This is the opposite of what one might
261         * expect. It is necessary because the range of the negative values is
262         * strictly larger than that of the positive values: there is no
263         * positive value corresponding to Integer.MIN_VALUE.
264         */
265        boolean negative = false;
266        if (v < 0) {
267            negative = true;
268        } else {
269            v = -v;
270        }
271
272        int bufLen = radix < 8 ? 65 : 23;  // Max chars in result (conservative)
273        char[] buf = new char[bufLen];
274        int cursor = bufLen;
275
276        do {
277            long q = v / radix;
278            buf[--cursor] = DIGITS[(int) (radix * q - v)];
279            v = q;
280        } while (v != 0);
281
282        if (negative) {
283            buf[--cursor] = '-';
284        }
285
286        return new String(buf, cursor, bufLen - cursor);
287    }
288
289    /**
290     * Equivalent to Long.toString(l).
291     */
292    public static String longToString(long l) {
293        return convertLong(null, l);
294    }
295
296    /**
297     * Equivalent to sb.append(Long.toString(l)).
298     */
299    public static void appendLong(StringBuilder sb, long l) {
300        convertLong(sb, l);
301    }
302
303    /**
304     * Returns the string representation of n and leaves sb alone if sb is null.
305     * Returns null and appends the string representation of n to sb if sb is non-null.
306     */
307    private static String convertLong(StringBuilder sb, long n) {
308        int i = (int) n;
309        if (i == n) {
310            return convertInt(sb, i);
311        }
312
313        boolean negative = (n < 0);
314        if (negative) {
315            n = -n;
316            if (n < 0) {
317                // If -n is still negative, n is Long.MIN_VALUE
318                String quickResult = "-9223372036854775808";
319                if (sb != null) {
320                    sb.append(quickResult);
321                    return null;
322                }
323                return quickResult;
324            }
325        }
326
327        int bufLen = 20; // Maximum number of chars in result
328        char[] buf = (sb != null) ? BUFFER.get() : new char[bufLen];
329
330        int low = (int) (n % 1000000000); // Extract low-order 9 digits
331        int cursor = intIntoCharArray(buf, bufLen, low);
332
333        // Zero-pad Low order part to 9 digits
334        while (cursor != (bufLen - 9)) {
335            buf[--cursor] = '0';
336        }
337
338        /*
339         * The remaining digits are (n - low) / 1,000,000,000.  This
340         * "exact division" is done as per the online addendum to Hank Warren's
341         * "Hacker's Delight" 10-20, http://www.hackersdelight.org/divcMore.pdf
342         */
343        n = ((n - low) >>> 9) * 0x8E47CE423A2E9C6DL;
344
345        /*
346         * If the remaining digits fit in an int, emit them using a
347         * single call to intIntoCharArray. Otherwise, strip off the
348         * low-order digit, put it in buf, and then call intIntoCharArray
349         * on the remaining digits (which now fit in an int).
350         */
351        if ((n & (-1L << 32)) == 0) {
352            cursor = intIntoCharArray(buf, cursor, (int) n);
353        } else {
354            /*
355             * Set midDigit to n % 10
356             */
357            int lo32 = (int) n;
358            int hi32 = (int) (n >>> 32);
359
360            // midDigit = ((unsigned) low32) % 10, per "Hacker's Delight" 10-21
361            int midDigit = MOD_10_TABLE[(0x19999999 * lo32 + (lo32 >>> 1) + (lo32 >>> 3)) >>> 28];
362
363            // Adjust midDigit for hi32. (assert hi32 == 1 || hi32 == 2)
364            midDigit -= hi32 << 2;  // 1L << 32 == -4 MOD 10
365            if (midDigit < 0) {
366                midDigit += 10;
367            }
368            buf[--cursor] = DIGITS[midDigit];
369
370            // Exact division as per Warren 10-20
371            int rest = ((int) ((n - midDigit) >>> 1)) * 0xCCCCCCCD;
372            cursor = intIntoCharArray(buf, cursor, rest);
373        }
374
375        if (negative) {
376            buf[--cursor] = '-';
377        }
378        if (sb != null) {
379            sb.append(buf, cursor, bufLen - cursor);
380            return null;
381        } else {
382            return new String(buf, cursor, bufLen - cursor);
383        }
384    }
385
386    /**
387     * Inserts the unsigned decimal integer represented by n into the specified
388     * character array starting at position cursor.  Returns the index after
389     * the last character inserted (i.e., the value to pass in as cursor the
390     * next time this method is called). Note that n is interpreted as a large
391     * positive integer (not a negative integer) if its sign bit is set.
392     */
393    private static int intIntoCharArray(char[] buf, int cursor, int n) {
394        // Calculate digits two-at-a-time till remaining digits fit in 16 bits
395        while ((n & 0xffff0000) != 0) {
396            /*
397             * Compute q = n/100 and r = n % 100 as per "Hacker's Delight" 10-8.
398             * This computation is slightly different from the corresponding
399             * computation in intToString: the shifts before and after
400             * multiply can't be combined, as that would yield the wrong result
401             * if n's sign bit were set.
402             */
403            int q = (int) ((0x51EB851FL * (n >>> 2)) >>> 35);
404            int r = n - 100*q;
405            buf[--cursor] = ONES[r];
406            buf[--cursor] = TENS[r];
407            n = q;
408        }
409
410        // Calculate remaining digits one-at-a-time for performance
411        while (n != 0) {
412            // Compute q = n / 10 and r = n % 10 as per "Hacker's Delight" 10-8
413            int q = (0xCCCD * n) >>> 19;
414            int r = n - 10*q;
415            buf[--cursor] = DIGITS[r];
416            n = q;
417        }
418        return cursor;
419    }
420
421    public static String intToBinaryString(int i) {
422        int bufLen = 32;  // Max number of binary digits in an int
423        char[] buf = new char[bufLen];
424        int cursor = bufLen;
425
426        do {
427            buf[--cursor] = DIGITS[i & 1];
428        }  while ((i >>>= 1) != 0);
429
430        return new String(buf, cursor, bufLen - cursor);
431    }
432
433    public static String longToBinaryString(long v) {
434        int i = (int) v;
435        if (v >= 0 && i == v) {
436            return intToBinaryString(i);
437        }
438
439        int bufLen = 64;  // Max number of binary digits in a long
440        char[] buf = new char[bufLen];
441        int cursor = bufLen;
442
443        do {
444            buf[--cursor] = DIGITS[((int) v) & 1];
445        }  while ((v >>>= 1) != 0);
446
447        return new String(buf, cursor, bufLen - cursor);
448    }
449
450    public static StringBuilder appendByteAsHex(StringBuilder sb, byte b, boolean upperCase) {
451        char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
452        sb.append(digits[(b >> 4) & 0xf]);
453        sb.append(digits[b & 0xf]);
454        return sb;
455    }
456
457    public static String byteToHexString(byte b, boolean upperCase) {
458        char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
459        char[] buf = new char[2]; // We always want two digits.
460        buf[0] = digits[(b >> 4) & 0xf];
461        buf[1] = digits[b & 0xf];
462        return new String(buf, 0, 2);
463    }
464
465    public static String bytesToHexString(byte[] bytes, boolean upperCase) {
466        char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
467        char[] buf = new char[bytes.length * 2];
468        int c = 0;
469        for (byte b : bytes) {
470            buf[c++] = digits[(b >> 4) & 0xf];
471            buf[c++] = digits[b & 0xf];
472        }
473        return new String(buf);
474    }
475
476    public static String intToHexString(int i, boolean upperCase, int minWidth) {
477        int bufLen = 8;  // Max number of hex digits in an int
478        char[] buf = new char[bufLen];
479        int cursor = bufLen;
480
481        char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
482        do {
483            buf[--cursor] = digits[i & 0xf];
484        } while ((i >>>= 4) != 0 || (bufLen - cursor < minWidth));
485
486        return new String(buf, cursor, bufLen - cursor);
487    }
488
489    public static String longToHexString(long v) {
490        int i = (int) v;
491        if (v >= 0 && i == v) {
492            return intToHexString(i, false, 0);
493        }
494
495        int bufLen = 16;  // Max number of hex digits in a long
496        char[] buf = new char[bufLen];
497        int cursor = bufLen;
498
499        do {
500            buf[--cursor] = DIGITS[((int) v) & 0xF];
501        } while ((v >>>= 4) != 0);
502
503        return new String(buf, cursor, bufLen - cursor);
504    }
505
506    public static String intToOctalString(int i) {
507        int bufLen = 11;  // Max number of octal digits in an int
508        char[] buf = new char[bufLen];
509        int cursor = bufLen;
510
511        do {
512            buf[--cursor] = DIGITS[i & 7];
513        } while ((i >>>= 3) != 0);
514
515        return new String(buf, cursor, bufLen - cursor);
516    }
517
518    public static String longToOctalString(long v) {
519        int i = (int) v;
520        if (v >= 0 && i == v) {
521            return intToOctalString(i);
522        }
523        int bufLen = 22;  // Max number of octal digits in a long
524        char[] buf = new char[bufLen];
525        int cursor = bufLen;
526
527        do {
528            buf[--cursor] = DIGITS[((int) v) & 7];
529        } while ((v >>>= 3) != 0);
530
531        return new String(buf, cursor, bufLen - cursor);
532    }
533
534    private static String stringOf(char... args) {
535        return new String(args, 0, args.length);
536    }
537}
538