UCharacter.java revision 10444:f08705540498
1/*
2 * Copyright (c) 2009, 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 *******************************************************************************
27 * (C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved         *
28 *                                                                             *
29 * The original version of this source code and documentation is copyrighted   *
30 * and owned by IBM, These materials are provided under terms of a License     *
31 * Agreement between IBM and Sun. This technology is protected by multiple     *
32 * US and International patents. This notice and attribution to IBM may not    *
33 * to removed.                                                                 *
34 *******************************************************************************
35 */
36
37package sun.text.normalizer;
38
39import java.io.IOException;
40import java.util.MissingResourceException;
41
42/**
43 * <p>
44 * The UCharacter class provides extensions to the
45 * <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Character.html">
46 * java.lang.Character</a> class. These extensions provide support for
47 * more Unicode properties and together with the <a href=../text/UTF16.html>UTF16</a>
48 * class, provide support for supplementary characters (those with code
49 * points above U+FFFF).
50 * Each ICU release supports the latest version of Unicode available at that time.
51 * </p>
52 * <p>
53 * Code points are represented in these API using ints. While it would be
54 * more convenient in Java to have a separate primitive datatype for them,
55 * ints suffice in the meantime.
56 * </p>
57 * <p>
58 * To use this class please add the jar file name icu4j.jar to the
59 * class path, since it contains data files which supply the information used
60 * by this file.<br>
61 * E.g. In Windows <br>
62 * <code>set CLASSPATH=%CLASSPATH%;$JAR_FILE_PATH/ucharacter.jar</code>.<br>
63 * Otherwise, another method would be to copy the files uprops.dat and
64 * unames.icu from the icu4j source subdirectory
65 * <i>$ICU4J_SRC/src/com.ibm.icu.impl.data</i> to your class directory
66 * <i>$ICU4J_CLASS/com.ibm.icu.impl.data</i>.
67 * </p>
68 * <p>
69 * Aside from the additions for UTF-16 support, and the updated Unicode
70 * properties, the main differences between UCharacter and Character are:
71 * <ul>
72 * <li> UCharacter is not designed to be a char wrapper and does not have
73 *      APIs to which involves management of that single char.<br>
74 *      These include:
75 *      <ul>
76 *        <li> char charValue(),
77 *        <li> int compareTo(java.lang.Character, java.lang.Character), etc.
78 *      </ul>
79 * <li> UCharacter does not include Character APIs that are deprecated, nor
80 *      does it include the Java-specific character information, such as
81 *      boolean isJavaIdentifierPart(char ch).
82 * <li> Character maps characters 'A' - 'Z' and 'a' - 'z' to the numeric
83 *      values '10' - '35'. UCharacter also does this in digit and
84 *      getNumericValue, to adhere to the java semantics of these
85 *      methods.  New methods unicodeDigit, and
86 *      getUnicodeNumericValue do not treat the above code points
87 *      as having numeric values.  This is a semantic change from ICU4J 1.3.1.
88 * </ul>
89 * <p>
90 * Further detail differences can be determined from the program
91 *        <a href="http://source.icu-project.org/repos/icu/icu4j/trunk/src/com/ibm/icu/dev/test/lang/UCharacterCompare.java">
92 *        com.ibm.icu.dev.test.lang.UCharacterCompare</a>
93 * </p>
94 * <p>
95 * In addition to Java compatibility functions, which calculate derived properties,
96 * this API provides low-level access to the Unicode Character Database.
97 * </p>
98 * <p>
99 * Unicode assigns each code point (not just assigned character) values for
100 * many properties.
101 * Most of them are simple boolean flags, or constants from a small enumerated list.
102 * For some properties, values are strings or other relatively more complex types.
103 * </p>
104 * <p>
105 * For more information see
106 * "About the Unicode Character Database" (http://www.unicode.org/ucd/)
107 * and the ICU User Guide chapter on Properties (http://www.icu-project.org/userguide/properties.html).
108 * </p>
109 * <p>
110 * There are also functions that provide easy migration from C/POSIX functions
111 * like isblank(). Their use is generally discouraged because the C/POSIX
112 * standards do not define their semantics beyond the ASCII range, which means
113 * that different implementations exhibit very different behavior.
114 * Instead, Unicode properties should be used directly.
115 * </p>
116 * <p>
117 * There are also only a few, broad C/POSIX character classes, and they tend
118 * to be used for conflicting purposes. For example, the "isalpha()" class
119 * is sometimes used to determine word boundaries, while a more sophisticated
120 * approach would at least distinguish initial letters from continuation
121 * characters (the latter including combining marks).
122 * (In ICU, BreakIterator is the most sophisticated API for word boundaries.)
123 * Another example: There is no "istitle()" class for titlecase characters.
124 * </p>
125 * <p>
126 * ICU 3.4 and later provides API access for all twelve C/POSIX character classes.
127 * ICU implements them according to the Standard Recommendations in
128 * Annex C: Compatibility Properties of UTS #18 Unicode Regular Expressions
129 * (http://www.unicode.org/reports/tr18/#Compatibility_Properties).
130 * </p>
131 * <p>
132 * API access for C/POSIX character classes is as follows:
133 * - alpha:     isUAlphabetic(c) or hasBinaryProperty(c, UProperty.ALPHABETIC)
134 * - lower:     isULowercase(c) or hasBinaryProperty(c, UProperty.LOWERCASE)
135 * - upper:     isUUppercase(c) or hasBinaryProperty(c, UProperty.UPPERCASE)
136 * - punct:     ((1<<getType(c)) & ((1<<DASH_PUNCTUATION)|(1<<START_PUNCTUATION)|(1<<END_PUNCTUATION)|(1<<CONNECTOR_PUNCTUATION)|(1<<OTHER_PUNCTUATION)|(1<<INITIAL_PUNCTUATION)|(1<<FINAL_PUNCTUATION)))!=0
137 * - digit:     isDigit(c) or getType(c)==DECIMAL_DIGIT_NUMBER
138 * - xdigit:    hasBinaryProperty(c, UProperty.POSIX_XDIGIT)
139 * - alnum:     hasBinaryProperty(c, UProperty.POSIX_ALNUM)
140 * - space:     isUWhiteSpace(c) or hasBinaryProperty(c, UProperty.WHITE_SPACE)
141 * - blank:     hasBinaryProperty(c, UProperty.POSIX_BLANK)
142 * - cntrl:     getType(c)==CONTROL
143 * - graph:     hasBinaryProperty(c, UProperty.POSIX_GRAPH)
144 * - print:     hasBinaryProperty(c, UProperty.POSIX_PRINT)
145 * </p>
146 * <p>
147 * The C/POSIX character classes are also available in UnicodeSet patterns,
148 * using patterns like [:graph:] or \p{graph}.
149 * </p>
150 * <p>
151 * Note: There are several ICU (and Java) whitespace functions.
152 * Comparison:
153 * - isUWhiteSpace=UCHAR_WHITE_SPACE: Unicode White_Space property;
154 *       most of general categories "Z" (separators) + most whitespace ISO controls
155 *       (including no-break spaces, but excluding IS1..IS4 and ZWSP)
156 * - isWhitespace: Java isWhitespace; Z + whitespace ISO controls but excluding no-break spaces
157 * - isSpaceChar: just Z (including no-break spaces)
158 * </p>
159 * <p>
160 * This class is not subclassable
161 * </p>
162 * @author Syn Wee Quek
163 * @stable ICU 2.1
164 * @see com.ibm.icu.lang.UCharacterEnums
165 */
166
167public final class UCharacter
168{
169
170    /**
171     * Numeric Type constants.
172     * @see UProperty#NUMERIC_TYPE
173     * @stable ICU 2.4
174     */
175    public static interface NumericType
176    {
177        /**
178         * @stable ICU 2.4
179         */
180        public static final int DECIMAL = 1;
181    }
182
183    // public data members -----------------------------------------------
184
185    /**
186     * The lowest Unicode code point value.
187     * @stable ICU 2.1
188     */
189    public static final int MIN_VALUE = UTF16.CODEPOINT_MIN_VALUE;
190
191    /**
192     * The highest Unicode code point value (scalar value) according to the
193     * Unicode Standard.
194     * This is a 21-bit value (21 bits, rounded up).<br>
195     * Up-to-date Unicode implementation of java.lang.Character.MIN_VALUE
196     * @stable ICU 2.1
197     */
198    public static final int MAX_VALUE = UTF16.CODEPOINT_MAX_VALUE;
199
200    /**
201     * The minimum value for Supplementary code points
202     * @stable ICU 2.1
203     */
204    public static final int SUPPLEMENTARY_MIN_VALUE =
205        UTF16.SUPPLEMENTARY_MIN_VALUE;
206
207    // public methods ----------------------------------------------------
208
209    /**
210     * Retrieves the numeric value of a decimal digit code point.
211     * <br>This method observes the semantics of
212     * <code>java.lang.Character.digit()</code>.  Note that this
213     * will return positive values for code points for which isDigit
214     * returns false, just like java.lang.Character.
215     * <br><em>Semantic Change:</em> In release 1.3.1 and
216     * prior, this did not treat the European letters as having a
217     * digit value, and also treated numeric letters and other numbers as
218     * digits.
219     * This has been changed to conform to the java semantics.
220     * <br>A code point is a valid digit if and only if:
221     * <ul>
222     *   <li>ch is a decimal digit or one of the european letters, and
223     *   <li>the value of ch is less than the specified radix.
224     * </ul>
225     * @param ch the code point to query
226     * @param radix the radix
227     * @return the numeric value represented by the code point in the
228     * specified radix, or -1 if the code point is not a decimal digit
229     * or if its value is too large for the radix
230     * @stable ICU 2.1
231     */
232    public static int digit(int ch, int radix)
233    {
234        // when ch is out of bounds getProperty == 0
235        int props = getProperty(ch);
236        int value;
237        if (getNumericType(props) == NumericType.DECIMAL) {
238            value = UCharacterProperty.getUnsignedValue(props);
239        } else {
240            value = getEuropeanDigit(ch);
241        }
242        return (0 <= value && value < radix) ? value : -1;
243    }
244
245    /**
246     * Returns the Bidirection property of a code point.
247     * For example, 0x0041 (letter A) has the LEFT_TO_RIGHT directional
248     * property.<br>
249     * Result returned belongs to the interface
250     * <a href=UCharacterDirection.html>UCharacterDirection</a>
251     * @param ch the code point to be determined its direction
252     * @return direction constant from UCharacterDirection.
253     * @stable ICU 2.1
254     */
255    public static int getDirection(int ch)
256    {
257        return gBdp.getClass(ch);
258    }
259
260    /**
261     * Returns a code point corresponding to the two UTF16 characters.
262     * @param lead the lead char
263     * @param trail the trail char
264     * @return code point if surrogate characters are valid.
265     * @exception IllegalArgumentException thrown when argument characters do
266     *            not form a valid codepoint
267     * @stable ICU 2.1
268     */
269    public static int getCodePoint(char lead, char trail)
270    {
271        if (UTF16.isLeadSurrogate(lead) && UTF16.isTrailSurrogate(trail)) {
272            return UCharacterProperty.getRawSupplementary(lead, trail);
273        }
274        throw new IllegalArgumentException("Illegal surrogate characters");
275    }
276
277    /**
278     * <p>Get the "age" of the code point.</p>
279     * <p>The "age" is the Unicode version when the code point was first
280     * designated (as a non-character or for Private Use) or assigned a
281     * character.
282     * <p>This can be useful to avoid emitting code points to receiving
283     * processes that do not accept newer characters.</p>
284     * <p>The data is from the UCD file DerivedAge.txt.</p>
285     * @param ch The code point.
286     * @return the Unicode version number
287     * @stable ICU 2.6
288     */
289    public static VersionInfo getAge(int ch)
290    {
291        if (ch < MIN_VALUE || ch > MAX_VALUE) {
292        throw new IllegalArgumentException("Codepoint out of bounds");
293        }
294        return PROPERTY_.getAge(ch);
295    }
296
297    // private variables -------------------------------------------------
298
299    /**
300     * Database storing the sets of character property
301     */
302    private static final UCharacterProperty PROPERTY_;
303    /**
304     * For optimization
305     */
306    private static final char[] PROPERTY_TRIE_INDEX_;
307    private static final char[] PROPERTY_TRIE_DATA_;
308    private static final int PROPERTY_INITIAL_VALUE_;
309
310    private static final UBiDiProps gBdp;
311
312    // block to initialise character property database
313    static
314    {
315        try
316        {
317            PROPERTY_ = UCharacterProperty.getInstance();
318            PROPERTY_TRIE_INDEX_ = PROPERTY_.m_trieIndex_;
319            PROPERTY_TRIE_DATA_ = PROPERTY_.m_trieData_;
320            PROPERTY_INITIAL_VALUE_ = PROPERTY_.m_trieInitialValue_;
321        }
322        catch (Exception e)
323        {
324            throw new MissingResourceException(e.getMessage(),"","");
325        }
326
327        UBiDiProps bdp;
328        try {
329            bdp=UBiDiProps.getSingleton();
330        } catch(IOException e) {
331            bdp=UBiDiProps.getDummy();
332        }
333        gBdp=bdp;
334    }
335
336    /**
337     * Shift to get numeric type
338     */
339    private static final int NUMERIC_TYPE_SHIFT_ = 5;
340    /**
341     * Mask to get numeric type
342     */
343    private static final int NUMERIC_TYPE_MASK_ = 0x7 << NUMERIC_TYPE_SHIFT_;
344
345    // private methods ---------------------------------------------------
346
347    /**
348     * Getting the digit values of characters like 'A' - 'Z', normal,
349     * half-width and full-width. This method assumes that the other digit
350     * characters are checked by the calling method.
351     * @param ch character to test
352     * @return -1 if ch is not a character of the form 'A' - 'Z', otherwise
353     *         its corresponding digit will be returned.
354     */
355    private static int getEuropeanDigit(int ch) {
356        if ((ch > 0x7a && ch < 0xff21)
357            || ch < 0x41 || (ch > 0x5a && ch < 0x61)
358            || ch > 0xff5a || (ch > 0xff3a && ch < 0xff41)) {
359            return -1;
360        }
361        if (ch <= 0x7a) {
362            // ch >= 0x41 or ch < 0x61
363            return ch + 10 - ((ch <= 0x5a) ? 0x41 : 0x61);
364        }
365        // ch >= 0xff21
366        if (ch <= 0xff3a) {
367            return ch + 10 - 0xff21;
368        }
369        // ch >= 0xff41 && ch <= 0xff5a
370        return ch + 10 - 0xff41;
371    }
372
373    /**
374     * Gets the numeric type of the property argument
375     * @param props 32 bit property
376     * @return the numeric type
377     */
378    private static int getNumericType(int props)
379    {
380        return (props & NUMERIC_TYPE_MASK_) >> NUMERIC_TYPE_SHIFT_;
381    }
382
383    /**
384     * Gets the property value at the index.
385     * This is optimized.
386     * Note this is alittle different from CharTrie the index m_trieData_
387     * is never negative.
388     * This is a duplicate of UCharacterProperty.getProperty. For optimization
389     * purposes, this method calls the trie data directly instead of through
390     * UCharacterProperty.getProperty.
391     * @param ch code point whose property value is to be retrieved
392     * @return property value of code point
393     * @stable ICU 2.6
394     */
395    private static final int getProperty(int ch)
396    {
397        if (ch < UTF16.LEAD_SURROGATE_MIN_VALUE
398            || (ch > UTF16.LEAD_SURROGATE_MAX_VALUE
399                && ch < UTF16.SUPPLEMENTARY_MIN_VALUE)) {
400            // BMP codepoint 0000..D7FF or DC00..FFFF
401            try { // using try for ch < 0 is faster than using an if statement
402                return PROPERTY_TRIE_DATA_[
403                              (PROPERTY_TRIE_INDEX_[ch >> 5] << 2)
404                              + (ch & 0x1f)];
405            } catch (ArrayIndexOutOfBoundsException e) {
406                return PROPERTY_INITIAL_VALUE_;
407            }
408        }
409        if (ch <= UTF16.LEAD_SURROGATE_MAX_VALUE) {
410            // lead surrogate D800..DBFF
411            return PROPERTY_TRIE_DATA_[
412                              (PROPERTY_TRIE_INDEX_[(0x2800 >> 5) + (ch >> 5)] << 2)
413                              + (ch & 0x1f)];
414        }
415        // for optimization
416        if (ch <= UTF16.CODEPOINT_MAX_VALUE) {
417            // supplementary code point 10000..10FFFF
418            // look at the construction of supplementary characters
419            // trail forms the ends of it.
420            return PROPERTY_.m_trie_.getSurrogateValue(
421                                      UTF16.getLeadSurrogate(ch),
422                                      (char)(ch & 0x3ff));
423        }
424        // return m_dataOffset_ if there is an error, in this case we return
425        // the default value: m_initialValue_
426        // we cannot assume that m_initialValue_ is at offset 0
427        // this is for optimization.
428        return PROPERTY_INITIAL_VALUE_;
429    }
430
431}
432