1 /* 2 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package build.tools.generatecharacter; 27 28 import java.lang.reflect.*; 29 import java.util.*; 30 31 /** Recovers and prints ranges for certain java.lang.Character 32 properties. Useful for generating fast-path Latin-1 code. */ 33 34 public class PrintCharacterRanges { 35 static class BooleanRange { 36 private int begin; 37 private int end; 38 39 BooleanRange(int begin, int end) { 40 this.begin = begin; 41 this.end = end; 42 } 43 44 int begin() { return begin; } 45 int end() { return end; } 46 } 47 48 private static List/*<BooleanRange>*/ recoverBooleanRanges(String methodName) throws Exception { 49 List result = new ArrayList(); 50 int currentRangeStart = -1; 51 Method method = Character.class.getDeclaredMethod(methodName, new Class[] { Character.TYPE }); 52 if (method == null) { 53 throw new RuntimeException("No method \"" + methodName + "\"(C) found"); 54 } 55 56 for (int i = 0; i <= 255; i++) { 57 boolean methodRes = ((Boolean) method.invoke(null, new Object[] { new Character((char) i) })).booleanValue(); 58 if (methodRes) { 59 if (currentRangeStart < 0) { 60 currentRangeStart = i; 61 } 62 if (i == 255) { 63 result.add(new BooleanRange(currentRangeStart, i)); 64 } 65 } else { 66 if (currentRangeStart >= 0) { 67 result.add(new BooleanRange(currentRangeStart, i - 1)); 68 currentRangeStart = -1; 69 } 70 } 71 } 72 73 return result; 74 } 75 76 private static String describe(int num) { 77 StringBuffer s = new StringBuffer(); 78 s.append(num); 79 s.append(" ('"); 80 if (num > 32 && num < 123) { 81 s.append((char) num); 82 } else { 83 s.append("\\u"); 84 String hex = Long.toHexString(num).toUpperCase(); 85 for (int i = 0; i < (4 - hex.length()); i++) { 86 s.append('0'); 87 } 88 s.append(hex); 89 } 90 s.append("')"); 91 return s.toString(); 92 } 93 94 private static void printBooleanRanges(List/*<BooleanRange>*/ ranges, String methodName) { 95 System.out.print(methodName + ":"); 96 for (Iterator iter = ranges.iterator(); iter.hasNext();) { 97 BooleanRange range = (BooleanRange) iter.next(); 98 System.out.print(" [ " + describe(range.begin()) + ", " + describe(range.end()) + " ]"); 99 } 100 System.out.println(""); 101 } 102 103 private static void recoverAndPrintBooleanRanges(String methodName) throws Exception { 104 List ranges = recoverBooleanRanges(methodName); 105 printBooleanRanges(ranges, methodName); 106 } 107 108 static class ShiftRange { 109 private int begin; 110 private int end; 111 private int offset; 112 113 ShiftRange(int begin, int end, int offset) { 114 this.begin = begin; 115 this.end = end; 116 this.offset = offset; 117 } 118 119 int begin() { return begin; } 120 int end() { return end; } 121 int offset() { return offset; } 122 } 123 124 private static List/*<ShiftRange>*/ recoverShiftRanges(String methodName) throws Exception { 125 List result = new ArrayList(); 126 int currentRangeStart = -1; 127 int currentRangeOffset = -1; 128 Method method = Character.class.getDeclaredMethod(methodName, new Class[] { Character.TYPE }); 129 if (method == null) { 130 throw new RuntimeException("No method \"" + methodName + "\"(C) found"); 131 } 132 133 for (int i = 0; i <= 255; i++) { 134 char methodRes = ((Character) method.invoke(null, new Object[] { new Character((char) i) })).charValue(); 135 if (methodRes != i) { 136 int offset = methodRes - i; 137 if (currentRangeStart < 0) { 138 currentRangeStart = i; 139 } else if (offset != currentRangeOffset) { 140 result.add(new ShiftRange(currentRangeStart, i - 1, currentRangeOffset)); 141 currentRangeStart = i; 142 } 143 currentRangeOffset = offset; 144 if (i == 255) { 145 result.add(new ShiftRange(currentRangeStart, i, currentRangeOffset)); 146 } 147 } else { 148 if (currentRangeStart >= 0) { 149 result.add(new ShiftRange(currentRangeStart, i - 1, currentRangeOffset)); 150 currentRangeStart = -1; 151 } 152 } 153 } 154 155 return result; 156 } 157 158 private static void printShiftRanges(List/*<ShiftRange>*/ ranges, String methodName) { 159 System.out.print(methodName + ":"); 160 boolean isFirst = true; 161 for (Iterator iter = ranges.iterator(); iter.hasNext();) { 162 ShiftRange range = (ShiftRange) iter.next(); 163 if (isFirst) { 164 isFirst = false; 165 } else { 166 System.out.print(", "); 167 } 168 System.out.print(" [ " + describe(range.begin()) + ", " + describe(range.end()) + " ] -> [ " + 169 describe((range.begin() + range.offset())) + ", " + describe((range.end() + range.offset())) + " ] (" + 170 range.offset() + ")"); 171 } 172 System.out.println(""); 173 } 174 175 private static void recoverAndPrintShiftRanges(String methodName) throws Exception { 176 List ranges = recoverShiftRanges(methodName); 177 printShiftRanges(ranges, methodName); 178 } 179 180 public static void main(String[] args) { 181 try { 182 recoverAndPrintBooleanRanges("isDefined"); 183 recoverAndPrintBooleanRanges("isDigit"); 184 recoverAndPrintBooleanRanges("isIdentifierIgnorable"); 185 recoverAndPrintBooleanRanges("isISOControl"); 186 recoverAndPrintBooleanRanges("isJavaIdentifierPart"); 187 recoverAndPrintBooleanRanges("isJavaIdentifierStart"); 188 recoverAndPrintBooleanRanges("isLetter"); 189 recoverAndPrintBooleanRanges("isLetterOrDigit"); 190 recoverAndPrintBooleanRanges("isLowerCase"); 191 recoverAndPrintBooleanRanges("isMirrored"); 192 recoverAndPrintBooleanRanges("isSpaceChar"); 193 recoverAndPrintBooleanRanges("isTitleCase"); 194 recoverAndPrintBooleanRanges("isUnicodeIdentifierPart"); 195 recoverAndPrintBooleanRanges("isUnicodeIdentifierStart"); 196 recoverAndPrintBooleanRanges("isUpperCase"); 197 recoverAndPrintBooleanRanges("isWhitespace"); 198 199 recoverAndPrintShiftRanges("toUpperCase"); 200 recoverAndPrintShiftRanges("toLowerCase"); 201 } catch (Exception e) { 202 e.printStackTrace(); 203 } 204 } 205 }