Path: blob/master/src/java.base/share/classes/java/text/PatternEntry.java
41152 views
/*1* Copyright (c) 1996, 2000, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved27* (C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved28*29* The original version of this source code and documentation is copyrighted30* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These31* materials are provided under terms of a License Agreement between Taligent32* and Sun. This technology is protected by multiple US and International33* patents. This notice and attribution to Taligent may not be removed.34* Taligent is a registered trademark of Taligent, Inc.35*36*/3738package java.text;3940import java.lang.Character;4142/**43* Utility class for normalizing and merging patterns for collation.44* This is to be used with MergeCollation for adding patterns to an45* existing rule table.46* @see MergeCollation47* @author Mark Davis, Helena Shih48*/4950class PatternEntry {51/**52* Gets the current extension, quoted53*/54public void appendQuotedExtension(StringBuffer toAddTo) {55appendQuoted(extension,toAddTo);56}5758/**59* Gets the current chars, quoted60*/61public void appendQuotedChars(StringBuffer toAddTo) {62appendQuoted(chars,toAddTo);63}6465/**66* WARNING this is used for searching in a Vector.67* Because Vector.indexOf doesn't take a comparator,68* this method is ill-defined and ignores strength.69*/70public boolean equals(Object obj) {71if (obj == null) return false;72PatternEntry other = (PatternEntry) obj;73boolean result = chars.equals(other.chars);74return result;75}7677public int hashCode() {78return chars.hashCode();79}8081/**82* For debugging.83*/84public String toString() {85StringBuffer result = new StringBuffer();86addToBuffer(result, true, false, null);87return result.toString();88}8990/**91* Gets the strength of the entry.92*/93final int getStrength() {94return strength;95}9697/**98* Gets the expanding characters of the entry.99*/100final String getExtension() {101return extension;102}103104/**105* Gets the core characters of the entry.106*/107final String getChars() {108return chars;109}110111// ===== privates =====112113void addToBuffer(StringBuffer toAddTo,114boolean showExtension,115boolean showWhiteSpace,116PatternEntry lastEntry)117{118if (showWhiteSpace && toAddTo.length() > 0)119if (strength == Collator.PRIMARY || lastEntry != null)120toAddTo.append('\n');121else122toAddTo.append(' ');123if (lastEntry != null) {124toAddTo.append('&');125if (showWhiteSpace)126toAddTo.append(' ');127lastEntry.appendQuotedChars(toAddTo);128appendQuotedExtension(toAddTo);129if (showWhiteSpace)130toAddTo.append(' ');131}132var c = switch (strength) {133case Collator.IDENTICAL -> '=';134case Collator.TERTIARY -> ',';135case Collator.SECONDARY -> ';';136case Collator.PRIMARY -> '<';137case RESET -> '&';138case UNSET -> '?';139140default -> throw new IllegalStateException("Unexpected value: " + strength);141};142toAddTo.append(c);143144if (showWhiteSpace)145toAddTo.append(' ');146appendQuoted(chars,toAddTo);147if (showExtension && !extension.isEmpty()) {148toAddTo.append('/');149appendQuoted(extension,toAddTo);150}151}152153static void appendQuoted(String chars, StringBuffer toAddTo) {154boolean inQuote = false;155char ch = chars.charAt(0);156if (Character.isSpaceChar(ch)) {157inQuote = true;158toAddTo.append('\'');159} else {160if (PatternEntry.isSpecialChar(ch)) {161inQuote = true;162toAddTo.append('\'');163} else {164switch (ch) {165case 0x0010: case '\f': case '\r':166case '\t': case '\n': case '@':167inQuote = true;168toAddTo.append('\'');169break;170case '\'':171inQuote = true;172toAddTo.append('\'');173break;174default:175if (inQuote) {176inQuote = false; toAddTo.append('\'');177}178break;179}180}181}182toAddTo.append(chars);183if (inQuote)184toAddTo.append('\'');185}186187//========================================================================188// Parsing a pattern into a list of PatternEntries....189//========================================================================190191PatternEntry(int strength,192StringBuffer chars,193StringBuffer extension)194{195this.strength = strength;196this.chars = chars.toString();197this.extension = (extension.length() > 0) ? extension.toString()198: "";199}200201static class Parser {202private String pattern;203private int i;204205public Parser(String pattern) {206this.pattern = pattern;207this.i = 0;208}209210public PatternEntry next() throws ParseException {211int newStrength = UNSET;212213newChars.setLength(0);214newExtension.setLength(0);215216boolean inChars = true;217boolean inQuote = false;218mainLoop:219while (i < pattern.length()) {220char ch = pattern.charAt(i);221if (inQuote) {222if (ch == '\'') {223inQuote = false;224} else {225if (newChars.length() == 0) newChars.append(ch);226else if (inChars) newChars.append(ch);227else newExtension.append(ch);228}229} else switch (ch) {230case '=': if (newStrength != UNSET) break mainLoop;231newStrength = Collator.IDENTICAL; break;232case ',': if (newStrength != UNSET) break mainLoop;233newStrength = Collator.TERTIARY; break;234case ';': if (newStrength != UNSET) break mainLoop;235newStrength = Collator.SECONDARY; break;236case '<': if (newStrength != UNSET) break mainLoop;237newStrength = Collator.PRIMARY; break;238case '&': if (newStrength != UNSET) break mainLoop;239newStrength = RESET; break;240case '\t':241case '\n':242case '\f':243case '\r':244case ' ': break; // skip whitespace TODO use Character245case '/': inChars = false; break;246case '\'':247inQuote = true;248ch = pattern.charAt(++i);249if (newChars.length() == 0) newChars.append(ch);250else if (inChars) newChars.append(ch);251else newExtension.append(ch);252break;253default:254if (newStrength == UNSET) {255throw new ParseException256("missing char (=,;<&) : " +257pattern.substring(i,258(i+10 < pattern.length()) ?259i+10 : pattern.length()),260i);261}262if (PatternEntry.isSpecialChar(ch) && (inQuote == false))263throw new ParseException264("Unquoted punctuation character : " + Integer.toString(ch, 16), i);265if (inChars) {266newChars.append(ch);267} else {268newExtension.append(ch);269}270break;271}272i++;273}274if (newStrength == UNSET)275return null;276if (newChars.length() == 0) {277throw new ParseException278("missing chars (=,;<&): " +279pattern.substring(i,280(i+10 < pattern.length()) ?281i+10 : pattern.length()),282i);283}284285return new PatternEntry(newStrength, newChars, newExtension);286}287288// We re-use these objects in order to improve performance289private StringBuffer newChars = new StringBuffer();290private StringBuffer newExtension = new StringBuffer();291292}293294static boolean isSpecialChar(char ch) {295return ((ch == '\u0020') ||296((ch <= '\u002F') && (ch >= '\u0022')) ||297((ch <= '\u003F') && (ch >= '\u003A')) ||298((ch <= '\u0060') && (ch >= '\u005B')) ||299((ch <= '\u007E') && (ch >= '\u007B')));300}301302303static final int RESET = -2;304static final int UNSET = -1;305306int strength = UNSET;307String chars = "";308String extension = "";309}310311312