2 *******************************************************************************
\r
3 * Copyright (C) 2006-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 *******************************************************************************
\r
9 package com.ibm.icu.charset;
\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
16 import com.ibm.icu.impl.ICUData;
\r
17 import com.ibm.icu.impl.ICUResourceBundle;
\r
19 final class UConverterAlias {
\r
20 static final int UNNORMALIZED = 0;
\r
22 static final int STD_NORMALIZED = 1;
\r
24 static final int AMBIGUOUS_ALIAS_MAP_BIT = 0x8000;
\r
26 static final int CONTAINS_OPTION_BIT = 0x4000;
\r
28 static final int CONVERTER_INDEX_MASK = 0xFFF;
\r
30 static final int NUM_RESERVED_TAGS = 2;
\r
32 static final int NUM_HIDDEN_TAGS = 1;
\r
34 static int[] gConverterList = null;
\r
36 static int[] gTagList = null;
\r
38 static int[] gAliasList = null;
\r
40 static int[] gUntaggedConvArray = null;
\r
42 static int[] gTaggedAliasArray = null;
\r
44 static int[] gTaggedAliasLists = null;
\r
46 static int[] gOptionTable = null;
\r
48 static byte[] gStringTable = null;
\r
50 static byte[] gNormalizedStringTable = null;
\r
52 static final String GET_STRING(int idx) {
\r
53 return extractString(gStringTable, 2 * idx);
\r
56 private static final String GET_NORMALIZED_STRING(int idx) {
\r
57 return extractString(gNormalizedStringTable, 2 * idx);
\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
65 return new String(buf);
\r
68 private static final int strlen(byte[] sArray, int sBegin)
\r
71 while(i < sArray.length && sArray[i++] != 0) {}
\r
72 return i - sBegin - 1;
\r
75 /*private*/ static final int tocLengthIndex = 0;
\r
77 private static final int converterListIndex = 1;
\r
79 private static final int tagListIndex = 2;
\r
81 private static final int aliasListIndex = 3;
\r
83 private static final int untaggedConvArrayIndex = 4;
\r
85 private static final int taggedAliasArrayIndex = 5;
\r
87 private static final int taggedAliasListsIndex = 6;
\r
89 private static final int optionTableIndex = 7;
\r
91 private static final int stringTableIndex = 8;
\r
93 private static final int normalizedStringTableIndex = 9;
\r
95 private static final int minTocLength = 9; /*
\r
96 * min. tocLength in the file,
\r
97 * does not count the
\r
101 private static final int offsetsCount = minTocLength + 1; /*
\r
108 static ByteBuffer gAliasData = null;
\r
110 private static final boolean isAlias(String alias) {
\r
111 if (alias == null) {
\r
112 throw new IllegalArgumentException("Alias param is null!");
\r
114 return (alias.length() != 0);
\r
117 private static final String CNVALIAS_DATA_FILE_NAME = ICUResourceBundle.ICU_BUNDLE + "/cnvalias.icu";
\r
120 * Default buffer size of datafile
\r
122 private static final int CNVALIAS_DATA_BUFFER_SIZE = 25000;
\r
124 private static final synchronized boolean haveAliasData()
\r
125 throws IOException{
\r
128 // agljport:todo umtx_lock(NULL);
\r
129 needInit = gAliasData == null;
\r
131 /* load converter alias data from file if necessary */
\r
133 ByteBuffer data = null;
\r
134 int[] tableArray = null;
\r
136 //byte[] reservedBytes = null;
\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
143 tableStart = tableArray[0];
\r
144 if (tableStart < minTocLength) {
\r
145 throw new IOException("Invalid data format.");
\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
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
164 if (gOptionTable[0] != STD_NORMALIZED) {
\r
165 throw new IOException("Unsupported alias normalization");
\r
168 // agljport:todo umtx_lock(NULL);
\r
169 if (gAliasData == null) {
\r
173 // agljport:fix ucln_common_registerCleanup(UCLN_COMMON_IO,
\r
176 // agljport:todo umtx_unlock(NULL);
\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
188 // U_CFUNC const char * io_getConverterName(const char *alias, UErrorCode
\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
198 // /* else converter not found */
\r
204 * search for an alias return the converter number index for gConverterList
\r
206 // static U_INLINE uint32_t findConverter(const char *alias, UErrorCode
\r
208 private static final int findConverter(String alias, boolean[] isAmbigous) {
\r
209 int mid, start, limit;
\r
212 StringBuilder strippedName = new StringBuilder();
\r
213 String aliasToCompare;
\r
215 stripForCompare(strippedName, alias);
\r
216 alias = strippedName.toString();
\r
218 /* do a binary search for the alias */
\r
220 limit = gUntaggedConvArray.length;
\r
222 lastMid = Integer.MAX_VALUE;
\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
230 aliasToCompare = GET_NORMALIZED_STRING(gAliasList[mid]);
\r
231 result = alias.compareTo(aliasToCompare);
\r
235 } else if (result > 0) {
\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
243 if ((gUntaggedConvArray[mid] & AMBIGUOUS_ALIAS_MAP_BIT) != 0) {
\r
244 isAmbigous[0]=true;
\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
254 return gUntaggedConvArray[mid] & CONVERTER_INDEX_MASK;
\r
257 return Integer.MAX_VALUE;
\r
261 * stripForCompare Remove the underscores, dashes and spaces from
\r
262 * the name, and convert the name to lower case.
\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
268 public static final StringBuilder stripForCompare(StringBuilder dst, String name) {
\r
269 return io_stripASCIIForCompare(dst, name);
\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
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
291 private static final char GET_CHAR_TYPE(char c) {
\r
292 return (char)((c < asciiTypes.length) ? asciiTypes[c] : (char)IGNORE);
\r
295 /** @see UConverterAlias#compareNames */
\r
296 private static final StringBuilder io_stripASCIIForCompare(StringBuilder dst, String name) {
\r
298 char type, nextType;
\r
300 boolean afterDigit = false;
\r
302 while (nameIndex < name.length()) {
\r
303 c1 = name.charAt(nameIndex++);
\r
304 type = GET_CHAR_TYPE(c1);
\r
307 afterDigit = false;
\r
308 continue; /* ignore all but letters and digits */
\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
321 c1 = type; /* lowercased letter */
\r
322 afterDigit = false;
\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
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
342 * a converter name or alias, zero-terminated
\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
349 * @see UConverterAlias#stripForCompare
\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
358 while (name1Index < name1.length()) {
\r
359 c1 = name1.charAt(name1Index++);
\r
360 type = GET_CHAR_TYPE(c1);
\r
363 afterDigit1 = false;
\r
364 continue; /* ignore all but letters and digits */
\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
374 afterDigit1 = true;
\r
377 c1 = type; /* lowercased letter */
\r
378 afterDigit1 = false;
\r
381 break; /* deliver c1 */
\r
383 while (name2Index < name2.length()) {
\r
384 c2 = name2.charAt(name2Index++);
\r
385 type = GET_CHAR_TYPE(c2);
\r
388 afterDigit2 = false;
\r
389 continue; /* ignore all but letters and digits */
\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
399 afterDigit2 = true;
\r
402 c2 = type; /* lowercased letter */
\r
403 afterDigit2 = false;
\r
406 break; /* deliver c2 */
\r
409 /* If we reach the ends of both strings then they match */
\r
410 if (name1Index >= name1.length() && name2Index >= name2.length()) {
\r
414 /* Case-insensitive comparison */
\r
415 rc = (int)c1 - (int)c2;
\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
432 if (listOffset != 0) {
\r
433 return gTaggedAliasLists[listOffset];
\r
435 /* else this shouldn't happen. internal program error */
\r
437 /* else converter not found */
\r
443 * Return the number of all aliases (and converter names).
\r
445 * @return the number of all aliases
\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
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
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
472 return GET_STRING(currListArray[currListArrayIndex + n]);
\r
475 /* else this shouldn't happen. internal program error */
\r
477 /* else converter not found */
\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
490 // U_CAPI const char * U_EXPORT2getStandard(uint16_t n, UErrorCode
\r
492 // static String getStandard(int n) throws IOException{
\r
493 // if (haveAliasData()) {
\r
494 // return GET_STRING(gTagList[n]);
\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
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
516 // U_CAPI uint16_t U_EXPORT2 countAliases(const char *alias, UErrorCode
\r
518 static int countAliases(String alias) throws IOException{
\r
519 return io_countAliases(alias);
\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
528 // U_CFUNC uint16_t countStandards(void)
\r
529 // static int countStandards()throws IOException{
\r
530 // return io_countStandards();
\r
533 /*returns a single Name from the list, will return NULL if out of bounds
\r
535 static String getAvailableName (int n){
\r
537 if (0 <= n && n <= 0xffff) {
\r
538 String name = bld_getAvailableConverter(n);
\r
541 }catch(IOException ex){
\r
542 //throw away exception
\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
552 if (convNum < gConverterList.length) {
\r
553 return GET_STRING(gConverterList[convNum]);
\r
559 static int countAvailable (){
\r
561 return bld_countAvailableConverters();
\r
562 }catch(IOException ex){
\r
563 //throw away exception
\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
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
579 if (listOffset < gTaggedAliasLists.length) {
\r
581 UConverterAliasesEnumeration.UAliasContext context = new UConverterAliasesEnumeration.UAliasContext(listOffset, 0);
\r
582 aliasEnum = new UConverterAliasesEnumeration();
\r
583 aliasEnum.setContext(context);
\r
585 else converter or tag not found
\r
590 // static uint32_t getTagNumber(const char *tagname)
\r
591 private static int getTagNumber(String tagName) {
\r
592 if (gTagList != null) {
\r
594 for (tagNum = 0; tagNum < gTagList.length; tagNum++) {
\r
595 if (tagName.equals(GET_STRING(gTagList[tagNum]))) {
\r
601 return Integer.MAX_VALUE;
\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
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
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
623 if (isAmbigous[0]==true) {
\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
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
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
650 /* The standard doesn't know about the alias */
\r
652 /* else no default name */
\r
655 /* else converter or tag not found */
\r
657 return Integer.MAX_VALUE;
\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
667 int tagNum = getTagNumber(standard);
\r
668 boolean[] isAmbigous = new boolean[1];
\r
670 /* Make a quick guess. Hopefully they used a TR22 canonical alias. */
\r
671 convNum = findConverter(alias, isAmbigous);
\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
680 if (isAmbigous[0] == true) {
\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
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
694 /* The standard doesn't know about the alias */
\r
696 /* else no canonical name */
\r
698 /* else converter or tag not found */
\r
700 return Integer.MAX_VALUE;
\r
703 // static U_INLINE UBool isAliasInList(const char *alias, uint32_t
\r
705 private static boolean isAliasInList(String alias, int listOffset) {
\r
706 if (listOffset != 0) {
\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
716 GET_STRING(currList[currAlias + currListArrayIndex])) == 0) {
\r
725 static String[] gAvailableConverters = null;
\r
727 static int gAvailableConverterCount = 0;
\r
729 static byte[] gDefaultConverterNameBuffer; // [MAX_CONVERTER_NAME_LENGTH +
\r
730 // 1]; /* +1 for NULL */
\r
732 static String gDefaultConverterName = null;
\r
734 // static UBool haveAvailableConverterList(UErrorCode *pErrorCode)
\r
735 static boolean haveAvailableConverterList() throws IOException{
\r
736 if (gAvailableConverters == null) {
\r
738 int localConverterCount;
\r
739 String converterName;
\r
740 String[] localConverterList;
\r
742 if (!haveAliasData()) {
\r
746 /* We can't have more than "*converterTable" converters to open */
\r
747 localConverterList = new String[gConverterList.length];
\r
749 localConverterCount = 0;
\r
751 for (idx = 0; idx < gConverterList.length; idx++) {
\r
752 converterName = GET_STRING(gConverterList[idx]);
\r
753 //UConverter cnv = UConverter.open(converterName);
\r
755 localConverterList[localConverterCount++] = converterName;
\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
765 // agljport:todo free((char **)localConverterList);
\r
767 // agljport:todo umtx_unlock(NULL);
\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
780 // U_CFUNC const char * bld_getAvailableConverter(uint16_t n, UErrorCode
\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
791 /* default converter name --------------------------------------------------- */
\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
801 // U_CFUNC const char * getDefaultName()
\r
802 // static final synchronized String getDefaultName() {
\r
803 // /* local variable to be thread-safe */
\r
806 // //agljport:todo umtx_lock(null);
\r
807 // name = gDefaultConverterName;
\r
808 // //agljport:todo umtx_unlock(null);
\r
810 // if (name == null) {
\r
811 // //UConverter cnv = null;
\r
814 // name = CharsetICU.getDefaultCharsetName();
\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
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
829 // //length=(int32_t)(strlen(name));
\r
831 // /* Copy the name before we close the converter. */
\r
832 // name = gDefaultConverterName;
\r