]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/charset/src/com/ibm/icu/charset/UConverterAlias.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / charset / src / com / ibm / icu / charset / UConverterAlias.java
1 /**\r
2 *******************************************************************************\r
3 * Copyright (C) 2006-2010, International Business Machines Corporation and    *\r
4 * others. All Rights Reserved.                                                *\r
5 *******************************************************************************\r
6 *\r
7 *******************************************************************************\r
8 */ \r
9 package com.ibm.icu.charset;\r
10 \r
11 import java.io.BufferedInputStream;\r
12 import java.io.IOException;\r
13 import java.io.InputStream;\r
14 import java.nio.ByteBuffer;\r
15 \r
16 import com.ibm.icu.impl.ICUData;\r
17 import com.ibm.icu.impl.ICUResourceBundle;\r
18 \r
19 final class UConverterAlias {\r
20     static final int UNNORMALIZED = 0;\r
21 \r
22     static final int STD_NORMALIZED = 1;\r
23 \r
24     static final int AMBIGUOUS_ALIAS_MAP_BIT = 0x8000;\r
25     \r
26     static final int CONTAINS_OPTION_BIT = 0x4000;\r
27 \r
28     static final int CONVERTER_INDEX_MASK = 0xFFF;\r
29 \r
30     static final int NUM_RESERVED_TAGS = 2;\r
31 \r
32     static final int NUM_HIDDEN_TAGS = 1;\r
33 \r
34     static int[] gConverterList = null;\r
35 \r
36     static int[] gTagList = null;\r
37 \r
38     static int[] gAliasList = null;\r
39 \r
40     static int[] gUntaggedConvArray = null;\r
41 \r
42     static int[] gTaggedAliasArray = null;\r
43 \r
44     static int[] gTaggedAliasLists = null;\r
45 \r
46     static int[] gOptionTable = null;\r
47 \r
48     static byte[] gStringTable = null;\r
49 \r
50     static byte[] gNormalizedStringTable = null;\r
51 \r
52     static final String GET_STRING(int idx) {\r
53         return extractString(gStringTable, 2 * idx);\r
54     }\r
55 \r
56     private static final String GET_NORMALIZED_STRING(int idx) {\r
57         return extractString(gNormalizedStringTable, 2 * idx);\r
58     }\r
59 \r
60     private static final String extractString(byte[] sArray, int sBegin) {\r
61         char[] buf = new char[strlen(sArray, sBegin)];\r
62         for (int i = 0; i < buf.length; i++) {\r
63            buf[i] = (char)(sArray[sBegin + i] & 0xff);\r
64         }\r
65         return new String(buf);\r
66     }\r
67 \r
68     private static final int strlen(byte[] sArray, int sBegin)\r
69     {\r
70         int i = sBegin;\r
71         while(i < sArray.length && sArray[i++] != 0) {}\r
72         return i - sBegin - 1;\r
73     }\r
74 \r
75     /*private*/ static final int tocLengthIndex = 0;\r
76 \r
77     private static final int converterListIndex = 1;\r
78 \r
79     private static final int tagListIndex = 2;\r
80 \r
81     private static final int aliasListIndex = 3;\r
82 \r
83     private static final int untaggedConvArrayIndex = 4;\r
84 \r
85     private static final int taggedAliasArrayIndex = 5;\r
86 \r
87     private static final int taggedAliasListsIndex = 6;\r
88 \r
89     private static final int optionTableIndex = 7;\r
90 \r
91     private static final int stringTableIndex = 8;\r
92 \r
93     private static final int normalizedStringTableIndex = 9;\r
94 \r
95     private static final int minTocLength = 9; /*\r
96                                                  * min. tocLength in the file,\r
97                                                  * does not count the\r
98                                                  * tocLengthIndex!\r
99                                                  */\r
100 \r
101     private static final int offsetsCount = minTocLength + 1; /*\r
102                                                                  * length of the\r
103                                                                  * swapper's\r
104                                                                  * temporary\r
105                                                                  * offsets[]\r
106                                                                  */\r
107 \r
108     static ByteBuffer gAliasData = null;\r
109 \r
110     private static final boolean isAlias(String alias) {\r
111         if (alias == null) {\r
112             throw new IllegalArgumentException("Alias param is null!");\r
113         }\r
114         return (alias.length() != 0);\r
115     }\r
116 \r
117     private static final String CNVALIAS_DATA_FILE_NAME = ICUResourceBundle.ICU_BUNDLE + "/cnvalias.icu";\r
118 \r
119     /**\r
120      * Default buffer size of datafile\r
121      */\r
122     private static final int CNVALIAS_DATA_BUFFER_SIZE = 25000;\r
123 \r
124     private static final synchronized boolean haveAliasData() \r
125                                                throws IOException{\r
126         boolean needInit;\r
127 \r
128         // agljport:todo umtx_lock(NULL);\r
129         needInit = gAliasData == null;\r
130 \r
131         /* load converter alias data from file if necessary */\r
132         if (needInit) {\r
133             ByteBuffer data = null;\r
134             int[] tableArray = null;\r
135             int tableStart;\r
136             //byte[] reservedBytes = null;\r
137 \r
138             InputStream i = ICUData.getRequiredStream(CNVALIAS_DATA_FILE_NAME);\r
139             BufferedInputStream b = new BufferedInputStream(i, CNVALIAS_DATA_BUFFER_SIZE);\r
140             UConverterAliasDataReader reader = new UConverterAliasDataReader(b);\r
141             tableArray = reader.readToc(offsetsCount);\r
142 \r
143             tableStart = tableArray[0];\r
144             if (tableStart < minTocLength) {\r
145                 throw new IOException("Invalid data format.");\r
146             }\r
147             gConverterList = new int[tableArray[converterListIndex]];\r
148             gTagList= new int[tableArray[tagListIndex]];\r
149             gAliasList = new int[tableArray[aliasListIndex]];\r
150             gUntaggedConvArray = new int[tableArray[untaggedConvArrayIndex]];\r
151             gTaggedAliasArray = new int[tableArray[taggedAliasArrayIndex]];\r
152             gTaggedAliasLists = new int[tableArray[taggedAliasListsIndex]];\r
153             gOptionTable = new int[tableArray[optionTableIndex]];\r
154             gStringTable = new byte[tableArray[stringTableIndex]*2];\r
155             gNormalizedStringTable = new byte[tableArray[normalizedStringTableIndex]*2];\r
156 \r
157             reader.read(gConverterList, gTagList,\r
158                     gAliasList, gUntaggedConvArray,\r
159                     gTaggedAliasArray, gTaggedAliasLists,\r
160                     gOptionTable, gStringTable, gNormalizedStringTable);\r
161             data =  ByteBuffer.allocate(0); // dummy UDataMemory object in absence\r
162                                         // of memory mapping\r
163 \r
164             if (gOptionTable[0] != STD_NORMALIZED) {\r
165                 throw new IOException("Unsupported alias normalization");\r
166             }\r
167             \r
168             // agljport:todo umtx_lock(NULL);\r
169             if (gAliasData == null) {\r
170                 gAliasData = data;\r
171                 data = null;\r
172 \r
173                 // agljport:fix ucln_common_registerCleanup(UCLN_COMMON_IO,\r
174                 // io_cleanup);\r
175             }\r
176             // agljport:todo umtx_unlock(NULL);\r
177 \r
178             /* if a different thread set it first, then close the extra data */\r
179             if (data != null) {\r
180                 // agljport:fix udata_close(data); /* NULL if it was set\r
181                 // correctly */\r
182             }\r
183         }\r
184 \r
185         return true;\r
186     }\r
187 \r
188     // U_CFUNC const char * io_getConverterName(const char *alias, UErrorCode\r
189     // *pErrorCode)\r
190 //    public static final String io_getConverterName(String alias)\r
191 //                                    throws IOException{\r
192 //        if (haveAliasData() && isAlias(alias)) {\r
193 //            boolean[] isAmbigous = new boolean[1];\r
194 //            int convNum = findConverter(alias, isAmbigous);\r
195 //            if (convNum < gConverterList.length) {\r
196 //                return GET_STRING(gConverterList[(int) convNum]);\r
197 //            }\r
198 //            /* else converter not found */\r
199 //        }\r
200 //        return null;\r
201 //    }\r
202 \r
203     /*\r
204      * search for an alias return the converter number index for gConverterList\r
205      */\r
206     // static U_INLINE uint32_t findConverter(const char *alias, UErrorCode\r
207     // *pErrorCode)\r
208     private static final int findConverter(String alias, boolean[] isAmbigous) {\r
209         int mid, start, limit;\r
210         int lastMid;\r
211         int result;\r
212         StringBuilder strippedName = new StringBuilder();\r
213         String aliasToCompare;\r
214 \r
215         stripForCompare(strippedName, alias);\r
216         alias = strippedName.toString();\r
217 \r
218         /* do a binary search for the alias */\r
219         start = 0;\r
220         limit = gUntaggedConvArray.length;\r
221         mid = limit;\r
222         lastMid = Integer.MAX_VALUE;\r
223 \r
224         for (;;) {\r
225             mid = (start + limit) / 2;\r
226             if (lastMid == mid) { /* Have we moved? */\r
227                 break; /* We haven't moved, and it wasn't found. */\r
228             }\r
229             lastMid = mid;\r
230             aliasToCompare = GET_NORMALIZED_STRING(gAliasList[mid]);\r
231             result = alias.compareTo(aliasToCompare);\r
232 \r
233             if (result < 0) {\r
234                 limit = mid;\r
235             } else if (result > 0) {\r
236                 start = mid;\r
237             } else {\r
238                 /*\r
239                  * Since the gencnval tool folds duplicates into one entry, this\r
240                  * alias in gAliasList is unique, but different standards may\r
241                  * map an alias to different converters.\r
242                  */\r
243                 if ((gUntaggedConvArray[mid] & AMBIGUOUS_ALIAS_MAP_BIT) != 0) {\r
244                     isAmbigous[0]=true;\r
245                 }\r
246                 /* State whether the canonical converter name contains an option.\r
247                 This information is contained in this list in order to maintain backward & forward compatibility. */\r
248                 /*if (containsOption) {\r
249                     UBool containsCnvOptionInfo = (UBool)gMainTable.optionTable->containsCnvOptionInfo;\r
250                     *containsOption = (UBool)((containsCnvOptionInfo\r
251                         && ((gMainTable.untaggedConvArray[mid] & UCNV_CONTAINS_OPTION_BIT) != 0))\r
252                         || !containsCnvOptionInfo);\r
253                 }*/\r
254                 return gUntaggedConvArray[mid] & CONVERTER_INDEX_MASK;\r
255             }\r
256         }\r
257         return Integer.MAX_VALUE;\r
258     }\r
259 \r
260     /**\r
261      * stripForCompare Remove the underscores, dashes and spaces from\r
262      * the name, and convert the name to lower case.\r
263      * \r
264      * @param dst The destination buffer, which is <= the buffer of name.\r
265      * @param name The alias to strip\r
266      * @return the destination buffer.\r
267      */\r
268     public static final StringBuilder stripForCompare(StringBuilder dst, String name) {\r
269         return io_stripASCIIForCompare(dst, name);\r
270     }\r
271 \r
272     // enum {\r
273     private static final byte IGNORE = 0;\r
274     private static final byte ZERO = 1;\r
275     private static final byte NONZERO = 2;\r
276     static final byte MINLETTER = 3; /* any values from here on are lowercase letter mappings */\r
277     // }\r
278     \r
279     /* character types for ASCII 00..7F */\r
280     static final byte asciiTypes[] = new byte[] {\r
281         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
282         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
283         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
284         ZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, 0, 0, 0, 0, 0, 0,\r
285         0, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,\r
286         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0,\r
287         0, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,\r
288         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0\r
289     };\r
290 \r
291     private static final char GET_CHAR_TYPE(char c) {\r
292         return (char)((c < asciiTypes.length) ? asciiTypes[c] : (char)IGNORE);\r
293     }\r
294     \r
295     /** @see UConverterAlias#compareNames */\r
296     private static final StringBuilder io_stripASCIIForCompare(StringBuilder dst, String name) {\r
297         int nameIndex = 0;\r
298         char type, nextType;\r
299         char c1;\r
300         boolean afterDigit = false;\r
301 \r
302         while (nameIndex < name.length()) {\r
303             c1 = name.charAt(nameIndex++);\r
304             type = GET_CHAR_TYPE(c1);\r
305             switch (type) {\r
306             case IGNORE:\r
307                 afterDigit = false;\r
308                 continue; /* ignore all but letters and digits */\r
309             case ZERO:\r
310                 if (!afterDigit && nameIndex < name.length()) {\r
311                     nextType = GET_CHAR_TYPE(name.charAt(nameIndex));\r
312                     if (nextType == ZERO || nextType == NONZERO) {\r
313                         continue; /* ignore leading zero before another digit */\r
314                     }\r
315                 }\r
316                 break;\r
317             case NONZERO:\r
318                 afterDigit = true;\r
319                 break;\r
320             default:\r
321                 c1 = type; /* lowercased letter */\r
322                 afterDigit = false;\r
323                 break;\r
324             }\r
325             dst.append(c1);\r
326         }\r
327         return dst;\r
328     }\r
329 \r
330     /**\r
331      * Do a fuzzy compare of a two converter/alias names. The comparison is\r
332      * case-insensitive. It also ignores the characters '-', '_', and ' ' (dash,\r
333      * underscore, and space). Thus the strings "UTF-8", "utf_8", and "Utf 8"\r
334      * are exactly equivalent.\r
335      * \r
336      * This is a symmetrical (commutative) operation; order of arguments is\r
337      * insignificant. This is an important property for sorting the list (when\r
338      * the list is preprocessed into binary form) and for performing binary\r
339      * searches on it at run time.\r
340      * \r
341      * @param name1\r
342      *            a converter name or alias, zero-terminated\r
343      * @param name2\r
344      *            a converter name or alias, zero-terminated\r
345      * @return 0 if the names match, or a negative value if the name1 lexically\r
346      *         precedes name2, or a positive value if the name1 lexically\r
347      *         follows name2.\r
348      * \r
349      * @see UConverterAlias#stripForCompare\r
350      */\r
351     static int compareNames(String name1, String name2){\r
352         int rc, name1Index = 0, name2Index = 0;\r
353         char type, nextType;\r
354         char c1 = 0, c2 = 0;\r
355         boolean afterDigit1 = false, afterDigit2 = false;\r
356 \r
357         for (;;) {\r
358             while (name1Index < name1.length()) {\r
359                 c1 = name1.charAt(name1Index++);\r
360                 type = GET_CHAR_TYPE(c1);\r
361                 switch (type) {\r
362                 case IGNORE:\r
363                     afterDigit1 = false;\r
364                     continue; /* ignore all but letters and digits */\r
365                 case ZERO:\r
366                     if (!afterDigit1 && name1Index < name1.length()) {\r
367                         nextType = GET_CHAR_TYPE(name1.charAt(name1Index));\r
368                         if (nextType == ZERO || nextType == NONZERO) {\r
369                             continue; /* ignore leading zero before another digit */\r
370                         }\r
371                     }\r
372                     break;\r
373                 case NONZERO:\r
374                     afterDigit1 = true;\r
375                     break;\r
376                 default:\r
377                     c1 = type; /* lowercased letter */\r
378                     afterDigit1 = false;\r
379                     break;\r
380                 }\r
381                 break; /* deliver c1 */\r
382             }\r
383             while (name2Index < name2.length()) {\r
384                 c2 = name2.charAt(name2Index++);\r
385                 type = GET_CHAR_TYPE(c2);\r
386                 switch (type) {\r
387                 case IGNORE:\r
388                     afterDigit2 = false;\r
389                     continue; /* ignore all but letters and digits */\r
390                 case ZERO:\r
391                     if (!afterDigit2 && name1Index < name1.length()) {\r
392                         nextType = GET_CHAR_TYPE(name2.charAt(name2Index));\r
393                         if (nextType == ZERO || nextType == NONZERO) {\r
394                             continue; /* ignore leading zero before another digit */\r
395                         }\r
396                     }\r
397                     break;\r
398                 case NONZERO:\r
399                     afterDigit2 = true;\r
400                     break;\r
401                 default:\r
402                     c2 = type; /* lowercased letter */\r
403                     afterDigit2 = false;\r
404                     break;\r
405                 }\r
406                 break; /* deliver c2 */\r
407             }\r
408 \r
409             /* If we reach the ends of both strings then they match */\r
410             if (name1Index >= name1.length() && name2Index >= name2.length()) {\r
411                 return 0;\r
412             }\r
413 \r
414             /* Case-insensitive comparison */\r
415             rc = (int)c1 - (int)c2;\r
416             if (rc != 0) {\r
417                 return rc;\r
418             }\r
419         }\r
420     }\r
421 \r
422     static int io_countAliases(String alias) \r
423                         throws IOException{\r
424         if (haveAliasData() && isAlias(alias)) {\r
425             boolean[] isAmbigous = new boolean[1];\r
426             int convNum = findConverter(alias, isAmbigous);\r
427             if (convNum < gConverterList.length) {\r
428                 /* tagListNum - 1 is the ALL tag */\r
429                 int listOffset = gTaggedAliasArray[(gTagList.length - 1)\r
430                         * gConverterList.length + convNum];\r
431 \r
432                 if (listOffset != 0) {\r
433                     return gTaggedAliasLists[listOffset];\r
434                 }\r
435                 /* else this shouldn't happen. internal program error */\r
436             }\r
437             /* else converter not found */\r
438         }\r
439         return 0;\r
440     }\r
441 \r
442     /**\r
443      * Return the number of all aliases (and converter names).\r
444      * \r
445      * @return the number of all aliases\r
446      */\r
447     // U_CFUNC uint16_t io_countTotalAliases(UErrorCode *pErrorCode);\r
448 //    static int io_countTotalAliases() throws IOException{\r
449 //        if (haveAliasData()) {\r
450 //            return (int) gAliasList.length;\r
451 //        }\r
452 //        return 0;\r
453 //    }\r
454 \r
455     // U_CFUNC const char * io_getAlias(const char *alias, uint16_t n,\r
456     // UErrorCode *pErrorCode)\r
457     static String io_getAlias(String alias, int n) throws IOException{\r
458         if (haveAliasData() && isAlias(alias)) {\r
459             boolean[] isAmbigous = new boolean[1];\r
460             int convNum = findConverter(alias,isAmbigous);\r
461             if (convNum < gConverterList.length) {\r
462                 /* tagListNum - 1 is the ALL tag */\r
463                 int listOffset = gTaggedAliasArray[(gTagList.length - 1)\r
464                         * gConverterList.length + convNum];\r
465 \r
466                 if (listOffset != 0) {\r
467                     //int listCount = gTaggedAliasListsArray[listOffset];\r
468                     /* +1 to skip listCount */\r
469                     int[] currListArray = gTaggedAliasLists;\r
470                     int currListArrayIndex = listOffset + 1;\r
471 \r
472                     return GET_STRING(currListArray[currListArrayIndex + n]);\r
473                     \r
474                 }\r
475                 /* else this shouldn't happen. internal program error */\r
476             }\r
477             /* else converter not found */\r
478         }\r
479         return null;\r
480     }\r
481 \r
482     // U_CFUNC uint16_t io_countStandards(UErrorCode *pErrorCode) {\r
483 //    static int io_countStandards() throws IOException{\r
484 //        if (haveAliasData()) {\r
485 //            return (int) (gTagList.length - NUM_HIDDEN_TAGS);\r
486 //        }\r
487 //        return 0;\r
488 //    }\r
489 \r
490     // U_CAPI const char * U_EXPORT2getStandard(uint16_t n, UErrorCode\r
491     // *pErrorCode)\r
492 //    static String getStandard(int n) throws IOException{\r
493 //        if (haveAliasData()) {\r
494 //            return GET_STRING(gTagList[n]);\r
495 //        }\r
496 //        return null;\r
497 //    }\r
498 \r
499     // U_CAPI const char * U_EXPORT2 getStandardName(const char *alias, const\r
500     // char *standard, UErrorCode *pErrorCode)\r
501     static final String getStandardName(String alias, String standard)throws IOException {\r
502         if (haveAliasData() && isAlias(alias)) {\r
503             int listOffset = findTaggedAliasListsOffset(alias, standard);\r
504 \r
505             if (0 < listOffset && listOffset < gTaggedAliasLists.length) {\r
506                 int[] currListArray = gTaggedAliasLists;\r
507                 int currListArrayIndex = listOffset + 1;\r
508                 if (currListArray[0] != 0) {\r
509                     return GET_STRING(currListArray[currListArrayIndex]);\r
510                 }\r
511             }\r
512         }\r
513         return null;\r
514     }\r
515 \r
516     // U_CAPI uint16_t U_EXPORT2 countAliases(const char *alias, UErrorCode\r
517     // *pErrorCode)\r
518     static int countAliases(String alias) throws IOException{\r
519         return io_countAliases(alias);\r
520     }\r
521 \r
522     // U_CAPI const char* U_EXPORT2 getAlias(const char *alias, uint16_t n,\r
523     // UErrorCode *pErrorCode)\r
524     static String getAlias(String alias, int n) throws IOException{\r
525         return io_getAlias(alias, n);\r
526     }\r
527 \r
528     // U_CFUNC uint16_t countStandards(void)\r
529 //    static int countStandards()throws IOException{\r
530 //        return io_countStandards();\r
531 //    }\r
532     \r
533     /*returns a single Name from the list, will return NULL if out of bounds\r
534      */\r
535     static String getAvailableName (int n){\r
536         try{\r
537           if (0 <= n && n <= 0xffff) {\r
538             String name = bld_getAvailableConverter(n);\r
539             return name;\r
540           }\r
541         }catch(IOException ex){\r
542             //throw away exception\r
543         }\r
544         return null;\r
545     }\r
546     // U_CAPI const char * U_EXPORT2 getCanonicalName(const char *alias, const\r
547     // char *standard, UErrorCode *pErrorCode) {\r
548     static String getCanonicalName(String alias, String standard) throws IOException{\r
549         if (haveAliasData() && isAlias(alias)) {\r
550             int convNum = findTaggedConverterNum(alias, standard);\r
551 \r
552             if (convNum < gConverterList.length) {\r
553                 return GET_STRING(gConverterList[convNum]);\r
554             }\r
555         }\r
556 \r
557         return null;\r
558     }\r
559     static int countAvailable (){\r
560         try{\r
561             return bld_countAvailableConverters();\r
562         }catch(IOException ex){\r
563             //throw away exception\r
564         }\r
565         return -1;\r
566     }\r
567         \r
568     // U_CAPI UEnumeration * U_EXPORT2 openStandardNames(const char *convName,\r
569     // const char *standard, UErrorCode *pErrorCode)\r
570 /*    static final UConverterAliasesEnumeration openStandardNames(String convName, String standard)throws IOException {\r
571         UConverterAliasesEnumeration aliasEnum = null;\r
572         if (haveAliasData() && isAlias(convName)) {\r
573             int listOffset = findTaggedAliasListsOffset(convName, standard);\r
574 \r
575             \r
576              * When listOffset == 0, we want to acknowledge that the converter\r
577              * name and standard are okay, but there is nothing to enumerate.\r
578              \r
579             if (listOffset < gTaggedAliasLists.length) {\r
580 \r
581                 UConverterAliasesEnumeration.UAliasContext context = new UConverterAliasesEnumeration.UAliasContext(listOffset, 0);\r
582                 aliasEnum = new UConverterAliasesEnumeration();\r
583                 aliasEnum.setContext(context);\r
584             }\r
585              else converter or tag not found \r
586         }\r
587         return aliasEnum;\r
588     }*/\r
589 \r
590     // static uint32_t getTagNumber(const char *tagname)\r
591     private static int getTagNumber(String tagName) {\r
592         if (gTagList != null) {\r
593             int tagNum;\r
594             for (tagNum = 0; tagNum < gTagList.length; tagNum++) {\r
595                 if (tagName.equals(GET_STRING(gTagList[tagNum]))) {\r
596                     return tagNum;\r
597                 }\r
598             }\r
599         }\r
600 \r
601         return Integer.MAX_VALUE;\r
602     }\r
603 \r
604     // static uint32_t findTaggedAliasListsOffset(const char *alias, const char\r
605     // *standard, UErrorCode *pErrorCode)\r
606     private static int findTaggedAliasListsOffset(String alias, String standard) {\r
607         int idx;\r
608         int listOffset;\r
609         int convNum;\r
610         int tagNum = getTagNumber(standard);\r
611         boolean[] isAmbigous = new boolean[1];\r
612         /* Make a quick guess. Hopefully they used a TR22 canonical alias. */\r
613         convNum = findConverter(alias, isAmbigous);\r
614 \r
615         if (tagNum < (gTagList.length - NUM_HIDDEN_TAGS)\r
616                 && convNum < gConverterList.length) {\r
617             listOffset = gTaggedAliasArray[tagNum\r
618                     * gConverterList.length + convNum];\r
619             if (listOffset != 0\r
620                     && gTaggedAliasLists[listOffset + 1] != 0) {\r
621                 return listOffset;\r
622             }\r
623             if (isAmbigous[0]==true) {\r
624                 /*\r
625                  * Uh Oh! They used an ambiguous alias. We have to search the\r
626                  * whole swiss cheese starting at the highest standard affinity.\r
627                  * This may take a while.\r
628                  */\r
629 \r
630                 for (idx = 0; idx < gTaggedAliasArray.length; idx++) {\r
631                     listOffset = gTaggedAliasArray[idx];\r
632                     if (listOffset != 0 && isAliasInList(alias, listOffset)) {\r
633                         int currTagNum = idx / gConverterList.length;\r
634                         int currConvNum = (idx - currTagNum\r
635                                 * gConverterList.length);\r
636                         int tempListOffset = gTaggedAliasArray[tagNum\r
637                                 * gConverterList.length + currConvNum];\r
638                         if (tempListOffset != 0\r
639                                 && gTaggedAliasLists[tempListOffset + 1] != 0) {\r
640                             return tempListOffset;\r
641                         }\r
642                         /*\r
643                          * else keep on looking We could speed this up by\r
644                          * starting on the next row because an alias is unique\r
645                          * per row, right now. This would change if alias\r
646                          * versioning appears.\r
647                          */\r
648                     }\r
649                 }\r
650                 /* The standard doesn't know about the alias */\r
651             }\r
652             /* else no default name */\r
653             return 0;\r
654         }\r
655         /* else converter or tag not found */\r
656 \r
657         return Integer.MAX_VALUE;\r
658     }\r
659 \r
660     /* Return the canonical name */\r
661     // static uint32_t findTaggedConverterNum(const char *alias, const char\r
662     // *standard, UErrorCode *pErrorCode)\r
663     private static int findTaggedConverterNum(String alias, String standard) {\r
664         int idx;\r
665         int listOffset;\r
666         int convNum;\r
667         int tagNum = getTagNumber(standard);\r
668         boolean[] isAmbigous = new boolean[1];\r
669         \r
670         /* Make a quick guess. Hopefully they used a TR22 canonical alias. */\r
671         convNum = findConverter(alias, isAmbigous);        \r
672 \r
673         if (tagNum < (gTagList.length - NUM_HIDDEN_TAGS)\r
674                 && convNum < gConverterList.length) {\r
675             listOffset = gTaggedAliasArray[tagNum\r
676                     * gConverterList.length + convNum];\r
677             if (listOffset != 0 && isAliasInList(alias, listOffset)) {\r
678                 return convNum;\r
679             }\r
680             if (isAmbigous[0] == true) {\r
681                 /*\r
682                  * Uh Oh! They used an ambiguous alias. We have to search one\r
683                  * slice of the swiss cheese. We search only in the requested\r
684                  * tag, not the whole thing. This may take a while.\r
685                  */\r
686                 int convStart = (tagNum) * gConverterList.length;\r
687                 int convLimit = (tagNum + 1) * gConverterList.length;\r
688                 for (idx = convStart; idx < convLimit; idx++) {\r
689                     listOffset = gTaggedAliasArray[idx];\r
690                     if (listOffset != 0 && isAliasInList(alias, listOffset)) {\r
691                         return idx - convStart;\r
692                     }\r
693                 }\r
694                 /* The standard doesn't know about the alias */\r
695             }\r
696             /* else no canonical name */\r
697         }\r
698         /* else converter or tag not found */\r
699 \r
700         return Integer.MAX_VALUE;\r
701     }\r
702 \r
703     // static U_INLINE UBool isAliasInList(const char *alias, uint32_t\r
704     // listOffset)\r
705     private static boolean isAliasInList(String alias, int listOffset) {\r
706         if (listOffset != 0) {\r
707             int currAlias;\r
708             int listCount = gTaggedAliasLists[listOffset];\r
709             /* +1 to skip listCount */\r
710             int[] currList = gTaggedAliasLists;\r
711             int currListArrayIndex = listOffset + 1;\r
712             for (currAlias = 0; currAlias < listCount; currAlias++) {\r
713                 if (currList[currAlias + currListArrayIndex] != 0\r
714                         && compareNames(\r
715                                 alias,\r
716                                 GET_STRING(currList[currAlias + currListArrayIndex])) == 0) {\r
717                     return true;\r
718                 }\r
719             }\r
720         }\r
721         return false;\r
722     }\r
723 \r
724     // begin bld.c\r
725     static String[] gAvailableConverters = null;\r
726 \r
727     static int gAvailableConverterCount = 0;\r
728 \r
729     static byte[] gDefaultConverterNameBuffer; // [MAX_CONVERTER_NAME_LENGTH +\r
730                                                 // 1]; /* +1 for NULL */\r
731 \r
732     static String gDefaultConverterName = null;\r
733 \r
734     // static UBool haveAvailableConverterList(UErrorCode *pErrorCode)\r
735     static boolean haveAvailableConverterList() throws IOException{\r
736         if (gAvailableConverters == null) {\r
737             int idx;\r
738             int localConverterCount;\r
739             String converterName;\r
740             String[] localConverterList;\r
741 \r
742             if (!haveAliasData()) {\r
743                 return false;\r
744             }\r
745 \r
746             /* We can't have more than "*converterTable" converters to open */\r
747             localConverterList = new String[gConverterList.length];\r
748 \r
749             localConverterCount = 0;\r
750 \r
751             for (idx = 0; idx < gConverterList.length; idx++) {\r
752                 converterName = GET_STRING(gConverterList[idx]);\r
753                 //UConverter cnv = UConverter.open(converterName);\r
754                 //TODO: Fix me\r
755                 localConverterList[localConverterCount++] = converterName;\r
756                 \r
757             }\r
758 \r
759             // agljport:todo umtx_lock(NULL);\r
760             if (gAvailableConverters == null) {\r
761                 gAvailableConverters = localConverterList;\r
762                 gAvailableConverterCount = localConverterCount;\r
763                 /* haveData should have already registered the cleanup function */\r
764             } else {\r
765                 // agljport:todo free((char **)localConverterList);\r
766             }\r
767             // agljport:todo umtx_unlock(NULL);\r
768         }\r
769         return true;\r
770     }\r
771 \r
772     // U_CFUNC uint16_t bld_countAvailableConverters(UErrorCode *pErrorCode)\r
773     static int bld_countAvailableConverters() throws IOException{\r
774         if (haveAvailableConverterList()) {\r
775             return gAvailableConverterCount;\r
776         }\r
777         return 0;\r
778     }\r
779 \r
780     // U_CFUNC const char * bld_getAvailableConverter(uint16_t n, UErrorCode\r
781     // *pErrorCode)\r
782     static String bld_getAvailableConverter(int n) throws IOException{\r
783         if (haveAvailableConverterList()) {\r
784             if (n < gAvailableConverterCount) {\r
785                 return gAvailableConverters[n];\r
786             }\r
787         }\r
788         return null;\r
789     }\r
790 \r
791     /* default converter name --------------------------------------------------- */\r
792 \r
793     /*\r
794      * In order to be really thread-safe, the get function would have to take\r
795      * a buffer parameter and copy the current string inside a mutex block.\r
796      * This implementation only tries to be really thread-safe while\r
797      * setting the name.\r
798      * It assumes that setting a pointer is atomic.\r
799      */\r
800 \r
801     // U_CFUNC const char * getDefaultName()\r
802 //    static final synchronized String getDefaultName() {\r
803 //        /* local variable to be thread-safe */\r
804 //        String name;\r
805 //\r
806 //        //agljport:todo umtx_lock(null);\r
807 //        name = gDefaultConverterName;\r
808 //        //agljport:todo umtx_unlock(null);\r
809 //\r
810 //        if (name == null) {\r
811 //            //UConverter cnv = null;\r
812 //            int length = 0;\r
813 //\r
814 //            name = CharsetICU.getDefaultCharsetName();\r
815 //\r
816 //            /* if the name is there, test it out and get the canonical name with options */\r
817 //            if (name != null) {\r
818 //               // cnv = UConverter.open(name); \r
819 //               // name = cnv.getName(cnv);\r
820 //                // TODO: fix me\r
821 //            }\r
822 //\r
823 //            if (name == null || name.length() == 0 ||/* cnv == null ||*/\r
824 //                     length >= gDefaultConverterNameBuffer.length) {\r
825 //                /* Panic time, let's use a fallback. */\r
826 //                name = new String("US-ASCII");\r
827 //            }\r
828 //\r
829 //            //length=(int32_t)(strlen(name));\r
830 //\r
831 //            /* Copy the name before we close the converter. */\r
832 //            name = gDefaultConverterName;\r
833 //        }\r
834 //\r
835 //        return name;\r
836 //    }\r
837 \r
838     //end bld.c\r
839 }