1/*
2 * Copyright (c) 2005, 2012, 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 * Copyright (C) 2004-2011
27 *
28 * Permission is hereby granted, free of charge, to any person obtaining a copy
29 * of this software and associated documentation files (the "Software"), to deal
30 * in the Software without restriction, including without limitation the rights
31 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32 * copies of the Software, and to permit persons to whom the Software is
33 * furnished to do so, subject to the following conditions:
34 *
35 * The above copyright notice and this permission notice shall be included in
36 * all copies or substantial portions of the Software.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44 * THE SOFTWARE.
45 */
46package com.sun.xml.internal.rngom.xml.util;
47
48public class Naming {
49
50  private Naming() { }
51
52  private static final int CT_NAME = 1;
53  private static final int CT_NMSTRT = 2;
54
55  private static final String nameStartSingles =
56  "\u003a\u005f\u0386\u038c\u03da\u03dc\u03de\u03e0\u0559\u06d5\u093d\u09b2" +
57  "\u0a5e\u0a8d\u0abd\u0ae0\u0b3d\u0b9c\u0cde\u0e30\u0e84\u0e8a\u0e8d\u0ea5" +
58  "\u0ea7\u0eb0\u0ebd\u1100\u1109\u113c\u113e\u1140\u114c\u114e\u1150\u1159" +
59  "\u1163\u1165\u1167\u1169\u1175\u119e\u11a8\u11ab\u11ba\u11eb\u11f0\u11f9" +
60  "\u1f59\u1f5b\u1f5d\u1fbe\u2126\u212e\u3007";
61  private static final String nameStartRanges =
62  "\u0041\u005a\u0061\u007a\u00c0\u00d6\u00d8\u00f6\u00f8\u00ff\u0100\u0131" +
63  "\u0134\u013e\u0141\u0148\u014a\u017e\u0180\u01c3\u01cd\u01f0\u01f4\u01f5" +
64  "\u01fa\u0217\u0250\u02a8\u02bb\u02c1\u0388\u038a\u038e\u03a1\u03a3\u03ce" +
65  "\u03d0\u03d6\u03e2\u03f3\u0401\u040c\u040e\u044f\u0451\u045c\u045e\u0481" +
66  "\u0490\u04c4\u04c7\u04c8\u04cb\u04cc\u04d0\u04eb\u04ee\u04f5\u04f8\u04f9" +
67  "\u0531\u0556\u0561\u0586\u05d0\u05ea\u05f0\u05f2\u0621\u063a\u0641\u064a" +
68  "\u0671\u06b7\u06ba\u06be\u06c0\u06ce\u06d0\u06d3\u06e5\u06e6\u0905\u0939" +
69  "\u0958\u0961\u0985\u098c\u098f\u0990\u0993\u09a8\u09aa\u09b0\u09b6\u09b9" +
70  "\u09dc\u09dd\u09df\u09e1\u09f0\u09f1\u0a05\u0a0a\u0a0f\u0a10\u0a13\u0a28" +
71  "\u0a2a\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59\u0a5c\u0a72\u0a74" +
72  "\u0a85\u0a8b\u0a8f\u0a91\u0a93\u0aa8\u0aaa\u0ab0\u0ab2\u0ab3\u0ab5\u0ab9" +
73  "\u0b05\u0b0c\u0b0f\u0b10\u0b13\u0b28\u0b2a\u0b30\u0b32\u0b33\u0b36\u0b39" +
74  "\u0b5c\u0b5d\u0b5f\u0b61\u0b85\u0b8a\u0b8e\u0b90\u0b92\u0b95\u0b99\u0b9a" +
75  "\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8\u0baa\u0bae\u0bb5\u0bb7\u0bb9\u0c05\u0c0c" +
76  "\u0c0e\u0c10\u0c12\u0c28\u0c2a\u0c33\u0c35\u0c39\u0c60\u0c61\u0c85\u0c8c" +
77  "\u0c8e\u0c90\u0c92\u0ca8\u0caa\u0cb3\u0cb5\u0cb9\u0ce0\u0ce1\u0d05\u0d0c" +
78  "\u0d0e\u0d10\u0d12\u0d28\u0d2a\u0d39\u0d60\u0d61\u0e01\u0e2e\u0e32\u0e33" +
79  "\u0e40\u0e45\u0e81\u0e82\u0e87\u0e88\u0e94\u0e97\u0e99\u0e9f\u0ea1\u0ea3" +
80  "\u0eaa\u0eab\u0ead\u0eae\u0eb2\u0eb3\u0ec0\u0ec4\u0f40\u0f47\u0f49\u0f69" +
81  "\u10a0\u10c5\u10d0\u10f6\u1102\u1103\u1105\u1107\u110b\u110c\u110e\u1112" +
82  "\u1154\u1155\u115f\u1161\u116d\u116e\u1172\u1173\u11ae\u11af\u11b7\u11b8" +
83  "\u11bc\u11c2\u1e00\u1e9b\u1ea0\u1ef9\u1f00\u1f15\u1f18\u1f1d\u1f20\u1f45" +
84  "\u1f48\u1f4d\u1f50\u1f57\u1f5f\u1f7d\u1f80\u1fb4\u1fb6\u1fbc\u1fc2\u1fc4" +
85  "\u1fc6\u1fcc\u1fd0\u1fd3\u1fd6\u1fdb\u1fe0\u1fec\u1ff2\u1ff4\u1ff6\u1ffc" +
86  "\u212a\u212b\u2180\u2182\u3041\u3094\u30a1\u30fa\u3105\u312c\uac00\ud7a3" +
87  "\u4e00\u9fa5\u3021\u3029";
88  private static final String nameSingles =
89  "\u002d\u002e\u05bf\u05c4\u0670\u093c\u094d\u09bc\u09be\u09bf\u09d7\u0a02" +
90  "\u0a3c\u0a3e\u0a3f\u0abc\u0b3c\u0bd7\u0d57\u0e31\u0eb1\u0f35\u0f37\u0f39" +
91  "\u0f3e\u0f3f\u0f97\u0fb9\u20e1\u3099\u309a\u00b7\u02d0\u02d1\u0387\u0640" +
92  "\u0e46\u0ec6\u3005";
93  private static final String nameRanges =
94  "\u0300\u0345\u0360\u0361\u0483\u0486\u0591\u05a1\u05a3\u05b9\u05bb\u05bd" +
95  "\u05c1\u05c2\u064b\u0652\u06d6\u06dc\u06dd\u06df\u06e0\u06e4\u06e7\u06e8" +
96  "\u06ea\u06ed\u0901\u0903\u093e\u094c\u0951\u0954\u0962\u0963\u0981\u0983" +
97  "\u09c0\u09c4\u09c7\u09c8\u09cb\u09cd\u09e2\u09e3\u0a40\u0a42\u0a47\u0a48" +
98  "\u0a4b\u0a4d\u0a70\u0a71\u0a81\u0a83\u0abe\u0ac5\u0ac7\u0ac9\u0acb\u0acd" +
99  "\u0b01\u0b03\u0b3e\u0b43\u0b47\u0b48\u0b4b\u0b4d\u0b56\u0b57\u0b82\u0b83" +
100  "\u0bbe\u0bc2\u0bc6\u0bc8\u0bca\u0bcd\u0c01\u0c03\u0c3e\u0c44\u0c46\u0c48" +
101  "\u0c4a\u0c4d\u0c55\u0c56\u0c82\u0c83\u0cbe\u0cc4\u0cc6\u0cc8\u0cca\u0ccd" +
102  "\u0cd5\u0cd6\u0d02\u0d03\u0d3e\u0d43\u0d46\u0d48\u0d4a\u0d4d\u0e34\u0e3a" +
103  "\u0e47\u0e4e\u0eb4\u0eb9\u0ebb\u0ebc\u0ec8\u0ecd\u0f18\u0f19\u0f71\u0f84" +
104  "\u0f86\u0f8b\u0f90\u0f95\u0f99\u0fad\u0fb1\u0fb7\u20d0\u20dc\u302a\u302f" +
105  "\u0030\u0039\u0660\u0669\u06f0\u06f9\u0966\u096f\u09e6\u09ef\u0a66\u0a6f" +
106  "\u0ae6\u0aef\u0b66\u0b6f\u0be7\u0bef\u0c66\u0c6f\u0ce6\u0cef\u0d66\u0d6f" +
107  "\u0e50\u0e59\u0ed0\u0ed9\u0f20\u0f29\u3031\u3035\u309d\u309e\u30fc\u30fe";
108
109  private final static byte[][] charTypeTable;
110
111  static {
112    charTypeTable = new byte[256][];
113    for (int i = 0; i < nameSingles.length(); i++)
114      setCharType(nameSingles.charAt(i), CT_NAME);
115    for (int i = 0; i < nameRanges.length(); i += 2)
116      setCharType(nameRanges.charAt(i), nameRanges.charAt(i + 1), CT_NAME);
117    for (int i = 0; i < nameStartSingles.length(); i++)
118      setCharType(nameStartSingles.charAt(i), CT_NMSTRT);
119    for (int i = 0; i < nameStartRanges.length(); i += 2)
120      setCharType(nameStartRanges.charAt(i), nameStartRanges.charAt(i + 1),
121                  CT_NMSTRT);
122    byte[] other = new byte[256];
123    for (int i = 0; i < 256; i++)
124      if (charTypeTable[i] == null)
125        charTypeTable[i] = other;
126  }
127
128  private static void setCharType(char c, int type) {
129    int hi = c >> 8;
130    if (charTypeTable[hi] == null)
131      charTypeTable[hi] = new byte[256];
132    charTypeTable[hi][c & 0xFF] = (byte)type;
133  }
134
135  private static void setCharType(char min, char max, int type) {
136    byte[] shared = null;
137    do {
138      if ((min & 0xFF) == 0) {
139        for (; min + 0xFF <= max; min += 0x100) {
140          if (shared == null) {
141            shared = new byte[256];
142            for (int i = 0; i < 256; i++)
143              shared[i] = (byte)type;
144          }
145          charTypeTable[min >> 8] = shared;
146          if (min + 0xFF == max)
147            return;
148        }
149      }
150      setCharType(min, type);
151    } while (min++ != max);
152  }
153
154  private static boolean isNameStartChar(char c) {
155    return charTypeTable[c >> 8][c & 0xff] == CT_NMSTRT;
156  }
157
158  private static boolean isNameStartCharNs(char c) {
159    return isNameStartChar(c) && c != ':';
160  }
161
162  private static boolean isNameChar(char c) {
163    return charTypeTable[c >> 8][c & 0xff] != 0;
164  }
165
166  private static boolean isNameCharNs(char c) {
167    return isNameChar(c) && c != ':';
168  }
169
170  public static boolean isName(String s) {
171    int len = s.length();
172    if (len == 0)
173      return false;
174    if (!isNameStartChar(s.charAt(0)))
175      return false;
176    for (int i = 1; i < len; i++)
177      if (!isNameChar(s.charAt(i)))
178        return false;
179    return true;
180  }
181
182  public static boolean isNmtoken(String s) {
183    int len = s.length();
184    if (len == 0)
185      return false;
186    for (int i = 0; i < len; i++)
187      if (!isNameChar(s.charAt(i)))
188        return false;
189    return true;
190  }
191
192  public static boolean isNcname(String s) {
193    int len = s.length();
194    if (len == 0)
195      return false;
196    if (!isNameStartCharNs(s.charAt(0)))
197      return false;
198    for (int i = 1; i < len; i++)
199      if (!isNameCharNs(s.charAt(i)))
200        return false;
201    return true;
202  }
203
204  public static boolean isQname(String s) {
205    int len = s.length();
206    if (len == 0)
207      return false;
208    if (!isNameStartCharNs(s.charAt(0)))
209      return false;
210    for (int i = 1; i < len; i++) {
211      char c = s.charAt(i);
212      if (!isNameChar(c)) {
213        if (c == ':' && ++i < len && isNameStartCharNs(s.charAt(i))) {
214          for (++i; i < len; i++)
215            if (!isNameCharNs(s.charAt(i)))
216              return false;
217          return true;
218        }
219        return false;
220      }
221    }
222    return true;
223  }
224
225
226}
227