1 /*
   2  * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 
  26 package com.sun.tools.javac.util;
  27 
  28 /** Utility class for static conversion methods between numbers
  29  *  and strings in various formats.
  30  *
  31  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
  32  *  you write code that depends on this, you do so at your own risk.
  33  *  This code and its internal interfaces are subject to change or
  34  *  deletion without notice.</b>
  35  */
  36 public class Convert {
  37 
  38     /** Convert string to integer.
  39      */
  40     public static int string2int(String s, int radix)
  41         throws NumberFormatException {
  42         if (radix == 10) {
  43             return Integer.parseInt(s, radix);
  44         } else {
  45             char[] cs = s.toCharArray();
  46             int limit = Integer.MAX_VALUE / (radix/2);
  47             int n = 0;
  48             for (int i = 0; i < cs.length; i++) {
  49                 int d = Character.digit(cs[i], radix);
  50                 if (n < 0 ||
  51                     n > limit ||
  52                     n * radix > Integer.MAX_VALUE - d)
  53                     throw new NumberFormatException();
  54                 n = n * radix + d;
  55             }
  56             return n;
  57         }
  58     }
  59 
  60     /** Convert string to long integer.
  61      */
  62     public static long string2long(String s, int radix)
  63         throws NumberFormatException {
  64         if (radix == 10) {
  65             return Long.parseLong(s, radix);
  66         } else {
  67             char[] cs = s.toCharArray();
  68             long limit = Long.MAX_VALUE / (radix/2);
  69             long n = 0;
  70             for (int i = 0; i < cs.length; i++) {
  71                 int d = Character.digit(cs[i], radix);
  72                 if (n < 0 ||
  73                     n > limit ||
  74                     n * radix > Long.MAX_VALUE - d)
  75                     throw new NumberFormatException();
  76                 n = n * radix + d;
  77             }
  78             return n;
  79         }
  80     }
  81 
  82 /* Conversion routines between names, strings, and byte arrays in Utf8 format
  83  */
  84 
  85     /** Convert `len' bytes from utf8 to characters.
  86      *  Parameters are as in System.arraycopy
  87      *  Return first index in `dst' past the last copied char.
  88      *  @param src        The array holding the bytes to convert.
  89      *  @param sindex     The start index from which bytes are converted.
  90      *  @param dst        The array holding the converted characters..
  91      *  @param dindex     The start index from which converted characters
  92      *                    are written.
  93      *  @param len        The maximum number of bytes to convert.
  94      */
  95     public static int utf2chars(byte[] src, int sindex,
  96                                 char[] dst, int dindex,
  97                                 int len) {
  98         int i = sindex;
  99         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 }