1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
459d709d503bab6e2b61931737e662dd293b40578ccornelius*   Copyright (C) 1999-2013, International Business Machines
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
10103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius*  ucnv_io.cpp:
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*  initializes global variables and defines functions pertaining to converter
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*  name resolution aspect of the conversion code.
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   new implementation:
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   created on: 1999nov22
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   created by: Markus W. Scherer
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Use the binary cnvalias.icu (created from convrtrs.txt) to work
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   with aliases for converter names.
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Date        Name        Description
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   11/22/1999  markus      Created
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   06/28/2002  grhoten     Major overhaul of the converter alias design.
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*                           Now an alias can map to different converters
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*                           depending on the specified standard.
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_CONVERSION
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucnv.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/udata.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "umutex.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uarrsort.h"
3959d709d503bab6e2b61931737e662dd293b40578ccornelius#include "uassert.h"
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "udataswp.h"
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_io.h"
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uenumimp.h"
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucln_cmn.h"
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Format of cnvalias.icu -----------------------------------------------------
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * cnvalias.icu is a binary, memory-mappable form of convrtrs.txt.
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This binary form contains several tables. All indexes are to uint16_t
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * units, and not to the bytes (uint8_t units). Addressing everything on
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 16-bit boundaries allows us to store more information with small index
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * numbers, which are also 16-bit in size. The majority of the table (except
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the string table) are 16-bit numbers.
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * First there is the size of the Table of Contents (TOC). The TOC
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * entries contain the size of each section. In order to find the offset
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * you just need to sum up the previous offsets.
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The TOC length and entries are an array of uint32_t values.
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The first section after the TOC starts immediately after the TOC.
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1) This section contains a list of converters. This list contains indexes
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * into the string table for the converter name. The index of this list is
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * also used by other sections, which are mentioned later on.
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This list is not sorted.
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 2) This section contains a list of tags. This list contains indexes
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * into the string table for the tag name. The index of this list is
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * also used by other sections, which are mentioned later on.
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This list is in priority order of standards.
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 3) This section contains a list of sorted unique aliases. This
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * list contains indexes into the string table for the alias name. The
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * index of this list is also used by other sections, like the 4th section.
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The index for the 3rd and 4th section is used to get the
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * alias -> converter name mapping. Section 3 and 4 form a two column table.
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Some of the most significant bits of each index may contain other
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * information (see findConverter for details).
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 4) This section contains a list of mapped converter names. Consider this
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * as a table that maps the 3rd section to the 1st section. This list contains
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * indexes into the 1st section. The index of this list is the same index in
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the 3rd section. There is also some extra information in the high bits of
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * each converter index in this table. Currently it's only used to say that
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * an alias mapped to this converter is ambiguous. See UCNV_CONVERTER_INDEX_MASK
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and UCNV_AMBIGUOUS_ALIAS_MAP_BIT for more information. This section is
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the predigested form of the 5th section so that an alias lookup can be fast.
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 5) This section contains a 2D array with indexes to the 6th section. This
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * section is the full form of all alias mappings. The column index is the
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * index into the converter list (column header). The row index is the index
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to tag list (row header). This 2D array is the top part a 3D array. The
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * third dimension is in the 6th section.
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 6) This is blob of variable length arrays. Each array starts with a size,
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and is followed by indexes to alias names in the string table. This is
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the third dimension to the section 5. No other section should be referencing
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * this section.
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 7) Starting in ICU 3.6, this can be a UConverterAliasOptions struct. Its
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * presence indicates that a section 9 exists. UConverterAliasOptions specifies
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * what type of string normalization is used among other potential things in the
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * future.
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 8) This is the string table. All strings are indexed on an even address.
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * There are two reasons for this. First many chip architectures locate strings
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * faster on even address boundaries. Second, since all indexes are 16-bit
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * numbers, this string table can be 128KB in size instead of 64KB when we
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * only have strings starting on an even address.
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 9) When present this is a set of prenormalized strings from section 8. This
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * table contains normalized strings with the dashes and spaces stripped out,
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and all strings lowercased. In the future, the options in section 7 may state
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * other types of normalization.
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Here is the concept of section 5 and 6. It's a 3D cube. Each tag
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * has a unique alias among all converters. That same alias can
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * be mentioned in other standards on different converters,
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * but only one alias per tag can be unique.
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *              Converter Names (Usually in TR22 form)
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *           -------------------------------------------.
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *     T    /                                          /|
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *     a   /                                          / |
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *     g  /                                          /  |
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *     s /                                          /   |
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *      /                                          /    |
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *      ------------------------------------------/     |
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    A |                                         |     |
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    l |                                         |     |
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    i |                                         |    /
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    a |                                         |   /
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    s |                                         |  /
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    e |                                         | /
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    s |                                         |/
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *      -------------------------------------------
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Here is what it really looks like. It's like swiss cheese.
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * There are holes. Some converters aren't recognized by
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * a standard, or they are really old converters that the
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * standard doesn't recognize anymore.
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *              Converter Names (Usually in TR22 form)
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *           -------------------------------------------.
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *     T    /##########################################/|
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *     a   /     #            #                       /#
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *     g  /  #      ##     ##     ### # ### ### ### #/
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *     s / #             #####  ####        ##  ## #/#
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *      / ### # # ##  #  #   #          ### # #   #/##
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *      ------------------------------------------/# #
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    A |### # # ##  #  #   #          ### # #   #|# #
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    l |# # #    #     #               ## #     #|# #
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    i |# # #    #     #                #       #|#
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    a |#                                       #|#
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    s |                                        #|#
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    e
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *    s
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Used by the UEnumeration API
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef struct UAliasContext {
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t listOffset;
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t listIdx;
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} UAliasContext;
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char DATA_NAME[] = "cnvalias";
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char DATA_TYPE[] = "icu";
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UDataMemory *gAliasData=NULL;
17659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gAliasDataInitOnce = U_INITONCE_INITIALIZER;
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruenum {
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    tocLengthIndex=0,
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    converterListIndex=1,
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    tagListIndex=2,
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    aliasListIndex=3,
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    untaggedConvArrayIndex=4,
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    taggedAliasArrayIndex=5,
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    taggedAliasListsIndex=6,
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    tableOptionsIndex=7,
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    stringTableIndex=8,
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    normalizedStringTableIndex=9,
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    offsetsCount,    /* length of the swapper's temporary offsets[] */
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    minTocLength=8 /* min. tocLength in the file, does not count the tocLengthIndex! */
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UConverterAliasOptions defaultTableOptions = {
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCNV_IO_UNNORMALIZED,
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0 /* containsCnvOptionInfo */
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UConverterAlias gMainTable;
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define GET_STRING(idx) (const char *)(gMainTable.stringTable + (idx))
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define GET_NORMALIZED_STRING(idx) (const char *)(gMainTable.normalizedStringTable + (idx))
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool U_CALLCONV
203103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusisAcceptable(void * /*context*/,
204103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius             const char * /*type*/, const char * /*name*/,
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             const UDataInfo *pInfo) {
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (UBool)(
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->size>=20 &&
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->charsetFamily==U_CHARSET_FAMILY &&
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[0]==0x43 &&   /* dataFormat="CvAl" */
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[1]==0x76 &&
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[2]==0x41 &&
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[3]==0x6c &&
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->formatVersion[0]==3);
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool U_CALLCONV ucnv_io_cleanup(void)
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (gAliasData) {
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_close(gAliasData);
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        gAliasData = NULL;
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
22359d709d503bab6e2b61931737e662dd293b40578ccornelius    gAliasDataInitOnce.reset();
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(&gMainTable, 0, sizeof(gMainTable));
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return TRUE;                   /* Everything was cleaned up */
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
23059d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initAliasData(UErrorCode &errCode) {
23159d709d503bab6e2b61931737e662dd293b40578ccornelius    UDataMemory *data;
23259d709d503bab6e2b61931737e662dd293b40578ccornelius    const uint16_t *table;
23359d709d503bab6e2b61931737e662dd293b40578ccornelius    const uint32_t *sectionSizes;
23459d709d503bab6e2b61931737e662dd293b40578ccornelius    uint32_t tableStart;
23559d709d503bab6e2b61931737e662dd293b40578ccornelius    uint32_t currOffset;
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
23759d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup);
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
23959d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(gAliasData == NULL);
24059d709d503bab6e2b61931737e662dd293b40578ccornelius    data = udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, &errCode);
24159d709d503bab6e2b61931737e662dd293b40578ccornelius    if(U_FAILURE(errCode)) {
24259d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
24359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24559d709d503bab6e2b61931737e662dd293b40578ccornelius    sectionSizes = (const uint32_t *)udata_getMemory(data);
24659d709d503bab6e2b61931737e662dd293b40578ccornelius    table = (const uint16_t *)sectionSizes;
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24859d709d503bab6e2b61931737e662dd293b40578ccornelius    tableStart      = sectionSizes[0];
24959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (tableStart < minTocLength) {
25059d709d503bab6e2b61931737e662dd293b40578ccornelius        errCode = U_INVALID_FORMAT_ERROR;
25159d709d503bab6e2b61931737e662dd293b40578ccornelius        udata_close(data);
25259d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
25359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
25459d709d503bab6e2b61931737e662dd293b40578ccornelius    gAliasData = data;
25559d709d503bab6e2b61931737e662dd293b40578ccornelius
25659d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.converterListSize      = sectionSizes[1];
25759d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.tagListSize            = sectionSizes[2];
25859d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.aliasListSize          = sectionSizes[3];
25959d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.untaggedConvArraySize  = sectionSizes[4];
26059d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.taggedAliasArraySize   = sectionSizes[5];
26159d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.taggedAliasListsSize   = sectionSizes[6];
26259d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.optionTableSize        = sectionSizes[7];
26359d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.stringTableSize        = sectionSizes[8];
26459d709d503bab6e2b61931737e662dd293b40578ccornelius
26559d709d503bab6e2b61931737e662dd293b40578ccornelius    if (tableStart > 8) {
26659d709d503bab6e2b61931737e662dd293b40578ccornelius        gMainTable.normalizedStringTableSize = sectionSizes[9];
26759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
26959d709d503bab6e2b61931737e662dd293b40578ccornelius    currOffset = tableStart * (sizeof(uint32_t)/sizeof(uint16_t)) + (sizeof(uint32_t)/sizeof(uint16_t));
27059d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.converterList = table + currOffset;
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27259d709d503bab6e2b61931737e662dd293b40578ccornelius    currOffset += gMainTable.converterListSize;
27359d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.tagList = table + currOffset;
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27559d709d503bab6e2b61931737e662dd293b40578ccornelius    currOffset += gMainTable.tagListSize;
27659d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.aliasList = table + currOffset;
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27859d709d503bab6e2b61931737e662dd293b40578ccornelius    currOffset += gMainTable.aliasListSize;
27959d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.untaggedConvArray = table + currOffset;
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
28159d709d503bab6e2b61931737e662dd293b40578ccornelius    currOffset += gMainTable.untaggedConvArraySize;
28259d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.taggedAliasArray = table + currOffset;
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
28459d709d503bab6e2b61931737e662dd293b40578ccornelius    /* aliasLists is a 1's based array, but it has a padding character */
28559d709d503bab6e2b61931737e662dd293b40578ccornelius    currOffset += gMainTable.taggedAliasArraySize;
28659d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.taggedAliasLists = table + currOffset;
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
28859d709d503bab6e2b61931737e662dd293b40578ccornelius    currOffset += gMainTable.taggedAliasListsSize;
28959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (gMainTable.optionTableSize > 0
29059d709d503bab6e2b61931737e662dd293b40578ccornelius        && ((const UConverterAliasOptions *)(table + currOffset))->stringNormalizationType < UCNV_IO_NORM_TYPE_COUNT)
29159d709d503bab6e2b61931737e662dd293b40578ccornelius    {
29259d709d503bab6e2b61931737e662dd293b40578ccornelius        /* Faster table */
29359d709d503bab6e2b61931737e662dd293b40578ccornelius        gMainTable.optionTable = (const UConverterAliasOptions *)(table + currOffset);
29459d709d503bab6e2b61931737e662dd293b40578ccornelius    }
29559d709d503bab6e2b61931737e662dd293b40578ccornelius    else {
29659d709d503bab6e2b61931737e662dd293b40578ccornelius        /* Smaller table, or I can't handle this normalization mode!
29759d709d503bab6e2b61931737e662dd293b40578ccornelius        Use the original slower table lookup. */
29859d709d503bab6e2b61931737e662dd293b40578ccornelius        gMainTable.optionTable = &defaultTableOptions;
29959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
30159d709d503bab6e2b61931737e662dd293b40578ccornelius    currOffset += gMainTable.optionTableSize;
30259d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.stringTable = table + currOffset;
30385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
30459d709d503bab6e2b61931737e662dd293b40578ccornelius    currOffset += gMainTable.stringTableSize;
30559d709d503bab6e2b61931737e662dd293b40578ccornelius    gMainTable.normalizedStringTable = ((gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED)
30659d709d503bab6e2b61931737e662dd293b40578ccornelius        ? gMainTable.stringTable : (table + currOffset));
30759d709d503bab6e2b61931737e662dd293b40578ccornelius}
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
31059d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic UBool
31159d709d503bab6e2b61931737e662dd293b40578ccorneliushaveAliasData(UErrorCode *pErrorCode) {
31259d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gAliasDataInitOnce, &initAliasData, *pErrorCode);
31359d709d503bab6e2b61931737e662dd293b40578ccornelius    return U_SUCCESS(*pErrorCode);
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
316103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic inline UBool
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruisAlias(const char *alias, UErrorCode *pErrorCode) {
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(alias==NULL) {
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (UBool)(*alias!=0);
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint32_t getTagNumber(const char *tagname) {
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (gMainTable.tagList) {
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t tagNum;
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (tagNum = 0; tagNum < gMainTable.tagListSize; tagNum++) {
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (!uprv_stricmp(GET_STRING(gMainTable.tagList[tagNum]), tagname)) {
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return tagNum;
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return UINT32_MAX;
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* character types relevant for ucnv_compareNames() */
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruenum {
34059d709d503bab6e2b61931737e662dd293b40578ccornelius    UIGNORE,
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ZERO,
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NONZERO,
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    MINLETTER /* any values from here on are lowercase letter mappings */
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* character types for ASCII 00..7F */
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const uint8_t asciiTypes[128] = {
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, 0, 0, 0, 0, 0, 0,
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0,
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
35859d709d503bab6e2b61931737e662dd293b40578ccornelius#define GET_ASCII_TYPE(c) ((int8_t)(c) >= 0 ? asciiTypes[(uint8_t)c] : (uint8_t)UIGNORE)
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* character types for EBCDIC 80..FF */
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const uint8_t ebcdicTypes[128] = {
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0,    0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0, 0, 0, 0, 0, 0,
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0,    0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0, 0, 0, 0, 0, 0,
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0,    0,    0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0, 0, 0, 0, 0, 0,
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0,    0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0, 0, 0, 0, 0, 0,
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0,    0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0, 0, 0, 0, 0, 0,
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0,    0,    0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0, 0, 0, 0, 0, 0,
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, 0, 0, 0, 0, 0, 0
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
37259d709d503bab6e2b61931737e662dd293b40578ccornelius#define GET_EBCDIC_TYPE(c) ((int8_t)(c) < 0 ? ebcdicTypes[(c)&0x7f] : (uint8_t)UIGNORE)
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if U_CHARSET_FAMILY==U_ASCII_FAMILY
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define GET_CHAR_TYPE(c) GET_ASCII_TYPE(c)
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define GET_CHAR_TYPE(c) GET_EBCDIC_TYPE(c)
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   error U_CHARSET_FAMILY is not valid
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* @see ucnv_compareNames */
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC char * U_EXPORT2
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_stripASCIIForCompare(char *dst, const char *name) {
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *dstItr = dst;
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t type, nextType;
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char c1;
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool afterDigit = FALSE;
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while ((c1 = *name++) != 0) {
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        type = GET_ASCII_TYPE(c1);
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch (type) {
39359d709d503bab6e2b61931737e662dd293b40578ccornelius        case UIGNORE:
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            afterDigit = FALSE;
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            continue; /* ignore all but letters and digits */
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case ZERO:
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (!afterDigit) {
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                nextType = GET_ASCII_TYPE(*name);
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (nextType == ZERO || nextType == NONZERO) {
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue; /* ignore leading zero before another digit */
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case NONZERO:
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            afterDigit = TRUE;
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        default:
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            c1 = (char)type; /* lowercased letter */
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            afterDigit = FALSE;
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *dstItr++ = c1;
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *dstItr = 0;
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return dst;
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC char * U_EXPORT2
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_stripEBCDICForCompare(char *dst, const char *name) {
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *dstItr = dst;
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t type, nextType;
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char c1;
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool afterDigit = FALSE;
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while ((c1 = *name++) != 0) {
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        type = GET_EBCDIC_TYPE(c1);
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch (type) {
42859d709d503bab6e2b61931737e662dd293b40578ccornelius        case UIGNORE:
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            afterDigit = FALSE;
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            continue; /* ignore all but letters and digits */
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case ZERO:
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (!afterDigit) {
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                nextType = GET_EBCDIC_TYPE(*name);
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (nextType == ZERO || nextType == NONZERO) {
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue; /* ignore leading zero before another digit */
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case NONZERO:
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            afterDigit = TRUE;
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        default:
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            c1 = (char)type; /* lowercased letter */
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            afterDigit = FALSE;
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *dstItr++ = c1;
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *dstItr = 0;
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return dst;
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Do a fuzzy compare of two converter/alias names.
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The comparison is case-insensitive, ignores leading zeroes if they are not
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * followed by further digits, and ignores all but letters and digits.
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Thus the strings "UTF-8", "utf_8", "u*T@f08" and "Utf 8" are exactly equivalent.
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * See section 1.4, Charset Alias Matching in Unicode Technical Standard #22
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * at http://www.unicode.org/reports/tr22/
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This is a symmetrical (commutative) operation; order of arguments
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is insignificant.  This is an important property for sorting the
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * list (when the list is preprocessed into binary form) and for
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * performing binary searches on it at run time.
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param name1 a converter name or alias, zero-terminated
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param name2 a converter name or alias, zero-terminated
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return 0 if the names match, or a negative value if the name1
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * lexically precedes name2, or a positive value if the name1
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * lexically follows name2.
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see ucnv_io_stripForCompare
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int U_EXPORT2
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_compareNames(const char *name1, const char *name2) {
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int rc;
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t type, nextType;
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char c1, c2;
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool afterDigit1 = FALSE, afterDigit2 = FALSE;
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (;;) {
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while ((c1 = *name1++) != 0) {
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            type = GET_CHAR_TYPE(c1);
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            switch (type) {
48559d709d503bab6e2b61931737e662dd293b40578ccornelius            case UIGNORE:
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                afterDigit1 = FALSE;
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                continue; /* ignore all but letters and digits */
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case ZERO:
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (!afterDigit1) {
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    nextType = GET_CHAR_TYPE(*name1);
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (nextType == ZERO || nextType == NONZERO) {
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        continue; /* ignore leading zero before another digit */
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case NONZERO:
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                afterDigit1 = TRUE;
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            default:
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                c1 = (char)type; /* lowercased letter */
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                afterDigit1 = FALSE;
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break; /* deliver c1 */
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while ((c2 = *name2++) != 0) {
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            type = GET_CHAR_TYPE(c2);
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            switch (type) {
50959d709d503bab6e2b61931737e662dd293b40578ccornelius            case UIGNORE:
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                afterDigit2 = FALSE;
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                continue; /* ignore all but letters and digits */
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case ZERO:
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (!afterDigit2) {
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    nextType = GET_CHAR_TYPE(*name2);
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (nextType == ZERO || nextType == NONZERO) {
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        continue; /* ignore leading zero before another digit */
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case NONZERO:
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                afterDigit2 = TRUE;
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            default:
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                c2 = (char)type; /* lowercased letter */
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                afterDigit2 = FALSE;
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break; /* deliver c2 */
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* If we reach the ends of both strings then they match */
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if ((c1|c2)==0) {
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Case-insensitive comparison */
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        rc = (int)(unsigned char)c1 - (int)(unsigned char)c2;
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (rc != 0) {
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return rc;
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * search for an alias
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * return the converter number index for gConverterList
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
548103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic inline uint32_t
549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerufindConverter(const char *alias, UBool *containsOption, UErrorCode *pErrorCode) {
550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t mid, start, limit;
551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t lastMid;
552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int result;
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int isUnnormalized = (gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED);
554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char strippedName[UCNV_MAX_CONVERTER_NAME_LENGTH];
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!isUnnormalized) {
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (uprv_strlen(alias) >= UCNV_MAX_CONVERTER_NAME_LENGTH) {
558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode = U_BUFFER_OVERFLOW_ERROR;
559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return UINT32_MAX;
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Lower case and remove ignoreable characters. */
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_io_stripForCompare(strippedName, alias);
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        alias = strippedName;
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* do a binary search for the alias */
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    start = 0;
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    limit = gMainTable.untaggedConvArraySize;
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    mid = limit;
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lastMid = UINT32_MAX;
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (;;) {
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mid = (uint32_t)((start + limit) / 2);
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (lastMid == mid) {   /* Have we moved? */
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;  /* We haven't moved, and it wasn't found. */
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lastMid = mid;
579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (isUnnormalized) {
580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result = ucnv_compareNames(alias, GET_STRING(gMainTable.aliasList[mid]));
581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result = uprv_strcmp(alias, GET_NORMALIZED_STRING(gMainTable.aliasList[mid]));
584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (result < 0) {
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            limit = mid;
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (result > 0) {
589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = mid;
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Since the gencnval tool folds duplicates into one entry,
592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * this alias in gAliasList is unique, but different standards
593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * may map an alias to different converters.
594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (gMainTable.untaggedConvArray[mid] & UCNV_AMBIGUOUS_ALIAS_MAP_BIT) {
596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode = U_AMBIGUOUS_ALIAS_WARNING;
597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* State whether the canonical converter name contains an option.
599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            This information is contained in this list in order to maintain backward & forward compatibility. */
600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (containsOption) {
601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UBool containsCnvOptionInfo = (UBool)gMainTable.optionTable->containsCnvOptionInfo;
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *containsOption = (UBool)((containsCnvOptionInfo
603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    && ((gMainTable.untaggedConvArray[mid] & UCNV_CONTAINS_OPTION_BIT) != 0))
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    || !containsCnvOptionInfo);
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return gMainTable.untaggedConvArray[mid] & UCNV_CONVERTER_INDEX_MASK;
607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return UINT32_MAX;
611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Is this alias in this list?
615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * alias and listOffset should be non-NULL.
616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
617103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic inline UBool
618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruisAliasInList(const char *alias, uint32_t listOffset) {
619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (listOffset) {
620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t currAlias;
621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t listCount = gMainTable.taggedAliasLists[listOffset];
622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* +1 to skip listCount */
623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (currAlias = 0; currAlias < listCount; currAlias++) {
625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (currList[currAlias]
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                && ucnv_compareNames(alias, GET_STRING(currList[currAlias]))==0)
627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            {
628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return TRUE;
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Search for an standard name of an alias (what is the default name
637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * that this standard uses?)
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * return the listOffset for gTaggedAliasLists. If it's 0,
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the it couldn't be found, but the parameters are valid.
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint32_t
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerufindTaggedAliasListsOffset(const char *alias, const char *standard, UErrorCode *pErrorCode) {
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t idx;
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t listOffset;
645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t convNum;
646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode myErr = U_ZERO_ERROR;
647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t tagNum = getTagNumber(standard);
648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Make a quick guess. Hopefully they used a TR22 canonical alias. */
650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    convNum = findConverter(alias, NULL, &myErr);
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (myErr != U_ZERO_ERROR) {
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode = myErr;
653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (tagNum < (gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS) && convNum < gMainTable.converterListSize) {
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        listOffset = gMainTable.taggedAliasArray[tagNum*gMainTable.converterListSize + convNum];
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (listOffset && gMainTable.taggedAliasLists[listOffset + 1]) {
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return listOffset;
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (myErr == U_AMBIGUOUS_ALIAS_WARNING) {
661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Uh Oh! They used an ambiguous alias.
662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               We have to search the whole swiss cheese starting
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               at the highest standard affinity.
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               This may take a while.
665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            */
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (idx = 0; idx < gMainTable.taggedAliasArraySize; idx++) {
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                listOffset = gMainTable.taggedAliasArray[idx];
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (listOffset && isAliasInList(alias, listOffset)) {
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    uint32_t currTagNum = idx/gMainTable.converterListSize;
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    uint32_t currConvNum = (idx - currTagNum*gMainTable.converterListSize);
671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    uint32_t tempListOffset = gMainTable.taggedAliasArray[tagNum*gMainTable.converterListSize + currConvNum];
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (tempListOffset && gMainTable.taggedAliasLists[tempListOffset + 1]) {
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        return tempListOffset;
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* else keep on looking */
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* We could speed this up by starting on the next row
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       because an alias is unique per row, right now.
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       This would change if alias versioning appears. */
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* The standard doesn't know about the alias */
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* else no default name */
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* else converter or tag not found */
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return UINT32_MAX;
689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Return the canonical name */
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint32_t
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerufindTaggedConverterNum(const char *alias, const char *standard, UErrorCode *pErrorCode) {
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t idx;
695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t listOffset;
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t convNum;
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode myErr = U_ZERO_ERROR;
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t tagNum = getTagNumber(standard);
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Make a quick guess. Hopefully they used a TR22 canonical alias. */
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    convNum = findConverter(alias, NULL, &myErr);
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (myErr != U_ZERO_ERROR) {
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode = myErr;
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (tagNum < (gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS) && convNum < gMainTable.converterListSize) {
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        listOffset = gMainTable.taggedAliasArray[tagNum*gMainTable.converterListSize + convNum];
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (listOffset && isAliasInList(alias, listOffset)) {
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return convNum;
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (myErr == U_AMBIGUOUS_ALIAS_WARNING) {
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Uh Oh! They used an ambiguous alias.
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               We have to search one slice of the swiss cheese.
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               We search only in the requested tag, not the whole thing.
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               This may take a while.
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            */
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uint32_t convStart = (tagNum)*gMainTable.converterListSize;
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uint32_t convLimit = (tagNum+1)*gMainTable.converterListSize;
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (idx = convStart; idx < convLimit; idx++) {
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                listOffset = gMainTable.taggedAliasArray[idx];
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (listOffset && isAliasInList(alias, listOffset)) {
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return idx-convStart;
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* The standard doesn't know about the alias */
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* else no canonical name */
728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* else converter or tag not found */
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return UINT32_MAX;
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC const char *
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_getConverterName(const char *alias, UBool *containsOption, UErrorCode *pErrorCode) {
738103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const char *aliasTmp = alias;
739103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t i = 0;
740103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    for (i = 0; i < 2; i++) {
741103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (i == 1) {
742103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            /*
743103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius             * After the first unsuccess converter lookup, check to see if
744103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius             * the name begins with 'x-'. If it does, strip it off and try
745103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius             * again.  This behaviour is similar to how ICU4J does it.
746103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius             */
747103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if (aliasTmp[0] == 'x' || aliasTmp[1] == '-') {
748103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                aliasTmp = aliasTmp+2;
749103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            } else {
750103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                break;
751103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            }
752103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
753103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if(haveAliasData(pErrorCode) && isAlias(aliasTmp, pErrorCode)) {
754103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            uint32_t convNum = findConverter(aliasTmp, containsOption, pErrorCode);
755103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if (convNum < gMainTable.converterListSize) {
756103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                return GET_STRING(gMainTable.converterList[convNum]);
757103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            }
758103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            /* else converter not found */
759103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        } else {
760103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
763103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t U_CALLCONV
768103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusucnv_io_countStandardAliases(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t value = 0;
770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UAliasContext *myContext = (UAliasContext *)(enumerator->context);
771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t listOffset = myContext->listOffset;
772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (listOffset) {
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        value = gMainTable.taggedAliasLists[listOffset];
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return value;
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char* U_CALLCONV
780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_nextStandardAliases(UEnumeration *enumerator,
781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            int32_t* resultLength,
782103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                            UErrorCode * /*pErrorCode*/)
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UAliasContext *myContext = (UAliasContext *)(enumerator->context);
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t listOffset = myContext->listOffset;
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (listOffset) {
788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t listCount = gMainTable.taggedAliasLists[listOffset];
789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (myContext->listIdx < listCount) {
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            const char *myStr = GET_STRING(currList[myContext->listIdx++]);
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (resultLength) {
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *resultLength = (int32_t)uprv_strlen(myStr);
795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return myStr;
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Either we accessed a zero length list, or we enumerated too far. */
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (resultLength) {
801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *resultLength = 0;
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void U_CALLCONV
807103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusucnv_io_resetStandardAliases(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ((UAliasContext *)(enumerator->context))->listIdx = 0;
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void U_CALLCONV
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_closeUEnumeration(UEnumeration *enumerator) {
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_free(enumerator->context);
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_free(enumerator);
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Enumerate the aliases for the specified converter and standard tag */
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UEnumeration gEnumAliases = {
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_closeUEnumeration,
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_countStandardAliases,
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uenum_unextDefault,
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_nextStandardAliases,
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_resetStandardAliases
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UEnumeration * U_EXPORT2
829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_openStandardNames(const char *convName,
830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       const char *standard,
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       UErrorCode *pErrorCode)
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UEnumeration *myEnum = NULL;
834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAliasData(pErrorCode) && isAlias(convName, pErrorCode)) {
835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t listOffset = findTaggedAliasListsOffset(convName, standard, pErrorCode);
836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* When listOffset == 0, we want to acknowledge that the
838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           converter name and standard are okay, but there
839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           is nothing to enumerate. */
840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (listOffset < gMainTable.taggedAliasListsSize) {
841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UAliasContext *myContext;
842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
84354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            myEnum = static_cast<UEnumeration *>(uprv_malloc(sizeof(UEnumeration)));
844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (myEnum == NULL) {
845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return NULL;
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_memcpy(myEnum, &gEnumAliases, sizeof(UEnumeration));
84954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            myContext = static_cast<UAliasContext *>(uprv_malloc(sizeof(UAliasContext)));
850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (myContext == NULL) {
851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uprv_free(myEnum);
853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return NULL;
854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            myContext->listOffset = listOffset;
856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            myContext->listIdx = 0;
857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            myEnum->context = myContext;
858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* else converter or tag not found */
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return myEnum;
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint16_t
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_countAliases(const char *alias, UErrorCode *pErrorCode) {
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t convNum = findConverter(alias, NULL, pErrorCode);
868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (convNum < gMainTable.converterListSize) {
869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* tagListNum - 1 is the ALL tag */
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t listOffset = gMainTable.taggedAliasArray[(gMainTable.tagListSize - 1)*gMainTable.converterListSize + convNum];
871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (listOffset) {
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return gMainTable.taggedAliasLists[listOffset];
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* else this shouldn't happen. internal program error */
876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* else converter not found */
878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint16_t
883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_getAliases(const char *alias, uint16_t start, const char **aliases, UErrorCode *pErrorCode) {
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t currAlias;
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t convNum = findConverter(alias, NULL, pErrorCode);
887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (convNum < gMainTable.converterListSize) {
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* tagListNum - 1 is the ALL tag */
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t listOffset = gMainTable.taggedAliasArray[(gMainTable.tagListSize - 1)*gMainTable.converterListSize + convNum];
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (listOffset) {
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uint32_t listCount = gMainTable.taggedAliasLists[listOffset];
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* +1 to skip listCount */
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                for (currAlias = start; currAlias < listCount; currAlias++) {
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    aliases[currAlias] = GET_STRING(currList[currAlias]);
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* else this shouldn't happen. internal program error */
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* else converter not found */
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char *
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode) {
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t convNum = findConverter(alias, NULL, pErrorCode);
911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (convNum < gMainTable.converterListSize) {
912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* tagListNum - 1 is the ALL tag */
913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t listOffset = gMainTable.taggedAliasArray[(gMainTable.tagListSize - 1)*gMainTable.converterListSize + convNum];
914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (listOffset) {
916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uint32_t listCount = gMainTable.taggedAliasLists[listOffset];
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* +1 to skip listCount */
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (n < listCount)  {
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return GET_STRING(currList[n]);
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* else this shouldn't happen. internal program error */
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* else converter not found */
928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint16_t
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_countStandards(UErrorCode *pErrorCode) {
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAliasData(pErrorCode)) {
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Don't include the empty list */
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (uint16_t)(gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS);
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI const char * U_EXPORT2
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getStandard(uint16_t n, UErrorCode *pErrorCode) {
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAliasData(pErrorCode)) {
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (n < gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS) {
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return GET_STRING(gMainTable.tagList[n]);
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI const char * U_EXPORT2
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getStandardName(const char *alias, const char *standard, UErrorCode *pErrorCode) {
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t listOffset = findTaggedAliasListsOffset(alias, standard, pErrorCode);
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (0 < listOffset && listOffset < gMainTable.taggedAliasListsSize) {
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Get the preferred name from this list */
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (currList[0]) {
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return GET_STRING(currList[0]);
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* else someone screwed up the alias table. */
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* *pErrorCode = U_INVALID_FORMAT_ERROR */
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI uint16_t U_EXPORT2
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_countAliases(const char *alias, UErrorCode *pErrorCode)
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ucnv_io_countAliases(alias, pErrorCode);
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI const char* U_EXPORT2
982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode)
983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ucnv_io_getAlias(alias, n, pErrorCode);
985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getAliases(const char *alias, const char **aliases, UErrorCode *pErrorCode)
989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_getAliases(alias, 0, aliases, pErrorCode);
991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI uint16_t U_EXPORT2
994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_countStandards(void)
995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode err = U_ZERO_ERROR;
997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ucnv_io_countStandards(&err);
998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI const char * U_EXPORT2
1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getCanonicalName(const char *alias, const char *standard, UErrorCode *pErrorCode) {
1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t convNum = findTaggedConverterNum(alias, standard, pErrorCode);
1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (convNum < gMainTable.converterListSize) {
1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return GET_STRING(gMainTable.converterList[convNum]);
1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t U_CALLCONV
1014103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusucnv_io_countAllConverters(UEnumeration * /*enumerator*/, UErrorCode * /*pErrorCode*/) {
1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return gMainTable.converterListSize;
1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char* U_CALLCONV
1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_nextAllConverters(UEnumeration *enumerator,
1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            int32_t* resultLength,
1021103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                            UErrorCode * /*pErrorCode*/)
1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint16_t *myContext = (uint16_t *)(enumerator->context);
1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (*myContext < gMainTable.converterListSize) {
1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *myStr = GET_STRING(gMainTable.converterList[(*myContext)++]);
1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (resultLength) {
1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *resultLength = (int32_t)uprv_strlen(myStr);
1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return myStr;
1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Either we accessed a zero length list, or we enumerated too far. */
1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (resultLength) {
1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *resultLength = 0;
1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void U_CALLCONV
1040103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusucnv_io_resetAllConverters(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *((uint16_t *)(enumerator->context)) = 0;
1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UEnumeration gEnumAllConverters = {
1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
1046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_closeUEnumeration,
1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_countAllConverters,
1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uenum_unextDefault,
1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_nextAllConverters,
1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_resetAllConverters
1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UEnumeration * U_EXPORT2
1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_openAllNames(UErrorCode *pErrorCode) {
1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UEnumeration *myEnum = NULL;
1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAliasData(pErrorCode)) {
1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint16_t *myContext;
1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
106054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        myEnum = static_cast<UEnumeration *>(uprv_malloc(sizeof(UEnumeration)));
1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (myEnum == NULL) {
1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
1063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memcpy(myEnum, &gEnumAllConverters, sizeof(UEnumeration));
106654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        myContext = static_cast<uint16_t *>(uprv_malloc(sizeof(uint16_t)));
1067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (myContext == NULL) {
1068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
1069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free(myEnum);
1070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
1071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *myContext = 0;
1073ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        myEnum->context = myContext;
1074ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1075ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return myEnum;
1076ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1077ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1078ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC uint16_t
1079ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_io_countKnownConverters(UErrorCode *pErrorCode) {
1080ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAliasData(pErrorCode)) {
1081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (uint16_t)gMainTable.converterListSize;
1082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1083ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
1084ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1085ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* alias table swapping ----------------------------------------------------- */
1087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef char * U_CALLCONV StripForCompareFn(char *dst, const char *name);
1089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * row of a temporary array
1092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * gets platform-endian charset string indexes and sorting indexes;
1094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * after sorting this array by strings, the actual arrays are permutated
1095ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * according to the sorting indexes
1096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef struct TempRow {
1098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint16_t strIndex, sortIndex;
1099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} TempRow;
1100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef struct TempAliasTable {
1102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *chars;
1103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TempRow *rows;
1104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint16_t *resort;
1105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    StripForCompareFn *stripForCompare;
1106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} TempAliasTable;
1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruenum {
1109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    STACK_ROW_CAPACITY=500
1110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
1111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
1113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruio_compareRows(const void *context, const void *left, const void *right) {
1114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char strippedLeft[UCNV_MAX_CONVERTER_NAME_LENGTH],
1115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         strippedRight[UCNV_MAX_CONVERTER_NAME_LENGTH];
1116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TempAliasTable *tempTable=(TempAliasTable *)context;
1118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *chars=tempTable->chars;
1119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (int32_t)uprv_strcmp(tempTable->stripForCompare(strippedLeft, chars+2*((const TempRow *)left)->strIndex),
1121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                tempTable->stripForCompare(strippedRight, chars+2*((const TempRow *)right)->strIndex));
1122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_swapAliases(const UDataSwapper *ds,
1126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 const void *inData, int32_t length, void *outData,
1127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 UErrorCode *pErrorCode) {
1128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UDataInfo *pInfo;
1129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t headerSize;
1130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const uint16_t *inTable;
1132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const uint32_t *inSectionSizes;
1133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t toc[offsetsCount];
1134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t offsets[offsetsCount]; /* 16-bit-addressed offsets from inTable/outTable */
1135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t i, count, tocLength, topOffset;
1136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TempRow rows[STACK_ROW_CAPACITY];
1138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint16_t resort[STACK_ROW_CAPACITY];
1139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TempAliasTable tempTable;
1140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* udata_swapDataHeader checks the arguments */
1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
1143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check data format and format version */
1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pInfo=(const UDataInfo *)((const char *)inData+4);
1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!(
1150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[0]==0x43 &&   /* dataFormat="CvAl" */
1151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[1]==0x76 &&
1152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[2]==0x41 &&
1153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[3]==0x6c &&
1154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->formatVersion[0]==3
1155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    )) {
1156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_printError(ds, "ucnv_swapAliases(): data format %02x.%02x.%02x.%02x (format version %02x) is not an alias table\n",
1157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         pInfo->dataFormat[0], pInfo->dataFormat[1],
1158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         pInfo->dataFormat[2], pInfo->dataFormat[3],
1159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         pInfo->formatVersion[0]);
1160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_UNSUPPORTED_ERROR;
1161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* an alias table must contain at least the table of contents array */
1165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length>=0 && (length-headerSize)<4*(1+minTocLength)) {
1166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_printError(ds, "ucnv_swapAliases(): too few bytes (%d after header) for an alias table\n",
1167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         length-headerSize);
1168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inSectionSizes=(const uint32_t *)((const char *)inData+headerSize);
1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inTable=(const uint16_t *)inSectionSizes;
1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(toc, 0, sizeof(toc));
1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toc[tocLengthIndex]=tocLength=ds->readUInt32(inSectionSizes[tocLengthIndex]);
1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(tocLength<minTocLength || offsetsCount<=tocLength) {
1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_printError(ds, "ucnv_swapAliases(): table of contents contains unsupported number of sections (%u sections)\n", tocLength);
1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_INVALID_FORMAT_ERROR;
1179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* read the known part of the table of contents */
1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(i=converterListIndex; i<=tocLength; ++i) {
1184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        toc[i]=ds->readUInt32(inSectionSizes[i]);
1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* compute offsets */
1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(offsets, 0, sizeof(offsets));
1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    offsets[converterListIndex]=2*(1+tocLength); /* count two 16-bit units per toc entry */
1190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(i=tagListIndex; i<=tocLength; ++i) {
1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        offsets[i]=offsets[i-1]+toc[i-1];
1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* compute the overall size of the after-header data, in numbers of 16-bit units */
1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    topOffset=offsets[i-1]+toc[i-1];
1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length>=0) {
1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint16_t *outTable;
1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const uint16_t *p, *p2;
1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint16_t *q, *q2;
1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint16_t oldIndex;
1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if((length-headerSize)<(2*(int32_t)topOffset)) {
1204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swapAliases(): too few bytes (%d after header) for an alias table\n",
1205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             length-headerSize);
1206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outTable=(uint16_t *)((char *)outData+headerSize);
1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* swap the entire table of contents */
1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ds->swapArray32(ds, inTable, 4*(1+tocLength), outTable, pErrorCode);
1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* swap unormalized strings & normalized strings */
1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ds->swapInvChars(ds, inTable+offsets[stringTableIndex], 2*(int32_t)(toc[stringTableIndex]+toc[normalizedStringTableIndex]),
1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             outTable+offsets[stringTableIndex], pErrorCode);
1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(*pErrorCode)) {
1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swapAliases().swapInvChars(charset names) failed\n");
1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(ds->inCharset==ds->outCharset) {
1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* no need to sort, just swap all 16-bit values together */
1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ds->swapArray16(ds,
1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            inTable+offsets[converterListIndex],
1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            2*(int32_t)(offsets[stringTableIndex]-offsets[converterListIndex]),
1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outTable+offsets[converterListIndex],
1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            pErrorCode);
1230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* allocate the temporary table for sorting */
1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            count=toc[aliasListIndex];
1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            tempTable.chars=(const char *)(outTable+offsets[stringTableIndex]); /* sort by outCharset */
1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(count<=STACK_ROW_CAPACITY) {
1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tempTable.rows=rows;
1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tempTable.resort=resort;
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tempTable.rows=(TempRow *)uprv_malloc(count*sizeof(TempRow)+count*2);
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(tempTable.rows==NULL) {
1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    udata_printError(ds, "ucnv_swapAliases(): unable to allocate memory for sorting tables (max length: %u)\n",
1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                     count);
1244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return 0;
1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tempTable.resort=(uint16_t *)(tempTable.rows+count);
1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(ds->outCharset==U_ASCII_FAMILY) {
1251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tempTable.stripForCompare=ucnv_io_stripASCIIForCompare;
1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else /* U_EBCDIC_FAMILY */ {
1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tempTable.stripForCompare=ucnv_io_stripEBCDICForCompare;
1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * Sort unique aliases+mapped names.
1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             *
1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * We need to sort the list again by outCharset strings because they
1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * sort differently for different charset families.
1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * First we set up a temporary table with the string indexes and
1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * sorting indexes and sort that.
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * Then we permutate and copy/swap the actual values.
1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            p=inTable+offsets[aliasListIndex];
1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            q=outTable+offsets[aliasListIndex];
1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            p2=inTable+offsets[untaggedConvArrayIndex];
1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            q2=outTable+offsets[untaggedConvArrayIndex];
1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for(i=0; i<count; ++i) {
1272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tempTable.rows[i].strIndex=ds->readUInt16(p[i]);
1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tempTable.rows[i].sortIndex=(uint16_t)i;
1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_sortArray(tempTable.rows, (int32_t)count, sizeof(TempRow),
1277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           io_compareRows, &tempTable,
1278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           FALSE, pErrorCode);
1279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(U_SUCCESS(*pErrorCode)) {
1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* copy/swap/permutate items */
1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(p!=q) {
1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    for(i=0; i<count; ++i) {
1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        oldIndex=tempTable.rows[i].sortIndex;
1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray16(ds, p+oldIndex, 2, q+i, pErrorCode);
1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray16(ds, p2+oldIndex, 2, q2+i, pErrorCode);
1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
1289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
1290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * If we swap in-place, then the permutation must use another
1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * temporary array (tempTable.resort)
1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * before the results are copied to the outBundle.
1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    uint16_t *r=tempTable.resort;
1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    for(i=0; i<count; ++i) {
1297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        oldIndex=tempTable.rows[i].sortIndex;
1298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray16(ds, p+oldIndex, 2, r+i, pErrorCode);
1299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    uprv_memcpy(q, r, 2*count);
1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    for(i=0; i<count; ++i) {
1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        oldIndex=tempTable.rows[i].sortIndex;
1304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray16(ds, p2+oldIndex, 2, r+i, pErrorCode);
1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    uprv_memcpy(q2, r, 2*count);
1307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(tempTable.rows!=rows) {
1311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uprv_free(tempTable.rows);
1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(U_FAILURE(*pErrorCode)) {
1315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                udata_printError(ds, "ucnv_swapAliases().uprv_sortArray(%u items) failed\n",
1316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 count);
1317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return 0;
1318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* swap remaining 16-bit values */
1321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ds->swapArray16(ds,
1322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            inTable+offsets[converterListIndex],
1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            2*(int32_t)(offsets[aliasListIndex]-offsets[converterListIndex]),
1324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outTable+offsets[converterListIndex],
1325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            pErrorCode);
1326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ds->swapArray16(ds,
1327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            inTable+offsets[taggedAliasArrayIndex],
1328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            2*(int32_t)(offsets[stringTableIndex]-offsets[taggedAliasArrayIndex]),
1329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outTable+offsets[taggedAliasArrayIndex],
1330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            pErrorCode);
1331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return headerSize+2*(int32_t)topOffset;
1335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
133959d709d503bab6e2b61931737e662dd293b40578ccornelius
1340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Hey, Emacs, please set the following:
1342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Local Variables:
1344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * indent-tabs-mode: nil
1345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * End:
1346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
1347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1348