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