~ubuntu-branches/ubuntu/vivid/icu4j-4.4/vivid

« back to all changes in this revision

Viewing changes to main/classes/charset/src/com/ibm/icu/charset/UConverterAlias.java

  • Committer: Bazaar Package Importer
  • Author(s): Niels Thykier
  • Date: 2011-08-02 15:50:33 UTC
  • Revision ID: james.westby@ubuntu.com-20110802155033-itjzsl21y2lqdonn
Tags: upstream-4.4.2
ImportĀ upstreamĀ versionĀ 4.4.2

Show diffs side-by-side

added added

removed removed

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