001    /*
002     * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.javac.util;
027    
028    /** Utility class for static conversion methods between numbers
029     *  and strings in various formats.
030     *
031     *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
032     *  you write code that depends on this, you do so at your own risk.
033     *  This code and its internal interfaces are subject to change or
034     *  deletion without notice.</b>
035     */
036    public class Convert {
037    
038        /** Convert string to integer.
039         */
040        public static int string2int(String s, int radix)
041            throws NumberFormatException {
042            if (radix == 10) {
043                return Integer.parseInt(s, radix);
044            } else {
045                char[] cs = s.toCharArray();
046                int limit = Integer.MAX_VALUE / (radix/2);
047                int n = 0;
048                for (int i = 0; i < cs.length; i++) {
049                    int d = Character.digit(cs[i], radix);
050                    if (n < 0 ||
051                        n > limit ||
052                        n * radix > Integer.MAX_VALUE - d)
053                        throw new NumberFormatException();
054                    n = n * radix + d;
055                }
056                return n;
057            }
058        }
059    
060        /** Convert string to long integer.
061         */
062        public static long string2long(String s, int radix)
063            throws NumberFormatException {
064            if (radix == 10) {
065                return Long.parseLong(s, radix);
066            } else {
067                char[] cs = s.toCharArray();
068                long limit = Long.MAX_VALUE / (radix/2);
069                long n = 0;
070                for (int i = 0; i < cs.length; i++) {
071                    int d = Character.digit(cs[i], radix);
072                    if (n < 0 ||
073                        n > limit ||
074                        n * radix > Long.MAX_VALUE - d)
075                        throw new NumberFormatException();
076                    n = n * radix + d;
077                }
078                return n;
079            }
080        }
081    
082    /* Conversion routines between names, strings, and byte arrays in Utf8 format
083     */
084    
085        /** Convert `len' bytes from utf8 to characters.
086         *  Parameters are as in System.arraycopy
087         *  Return first index in `dst' past the last copied char.
088         *  @param src        The array holding the bytes to convert.
089         *  @param sindex     The start index from which bytes are converted.
090         *  @param dst        The array holding the converted characters..
091         *  @param dindex     The start index from which converted characters
092         *                    are written.
093         *  @param len        The maximum number of bytes to convert.
094         */
095        public static int utf2chars(byte[] src, int sindex,
096                                    char[] dst, int dindex,
097                                    int len) {
098            int i = sindex;
099            int j = dindex;
100            int limit = sindex + len;
101            while (i < limit) {
102                int b = src[i++] & 0xFF;
103                if (b >= 0xE0) {
104                    b = (b & 0x0F) << 12;
105                    b = b | (src[i++] & 0x3F) << 6;
106                    b = b | (src[i++] & 0x3F);
107                } else if (b >= 0xC0) {
108                    b = (b & 0x1F) << 6;
109                    b = b | (src[i++] & 0x3F);
110                }
111                dst[j++] = (char)b;
112            }
113            return j;
114        }
115    
116        /** Return bytes in Utf8 representation as an array of characters.
117         *  @param src        The array holding the bytes.
118         *  @param sindex     The start index from which bytes are converted.
119         *  @param len        The maximum number of bytes to convert.
120         */
121        public static char[] utf2chars(byte[] src, int sindex, int len) {
122            char[] dst = new char[len];
123            int len1 = utf2chars(src, sindex, dst, 0, len);
124            char[] result = new char[len1];
125            System.arraycopy(dst, 0, result, 0, len1);
126            return result;
127        }
128    
129        /** Return all bytes of a given array in Utf8 representation
130         *  as an array of characters.
131         *  @param src        The array holding the bytes.
132         */
133        public static char[] utf2chars(byte[] src) {
134            return utf2chars(src, 0, src.length);
135        }
136    
137        /** Return bytes in Utf8 representation as a string.
138         *  @param src        The array holding the bytes.
139         *  @param sindex     The start index from which bytes are converted.
140         *  @param len        The maximum number of bytes to convert.
141         */
142        public static String utf2string(byte[] src, int sindex, int len) {
143            char dst[] = new char[len];
144            int len1 = utf2chars(src, sindex, dst, 0, len);
145            return new String(dst, 0, len1);
146        }
147    
148        /** Return all bytes of a given array in Utf8 representation
149         *  as a string.
150         *  @param src        The array holding the bytes.
151         */
152        public static String utf2string(byte[] src) {
153            return utf2string(src, 0, src.length);
154        }
155    
156        /** Copy characters in source array to bytes in target array,
157         *  converting them to Utf8 representation.
158         *  The target array must be large enough to hold the result.
159         *  returns first index in `dst' past the last copied byte.
160         *  @param src        The array holding the characters to convert.
161         *  @param sindex     The start index from which characters are converted.
162         *  @param dst        The array holding the converted characters..
163         *  @param dindex     The start index from which converted bytes
164         *                    are written.
165         *  @param len        The maximum number of characters to convert.
166         */
167        public static int chars2utf(char[] src, int sindex,
168                                    byte[] dst, int dindex,
169                                    int len) {
170            int j = dindex;
171            int limit = sindex + len;
172            for (int i = sindex; i < limit; i++) {
173                char ch = src[i];
174                if (1 <= ch && ch <= 0x7F) {
175                    dst[j++] = (byte)ch;
176                } else if (ch <= 0x7FF) {
177                    dst[j++] = (byte)(0xC0 | (ch >> 6));
178                    dst[j++] = (byte)(0x80 | (ch & 0x3F));
179                } else {
180                    dst[j++] = (byte)(0xE0 | (ch >> 12));
181                    dst[j++] = (byte)(0x80 | ((ch >> 6) & 0x3F));
182                    dst[j++] = (byte)(0x80 | (ch & 0x3F));
183                }
184            }
185            return j;
186        }
187    
188        /** Return characters as an array of bytes in Utf8 representation.
189         *  @param src        The array holding the characters.
190         *  @param sindex     The start index from which characters are converted.
191         *  @param len        The maximum number of characters to convert.
192         */
193        public static byte[] chars2utf(char[] src, int sindex, int len) {
194            byte[] dst = new byte[len * 3];
195            int len1 = chars2utf(src, sindex, dst, 0, len);
196            byte[] result = new byte[len1];
197            System.arraycopy(dst, 0, result, 0, len1);
198            return result;
199        }
200    
201        /** Return all characters in given array as an array of bytes
202         *  in Utf8 representation.
203         *  @param src        The array holding the characters.
204         */
205        public static byte[] chars2utf(char[] src) {
206            return chars2utf(src, 0, src.length);
207        }
208    
209        /** Return string as an array of bytes in in Utf8 representation.
210         */
211        public static byte[] string2utf(String s) {
212            return chars2utf(s.toCharArray());
213        }
214    
215        /**
216         * Escapes each character in a string that has an escape sequence or
217         * is non-printable ASCII.  Leaves non-ASCII characters alone.
218         */
219        public static String quote(String s) {
220            StringBuilder buf = new StringBuilder();
221            for (int i = 0; i < s.length(); i++) {
222                buf.append(quote(s.charAt(i)));
223            }
224            return buf.toString();
225        }
226    
227        /**
228         * Escapes a character if it has an escape sequence or is
229         * non-printable ASCII.  Leaves non-ASCII characters alone.
230         */
231        public static String quote(char ch) {
232            switch (ch) {
233            case '\b':  return "\\b";
234            case '\f':  return "\\f";
235            case '\n':  return "\\n";
236            case '\r':  return "\\r";
237            case '\t':  return "\\t";
238            case '\'':  return "\\'";
239            case '\"':  return "\\\"";
240            case '\\':  return "\\\\";
241            default:
242                return (ch > 127 || isPrintableAscii(ch))
243                    ? String.valueOf(ch)
244                    : String.format("\\%03o", (int) ch);
245            }
246        }
247    
248        /**
249         * Is a character printable ASCII?
250         */
251        private static boolean isPrintableAscii(char ch) {
252            return ch >= ' ' && ch <= '~';
253        }
254    
255        /** Escape all unicode characters in string.
256         */
257        public static String escapeUnicode(String s) {
258            int len = s.length();
259            int i = 0;
260            while (i < len) {
261                char ch = s.charAt(i);
262                if (ch > 255) {
263                    StringBuffer buf = new StringBuffer();
264                    buf.append(s.substring(0, i));
265                    while (i < len) {
266                        ch = s.charAt(i);
267                        if (ch > 255) {
268                            buf.append("\\u");
269                            buf.append(Character.forDigit((ch >> 12) % 16, 16));
270                            buf.append(Character.forDigit((ch >>  8) % 16, 16));
271                            buf.append(Character.forDigit((ch >>  4) % 16, 16));
272                            buf.append(Character.forDigit((ch      ) % 16, 16));
273                        } else {
274                            buf.append(ch);
275                        }
276                        i++;
277                    }
278                    s = buf.toString();
279                } else {
280                    i++;
281                }
282            }
283            return s;
284        }
285    
286    /* Conversion routines for qualified name splitting
287     */
288        /** Return the last part of a class name.
289         */
290        public static Name shortName(Name classname) {
291            return classname.subName(
292                classname.lastIndexOf((byte)'.') + 1, classname.getByteLength());
293        }
294    
295        public static String shortName(String classname) {
296            return classname.substring(classname.lastIndexOf('.') + 1);
297        }
298    
299        /** Return the package name of a class name, excluding the trailing '.',
300         *  "" if not existent.
301         */
302        public static Name packagePart(Name classname) {
303            return classname.subName(0, classname.lastIndexOf((byte)'.'));
304        }
305    
306        public static String packagePart(String classname) {
307            int lastDot = classname.lastIndexOf('.');
308            return (lastDot < 0 ? "" : classname.substring(0, lastDot));
309        }
310    
311        public static List<Name> enclosingCandidates(Name name) {
312            List<Name> names = List.nil();
313            int index;
314            while ((index = name.lastIndexOf((byte)'$')) > 0) {
315                name = name.subName(0, index);
316                names = names.prepend(name);
317            }
318            return names;
319        }
320    }