]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/charset/src/com/ibm/icu/charset/CharsetICU.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / charset / src / com / ibm / icu / charset / CharsetICU.java
1 /**\r
2 *******************************************************************************\r
3 * Copyright (C) 2006-2009, International Business Machines Corporation and    *\r
4 * others. All Rights Reserved.                                                *\r
5 *******************************************************************************\r
6 *\r
7 *******************************************************************************\r
8 */ \r
9 \r
10 package com.ibm.icu.charset;\r
11 \r
12 import java.lang.reflect.Constructor;\r
13 import java.lang.reflect.InvocationTargetException;\r
14 import java.nio.charset.Charset;\r
15 import java.nio.charset.IllegalCharsetNameException;\r
16 import java.nio.charset.UnsupportedCharsetException;\r
17 import java.util.HashMap;\r
18 \r
19 import com.ibm.icu.text.UnicodeSet;\r
20 \r
21 /**\r
22  * <p>A subclass of java.nio.Charset for providing implementation of ICU's charset converters.\r
23  * This API is used to convert codepage or character encoded data to and\r
24  * from UTF-16. You can open a converter with {@link Charset#forName } and {@link #forNameICU }. With that\r
25  * converter, you can get its properties, set options, convert your data.</p>\r
26  *\r
27  * <p>Since many software programs recogize different converter names for\r
28  * different types of converters, there are other functions in this API to\r
29  * iterate over the converter aliases. \r
30  * \r
31  * @stable ICU 3.6\r
32  */\r
33 public abstract class CharsetICU extends Charset{\r
34 \r
35      String icuCanonicalName;\r
36      String javaCanonicalName;\r
37      int options;\r
38 \r
39      float  maxCharsPerByte;\r
40     \r
41      String name; /* +4: 60  internal name of the converter- invariant chars */\r
42 \r
43      int codepage;               /* +64: 4 codepage # (now IBM-$codepage) */\r
44 \r
45      byte platform;                /* +68: 1 platform of the converter (only IBM now) */\r
46      byte conversionType;          /* +69: 1 conversion type */\r
47 \r
48      int minBytesPerChar;         /* +70: 1 Minimum # bytes per char in this codepage */\r
49      int maxBytesPerChar;         /* +71: 1 Maximum # bytes output per UChar in this codepage */\r
50 \r
51      byte subChar[/*UCNV_MAX_SUBCHAR_LEN*/]; /* +72: 4  [note:  4 and 8 byte boundary] */\r
52      byte subCharLen;              /* +76: 1 */\r
53     \r
54      byte hasToUnicodeFallback;   /* +77: 1 UBool needs to be changed to UBool to be consistent across platform */\r
55      byte hasFromUnicodeFallback; /* +78: 1 */\r
56      short unicodeMask;            /* +79: 1  bit 0: has supplementary  bit 1: has single surrogates */\r
57      byte subChar1;               /* +80: 1  single-byte substitution character for IBM MBCS (0 if none) */\r
58      //byte reserved[/*19*/];           /* +81: 19 to round out the structure */\r
59      \r
60      \r
61     // typedef enum UConverterUnicodeSet {\r
62      /** \r
63       * Parameter that select the set of roundtrippable Unicode code points. \r
64       * @stable ICU 4.0\r
65       */\r
66       public static final int ROUNDTRIP_SET=0; \r
67       /**\r
68        * Select the set of Unicode code points with roundtrip or fallback mappings.\r
69        * Not supported at this point.\r
70        * @internal\r
71        * @deprecated This API is ICU internal only.\r
72        */\r
73       public static final int ROUNDTRIP_AND_FALLBACK_SET =1;\r
74       \r
75     //} UConverterUnicodeSet;\r
76      \r
77     /**\r
78      * \r
79      * @param icuCanonicalName\r
80      * @param canonicalName\r
81      * @param aliases\r
82      * @stable ICU 3.6\r
83      */\r
84     protected CharsetICU(String icuCanonicalName, String canonicalName, String[] aliases) {\r
85         super(canonicalName,aliases);\r
86         if(canonicalName.length() == 0){\r
87             throw new IllegalCharsetNameException(canonicalName);\r
88         }\r
89         this.javaCanonicalName = canonicalName;\r
90         this.icuCanonicalName  = icuCanonicalName;\r
91     }\r
92     \r
93     /**\r
94      * Ascertains if a charset is a sub set of this charset\r
95      * Implements the abstract method of super class.\r
96      * @param cs charset to test\r
97      * @return true if the given charset is a subset of this charset\r
98      * @stable ICU 3.6\r
99      */\r
100     public boolean contains(Charset cs){\r
101         if (null == cs) {\r
102             return false;\r
103         } else if (this.equals(cs)) {\r
104             return true;\r
105         }\r
106         return false;\r
107     }\r
108     private static final HashMap<String, String> algorithmicCharsets = new HashMap<String, String>();\r
109     static{\r
110         algorithmicCharsets.put("LMBCS-1",               "com.ibm.icu.charset.CharsetLMBCS");\r
111         algorithmicCharsets.put("LMBCS-2",               "com.ibm.icu.charset.CharsetLMBCS");\r
112         algorithmicCharsets.put("LMBCS-3",               "com.ibm.icu.charset.CharsetLMBCS");\r
113         algorithmicCharsets.put("LMBCS-4",               "com.ibm.icu.charset.CharsetLMBCS");\r
114         algorithmicCharsets.put("LMBCS-5",               "com.ibm.icu.charset.CharsetLMBCS");\r
115         algorithmicCharsets.put("LMBCS-6",               "com.ibm.icu.charset.CharsetLMBCS");\r
116         algorithmicCharsets.put("LMBCS-8",               "com.ibm.icu.charset.CharsetLMBCS");\r
117         algorithmicCharsets.put("LMBCS-11",              "com.ibm.icu.charset.CharsetLMBCS");\r
118         algorithmicCharsets.put("LMBCS-16",              "com.ibm.icu.charset.CharsetLMBCS");\r
119         algorithmicCharsets.put("LMBCS-17",              "com.ibm.icu.charset.CharsetLMBCS");\r
120         algorithmicCharsets.put("LMBCS-18",              "com.ibm.icu.charset.CharsetLMBCS");\r
121         algorithmicCharsets.put("LMBCS-19",              "com.ibm.icu.charset.CharsetLMBCS");\r
122         algorithmicCharsets.put("BOCU-1",                "com.ibm.icu.charset.CharsetBOCU1" );\r
123         algorithmicCharsets.put("SCSU",                  "com.ibm.icu.charset.CharsetSCSU" ); \r
124         algorithmicCharsets.put("US-ASCII",              "com.ibm.icu.charset.CharsetASCII" );\r
125         algorithmicCharsets.put("ISO-8859-1",            "com.ibm.icu.charset.Charset88591" );\r
126         algorithmicCharsets.put("UTF-16",                "com.ibm.icu.charset.CharsetUTF16" );\r
127         algorithmicCharsets.put("UTF-16BE",              "com.ibm.icu.charset.CharsetUTF16BE" );\r
128         algorithmicCharsets.put("UTF-16LE",              "com.ibm.icu.charset.CharsetUTF16LE" );\r
129         algorithmicCharsets.put("UTF16_OppositeEndian",  "com.ibm.icu.charset.CharsetUTF16LE" );\r
130         algorithmicCharsets.put("UTF16_PlatformEndian",  "com.ibm.icu.charset.CharsetUTF16" );\r
131         algorithmicCharsets.put("UTF-32",                "com.ibm.icu.charset.CharsetUTF32" );\r
132         algorithmicCharsets.put("UTF-32BE",              "com.ibm.icu.charset.CharsetUTF32BE" );\r
133         algorithmicCharsets.put("UTF-32LE",              "com.ibm.icu.charset.CharsetUTF32LE" );\r
134         algorithmicCharsets.put("UTF32_OppositeEndian",  "com.ibm.icu.charset.CharsetUTF32LE" );\r
135         algorithmicCharsets.put("UTF32_PlatformEndian",  "com.ibm.icu.charset.CharsetUTF32" );\r
136         algorithmicCharsets.put("UTF-8",                 "com.ibm.icu.charset.CharsetUTF8" );\r
137         algorithmicCharsets.put("CESU-8",                "com.ibm.icu.charset.CharsetCESU8" );\r
138         algorithmicCharsets.put("UTF-7",                 "com.ibm.icu.charset.CharsetUTF7" );\r
139         algorithmicCharsets.put("ISCII,version=0",       "com.ibm.icu.charset.CharsetISCII" );\r
140         algorithmicCharsets.put("ISCII,version=1",       "com.ibm.icu.charset.CharsetISCII" );\r
141         algorithmicCharsets.put("ISCII,version=2",       "com.ibm.icu.charset.CharsetISCII" );\r
142         algorithmicCharsets.put("ISCII,version=3",       "com.ibm.icu.charset.CharsetISCII" );\r
143         algorithmicCharsets.put("ISCII,version=4",       "com.ibm.icu.charset.CharsetISCII" );\r
144         algorithmicCharsets.put("ISCII,version=5",       "com.ibm.icu.charset.CharsetISCII" );\r
145         algorithmicCharsets.put("ISCII,version=6",       "com.ibm.icu.charset.CharsetISCII" );\r
146         algorithmicCharsets.put("ISCII,version=7",       "com.ibm.icu.charset.CharsetISCII" );\r
147         algorithmicCharsets.put("ISCII,version=8",       "com.ibm.icu.charset.CharsetISCII" );\r
148         algorithmicCharsets.put("IMAP-mailbox-name",     "com.ibm.icu.charset.CharsetUTF7" );\r
149         algorithmicCharsets.put("HZ",                    "com.ibm.icu.charset.CharsetHZ" );\r
150         algorithmicCharsets.put("ISO_2022,locale=ja,version=0",               "com.ibm.icu.charset.CharsetISO2022" );\r
151         algorithmicCharsets.put("ISO_2022,locale=ja,version=1",               "com.ibm.icu.charset.CharsetISO2022" );\r
152         algorithmicCharsets.put("ISO_2022,locale=ja,version=2",               "com.ibm.icu.charset.CharsetISO2022" );\r
153         algorithmicCharsets.put("ISO_2022,locale=ja,version=3",               "com.ibm.icu.charset.CharsetISO2022" );\r
154         algorithmicCharsets.put("ISO_2022,locale=ja,version=4",               "com.ibm.icu.charset.CharsetISO2022" );\r
155         algorithmicCharsets.put("ISO_2022,locale=zh,version=0",               "com.ibm.icu.charset.CharsetISO2022" );\r
156         algorithmicCharsets.put("ISO_2022,locale=zh,version=1",               "com.ibm.icu.charset.CharsetISO2022" );\r
157         algorithmicCharsets.put("ISO_2022,locale=ko,version=0",               "com.ibm.icu.charset.CharsetISO2022" );\r
158         algorithmicCharsets.put("ISO_2022,locale=ko,version=1",               "com.ibm.icu.charset.CharsetISO2022" );\r
159         }\r
160 \r
161     /*public*/ static final Charset getCharset(String icuCanonicalName, String javaCanonicalName, String[] aliases){\r
162        String className = algorithmicCharsets.get(icuCanonicalName);\r
163        if(className==null){\r
164            //all the cnv files are loaded as MBCS\r
165            className = "com.ibm.icu.charset.CharsetMBCS";\r
166        }\r
167        try{\r
168            CharsetICU conv = null;\r
169            Class<? extends CharsetICU> cs = Class.forName(className).asSubclass(CharsetICU.class);\r
170            Class<?>[] paramTypes = new Class<?>[]{ String.class, String.class,  String[].class};\r
171            final Constructor<? extends CharsetICU> c = cs.getConstructor(paramTypes);\r
172            Object[] params = new Object[]{ icuCanonicalName, javaCanonicalName, aliases};\r
173            \r
174            // Run constructor\r
175            try {\r
176                conv = c.newInstance(params);\r
177                if (conv != null) {\r
178                    return conv;\r
179                }\r
180            }catch (InvocationTargetException e) {\r
181                throw new UnsupportedCharsetException( icuCanonicalName+": "+"Could not load " + className+ ". Exception:" + e.getTargetException());    \r
182            }\r
183        }catch(ClassNotFoundException ex){\r
184        }catch(NoSuchMethodException ex){\r
185        }catch (IllegalAccessException ex){ \r
186        }catch (InstantiationException ex){ \r
187        }\r
188        throw new UnsupportedCharsetException( icuCanonicalName+": "+"Could not load " + className);    \r
189     }\r
190     \r
191     static final boolean isSurrogate(int c){\r
192         return (((c)&0xfffff800)==0xd800);\r
193     }\r
194     \r
195     /*\r
196      * Returns the default charset name \r
197      */\r
198 //    static final String getDefaultCharsetName(){\r
199 //        String defaultEncoding = new InputStreamReader(new ByteArrayInputStream(new byte[0])).getEncoding();\r
200 //        return defaultEncoding;\r
201 //    }\r
202 \r
203     /**\r
204      * Returns a charset object for the named charset.\r
205      * This method gurantee that ICU charset is returned when\r
206      * available.  If the ICU charset provider does not support\r
207      * the specified charset, then try other charset providers\r
208      * including the standard Java charset provider.\r
209      * \r
210      * @param charsetName The name of the requested charset,\r
211      * may be either a canonical name or an alias\r
212      * @return A charset object for the named charset\r
213      * @throws IllegalCharsetNameException If the given charset name\r
214      * is illegal\r
215      * @throws UnsupportedCharsetException If no support for the\r
216      * named charset is available in this instance of th Java\r
217      * virtual machine\r
218      * @stable ICU 3.6\r
219      */\r
220     public static Charset forNameICU(String charsetName) throws IllegalCharsetNameException, UnsupportedCharsetException {\r
221         CharsetProviderICU icuProvider = new CharsetProviderICU();\r
222         CharsetICU cs = (CharsetICU) icuProvider.charsetForName(charsetName);\r
223         if (cs != null) {\r
224             return cs;\r
225         }\r
226         return Charset.forName(charsetName);\r
227     }\r
228 \r
229 //    /**\r
230 //     * @see java.lang.Comparable#compareTo(java.lang.Object)\r
231 //     * @stable 3.8\r
232 //     */\r
233 //    public int compareTo(Object otherObj) {\r
234 //        if (!(otherObj instanceof CharsetICU)) {\r
235 //            return -1;\r
236 //        }\r
237 //        return icuCanonicalName.compareTo(((CharsetICU)otherObj).icuCanonicalName);\r
238 //    }\r
239 \r
240     /**\r
241      * This follows ucnv.c method ucnv_detectUnicodeSignature() to detect the\r
242      * start of the stream for example U+FEFF (the Unicode BOM/signature\r
243      * character) that can be ignored.\r
244      * \r
245      * Detects Unicode signature byte sequences at the start of the byte stream\r
246      * and returns number of bytes of the BOM of the indicated Unicode charset.\r
247      * 0 is returned when no Unicode signature is recognized.\r
248      * \r
249      */\r
250     // TODO This should be proposed as CharsetDecoderICU API.\r
251 //    static String detectUnicodeSignature(ByteBuffer source) {\r
252 //        int signatureLength = 0; // number of bytes of the signature\r
253 //        final int SIG_MAX_LEN = 5;\r
254 //        String sigUniCharset = null; // states what unicode charset is the BOM\r
255 //        int i = 0;\r
256 //\r
257 //        /*\r
258 //         * initial 0xa5 bytes: make sure that if we read <SIG_MAX_LEN bytes we\r
259 //         * don't misdetect something\r
260 //         */\r
261 //        byte start[] = { (byte) 0xa5, (byte) 0xa5, (byte) 0xa5, (byte) 0xa5,\r
262 //                (byte) 0xa5 };\r
263 //\r
264 //        while (i < source.remaining() && i < SIG_MAX_LEN) {\r
265 //            start[i] = source.get(i);\r
266 //            i++;\r
267 //        }\r
268 //\r
269 //        if (start[0] == (byte) 0xFE && start[1] == (byte) 0xFF) {\r
270 //            signatureLength = 2;\r
271 //            sigUniCharset = "UTF-16BE";\r
272 //            source.position(signatureLength);\r
273 //            return sigUniCharset;\r
274 //        } else if (start[0] == (byte) 0xFF && start[1] == (byte) 0xFE) {\r
275 //            if (start[2] == (byte) 0x00 && start[3] == (byte) 0x00) {\r
276 //                signatureLength = 4;\r
277 //                sigUniCharset = "UTF-32LE";\r
278 //                source.position(signatureLength);\r
279 //                return sigUniCharset;\r
280 //            } else {\r
281 //                signatureLength = 2;\r
282 //                sigUniCharset = "UTF-16LE";\r
283 //                source.position(signatureLength);\r
284 //                return sigUniCharset;\r
285 //            }\r
286 //        } else if (start[0] == (byte) 0xEF && start[1] == (byte) 0xBB\r
287 //                && start[2] == (byte) 0xBF) {\r
288 //            signatureLength = 3;\r
289 //            sigUniCharset = "UTF-8";\r
290 //            source.position(signatureLength);\r
291 //            return sigUniCharset;\r
292 //        } else if (start[0] == (byte) 0x00 && start[1] == (byte) 0x00\r
293 //                && start[2] == (byte) 0xFE && start[3] == (byte) 0xFF) {\r
294 //            signatureLength = 4;\r
295 //            sigUniCharset = "UTF-32BE";\r
296 //            source.position(signatureLength);\r
297 //            return sigUniCharset;\r
298 //        } else if (start[0] == (byte) 0x0E && start[1] == (byte) 0xFE\r
299 //                && start[2] == (byte) 0xFF) {\r
300 //            signatureLength = 3;\r
301 //            sigUniCharset = "SCSU";\r
302 //            source.position(signatureLength);\r
303 //            return sigUniCharset;\r
304 //        } else if (start[0] == (byte) 0xFB && start[1] == (byte) 0xEE\r
305 //                && start[2] == (byte) 0x28) {\r
306 //            signatureLength = 3;\r
307 //            sigUniCharset = "BOCU-1";\r
308 //            source.position(signatureLength);\r
309 //            return sigUniCharset;\r
310 //        } else if (start[0] == (byte) 0x2B && start[1] == (byte) 0x2F\r
311 //                && start[2] == (byte) 0x76) {\r
312 //\r
313 //            if (start[3] == (byte) 0x38 && start[4] == (byte) 0x2D) {\r
314 //                signatureLength = 5;\r
315 //                sigUniCharset = "UTF-7";\r
316 //                source.position(signatureLength);\r
317 //                return sigUniCharset;\r
318 //            } else if (start[3] == (byte) 0x38 || start[3] == (byte) 0x39\r
319 //                    || start[3] == (byte) 0x2B || start[3] == (byte) 0x2F) {\r
320 //                signatureLength = 4;\r
321 //                sigUniCharset = "UTF-7";\r
322 //                source.position(signatureLength);\r
323 //                return sigUniCharset;\r
324 //            }\r
325 //        } else if (start[0] == (byte) 0xDD && start[2] == (byte) 0x73\r
326 //                && start[2] == (byte) 0x66 && start[3] == (byte) 0x73) {\r
327 //            signatureLength = 4;\r
328 //            sigUniCharset = "UTF-EBCDIC";\r
329 //            source.position(signatureLength);\r
330 //            return sigUniCharset;\r
331 //        }\r
332 //\r
333 //        /* no known Unicode signature byte sequence recognized */\r
334 //        return null;\r
335 //    }\r
336     \r
337     \r
338     abstract void getUnicodeSetImpl(UnicodeSet setFillIn, int which);\r
339     \r
340     /**\r
341     * <p>Returns the set of Unicode code points that can be converted by an ICU Converter. \r
342     * <p>\r
343     * The current implementation returns only one kind of set (UCNV_ROUNDTRIP_SET): The set of all Unicode code points that can be \r
344     * roundtrip-converted (converted without any data loss) with the converter This set will not include code points that have fallback \r
345     * mappings or are only the result of reverse fallback mappings.  See UTR #22 "Character Mapping Markup Language" at  <a href="http://www.unicode.org/reports/tr22/">http://www.unicode.org/reports/tr22/</a>\r
346     * <p>* In the future, there may be more UConverterUnicodeSet choices to select sets with different properties.\r
347     * <p>\r
348     * <p>This is useful for example for\r
349     * <ul><li>checking that a string or document can be roundtrip-converted with a converter,\r
350     *   without/before actually performing the conversion</li>\r
351     * <li>testing if a converter can be used for text for typical text for a certain locale,\r
352     *   by comparing its roundtrip set with the set of ExemplarCharacters from\r
353     *   ICU's locale data or other sources</li></ul>\r
354     *\r
355     * @param setFillIn A valid UnicodeSet. It will be cleared by this function before \r
356     *                   the converter's specific set is filled in.\r
357     * @param which A selector; currently ROUNDTRIP_SET is the only supported value.\r
358     * @throws IllegalArgumentException if the parameters does not match.              \r
359     * @stable ICU 4.0\r
360     */\r
361        public void getUnicodeSet(UnicodeSet setFillIn, int which){\r
362            if( setFillIn == null || which != ROUNDTRIP_SET ){\r
363                throw new IllegalArgumentException();\r
364            }\r
365            setFillIn.clear();\r
366            getUnicodeSetImpl(setFillIn, which);\r
367        }\r
368       \r
369        static void getNonSurrogateUnicodeSet(UnicodeSet setFillIn){\r
370            setFillIn.add(0, 0xd7ff);\r
371            setFillIn.add(0xe000, 0x10ffff);\r
372        }\r
373        \r
374        static void getCompleteUnicodeSet(UnicodeSet setFillIn){\r
375            setFillIn.add(0, 0x10ffff);\r
376        }\r
377 \r
378 }\r