11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
31cb0ef41Sopenharmony_ci/*
41cb0ef41Sopenharmony_ci******************************************************************************
51cb0ef41Sopenharmony_ci*
61cb0ef41Sopenharmony_ci*   Copyright (C) 1999-2015, International Business Machines
71cb0ef41Sopenharmony_ci*   Corporation and others.  All Rights Reserved.
81cb0ef41Sopenharmony_ci*
91cb0ef41Sopenharmony_ci******************************************************************************
101cb0ef41Sopenharmony_ci*
111cb0ef41Sopenharmony_ci*
121cb0ef41Sopenharmony_ci*  ucnv_io.cpp:
131cb0ef41Sopenharmony_ci*  initializes global variables and defines functions pertaining to converter
141cb0ef41Sopenharmony_ci*  name resolution aspect of the conversion code.
151cb0ef41Sopenharmony_ci*
161cb0ef41Sopenharmony_ci*   new implementation:
171cb0ef41Sopenharmony_ci*
181cb0ef41Sopenharmony_ci*   created on: 1999nov22
191cb0ef41Sopenharmony_ci*   created by: Markus W. Scherer
201cb0ef41Sopenharmony_ci*
211cb0ef41Sopenharmony_ci*   Use the binary cnvalias.icu (created from convrtrs.txt) to work
221cb0ef41Sopenharmony_ci*   with aliases for converter names.
231cb0ef41Sopenharmony_ci*
241cb0ef41Sopenharmony_ci*   Date        Name        Description
251cb0ef41Sopenharmony_ci*   11/22/1999  markus      Created
261cb0ef41Sopenharmony_ci*   06/28/2002  grhoten     Major overhaul of the converter alias design.
271cb0ef41Sopenharmony_ci*                           Now an alias can map to different converters
281cb0ef41Sopenharmony_ci*                           depending on the specified standard.
291cb0ef41Sopenharmony_ci*******************************************************************************
301cb0ef41Sopenharmony_ci*/
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci#include "unicode/utypes.h"
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci#if !UCONFIG_NO_CONVERSION
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci#include "unicode/ucnv.h"
371cb0ef41Sopenharmony_ci#include "unicode/udata.h"
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci#include "umutex.h"
401cb0ef41Sopenharmony_ci#include "uarrsort.h"
411cb0ef41Sopenharmony_ci#include "uassert.h"
421cb0ef41Sopenharmony_ci#include "udataswp.h"
431cb0ef41Sopenharmony_ci#include "cstring.h"
441cb0ef41Sopenharmony_ci#include "cmemory.h"
451cb0ef41Sopenharmony_ci#include "ucnv_io.h"
461cb0ef41Sopenharmony_ci#include "uenumimp.h"
471cb0ef41Sopenharmony_ci#include "ucln_cmn.h"
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci/* Format of cnvalias.icu -----------------------------------------------------
501cb0ef41Sopenharmony_ci *
511cb0ef41Sopenharmony_ci * cnvalias.icu is a binary, memory-mappable form of convrtrs.txt.
521cb0ef41Sopenharmony_ci * This binary form contains several tables. All indexes are to uint16_t
531cb0ef41Sopenharmony_ci * units, and not to the bytes (uint8_t units). Addressing everything on
541cb0ef41Sopenharmony_ci * 16-bit boundaries allows us to store more information with small index
551cb0ef41Sopenharmony_ci * numbers, which are also 16-bit in size. The majority of the table (except
561cb0ef41Sopenharmony_ci * the string table) are 16-bit numbers.
571cb0ef41Sopenharmony_ci *
581cb0ef41Sopenharmony_ci * First there is the size of the Table of Contents (TOC). The TOC
591cb0ef41Sopenharmony_ci * entries contain the size of each section. In order to find the offset
601cb0ef41Sopenharmony_ci * you just need to sum up the previous offsets.
611cb0ef41Sopenharmony_ci * The TOC length and entries are an array of uint32_t values.
621cb0ef41Sopenharmony_ci * The first section after the TOC starts immediately after the TOC.
631cb0ef41Sopenharmony_ci *
641cb0ef41Sopenharmony_ci * 1) This section contains a list of converters. This list contains indexes
651cb0ef41Sopenharmony_ci * into the string table for the converter name. The index of this list is
661cb0ef41Sopenharmony_ci * also used by other sections, which are mentioned later on.
671cb0ef41Sopenharmony_ci * This list is not sorted.
681cb0ef41Sopenharmony_ci *
691cb0ef41Sopenharmony_ci * 2) This section contains a list of tags. This list contains indexes
701cb0ef41Sopenharmony_ci * into the string table for the tag name. The index of this list is
711cb0ef41Sopenharmony_ci * also used by other sections, which are mentioned later on.
721cb0ef41Sopenharmony_ci * This list is in priority order of standards.
731cb0ef41Sopenharmony_ci *
741cb0ef41Sopenharmony_ci * 3) This section contains a list of sorted unique aliases. This
751cb0ef41Sopenharmony_ci * list contains indexes into the string table for the alias name. The
761cb0ef41Sopenharmony_ci * index of this list is also used by other sections, like the 4th section.
771cb0ef41Sopenharmony_ci * The index for the 3rd and 4th section is used to get the
781cb0ef41Sopenharmony_ci * alias -> converter name mapping. Section 3 and 4 form a two column table.
791cb0ef41Sopenharmony_ci * Some of the most significant bits of each index may contain other
801cb0ef41Sopenharmony_ci * information (see findConverter for details).
811cb0ef41Sopenharmony_ci *
821cb0ef41Sopenharmony_ci * 4) This section contains a list of mapped converter names. Consider this
831cb0ef41Sopenharmony_ci * as a table that maps the 3rd section to the 1st section. This list contains
841cb0ef41Sopenharmony_ci * indexes into the 1st section. The index of this list is the same index in
851cb0ef41Sopenharmony_ci * the 3rd section. There is also some extra information in the high bits of
861cb0ef41Sopenharmony_ci * each converter index in this table. Currently it's only used to say that
871cb0ef41Sopenharmony_ci * an alias mapped to this converter is ambiguous. See UCNV_CONVERTER_INDEX_MASK
881cb0ef41Sopenharmony_ci * and UCNV_AMBIGUOUS_ALIAS_MAP_BIT for more information. This section is
891cb0ef41Sopenharmony_ci * the predigested form of the 5th section so that an alias lookup can be fast.
901cb0ef41Sopenharmony_ci *
911cb0ef41Sopenharmony_ci * 5) This section contains a 2D array with indexes to the 6th section. This
921cb0ef41Sopenharmony_ci * section is the full form of all alias mappings. The column index is the
931cb0ef41Sopenharmony_ci * index into the converter list (column header). The row index is the index
941cb0ef41Sopenharmony_ci * to tag list (row header). This 2D array is the top part a 3D array. The
951cb0ef41Sopenharmony_ci * third dimension is in the 6th section.
961cb0ef41Sopenharmony_ci *
971cb0ef41Sopenharmony_ci * 6) This is blob of variable length arrays. Each array starts with a size,
981cb0ef41Sopenharmony_ci * and is followed by indexes to alias names in the string table. This is
991cb0ef41Sopenharmony_ci * the third dimension to the section 5. No other section should be referencing
1001cb0ef41Sopenharmony_ci * this section.
1011cb0ef41Sopenharmony_ci *
1021cb0ef41Sopenharmony_ci * 7) Starting in ICU 3.6, this can be a UConverterAliasOptions struct. Its
1031cb0ef41Sopenharmony_ci * presence indicates that a section 9 exists. UConverterAliasOptions specifies
1041cb0ef41Sopenharmony_ci * what type of string normalization is used among other potential things in the
1051cb0ef41Sopenharmony_ci * future.
1061cb0ef41Sopenharmony_ci *
1071cb0ef41Sopenharmony_ci * 8) This is the string table. All strings are indexed on an even address.
1081cb0ef41Sopenharmony_ci * There are two reasons for this. First many chip architectures locate strings
1091cb0ef41Sopenharmony_ci * faster on even address boundaries. Second, since all indexes are 16-bit
1101cb0ef41Sopenharmony_ci * numbers, this string table can be 128KB in size instead of 64KB when we
1111cb0ef41Sopenharmony_ci * only have strings starting on an even address.
1121cb0ef41Sopenharmony_ci *
1131cb0ef41Sopenharmony_ci * 9) When present this is a set of prenormalized strings from section 8. This
1141cb0ef41Sopenharmony_ci * table contains normalized strings with the dashes and spaces stripped out,
1151cb0ef41Sopenharmony_ci * and all strings lowercased. In the future, the options in section 7 may state
1161cb0ef41Sopenharmony_ci * other types of normalization.
1171cb0ef41Sopenharmony_ci *
1181cb0ef41Sopenharmony_ci * Here is the concept of section 5 and 6. It's a 3D cube. Each tag
1191cb0ef41Sopenharmony_ci * has a unique alias among all converters. That same alias can
1201cb0ef41Sopenharmony_ci * be mentioned in other standards on different converters,
1211cb0ef41Sopenharmony_ci * but only one alias per tag can be unique.
1221cb0ef41Sopenharmony_ci *
1231cb0ef41Sopenharmony_ci *
1241cb0ef41Sopenharmony_ci *              Converter Names (Usually in TR22 form)
1251cb0ef41Sopenharmony_ci *           -------------------------------------------.
1261cb0ef41Sopenharmony_ci *     T    /                                          /|
1271cb0ef41Sopenharmony_ci *     a   /                                          / |
1281cb0ef41Sopenharmony_ci *     g  /                                          /  |
1291cb0ef41Sopenharmony_ci *     s /                                          /   |
1301cb0ef41Sopenharmony_ci *      /                                          /    |
1311cb0ef41Sopenharmony_ci *      ------------------------------------------/     |
1321cb0ef41Sopenharmony_ci *    A |                                         |     |
1331cb0ef41Sopenharmony_ci *    l |                                         |     |
1341cb0ef41Sopenharmony_ci *    i |                                         |    /
1351cb0ef41Sopenharmony_ci *    a |                                         |   /
1361cb0ef41Sopenharmony_ci *    s |                                         |  /
1371cb0ef41Sopenharmony_ci *    e |                                         | /
1381cb0ef41Sopenharmony_ci *    s |                                         |/
1391cb0ef41Sopenharmony_ci *      -------------------------------------------
1401cb0ef41Sopenharmony_ci *
1411cb0ef41Sopenharmony_ci *
1421cb0ef41Sopenharmony_ci *
1431cb0ef41Sopenharmony_ci * Here is what it really looks like. It's like swiss cheese.
1441cb0ef41Sopenharmony_ci * There are holes. Some converters aren't recognized by
1451cb0ef41Sopenharmony_ci * a standard, or they are really old converters that the
1461cb0ef41Sopenharmony_ci * standard doesn't recognize anymore.
1471cb0ef41Sopenharmony_ci *
1481cb0ef41Sopenharmony_ci *              Converter Names (Usually in TR22 form)
1491cb0ef41Sopenharmony_ci *           -------------------------------------------.
1501cb0ef41Sopenharmony_ci *     T    /##########################################/|
1511cb0ef41Sopenharmony_ci *     a   /     #            #                       /#
1521cb0ef41Sopenharmony_ci *     g  /  #      ##     ##     ### # ### ### ### #/
1531cb0ef41Sopenharmony_ci *     s / #             #####  ####        ##  ## #/#
1541cb0ef41Sopenharmony_ci *      / ### # # ##  #  #   #          ### # #   #/##
1551cb0ef41Sopenharmony_ci *      ------------------------------------------/# #
1561cb0ef41Sopenharmony_ci *    A |### # # ##  #  #   #          ### # #   #|# #
1571cb0ef41Sopenharmony_ci *    l |# # #    #     #               ## #     #|# #
1581cb0ef41Sopenharmony_ci *    i |# # #    #     #                #       #|#
1591cb0ef41Sopenharmony_ci *    a |#                                       #|#
1601cb0ef41Sopenharmony_ci *    s |                                        #|#
1611cb0ef41Sopenharmony_ci *    e
1621cb0ef41Sopenharmony_ci *    s
1631cb0ef41Sopenharmony_ci *
1641cb0ef41Sopenharmony_ci */
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci/**
1671cb0ef41Sopenharmony_ci * Used by the UEnumeration API
1681cb0ef41Sopenharmony_ci */
1691cb0ef41Sopenharmony_citypedef struct UAliasContext {
1701cb0ef41Sopenharmony_ci    uint32_t listOffset;
1711cb0ef41Sopenharmony_ci    uint32_t listIdx;
1721cb0ef41Sopenharmony_ci} UAliasContext;
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_cistatic const char DATA_NAME[] = "cnvalias";
1751cb0ef41Sopenharmony_cistatic const char DATA_TYPE[] = "icu";
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_cistatic UDataMemory *gAliasData=nullptr;
1781cb0ef41Sopenharmony_cistatic icu::UInitOnce gAliasDataInitOnce {};
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_cienum {
1811cb0ef41Sopenharmony_ci    tocLengthIndex=0,
1821cb0ef41Sopenharmony_ci    converterListIndex=1,
1831cb0ef41Sopenharmony_ci    tagListIndex=2,
1841cb0ef41Sopenharmony_ci    aliasListIndex=3,
1851cb0ef41Sopenharmony_ci    untaggedConvArrayIndex=4,
1861cb0ef41Sopenharmony_ci    taggedAliasArrayIndex=5,
1871cb0ef41Sopenharmony_ci    taggedAliasListsIndex=6,
1881cb0ef41Sopenharmony_ci    tableOptionsIndex=7,
1891cb0ef41Sopenharmony_ci    stringTableIndex=8,
1901cb0ef41Sopenharmony_ci    normalizedStringTableIndex=9,
1911cb0ef41Sopenharmony_ci    offsetsCount,    /* length of the swapper's temporary offsets[] */
1921cb0ef41Sopenharmony_ci    minTocLength=8 /* min. tocLength in the file, does not count the tocLengthIndex! */
1931cb0ef41Sopenharmony_ci};
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_cistatic const UConverterAliasOptions defaultTableOptions = {
1961cb0ef41Sopenharmony_ci    UCNV_IO_UNNORMALIZED,
1971cb0ef41Sopenharmony_ci    0 /* containsCnvOptionInfo */
1981cb0ef41Sopenharmony_ci};
1991cb0ef41Sopenharmony_cistatic UConverterAlias gMainTable;
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci#define GET_STRING(idx) (const char *)(gMainTable.stringTable + (idx))
2021cb0ef41Sopenharmony_ci#define GET_NORMALIZED_STRING(idx) (const char *)(gMainTable.normalizedStringTable + (idx))
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_cistatic UBool U_CALLCONV
2051cb0ef41Sopenharmony_ciisAcceptable(void * /*context*/,
2061cb0ef41Sopenharmony_ci             const char * /*type*/, const char * /*name*/,
2071cb0ef41Sopenharmony_ci             const UDataInfo *pInfo) {
2081cb0ef41Sopenharmony_ci    return (UBool)(
2091cb0ef41Sopenharmony_ci        pInfo->size>=20 &&
2101cb0ef41Sopenharmony_ci        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
2111cb0ef41Sopenharmony_ci        pInfo->charsetFamily==U_CHARSET_FAMILY &&
2121cb0ef41Sopenharmony_ci        pInfo->dataFormat[0]==0x43 &&   /* dataFormat="CvAl" */
2131cb0ef41Sopenharmony_ci        pInfo->dataFormat[1]==0x76 &&
2141cb0ef41Sopenharmony_ci        pInfo->dataFormat[2]==0x41 &&
2151cb0ef41Sopenharmony_ci        pInfo->dataFormat[3]==0x6c &&
2161cb0ef41Sopenharmony_ci        pInfo->formatVersion[0]==3);
2171cb0ef41Sopenharmony_ci}
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_cistatic UBool U_CALLCONV ucnv_io_cleanup()
2201cb0ef41Sopenharmony_ci{
2211cb0ef41Sopenharmony_ci    if (gAliasData) {
2221cb0ef41Sopenharmony_ci        udata_close(gAliasData);
2231cb0ef41Sopenharmony_ci        gAliasData = nullptr;
2241cb0ef41Sopenharmony_ci    }
2251cb0ef41Sopenharmony_ci    gAliasDataInitOnce.reset();
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci    uprv_memset(&gMainTable, 0, sizeof(gMainTable));
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci    return true;                   /* Everything was cleaned up */
2301cb0ef41Sopenharmony_ci}
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_cistatic void U_CALLCONV initAliasData(UErrorCode &errCode) {
2331cb0ef41Sopenharmony_ci    UDataMemory *data;
2341cb0ef41Sopenharmony_ci    const uint16_t *table;
2351cb0ef41Sopenharmony_ci    const uint32_t *sectionSizes;
2361cb0ef41Sopenharmony_ci    uint32_t tableStart;
2371cb0ef41Sopenharmony_ci    uint32_t currOffset;
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci    ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup);
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci    U_ASSERT(gAliasData == nullptr);
2421cb0ef41Sopenharmony_ci    data = udata_openChoice(nullptr, DATA_TYPE, DATA_NAME, isAcceptable, nullptr, &errCode);
2431cb0ef41Sopenharmony_ci    if(U_FAILURE(errCode)) {
2441cb0ef41Sopenharmony_ci        return;
2451cb0ef41Sopenharmony_ci    }
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci    sectionSizes = (const uint32_t *)udata_getMemory(data);
2481cb0ef41Sopenharmony_ci    table = (const uint16_t *)sectionSizes;
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci    tableStart      = sectionSizes[0];
2511cb0ef41Sopenharmony_ci    if (tableStart < minTocLength) {
2521cb0ef41Sopenharmony_ci        errCode = U_INVALID_FORMAT_ERROR;
2531cb0ef41Sopenharmony_ci        udata_close(data);
2541cb0ef41Sopenharmony_ci        return;
2551cb0ef41Sopenharmony_ci    }
2561cb0ef41Sopenharmony_ci    gAliasData = data;
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci    gMainTable.converterListSize      = sectionSizes[1];
2591cb0ef41Sopenharmony_ci    gMainTable.tagListSize            = sectionSizes[2];
2601cb0ef41Sopenharmony_ci    gMainTable.aliasListSize          = sectionSizes[3];
2611cb0ef41Sopenharmony_ci    gMainTable.untaggedConvArraySize  = sectionSizes[4];
2621cb0ef41Sopenharmony_ci    gMainTable.taggedAliasArraySize   = sectionSizes[5];
2631cb0ef41Sopenharmony_ci    gMainTable.taggedAliasListsSize   = sectionSizes[6];
2641cb0ef41Sopenharmony_ci    gMainTable.optionTableSize        = sectionSizes[7];
2651cb0ef41Sopenharmony_ci    gMainTable.stringTableSize        = sectionSizes[8];
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci    if (tableStart > 8) {
2681cb0ef41Sopenharmony_ci        gMainTable.normalizedStringTableSize = sectionSizes[9];
2691cb0ef41Sopenharmony_ci    }
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci    currOffset = tableStart * (sizeof(uint32_t)/sizeof(uint16_t)) + (sizeof(uint32_t)/sizeof(uint16_t));
2721cb0ef41Sopenharmony_ci    gMainTable.converterList = table + currOffset;
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci    currOffset += gMainTable.converterListSize;
2751cb0ef41Sopenharmony_ci    gMainTable.tagList = table + currOffset;
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci    currOffset += gMainTable.tagListSize;
2781cb0ef41Sopenharmony_ci    gMainTable.aliasList = table + currOffset;
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci    currOffset += gMainTable.aliasListSize;
2811cb0ef41Sopenharmony_ci    gMainTable.untaggedConvArray = table + currOffset;
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci    currOffset += gMainTable.untaggedConvArraySize;
2841cb0ef41Sopenharmony_ci    gMainTable.taggedAliasArray = table + currOffset;
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci    /* aliasLists is a 1's based array, but it has a padding character */
2871cb0ef41Sopenharmony_ci    currOffset += gMainTable.taggedAliasArraySize;
2881cb0ef41Sopenharmony_ci    gMainTable.taggedAliasLists = table + currOffset;
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci    currOffset += gMainTable.taggedAliasListsSize;
2911cb0ef41Sopenharmony_ci    if (gMainTable.optionTableSize > 0
2921cb0ef41Sopenharmony_ci        && ((const UConverterAliasOptions *)(table + currOffset))->stringNormalizationType < UCNV_IO_NORM_TYPE_COUNT)
2931cb0ef41Sopenharmony_ci    {
2941cb0ef41Sopenharmony_ci        /* Faster table */
2951cb0ef41Sopenharmony_ci        gMainTable.optionTable = (const UConverterAliasOptions *)(table + currOffset);
2961cb0ef41Sopenharmony_ci    }
2971cb0ef41Sopenharmony_ci    else {
2981cb0ef41Sopenharmony_ci        /* Smaller table, or I can't handle this normalization mode!
2991cb0ef41Sopenharmony_ci        Use the original slower table lookup. */
3001cb0ef41Sopenharmony_ci        gMainTable.optionTable = &defaultTableOptions;
3011cb0ef41Sopenharmony_ci    }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci    currOffset += gMainTable.optionTableSize;
3041cb0ef41Sopenharmony_ci    gMainTable.stringTable = table + currOffset;
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci    currOffset += gMainTable.stringTableSize;
3071cb0ef41Sopenharmony_ci    gMainTable.normalizedStringTable = ((gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED)
3081cb0ef41Sopenharmony_ci        ? gMainTable.stringTable : (table + currOffset));
3091cb0ef41Sopenharmony_ci}
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_cistatic UBool
3131cb0ef41Sopenharmony_cihaveAliasData(UErrorCode *pErrorCode) {
3141cb0ef41Sopenharmony_ci    umtx_initOnce(gAliasDataInitOnce, &initAliasData, *pErrorCode);
3151cb0ef41Sopenharmony_ci    return U_SUCCESS(*pErrorCode);
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_cistatic inline UBool
3191cb0ef41Sopenharmony_ciisAlias(const char *alias, UErrorCode *pErrorCode) {
3201cb0ef41Sopenharmony_ci    if(alias==nullptr) {
3211cb0ef41Sopenharmony_ci        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
3221cb0ef41Sopenharmony_ci        return false;
3231cb0ef41Sopenharmony_ci    }
3241cb0ef41Sopenharmony_ci    return (UBool)(*alias!=0);
3251cb0ef41Sopenharmony_ci}
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_cistatic uint32_t getTagNumber(const char *tagname) {
3281cb0ef41Sopenharmony_ci    if (gMainTable.tagList) {
3291cb0ef41Sopenharmony_ci        uint32_t tagNum;
3301cb0ef41Sopenharmony_ci        for (tagNum = 0; tagNum < gMainTable.tagListSize; tagNum++) {
3311cb0ef41Sopenharmony_ci            if (!uprv_stricmp(GET_STRING(gMainTable.tagList[tagNum]), tagname)) {
3321cb0ef41Sopenharmony_ci                return tagNum;
3331cb0ef41Sopenharmony_ci            }
3341cb0ef41Sopenharmony_ci        }
3351cb0ef41Sopenharmony_ci    }
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci    return UINT32_MAX;
3381cb0ef41Sopenharmony_ci}
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci/* character types relevant for ucnv_compareNames() */
3411cb0ef41Sopenharmony_cienum {
3421cb0ef41Sopenharmony_ci    UIGNORE,
3431cb0ef41Sopenharmony_ci    ZERO,
3441cb0ef41Sopenharmony_ci    NONZERO,
3451cb0ef41Sopenharmony_ci    MINLETTER /* any values from here on are lowercase letter mappings */
3461cb0ef41Sopenharmony_ci};
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ci/* character types for ASCII 00..7F */
3491cb0ef41Sopenharmony_cistatic const uint8_t asciiTypes[128] = {
3501cb0ef41Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3511cb0ef41Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3521cb0ef41Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3531cb0ef41Sopenharmony_ci    ZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, 0, 0, 0, 0, 0, 0,
3541cb0ef41Sopenharmony_ci    0, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
3551cb0ef41Sopenharmony_ci    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0,
3561cb0ef41Sopenharmony_ci    0, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
3571cb0ef41Sopenharmony_ci    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0
3581cb0ef41Sopenharmony_ci};
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci#define GET_ASCII_TYPE(c) ((int8_t)(c) >= 0 ? asciiTypes[(uint8_t)c] : (uint8_t)UIGNORE)
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci/* character types for EBCDIC 80..FF */
3631cb0ef41Sopenharmony_cistatic const uint8_t ebcdicTypes[128] = {
3641cb0ef41Sopenharmony_ci    0,    0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0, 0, 0, 0, 0, 0,
3651cb0ef41Sopenharmony_ci    0,    0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0, 0, 0, 0, 0, 0,
3661cb0ef41Sopenharmony_ci    0,    0,    0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0, 0, 0, 0, 0, 0,
3671cb0ef41Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3681cb0ef41Sopenharmony_ci    0,    0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0, 0, 0, 0, 0, 0,
3691cb0ef41Sopenharmony_ci    0,    0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0, 0, 0, 0, 0, 0,
3701cb0ef41Sopenharmony_ci    0,    0,    0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0, 0, 0, 0, 0, 0,
3711cb0ef41Sopenharmony_ci    ZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, 0, 0, 0, 0, 0, 0
3721cb0ef41Sopenharmony_ci};
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ci#define GET_EBCDIC_TYPE(c) ((int8_t)(c) < 0 ? ebcdicTypes[(c)&0x7f] : (uint8_t)UIGNORE)
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci#if U_CHARSET_FAMILY==U_ASCII_FAMILY
3771cb0ef41Sopenharmony_ci#   define GET_CHAR_TYPE(c) GET_ASCII_TYPE(c)
3781cb0ef41Sopenharmony_ci#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY
3791cb0ef41Sopenharmony_ci#   define GET_CHAR_TYPE(c) GET_EBCDIC_TYPE(c)
3801cb0ef41Sopenharmony_ci#else
3811cb0ef41Sopenharmony_ci#   error U_CHARSET_FAMILY is not valid
3821cb0ef41Sopenharmony_ci#endif
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci/* @see ucnv_compareNames */
3861cb0ef41Sopenharmony_ciU_CAPI char * U_CALLCONV
3871cb0ef41Sopenharmony_ciucnv_io_stripASCIIForCompare(char *dst, const char *name) {
3881cb0ef41Sopenharmony_ci    char *dstItr = dst;
3891cb0ef41Sopenharmony_ci    uint8_t type, nextType;
3901cb0ef41Sopenharmony_ci    char c1;
3911cb0ef41Sopenharmony_ci    UBool afterDigit = false;
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci    while ((c1 = *name++) != 0) {
3941cb0ef41Sopenharmony_ci        type = GET_ASCII_TYPE(c1);
3951cb0ef41Sopenharmony_ci        switch (type) {
3961cb0ef41Sopenharmony_ci        case UIGNORE:
3971cb0ef41Sopenharmony_ci            afterDigit = false;
3981cb0ef41Sopenharmony_ci            continue; /* ignore all but letters and digits */
3991cb0ef41Sopenharmony_ci        case ZERO:
4001cb0ef41Sopenharmony_ci            if (!afterDigit) {
4011cb0ef41Sopenharmony_ci                nextType = GET_ASCII_TYPE(*name);
4021cb0ef41Sopenharmony_ci                if (nextType == ZERO || nextType == NONZERO) {
4031cb0ef41Sopenharmony_ci                    continue; /* ignore leading zero before another digit */
4041cb0ef41Sopenharmony_ci                }
4051cb0ef41Sopenharmony_ci            }
4061cb0ef41Sopenharmony_ci            break;
4071cb0ef41Sopenharmony_ci        case NONZERO:
4081cb0ef41Sopenharmony_ci            afterDigit = true;
4091cb0ef41Sopenharmony_ci            break;
4101cb0ef41Sopenharmony_ci        default:
4111cb0ef41Sopenharmony_ci            c1 = (char)type; /* lowercased letter */
4121cb0ef41Sopenharmony_ci            afterDigit = false;
4131cb0ef41Sopenharmony_ci            break;
4141cb0ef41Sopenharmony_ci        }
4151cb0ef41Sopenharmony_ci        *dstItr++ = c1;
4161cb0ef41Sopenharmony_ci    }
4171cb0ef41Sopenharmony_ci    *dstItr = 0;
4181cb0ef41Sopenharmony_ci    return dst;
4191cb0ef41Sopenharmony_ci}
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ciU_CAPI char * U_CALLCONV
4221cb0ef41Sopenharmony_ciucnv_io_stripEBCDICForCompare(char *dst, const char *name) {
4231cb0ef41Sopenharmony_ci    char *dstItr = dst;
4241cb0ef41Sopenharmony_ci    uint8_t type, nextType;
4251cb0ef41Sopenharmony_ci    char c1;
4261cb0ef41Sopenharmony_ci    UBool afterDigit = false;
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci    while ((c1 = *name++) != 0) {
4291cb0ef41Sopenharmony_ci        type = GET_EBCDIC_TYPE(c1);
4301cb0ef41Sopenharmony_ci        switch (type) {
4311cb0ef41Sopenharmony_ci        case UIGNORE:
4321cb0ef41Sopenharmony_ci            afterDigit = false;
4331cb0ef41Sopenharmony_ci            continue; /* ignore all but letters and digits */
4341cb0ef41Sopenharmony_ci        case ZERO:
4351cb0ef41Sopenharmony_ci            if (!afterDigit) {
4361cb0ef41Sopenharmony_ci                nextType = GET_EBCDIC_TYPE(*name);
4371cb0ef41Sopenharmony_ci                if (nextType == ZERO || nextType == NONZERO) {
4381cb0ef41Sopenharmony_ci                    continue; /* ignore leading zero before another digit */
4391cb0ef41Sopenharmony_ci                }
4401cb0ef41Sopenharmony_ci            }
4411cb0ef41Sopenharmony_ci            break;
4421cb0ef41Sopenharmony_ci        case NONZERO:
4431cb0ef41Sopenharmony_ci            afterDigit = true;
4441cb0ef41Sopenharmony_ci            break;
4451cb0ef41Sopenharmony_ci        default:
4461cb0ef41Sopenharmony_ci            c1 = (char)type; /* lowercased letter */
4471cb0ef41Sopenharmony_ci            afterDigit = false;
4481cb0ef41Sopenharmony_ci            break;
4491cb0ef41Sopenharmony_ci        }
4501cb0ef41Sopenharmony_ci        *dstItr++ = c1;
4511cb0ef41Sopenharmony_ci    }
4521cb0ef41Sopenharmony_ci    *dstItr = 0;
4531cb0ef41Sopenharmony_ci    return dst;
4541cb0ef41Sopenharmony_ci}
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci/**
4571cb0ef41Sopenharmony_ci * Do a fuzzy compare of two converter/alias names.
4581cb0ef41Sopenharmony_ci * The comparison is case-insensitive, ignores leading zeroes if they are not
4591cb0ef41Sopenharmony_ci * followed by further digits, and ignores all but letters and digits.
4601cb0ef41Sopenharmony_ci * Thus the strings "UTF-8", "utf_8", "u*T@f08" and "Utf 8" are exactly equivalent.
4611cb0ef41Sopenharmony_ci * See section 1.4, Charset Alias Matching in Unicode Technical Standard #22
4621cb0ef41Sopenharmony_ci * at http://www.unicode.org/reports/tr22/
4631cb0ef41Sopenharmony_ci *
4641cb0ef41Sopenharmony_ci * This is a symmetrical (commutative) operation; order of arguments
4651cb0ef41Sopenharmony_ci * is insignificant.  This is an important property for sorting the
4661cb0ef41Sopenharmony_ci * list (when the list is preprocessed into binary form) and for
4671cb0ef41Sopenharmony_ci * performing binary searches on it at run time.
4681cb0ef41Sopenharmony_ci *
4691cb0ef41Sopenharmony_ci * @param name1 a converter name or alias, zero-terminated
4701cb0ef41Sopenharmony_ci * @param name2 a converter name or alias, zero-terminated
4711cb0ef41Sopenharmony_ci * @return 0 if the names match, or a negative value if the name1
4721cb0ef41Sopenharmony_ci * lexically precedes name2, or a positive value if the name1
4731cb0ef41Sopenharmony_ci * lexically follows name2.
4741cb0ef41Sopenharmony_ci *
4751cb0ef41Sopenharmony_ci * @see ucnv_io_stripForCompare
4761cb0ef41Sopenharmony_ci */
4771cb0ef41Sopenharmony_ciU_CAPI int U_EXPORT2
4781cb0ef41Sopenharmony_ciucnv_compareNames(const char *name1, const char *name2) {
4791cb0ef41Sopenharmony_ci    int rc;
4801cb0ef41Sopenharmony_ci    uint8_t type, nextType;
4811cb0ef41Sopenharmony_ci    char c1, c2;
4821cb0ef41Sopenharmony_ci    UBool afterDigit1 = false, afterDigit2 = false;
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci    for (;;) {
4851cb0ef41Sopenharmony_ci        while ((c1 = *name1++) != 0) {
4861cb0ef41Sopenharmony_ci            type = GET_CHAR_TYPE(c1);
4871cb0ef41Sopenharmony_ci            switch (type) {
4881cb0ef41Sopenharmony_ci            case UIGNORE:
4891cb0ef41Sopenharmony_ci                afterDigit1 = false;
4901cb0ef41Sopenharmony_ci                continue; /* ignore all but letters and digits */
4911cb0ef41Sopenharmony_ci            case ZERO:
4921cb0ef41Sopenharmony_ci                if (!afterDigit1) {
4931cb0ef41Sopenharmony_ci                    nextType = GET_CHAR_TYPE(*name1);
4941cb0ef41Sopenharmony_ci                    if (nextType == ZERO || nextType == NONZERO) {
4951cb0ef41Sopenharmony_ci                        continue; /* ignore leading zero before another digit */
4961cb0ef41Sopenharmony_ci                    }
4971cb0ef41Sopenharmony_ci                }
4981cb0ef41Sopenharmony_ci                break;
4991cb0ef41Sopenharmony_ci            case NONZERO:
5001cb0ef41Sopenharmony_ci                afterDigit1 = true;
5011cb0ef41Sopenharmony_ci                break;
5021cb0ef41Sopenharmony_ci            default:
5031cb0ef41Sopenharmony_ci                c1 = (char)type; /* lowercased letter */
5041cb0ef41Sopenharmony_ci                afterDigit1 = false;
5051cb0ef41Sopenharmony_ci                break;
5061cb0ef41Sopenharmony_ci            }
5071cb0ef41Sopenharmony_ci            break; /* deliver c1 */
5081cb0ef41Sopenharmony_ci        }
5091cb0ef41Sopenharmony_ci        while ((c2 = *name2++) != 0) {
5101cb0ef41Sopenharmony_ci            type = GET_CHAR_TYPE(c2);
5111cb0ef41Sopenharmony_ci            switch (type) {
5121cb0ef41Sopenharmony_ci            case UIGNORE:
5131cb0ef41Sopenharmony_ci                afterDigit2 = false;
5141cb0ef41Sopenharmony_ci                continue; /* ignore all but letters and digits */
5151cb0ef41Sopenharmony_ci            case ZERO:
5161cb0ef41Sopenharmony_ci                if (!afterDigit2) {
5171cb0ef41Sopenharmony_ci                    nextType = GET_CHAR_TYPE(*name2);
5181cb0ef41Sopenharmony_ci                    if (nextType == ZERO || nextType == NONZERO) {
5191cb0ef41Sopenharmony_ci                        continue; /* ignore leading zero before another digit */
5201cb0ef41Sopenharmony_ci                    }
5211cb0ef41Sopenharmony_ci                }
5221cb0ef41Sopenharmony_ci                break;
5231cb0ef41Sopenharmony_ci            case NONZERO:
5241cb0ef41Sopenharmony_ci                afterDigit2 = true;
5251cb0ef41Sopenharmony_ci                break;
5261cb0ef41Sopenharmony_ci            default:
5271cb0ef41Sopenharmony_ci                c2 = (char)type; /* lowercased letter */
5281cb0ef41Sopenharmony_ci                afterDigit2 = false;
5291cb0ef41Sopenharmony_ci                break;
5301cb0ef41Sopenharmony_ci            }
5311cb0ef41Sopenharmony_ci            break; /* deliver c2 */
5321cb0ef41Sopenharmony_ci        }
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_ci        /* If we reach the ends of both strings then they match */
5351cb0ef41Sopenharmony_ci        if ((c1|c2)==0) {
5361cb0ef41Sopenharmony_ci            return 0;
5371cb0ef41Sopenharmony_ci        }
5381cb0ef41Sopenharmony_ci
5391cb0ef41Sopenharmony_ci        /* Case-insensitive comparison */
5401cb0ef41Sopenharmony_ci        rc = (int)(unsigned char)c1 - (int)(unsigned char)c2;
5411cb0ef41Sopenharmony_ci        if (rc != 0) {
5421cb0ef41Sopenharmony_ci            return rc;
5431cb0ef41Sopenharmony_ci        }
5441cb0ef41Sopenharmony_ci    }
5451cb0ef41Sopenharmony_ci}
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_ci/*
5481cb0ef41Sopenharmony_ci * search for an alias
5491cb0ef41Sopenharmony_ci * return the converter number index for gConverterList
5501cb0ef41Sopenharmony_ci */
5511cb0ef41Sopenharmony_cistatic inline uint32_t
5521cb0ef41Sopenharmony_cifindConverter(const char *alias, UBool *containsOption, UErrorCode *pErrorCode) {
5531cb0ef41Sopenharmony_ci    uint32_t mid, start, limit;
5541cb0ef41Sopenharmony_ci    uint32_t lastMid;
5551cb0ef41Sopenharmony_ci    int result;
5561cb0ef41Sopenharmony_ci    int isUnnormalized = (gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED);
5571cb0ef41Sopenharmony_ci    char strippedName[UCNV_MAX_CONVERTER_NAME_LENGTH];
5581cb0ef41Sopenharmony_ci
5591cb0ef41Sopenharmony_ci    if (!isUnnormalized) {
5601cb0ef41Sopenharmony_ci        if (uprv_strlen(alias) >= UCNV_MAX_CONVERTER_NAME_LENGTH) {
5611cb0ef41Sopenharmony_ci            *pErrorCode = U_BUFFER_OVERFLOW_ERROR;
5621cb0ef41Sopenharmony_ci            return UINT32_MAX;
5631cb0ef41Sopenharmony_ci        }
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci        /* Lower case and remove ignoreable characters. */
5661cb0ef41Sopenharmony_ci        ucnv_io_stripForCompare(strippedName, alias);
5671cb0ef41Sopenharmony_ci        alias = strippedName;
5681cb0ef41Sopenharmony_ci    }
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci    /* do a binary search for the alias */
5711cb0ef41Sopenharmony_ci    start = 0;
5721cb0ef41Sopenharmony_ci    limit = gMainTable.untaggedConvArraySize;
5731cb0ef41Sopenharmony_ci    mid = limit;
5741cb0ef41Sopenharmony_ci    lastMid = UINT32_MAX;
5751cb0ef41Sopenharmony_ci
5761cb0ef41Sopenharmony_ci    for (;;) {
5771cb0ef41Sopenharmony_ci        mid = (uint32_t)((start + limit) / 2);
5781cb0ef41Sopenharmony_ci        if (lastMid == mid) {   /* Have we moved? */
5791cb0ef41Sopenharmony_ci            break;  /* We haven't moved, and it wasn't found. */
5801cb0ef41Sopenharmony_ci        }
5811cb0ef41Sopenharmony_ci        lastMid = mid;
5821cb0ef41Sopenharmony_ci        if (isUnnormalized) {
5831cb0ef41Sopenharmony_ci            result = ucnv_compareNames(alias, GET_STRING(gMainTable.aliasList[mid]));
5841cb0ef41Sopenharmony_ci        }
5851cb0ef41Sopenharmony_ci        else {
5861cb0ef41Sopenharmony_ci            result = uprv_strcmp(alias, GET_NORMALIZED_STRING(gMainTable.aliasList[mid]));
5871cb0ef41Sopenharmony_ci        }
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_ci        if (result < 0) {
5901cb0ef41Sopenharmony_ci            limit = mid;
5911cb0ef41Sopenharmony_ci        } else if (result > 0) {
5921cb0ef41Sopenharmony_ci            start = mid;
5931cb0ef41Sopenharmony_ci        } else {
5941cb0ef41Sopenharmony_ci            /* Since the gencnval tool folds duplicates into one entry,
5951cb0ef41Sopenharmony_ci             * this alias in gAliasList is unique, but different standards
5961cb0ef41Sopenharmony_ci             * may map an alias to different converters.
5971cb0ef41Sopenharmony_ci             */
5981cb0ef41Sopenharmony_ci            if (gMainTable.untaggedConvArray[mid] & UCNV_AMBIGUOUS_ALIAS_MAP_BIT) {
5991cb0ef41Sopenharmony_ci                *pErrorCode = U_AMBIGUOUS_ALIAS_WARNING;
6001cb0ef41Sopenharmony_ci            }
6011cb0ef41Sopenharmony_ci            /* State whether the canonical converter name contains an option.
6021cb0ef41Sopenharmony_ci            This information is contained in this list in order to maintain backward & forward compatibility. */
6031cb0ef41Sopenharmony_ci            if (containsOption) {
6041cb0ef41Sopenharmony_ci                UBool containsCnvOptionInfo = (UBool)gMainTable.optionTable->containsCnvOptionInfo;
6051cb0ef41Sopenharmony_ci                *containsOption = (UBool)((containsCnvOptionInfo
6061cb0ef41Sopenharmony_ci                    && ((gMainTable.untaggedConvArray[mid] & UCNV_CONTAINS_OPTION_BIT) != 0))
6071cb0ef41Sopenharmony_ci                    || !containsCnvOptionInfo);
6081cb0ef41Sopenharmony_ci            }
6091cb0ef41Sopenharmony_ci            return gMainTable.untaggedConvArray[mid] & UCNV_CONVERTER_INDEX_MASK;
6101cb0ef41Sopenharmony_ci        }
6111cb0ef41Sopenharmony_ci    }
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ci    return UINT32_MAX;
6141cb0ef41Sopenharmony_ci}
6151cb0ef41Sopenharmony_ci
6161cb0ef41Sopenharmony_ci/*
6171cb0ef41Sopenharmony_ci * Is this alias in this list?
6181cb0ef41Sopenharmony_ci * alias and listOffset should be non-nullptr.
6191cb0ef41Sopenharmony_ci */
6201cb0ef41Sopenharmony_cistatic inline UBool
6211cb0ef41Sopenharmony_ciisAliasInList(const char *alias, uint32_t listOffset) {
6221cb0ef41Sopenharmony_ci    if (listOffset) {
6231cb0ef41Sopenharmony_ci        uint32_t currAlias;
6241cb0ef41Sopenharmony_ci        uint32_t listCount = gMainTable.taggedAliasLists[listOffset];
6251cb0ef41Sopenharmony_ci        /* +1 to skip listCount */
6261cb0ef41Sopenharmony_ci        const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
6271cb0ef41Sopenharmony_ci        for (currAlias = 0; currAlias < listCount; currAlias++) {
6281cb0ef41Sopenharmony_ci            if (currList[currAlias]
6291cb0ef41Sopenharmony_ci                && ucnv_compareNames(alias, GET_STRING(currList[currAlias]))==0)
6301cb0ef41Sopenharmony_ci            {
6311cb0ef41Sopenharmony_ci                return true;
6321cb0ef41Sopenharmony_ci            }
6331cb0ef41Sopenharmony_ci        }
6341cb0ef41Sopenharmony_ci    }
6351cb0ef41Sopenharmony_ci    return false;
6361cb0ef41Sopenharmony_ci}
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_ci/*
6391cb0ef41Sopenharmony_ci * Search for an standard name of an alias (what is the default name
6401cb0ef41Sopenharmony_ci * that this standard uses?)
6411cb0ef41Sopenharmony_ci * return the listOffset for gTaggedAliasLists. If it's 0,
6421cb0ef41Sopenharmony_ci * the it couldn't be found, but the parameters are valid.
6431cb0ef41Sopenharmony_ci */
6441cb0ef41Sopenharmony_cistatic uint32_t
6451cb0ef41Sopenharmony_cifindTaggedAliasListsOffset(const char *alias, const char *standard, UErrorCode *pErrorCode) {
6461cb0ef41Sopenharmony_ci    uint32_t idx;
6471cb0ef41Sopenharmony_ci    uint32_t listOffset;
6481cb0ef41Sopenharmony_ci    uint32_t convNum;
6491cb0ef41Sopenharmony_ci    UErrorCode myErr = U_ZERO_ERROR;
6501cb0ef41Sopenharmony_ci    uint32_t tagNum = getTagNumber(standard);
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ci    /* Make a quick guess. Hopefully they used a TR22 canonical alias. */
6531cb0ef41Sopenharmony_ci    convNum = findConverter(alias, nullptr, &myErr);
6541cb0ef41Sopenharmony_ci    if (myErr != U_ZERO_ERROR) {
6551cb0ef41Sopenharmony_ci        *pErrorCode = myErr;
6561cb0ef41Sopenharmony_ci    }
6571cb0ef41Sopenharmony_ci
6581cb0ef41Sopenharmony_ci    if (tagNum < (gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS) && convNum < gMainTable.converterListSize) {
6591cb0ef41Sopenharmony_ci        listOffset = gMainTable.taggedAliasArray[tagNum*gMainTable.converterListSize + convNum];
6601cb0ef41Sopenharmony_ci        if (listOffset && gMainTable.taggedAliasLists[listOffset + 1]) {
6611cb0ef41Sopenharmony_ci            return listOffset;
6621cb0ef41Sopenharmony_ci        }
6631cb0ef41Sopenharmony_ci        if (myErr == U_AMBIGUOUS_ALIAS_WARNING) {
6641cb0ef41Sopenharmony_ci            /* Uh Oh! They used an ambiguous alias.
6651cb0ef41Sopenharmony_ci               We have to search the whole swiss cheese starting
6661cb0ef41Sopenharmony_ci               at the highest standard affinity.
6671cb0ef41Sopenharmony_ci               This may take a while.
6681cb0ef41Sopenharmony_ci            */
6691cb0ef41Sopenharmony_ci            for (idx = 0; idx < gMainTable.taggedAliasArraySize; idx++) {
6701cb0ef41Sopenharmony_ci                listOffset = gMainTable.taggedAliasArray[idx];
6711cb0ef41Sopenharmony_ci                if (listOffset && isAliasInList(alias, listOffset)) {
6721cb0ef41Sopenharmony_ci                    uint32_t currTagNum = idx/gMainTable.converterListSize;
6731cb0ef41Sopenharmony_ci                    uint32_t currConvNum = (idx - currTagNum*gMainTable.converterListSize);
6741cb0ef41Sopenharmony_ci                    uint32_t tempListOffset = gMainTable.taggedAliasArray[tagNum*gMainTable.converterListSize + currConvNum];
6751cb0ef41Sopenharmony_ci                    if (tempListOffset && gMainTable.taggedAliasLists[tempListOffset + 1]) {
6761cb0ef41Sopenharmony_ci                        return tempListOffset;
6771cb0ef41Sopenharmony_ci                    }
6781cb0ef41Sopenharmony_ci                    /* else keep on looking */
6791cb0ef41Sopenharmony_ci                    /* We could speed this up by starting on the next row
6801cb0ef41Sopenharmony_ci                       because an alias is unique per row, right now.
6811cb0ef41Sopenharmony_ci                       This would change if alias versioning appears. */
6821cb0ef41Sopenharmony_ci                }
6831cb0ef41Sopenharmony_ci            }
6841cb0ef41Sopenharmony_ci            /* The standard doesn't know about the alias */
6851cb0ef41Sopenharmony_ci        }
6861cb0ef41Sopenharmony_ci        /* else no default name */
6871cb0ef41Sopenharmony_ci        return 0;
6881cb0ef41Sopenharmony_ci    }
6891cb0ef41Sopenharmony_ci    /* else converter or tag not found */
6901cb0ef41Sopenharmony_ci
6911cb0ef41Sopenharmony_ci    return UINT32_MAX;
6921cb0ef41Sopenharmony_ci}
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_ci/* Return the canonical name */
6951cb0ef41Sopenharmony_cistatic uint32_t
6961cb0ef41Sopenharmony_cifindTaggedConverterNum(const char *alias, const char *standard, UErrorCode *pErrorCode) {
6971cb0ef41Sopenharmony_ci    uint32_t idx;
6981cb0ef41Sopenharmony_ci    uint32_t listOffset;
6991cb0ef41Sopenharmony_ci    uint32_t convNum;
7001cb0ef41Sopenharmony_ci    UErrorCode myErr = U_ZERO_ERROR;
7011cb0ef41Sopenharmony_ci    uint32_t tagNum = getTagNumber(standard);
7021cb0ef41Sopenharmony_ci
7031cb0ef41Sopenharmony_ci    /* Make a quick guess. Hopefully they used a TR22 canonical alias. */
7041cb0ef41Sopenharmony_ci    convNum = findConverter(alias, nullptr, &myErr);
7051cb0ef41Sopenharmony_ci    if (myErr != U_ZERO_ERROR) {
7061cb0ef41Sopenharmony_ci        *pErrorCode = myErr;
7071cb0ef41Sopenharmony_ci    }
7081cb0ef41Sopenharmony_ci
7091cb0ef41Sopenharmony_ci    if (tagNum < (gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS) && convNum < gMainTable.converterListSize) {
7101cb0ef41Sopenharmony_ci        listOffset = gMainTable.taggedAliasArray[tagNum*gMainTable.converterListSize + convNum];
7111cb0ef41Sopenharmony_ci        if (listOffset && isAliasInList(alias, listOffset)) {
7121cb0ef41Sopenharmony_ci            return convNum;
7131cb0ef41Sopenharmony_ci        }
7141cb0ef41Sopenharmony_ci        if (myErr == U_AMBIGUOUS_ALIAS_WARNING) {
7151cb0ef41Sopenharmony_ci            /* Uh Oh! They used an ambiguous alias.
7161cb0ef41Sopenharmony_ci               We have to search one slice of the swiss cheese.
7171cb0ef41Sopenharmony_ci               We search only in the requested tag, not the whole thing.
7181cb0ef41Sopenharmony_ci               This may take a while.
7191cb0ef41Sopenharmony_ci            */
7201cb0ef41Sopenharmony_ci            uint32_t convStart = (tagNum)*gMainTable.converterListSize;
7211cb0ef41Sopenharmony_ci            uint32_t convLimit = (tagNum+1)*gMainTable.converterListSize;
7221cb0ef41Sopenharmony_ci            for (idx = convStart; idx < convLimit; idx++) {
7231cb0ef41Sopenharmony_ci                listOffset = gMainTable.taggedAliasArray[idx];
7241cb0ef41Sopenharmony_ci                if (listOffset && isAliasInList(alias, listOffset)) {
7251cb0ef41Sopenharmony_ci                    return idx-convStart;
7261cb0ef41Sopenharmony_ci                }
7271cb0ef41Sopenharmony_ci            }
7281cb0ef41Sopenharmony_ci            /* The standard doesn't know about the alias */
7291cb0ef41Sopenharmony_ci        }
7301cb0ef41Sopenharmony_ci        /* else no canonical name */
7311cb0ef41Sopenharmony_ci    }
7321cb0ef41Sopenharmony_ci    /* else converter or tag not found */
7331cb0ef41Sopenharmony_ci
7341cb0ef41Sopenharmony_ci    return UINT32_MAX;
7351cb0ef41Sopenharmony_ci}
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_ciU_CAPI const char *
7381cb0ef41Sopenharmony_ciucnv_io_getConverterName(const char *alias, UBool *containsOption, UErrorCode *pErrorCode) {
7391cb0ef41Sopenharmony_ci    const char *aliasTmp = alias;
7401cb0ef41Sopenharmony_ci    int32_t i = 0;
7411cb0ef41Sopenharmony_ci    for (i = 0; i < 2; i++) {
7421cb0ef41Sopenharmony_ci        if (i == 1) {
7431cb0ef41Sopenharmony_ci            /*
7441cb0ef41Sopenharmony_ci             * After the first unsuccess converter lookup, check to see if
7451cb0ef41Sopenharmony_ci             * the name begins with 'x-'. If it does, strip it off and try
7461cb0ef41Sopenharmony_ci             * again.  This behaviour is similar to how ICU4J does it.
7471cb0ef41Sopenharmony_ci             */
7481cb0ef41Sopenharmony_ci            if (aliasTmp[0] == 'x' && aliasTmp[1] == '-') {
7491cb0ef41Sopenharmony_ci                aliasTmp = aliasTmp+2;
7501cb0ef41Sopenharmony_ci            } else {
7511cb0ef41Sopenharmony_ci                break;
7521cb0ef41Sopenharmony_ci            }
7531cb0ef41Sopenharmony_ci        }
7541cb0ef41Sopenharmony_ci        if(haveAliasData(pErrorCode) && isAlias(aliasTmp, pErrorCode)) {
7551cb0ef41Sopenharmony_ci            uint32_t convNum = findConverter(aliasTmp, containsOption, pErrorCode);
7561cb0ef41Sopenharmony_ci            if (convNum < gMainTable.converterListSize) {
7571cb0ef41Sopenharmony_ci                return GET_STRING(gMainTable.converterList[convNum]);
7581cb0ef41Sopenharmony_ci            }
7591cb0ef41Sopenharmony_ci            /* else converter not found */
7601cb0ef41Sopenharmony_ci        } else {
7611cb0ef41Sopenharmony_ci            break;
7621cb0ef41Sopenharmony_ci        }
7631cb0ef41Sopenharmony_ci    }
7641cb0ef41Sopenharmony_ci
7651cb0ef41Sopenharmony_ci    return nullptr;
7661cb0ef41Sopenharmony_ci}
7671cb0ef41Sopenharmony_ci
7681cb0ef41Sopenharmony_ciU_CDECL_BEGIN
7691cb0ef41Sopenharmony_ci
7701cb0ef41Sopenharmony_ci
7711cb0ef41Sopenharmony_cistatic int32_t U_CALLCONV
7721cb0ef41Sopenharmony_ciucnv_io_countStandardAliases(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
7731cb0ef41Sopenharmony_ci    int32_t value = 0;
7741cb0ef41Sopenharmony_ci    UAliasContext *myContext = (UAliasContext *)(enumerator->context);
7751cb0ef41Sopenharmony_ci    uint32_t listOffset = myContext->listOffset;
7761cb0ef41Sopenharmony_ci
7771cb0ef41Sopenharmony_ci    if (listOffset) {
7781cb0ef41Sopenharmony_ci        value = gMainTable.taggedAliasLists[listOffset];
7791cb0ef41Sopenharmony_ci    }
7801cb0ef41Sopenharmony_ci    return value;
7811cb0ef41Sopenharmony_ci}
7821cb0ef41Sopenharmony_ci
7831cb0ef41Sopenharmony_cistatic const char * U_CALLCONV
7841cb0ef41Sopenharmony_ciucnv_io_nextStandardAliases(UEnumeration *enumerator,
7851cb0ef41Sopenharmony_ci                            int32_t* resultLength,
7861cb0ef41Sopenharmony_ci                            UErrorCode * /*pErrorCode*/)
7871cb0ef41Sopenharmony_ci{
7881cb0ef41Sopenharmony_ci    UAliasContext *myContext = (UAliasContext *)(enumerator->context);
7891cb0ef41Sopenharmony_ci    uint32_t listOffset = myContext->listOffset;
7901cb0ef41Sopenharmony_ci
7911cb0ef41Sopenharmony_ci    if (listOffset) {
7921cb0ef41Sopenharmony_ci        uint32_t listCount = gMainTable.taggedAliasLists[listOffset];
7931cb0ef41Sopenharmony_ci        const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
7941cb0ef41Sopenharmony_ci
7951cb0ef41Sopenharmony_ci        if (myContext->listIdx < listCount) {
7961cb0ef41Sopenharmony_ci            const char *myStr = GET_STRING(currList[myContext->listIdx++]);
7971cb0ef41Sopenharmony_ci            if (resultLength) {
7981cb0ef41Sopenharmony_ci                *resultLength = (int32_t)uprv_strlen(myStr);
7991cb0ef41Sopenharmony_ci            }
8001cb0ef41Sopenharmony_ci            return myStr;
8011cb0ef41Sopenharmony_ci        }
8021cb0ef41Sopenharmony_ci    }
8031cb0ef41Sopenharmony_ci    /* Either we accessed a zero length list, or we enumerated too far. */
8041cb0ef41Sopenharmony_ci    if (resultLength) {
8051cb0ef41Sopenharmony_ci        *resultLength = 0;
8061cb0ef41Sopenharmony_ci    }
8071cb0ef41Sopenharmony_ci    return nullptr;
8081cb0ef41Sopenharmony_ci}
8091cb0ef41Sopenharmony_ci
8101cb0ef41Sopenharmony_cistatic void U_CALLCONV
8111cb0ef41Sopenharmony_ciucnv_io_resetStandardAliases(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
8121cb0ef41Sopenharmony_ci    ((UAliasContext *)(enumerator->context))->listIdx = 0;
8131cb0ef41Sopenharmony_ci}
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_cistatic void U_CALLCONV
8161cb0ef41Sopenharmony_ciucnv_io_closeUEnumeration(UEnumeration *enumerator) {
8171cb0ef41Sopenharmony_ci    uprv_free(enumerator->context);
8181cb0ef41Sopenharmony_ci    uprv_free(enumerator);
8191cb0ef41Sopenharmony_ci}
8201cb0ef41Sopenharmony_ci
8211cb0ef41Sopenharmony_ciU_CDECL_END
8221cb0ef41Sopenharmony_ci
8231cb0ef41Sopenharmony_ci/* Enumerate the aliases for the specified converter and standard tag */
8241cb0ef41Sopenharmony_cistatic const UEnumeration gEnumAliases = {
8251cb0ef41Sopenharmony_ci    nullptr,
8261cb0ef41Sopenharmony_ci    nullptr,
8271cb0ef41Sopenharmony_ci    ucnv_io_closeUEnumeration,
8281cb0ef41Sopenharmony_ci    ucnv_io_countStandardAliases,
8291cb0ef41Sopenharmony_ci    uenum_unextDefault,
8301cb0ef41Sopenharmony_ci    ucnv_io_nextStandardAliases,
8311cb0ef41Sopenharmony_ci    ucnv_io_resetStandardAliases
8321cb0ef41Sopenharmony_ci};
8331cb0ef41Sopenharmony_ci
8341cb0ef41Sopenharmony_ciU_CAPI UEnumeration * U_EXPORT2
8351cb0ef41Sopenharmony_ciucnv_openStandardNames(const char *convName,
8361cb0ef41Sopenharmony_ci                       const char *standard,
8371cb0ef41Sopenharmony_ci                       UErrorCode *pErrorCode)
8381cb0ef41Sopenharmony_ci{
8391cb0ef41Sopenharmony_ci    UEnumeration *myEnum = nullptr;
8401cb0ef41Sopenharmony_ci    if (haveAliasData(pErrorCode) && isAlias(convName, pErrorCode)) {
8411cb0ef41Sopenharmony_ci        uint32_t listOffset = findTaggedAliasListsOffset(convName, standard, pErrorCode);
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_ci        /* When listOffset == 0, we want to acknowledge that the
8441cb0ef41Sopenharmony_ci           converter name and standard are okay, but there
8451cb0ef41Sopenharmony_ci           is nothing to enumerate. */
8461cb0ef41Sopenharmony_ci        if (listOffset < gMainTable.taggedAliasListsSize) {
8471cb0ef41Sopenharmony_ci            UAliasContext *myContext;
8481cb0ef41Sopenharmony_ci
8491cb0ef41Sopenharmony_ci            myEnum = static_cast<UEnumeration *>(uprv_malloc(sizeof(UEnumeration)));
8501cb0ef41Sopenharmony_ci            if (myEnum == nullptr) {
8511cb0ef41Sopenharmony_ci                *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
8521cb0ef41Sopenharmony_ci                return nullptr;
8531cb0ef41Sopenharmony_ci            }
8541cb0ef41Sopenharmony_ci            uprv_memcpy(myEnum, &gEnumAliases, sizeof(UEnumeration));
8551cb0ef41Sopenharmony_ci            myContext = static_cast<UAliasContext *>(uprv_malloc(sizeof(UAliasContext)));
8561cb0ef41Sopenharmony_ci            if (myContext == nullptr) {
8571cb0ef41Sopenharmony_ci                *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
8581cb0ef41Sopenharmony_ci                uprv_free(myEnum);
8591cb0ef41Sopenharmony_ci                return nullptr;
8601cb0ef41Sopenharmony_ci            }
8611cb0ef41Sopenharmony_ci            myContext->listOffset = listOffset;
8621cb0ef41Sopenharmony_ci            myContext->listIdx = 0;
8631cb0ef41Sopenharmony_ci            myEnum->context = myContext;
8641cb0ef41Sopenharmony_ci        }
8651cb0ef41Sopenharmony_ci        /* else converter or tag not found */
8661cb0ef41Sopenharmony_ci    }
8671cb0ef41Sopenharmony_ci    return myEnum;
8681cb0ef41Sopenharmony_ci}
8691cb0ef41Sopenharmony_ci
8701cb0ef41Sopenharmony_cistatic uint16_t
8711cb0ef41Sopenharmony_ciucnv_io_countAliases(const char *alias, UErrorCode *pErrorCode) {
8721cb0ef41Sopenharmony_ci    if(haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
8731cb0ef41Sopenharmony_ci        uint32_t convNum = findConverter(alias, nullptr, pErrorCode);
8741cb0ef41Sopenharmony_ci        if (convNum < gMainTable.converterListSize) {
8751cb0ef41Sopenharmony_ci            /* tagListNum - 1 is the ALL tag */
8761cb0ef41Sopenharmony_ci            int32_t listOffset = gMainTable.taggedAliasArray[(gMainTable.tagListSize - 1)*gMainTable.converterListSize + convNum];
8771cb0ef41Sopenharmony_ci
8781cb0ef41Sopenharmony_ci            if (listOffset) {
8791cb0ef41Sopenharmony_ci                return gMainTable.taggedAliasLists[listOffset];
8801cb0ef41Sopenharmony_ci            }
8811cb0ef41Sopenharmony_ci            /* else this shouldn't happen. internal program error */
8821cb0ef41Sopenharmony_ci        }
8831cb0ef41Sopenharmony_ci        /* else converter not found */
8841cb0ef41Sopenharmony_ci    }
8851cb0ef41Sopenharmony_ci    return 0;
8861cb0ef41Sopenharmony_ci}
8871cb0ef41Sopenharmony_ci
8881cb0ef41Sopenharmony_cistatic uint16_t
8891cb0ef41Sopenharmony_ciucnv_io_getAliases(const char *alias, uint16_t start, const char **aliases, UErrorCode *pErrorCode) {
8901cb0ef41Sopenharmony_ci    if(haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
8911cb0ef41Sopenharmony_ci        uint32_t currAlias;
8921cb0ef41Sopenharmony_ci        uint32_t convNum = findConverter(alias, nullptr, pErrorCode);
8931cb0ef41Sopenharmony_ci        if (convNum < gMainTable.converterListSize) {
8941cb0ef41Sopenharmony_ci            /* tagListNum - 1 is the ALL tag */
8951cb0ef41Sopenharmony_ci            int32_t listOffset = gMainTable.taggedAliasArray[(gMainTable.tagListSize - 1)*gMainTable.converterListSize + convNum];
8961cb0ef41Sopenharmony_ci
8971cb0ef41Sopenharmony_ci            if (listOffset) {
8981cb0ef41Sopenharmony_ci                uint32_t listCount = gMainTable.taggedAliasLists[listOffset];
8991cb0ef41Sopenharmony_ci                /* +1 to skip listCount */
9001cb0ef41Sopenharmony_ci                const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
9011cb0ef41Sopenharmony_ci
9021cb0ef41Sopenharmony_ci                for (currAlias = start; currAlias < listCount; currAlias++) {
9031cb0ef41Sopenharmony_ci                    aliases[currAlias] = GET_STRING(currList[currAlias]);
9041cb0ef41Sopenharmony_ci                }
9051cb0ef41Sopenharmony_ci            }
9061cb0ef41Sopenharmony_ci            /* else this shouldn't happen. internal program error */
9071cb0ef41Sopenharmony_ci        }
9081cb0ef41Sopenharmony_ci        /* else converter not found */
9091cb0ef41Sopenharmony_ci    }
9101cb0ef41Sopenharmony_ci    return 0;
9111cb0ef41Sopenharmony_ci}
9121cb0ef41Sopenharmony_ci
9131cb0ef41Sopenharmony_cistatic const char *
9141cb0ef41Sopenharmony_ciucnv_io_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode) {
9151cb0ef41Sopenharmony_ci    if(haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
9161cb0ef41Sopenharmony_ci        uint32_t convNum = findConverter(alias, nullptr, pErrorCode);
9171cb0ef41Sopenharmony_ci        if (convNum < gMainTable.converterListSize) {
9181cb0ef41Sopenharmony_ci            /* tagListNum - 1 is the ALL tag */
9191cb0ef41Sopenharmony_ci            int32_t listOffset = gMainTable.taggedAliasArray[(gMainTable.tagListSize - 1)*gMainTable.converterListSize + convNum];
9201cb0ef41Sopenharmony_ci
9211cb0ef41Sopenharmony_ci            if (listOffset) {
9221cb0ef41Sopenharmony_ci                uint32_t listCount = gMainTable.taggedAliasLists[listOffset];
9231cb0ef41Sopenharmony_ci                /* +1 to skip listCount */
9241cb0ef41Sopenharmony_ci                const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
9251cb0ef41Sopenharmony_ci
9261cb0ef41Sopenharmony_ci                if (n < listCount)  {
9271cb0ef41Sopenharmony_ci                    return GET_STRING(currList[n]);
9281cb0ef41Sopenharmony_ci                }
9291cb0ef41Sopenharmony_ci                *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
9301cb0ef41Sopenharmony_ci            }
9311cb0ef41Sopenharmony_ci            /* else this shouldn't happen. internal program error */
9321cb0ef41Sopenharmony_ci        }
9331cb0ef41Sopenharmony_ci        /* else converter not found */
9341cb0ef41Sopenharmony_ci    }
9351cb0ef41Sopenharmony_ci    return nullptr;
9361cb0ef41Sopenharmony_ci}
9371cb0ef41Sopenharmony_ci
9381cb0ef41Sopenharmony_cistatic uint16_t
9391cb0ef41Sopenharmony_ciucnv_io_countStandards(UErrorCode *pErrorCode) {
9401cb0ef41Sopenharmony_ci    if (haveAliasData(pErrorCode)) {
9411cb0ef41Sopenharmony_ci        /* Don't include the empty list */
9421cb0ef41Sopenharmony_ci        return (uint16_t)(gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS);
9431cb0ef41Sopenharmony_ci    }
9441cb0ef41Sopenharmony_ci
9451cb0ef41Sopenharmony_ci    return 0;
9461cb0ef41Sopenharmony_ci}
9471cb0ef41Sopenharmony_ci
9481cb0ef41Sopenharmony_ciU_CAPI const char * U_EXPORT2
9491cb0ef41Sopenharmony_ciucnv_getStandard(uint16_t n, UErrorCode *pErrorCode) {
9501cb0ef41Sopenharmony_ci    if (haveAliasData(pErrorCode)) {
9511cb0ef41Sopenharmony_ci        if (n < gMainTable.tagListSize - UCNV_NUM_HIDDEN_TAGS) {
9521cb0ef41Sopenharmony_ci            return GET_STRING(gMainTable.tagList[n]);
9531cb0ef41Sopenharmony_ci        }
9541cb0ef41Sopenharmony_ci        *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
9551cb0ef41Sopenharmony_ci    }
9561cb0ef41Sopenharmony_ci
9571cb0ef41Sopenharmony_ci    return nullptr;
9581cb0ef41Sopenharmony_ci}
9591cb0ef41Sopenharmony_ci
9601cb0ef41Sopenharmony_ciU_CAPI const char * U_EXPORT2
9611cb0ef41Sopenharmony_ciucnv_getStandardName(const char *alias, const char *standard, UErrorCode *pErrorCode) {
9621cb0ef41Sopenharmony_ci    if (haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
9631cb0ef41Sopenharmony_ci        uint32_t listOffset = findTaggedAliasListsOffset(alias, standard, pErrorCode);
9641cb0ef41Sopenharmony_ci
9651cb0ef41Sopenharmony_ci        if (0 < listOffset && listOffset < gMainTable.taggedAliasListsSize) {
9661cb0ef41Sopenharmony_ci            const uint16_t *currList = gMainTable.taggedAliasLists + listOffset + 1;
9671cb0ef41Sopenharmony_ci
9681cb0ef41Sopenharmony_ci            /* Get the preferred name from this list */
9691cb0ef41Sopenharmony_ci            if (currList[0]) {
9701cb0ef41Sopenharmony_ci                return GET_STRING(currList[0]);
9711cb0ef41Sopenharmony_ci            }
9721cb0ef41Sopenharmony_ci            /* else someone screwed up the alias table. */
9731cb0ef41Sopenharmony_ci            /* *pErrorCode = U_INVALID_FORMAT_ERROR */
9741cb0ef41Sopenharmony_ci        }
9751cb0ef41Sopenharmony_ci    }
9761cb0ef41Sopenharmony_ci
9771cb0ef41Sopenharmony_ci    return nullptr;
9781cb0ef41Sopenharmony_ci}
9791cb0ef41Sopenharmony_ci
9801cb0ef41Sopenharmony_ciU_CAPI uint16_t U_EXPORT2
9811cb0ef41Sopenharmony_ciucnv_countAliases(const char *alias, UErrorCode *pErrorCode)
9821cb0ef41Sopenharmony_ci{
9831cb0ef41Sopenharmony_ci    return ucnv_io_countAliases(alias, pErrorCode);
9841cb0ef41Sopenharmony_ci}
9851cb0ef41Sopenharmony_ci
9861cb0ef41Sopenharmony_ci
9871cb0ef41Sopenharmony_ciU_CAPI const char* U_EXPORT2
9881cb0ef41Sopenharmony_ciucnv_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode)
9891cb0ef41Sopenharmony_ci{
9901cb0ef41Sopenharmony_ci    return ucnv_io_getAlias(alias, n, pErrorCode);
9911cb0ef41Sopenharmony_ci}
9921cb0ef41Sopenharmony_ci
9931cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
9941cb0ef41Sopenharmony_ciucnv_getAliases(const char *alias, const char **aliases, UErrorCode *pErrorCode)
9951cb0ef41Sopenharmony_ci{
9961cb0ef41Sopenharmony_ci    ucnv_io_getAliases(alias, 0, aliases, pErrorCode);
9971cb0ef41Sopenharmony_ci}
9981cb0ef41Sopenharmony_ci
9991cb0ef41Sopenharmony_ciU_CAPI uint16_t U_EXPORT2
10001cb0ef41Sopenharmony_ciucnv_countStandards()
10011cb0ef41Sopenharmony_ci{
10021cb0ef41Sopenharmony_ci    UErrorCode err = U_ZERO_ERROR;
10031cb0ef41Sopenharmony_ci    return ucnv_io_countStandards(&err);
10041cb0ef41Sopenharmony_ci}
10051cb0ef41Sopenharmony_ci
10061cb0ef41Sopenharmony_ciU_CAPI const char * U_EXPORT2
10071cb0ef41Sopenharmony_ciucnv_getCanonicalName(const char *alias, const char *standard, UErrorCode *pErrorCode) {
10081cb0ef41Sopenharmony_ci    if (haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
10091cb0ef41Sopenharmony_ci        uint32_t convNum = findTaggedConverterNum(alias, standard, pErrorCode);
10101cb0ef41Sopenharmony_ci
10111cb0ef41Sopenharmony_ci        if (convNum < gMainTable.converterListSize) {
10121cb0ef41Sopenharmony_ci            return GET_STRING(gMainTable.converterList[convNum]);
10131cb0ef41Sopenharmony_ci        }
10141cb0ef41Sopenharmony_ci    }
10151cb0ef41Sopenharmony_ci
10161cb0ef41Sopenharmony_ci    return nullptr;
10171cb0ef41Sopenharmony_ci}
10181cb0ef41Sopenharmony_ci
10191cb0ef41Sopenharmony_ciU_CDECL_BEGIN
10201cb0ef41Sopenharmony_ci
10211cb0ef41Sopenharmony_ci
10221cb0ef41Sopenharmony_cistatic int32_t U_CALLCONV
10231cb0ef41Sopenharmony_ciucnv_io_countAllConverters(UEnumeration * /*enumerator*/, UErrorCode * /*pErrorCode*/) {
10241cb0ef41Sopenharmony_ci    return gMainTable.converterListSize;
10251cb0ef41Sopenharmony_ci}
10261cb0ef41Sopenharmony_ci
10271cb0ef41Sopenharmony_cistatic const char * U_CALLCONV
10281cb0ef41Sopenharmony_ciucnv_io_nextAllConverters(UEnumeration *enumerator,
10291cb0ef41Sopenharmony_ci                            int32_t* resultLength,
10301cb0ef41Sopenharmony_ci                            UErrorCode * /*pErrorCode*/)
10311cb0ef41Sopenharmony_ci{
10321cb0ef41Sopenharmony_ci    uint16_t *myContext = (uint16_t *)(enumerator->context);
10331cb0ef41Sopenharmony_ci
10341cb0ef41Sopenharmony_ci    if (*myContext < gMainTable.converterListSize) {
10351cb0ef41Sopenharmony_ci        const char *myStr = GET_STRING(gMainTable.converterList[(*myContext)++]);
10361cb0ef41Sopenharmony_ci        if (resultLength) {
10371cb0ef41Sopenharmony_ci            *resultLength = (int32_t)uprv_strlen(myStr);
10381cb0ef41Sopenharmony_ci        }
10391cb0ef41Sopenharmony_ci        return myStr;
10401cb0ef41Sopenharmony_ci    }
10411cb0ef41Sopenharmony_ci    /* Either we accessed a zero length list, or we enumerated too far. */
10421cb0ef41Sopenharmony_ci    if (resultLength) {
10431cb0ef41Sopenharmony_ci        *resultLength = 0;
10441cb0ef41Sopenharmony_ci    }
10451cb0ef41Sopenharmony_ci    return nullptr;
10461cb0ef41Sopenharmony_ci}
10471cb0ef41Sopenharmony_ci
10481cb0ef41Sopenharmony_cistatic void U_CALLCONV
10491cb0ef41Sopenharmony_ciucnv_io_resetAllConverters(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
10501cb0ef41Sopenharmony_ci    *((uint16_t *)(enumerator->context)) = 0;
10511cb0ef41Sopenharmony_ci}
10521cb0ef41Sopenharmony_ciU_CDECL_END
10531cb0ef41Sopenharmony_cistatic const UEnumeration gEnumAllConverters = {
10541cb0ef41Sopenharmony_ci    nullptr,
10551cb0ef41Sopenharmony_ci    nullptr,
10561cb0ef41Sopenharmony_ci    ucnv_io_closeUEnumeration,
10571cb0ef41Sopenharmony_ci    ucnv_io_countAllConverters,
10581cb0ef41Sopenharmony_ci    uenum_unextDefault,
10591cb0ef41Sopenharmony_ci    ucnv_io_nextAllConverters,
10601cb0ef41Sopenharmony_ci    ucnv_io_resetAllConverters
10611cb0ef41Sopenharmony_ci};
10621cb0ef41Sopenharmony_ci
10631cb0ef41Sopenharmony_ciU_CAPI UEnumeration * U_EXPORT2
10641cb0ef41Sopenharmony_ciucnv_openAllNames(UErrorCode *pErrorCode) {
10651cb0ef41Sopenharmony_ci    UEnumeration *myEnum = nullptr;
10661cb0ef41Sopenharmony_ci    if (haveAliasData(pErrorCode)) {
10671cb0ef41Sopenharmony_ci        uint16_t *myContext;
10681cb0ef41Sopenharmony_ci
10691cb0ef41Sopenharmony_ci        myEnum = static_cast<UEnumeration *>(uprv_malloc(sizeof(UEnumeration)));
10701cb0ef41Sopenharmony_ci        if (myEnum == nullptr) {
10711cb0ef41Sopenharmony_ci            *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
10721cb0ef41Sopenharmony_ci            return nullptr;
10731cb0ef41Sopenharmony_ci        }
10741cb0ef41Sopenharmony_ci        uprv_memcpy(myEnum, &gEnumAllConverters, sizeof(UEnumeration));
10751cb0ef41Sopenharmony_ci        myContext = static_cast<uint16_t *>(uprv_malloc(sizeof(uint16_t)));
10761cb0ef41Sopenharmony_ci        if (myContext == nullptr) {
10771cb0ef41Sopenharmony_ci            *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
10781cb0ef41Sopenharmony_ci            uprv_free(myEnum);
10791cb0ef41Sopenharmony_ci            return nullptr;
10801cb0ef41Sopenharmony_ci        }
10811cb0ef41Sopenharmony_ci        *myContext = 0;
10821cb0ef41Sopenharmony_ci        myEnum->context = myContext;
10831cb0ef41Sopenharmony_ci    }
10841cb0ef41Sopenharmony_ci    return myEnum;
10851cb0ef41Sopenharmony_ci}
10861cb0ef41Sopenharmony_ci
10871cb0ef41Sopenharmony_ciU_CAPI uint16_t
10881cb0ef41Sopenharmony_ciucnv_io_countKnownConverters(UErrorCode *pErrorCode) {
10891cb0ef41Sopenharmony_ci    if (haveAliasData(pErrorCode)) {
10901cb0ef41Sopenharmony_ci        return (uint16_t)gMainTable.converterListSize;
10911cb0ef41Sopenharmony_ci    }
10921cb0ef41Sopenharmony_ci    return 0;
10931cb0ef41Sopenharmony_ci}
10941cb0ef41Sopenharmony_ci
10951cb0ef41Sopenharmony_ci/* alias table swapping ----------------------------------------------------- */
10961cb0ef41Sopenharmony_ci
10971cb0ef41Sopenharmony_ciU_CDECL_BEGIN
10981cb0ef41Sopenharmony_ci
10991cb0ef41Sopenharmony_citypedef char * U_CALLCONV StripForCompareFn(char *dst, const char *name);
11001cb0ef41Sopenharmony_ciU_CDECL_END
11011cb0ef41Sopenharmony_ci
11021cb0ef41Sopenharmony_ci
11031cb0ef41Sopenharmony_ci/*
11041cb0ef41Sopenharmony_ci * row of a temporary array
11051cb0ef41Sopenharmony_ci *
11061cb0ef41Sopenharmony_ci * gets platform-endian charset string indexes and sorting indexes;
11071cb0ef41Sopenharmony_ci * after sorting this array by strings, the actual arrays are permutated
11081cb0ef41Sopenharmony_ci * according to the sorting indexes
11091cb0ef41Sopenharmony_ci */
11101cb0ef41Sopenharmony_citypedef struct TempRow {
11111cb0ef41Sopenharmony_ci    uint16_t strIndex, sortIndex;
11121cb0ef41Sopenharmony_ci} TempRow;
11131cb0ef41Sopenharmony_ci
11141cb0ef41Sopenharmony_citypedef struct TempAliasTable {
11151cb0ef41Sopenharmony_ci    const char *chars;
11161cb0ef41Sopenharmony_ci    TempRow *rows;
11171cb0ef41Sopenharmony_ci    uint16_t *resort;
11181cb0ef41Sopenharmony_ci    StripForCompareFn *stripForCompare;
11191cb0ef41Sopenharmony_ci} TempAliasTable;
11201cb0ef41Sopenharmony_ci
11211cb0ef41Sopenharmony_cienum {
11221cb0ef41Sopenharmony_ci    STACK_ROW_CAPACITY=500
11231cb0ef41Sopenharmony_ci};
11241cb0ef41Sopenharmony_ci
11251cb0ef41Sopenharmony_cistatic int32_t U_CALLCONV
11261cb0ef41Sopenharmony_ciio_compareRows(const void *context, const void *left, const void *right) {
11271cb0ef41Sopenharmony_ci    char strippedLeft[UCNV_MAX_CONVERTER_NAME_LENGTH],
11281cb0ef41Sopenharmony_ci         strippedRight[UCNV_MAX_CONVERTER_NAME_LENGTH];
11291cb0ef41Sopenharmony_ci
11301cb0ef41Sopenharmony_ci    TempAliasTable *tempTable=(TempAliasTable *)context;
11311cb0ef41Sopenharmony_ci    const char *chars=tempTable->chars;
11321cb0ef41Sopenharmony_ci
11331cb0ef41Sopenharmony_ci    return (int32_t)uprv_strcmp(tempTable->stripForCompare(strippedLeft, chars+2*((const TempRow *)left)->strIndex),
11341cb0ef41Sopenharmony_ci                                tempTable->stripForCompare(strippedRight, chars+2*((const TempRow *)right)->strIndex));
11351cb0ef41Sopenharmony_ci}
11361cb0ef41Sopenharmony_ci
11371cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
11381cb0ef41Sopenharmony_ciucnv_swapAliases(const UDataSwapper *ds,
11391cb0ef41Sopenharmony_ci                 const void *inData, int32_t length, void *outData,
11401cb0ef41Sopenharmony_ci                 UErrorCode *pErrorCode) {
11411cb0ef41Sopenharmony_ci    const UDataInfo *pInfo;
11421cb0ef41Sopenharmony_ci    int32_t headerSize;
11431cb0ef41Sopenharmony_ci
11441cb0ef41Sopenharmony_ci    const uint16_t *inTable;
11451cb0ef41Sopenharmony_ci    const uint32_t *inSectionSizes;
11461cb0ef41Sopenharmony_ci    uint32_t toc[offsetsCount];
11471cb0ef41Sopenharmony_ci    uint32_t offsets[offsetsCount]; /* 16-bit-addressed offsets from inTable/outTable */
11481cb0ef41Sopenharmony_ci    uint32_t i, count, tocLength, topOffset;
11491cb0ef41Sopenharmony_ci
11501cb0ef41Sopenharmony_ci    TempRow rows[STACK_ROW_CAPACITY];
11511cb0ef41Sopenharmony_ci    uint16_t resort[STACK_ROW_CAPACITY];
11521cb0ef41Sopenharmony_ci    TempAliasTable tempTable;
11531cb0ef41Sopenharmony_ci
11541cb0ef41Sopenharmony_ci    /* udata_swapDataHeader checks the arguments */
11551cb0ef41Sopenharmony_ci    headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
11561cb0ef41Sopenharmony_ci    if(pErrorCode==nullptr || U_FAILURE(*pErrorCode)) {
11571cb0ef41Sopenharmony_ci        return 0;
11581cb0ef41Sopenharmony_ci    }
11591cb0ef41Sopenharmony_ci
11601cb0ef41Sopenharmony_ci    /* check data format and format version */
11611cb0ef41Sopenharmony_ci    pInfo=(const UDataInfo *)((const char *)inData+4);
11621cb0ef41Sopenharmony_ci    if(!(
11631cb0ef41Sopenharmony_ci        pInfo->dataFormat[0]==0x43 &&   /* dataFormat="CvAl" */
11641cb0ef41Sopenharmony_ci        pInfo->dataFormat[1]==0x76 &&
11651cb0ef41Sopenharmony_ci        pInfo->dataFormat[2]==0x41 &&
11661cb0ef41Sopenharmony_ci        pInfo->dataFormat[3]==0x6c &&
11671cb0ef41Sopenharmony_ci        pInfo->formatVersion[0]==3
11681cb0ef41Sopenharmony_ci    )) {
11691cb0ef41Sopenharmony_ci        udata_printError(ds, "ucnv_swapAliases(): data format %02x.%02x.%02x.%02x (format version %02x) is not an alias table\n",
11701cb0ef41Sopenharmony_ci                         pInfo->dataFormat[0], pInfo->dataFormat[1],
11711cb0ef41Sopenharmony_ci                         pInfo->dataFormat[2], pInfo->dataFormat[3],
11721cb0ef41Sopenharmony_ci                         pInfo->formatVersion[0]);
11731cb0ef41Sopenharmony_ci        *pErrorCode=U_UNSUPPORTED_ERROR;
11741cb0ef41Sopenharmony_ci        return 0;
11751cb0ef41Sopenharmony_ci    }
11761cb0ef41Sopenharmony_ci
11771cb0ef41Sopenharmony_ci    /* an alias table must contain at least the table of contents array */
11781cb0ef41Sopenharmony_ci    if(length>=0 && (length-headerSize)<4*(1+minTocLength)) {
11791cb0ef41Sopenharmony_ci        udata_printError(ds, "ucnv_swapAliases(): too few bytes (%d after header) for an alias table\n",
11801cb0ef41Sopenharmony_ci                         length-headerSize);
11811cb0ef41Sopenharmony_ci        *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
11821cb0ef41Sopenharmony_ci        return 0;
11831cb0ef41Sopenharmony_ci    }
11841cb0ef41Sopenharmony_ci
11851cb0ef41Sopenharmony_ci    inSectionSizes=(const uint32_t *)((const char *)inData+headerSize);
11861cb0ef41Sopenharmony_ci    inTable=(const uint16_t *)inSectionSizes;
11871cb0ef41Sopenharmony_ci    uprv_memset(toc, 0, sizeof(toc));
11881cb0ef41Sopenharmony_ci    toc[tocLengthIndex]=tocLength=ds->readUInt32(inSectionSizes[tocLengthIndex]);
11891cb0ef41Sopenharmony_ci    if(tocLength<minTocLength || offsetsCount<=tocLength) {
11901cb0ef41Sopenharmony_ci        udata_printError(ds, "ucnv_swapAliases(): table of contents contains unsupported number of sections (%u sections)\n", tocLength);
11911cb0ef41Sopenharmony_ci        *pErrorCode=U_INVALID_FORMAT_ERROR;
11921cb0ef41Sopenharmony_ci        return 0;
11931cb0ef41Sopenharmony_ci    }
11941cb0ef41Sopenharmony_ci
11951cb0ef41Sopenharmony_ci    /* read the known part of the table of contents */
11961cb0ef41Sopenharmony_ci    for(i=converterListIndex; i<=tocLength; ++i) {
11971cb0ef41Sopenharmony_ci        toc[i]=ds->readUInt32(inSectionSizes[i]);
11981cb0ef41Sopenharmony_ci    }
11991cb0ef41Sopenharmony_ci
12001cb0ef41Sopenharmony_ci    /* compute offsets */
12011cb0ef41Sopenharmony_ci    uprv_memset(offsets, 0, sizeof(offsets));
12021cb0ef41Sopenharmony_ci    offsets[converterListIndex]=2*(1+tocLength); /* count two 16-bit units per toc entry */
12031cb0ef41Sopenharmony_ci    for(i=tagListIndex; i<=tocLength; ++i) {
12041cb0ef41Sopenharmony_ci        offsets[i]=offsets[i-1]+toc[i-1];
12051cb0ef41Sopenharmony_ci    }
12061cb0ef41Sopenharmony_ci
12071cb0ef41Sopenharmony_ci    /* compute the overall size of the after-header data, in numbers of 16-bit units */
12081cb0ef41Sopenharmony_ci    topOffset=offsets[i-1]+toc[i-1];
12091cb0ef41Sopenharmony_ci
12101cb0ef41Sopenharmony_ci    if(length>=0) {
12111cb0ef41Sopenharmony_ci        uint16_t *outTable;
12121cb0ef41Sopenharmony_ci        const uint16_t *p, *p2;
12131cb0ef41Sopenharmony_ci        uint16_t *q, *q2;
12141cb0ef41Sopenharmony_ci        uint16_t oldIndex;
12151cb0ef41Sopenharmony_ci
12161cb0ef41Sopenharmony_ci        if((length-headerSize)<(2*(int32_t)topOffset)) {
12171cb0ef41Sopenharmony_ci            udata_printError(ds, "ucnv_swapAliases(): too few bytes (%d after header) for an alias table\n",
12181cb0ef41Sopenharmony_ci                             length-headerSize);
12191cb0ef41Sopenharmony_ci            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
12201cb0ef41Sopenharmony_ci            return 0;
12211cb0ef41Sopenharmony_ci        }
12221cb0ef41Sopenharmony_ci
12231cb0ef41Sopenharmony_ci        outTable=(uint16_t *)((char *)outData+headerSize);
12241cb0ef41Sopenharmony_ci
12251cb0ef41Sopenharmony_ci        /* swap the entire table of contents */
12261cb0ef41Sopenharmony_ci        ds->swapArray32(ds, inTable, 4*(1+tocLength), outTable, pErrorCode);
12271cb0ef41Sopenharmony_ci
12281cb0ef41Sopenharmony_ci        /* swap unormalized strings & normalized strings */
12291cb0ef41Sopenharmony_ci        ds->swapInvChars(ds, inTable+offsets[stringTableIndex], 2*(int32_t)(toc[stringTableIndex]+toc[normalizedStringTableIndex]),
12301cb0ef41Sopenharmony_ci                             outTable+offsets[stringTableIndex], pErrorCode);
12311cb0ef41Sopenharmony_ci        if(U_FAILURE(*pErrorCode)) {
12321cb0ef41Sopenharmony_ci            udata_printError(ds, "ucnv_swapAliases().swapInvChars(charset names) failed\n");
12331cb0ef41Sopenharmony_ci            return 0;
12341cb0ef41Sopenharmony_ci        }
12351cb0ef41Sopenharmony_ci
12361cb0ef41Sopenharmony_ci        if(ds->inCharset==ds->outCharset) {
12371cb0ef41Sopenharmony_ci            /* no need to sort, just swap all 16-bit values together */
12381cb0ef41Sopenharmony_ci            ds->swapArray16(ds,
12391cb0ef41Sopenharmony_ci                            inTable+offsets[converterListIndex],
12401cb0ef41Sopenharmony_ci                            2*(int32_t)(offsets[stringTableIndex]-offsets[converterListIndex]),
12411cb0ef41Sopenharmony_ci                            outTable+offsets[converterListIndex],
12421cb0ef41Sopenharmony_ci                            pErrorCode);
12431cb0ef41Sopenharmony_ci        } else {
12441cb0ef41Sopenharmony_ci            /* allocate the temporary table for sorting */
12451cb0ef41Sopenharmony_ci            count=toc[aliasListIndex];
12461cb0ef41Sopenharmony_ci
12471cb0ef41Sopenharmony_ci            tempTable.chars=(const char *)(outTable+offsets[stringTableIndex]); /* sort by outCharset */
12481cb0ef41Sopenharmony_ci
12491cb0ef41Sopenharmony_ci            if(count<=STACK_ROW_CAPACITY) {
12501cb0ef41Sopenharmony_ci                tempTable.rows=rows;
12511cb0ef41Sopenharmony_ci                tempTable.resort=resort;
12521cb0ef41Sopenharmony_ci            } else {
12531cb0ef41Sopenharmony_ci                tempTable.rows=(TempRow *)uprv_malloc(count*sizeof(TempRow)+count*2);
12541cb0ef41Sopenharmony_ci                if(tempTable.rows==nullptr) {
12551cb0ef41Sopenharmony_ci                    udata_printError(ds, "ucnv_swapAliases(): unable to allocate memory for sorting tables (max length: %u)\n",
12561cb0ef41Sopenharmony_ci                                     count);
12571cb0ef41Sopenharmony_ci                    *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
12581cb0ef41Sopenharmony_ci                    return 0;
12591cb0ef41Sopenharmony_ci                }
12601cb0ef41Sopenharmony_ci                tempTable.resort=(uint16_t *)(tempTable.rows+count);
12611cb0ef41Sopenharmony_ci            }
12621cb0ef41Sopenharmony_ci
12631cb0ef41Sopenharmony_ci            if(ds->outCharset==U_ASCII_FAMILY) {
12641cb0ef41Sopenharmony_ci                tempTable.stripForCompare=ucnv_io_stripASCIIForCompare;
12651cb0ef41Sopenharmony_ci            } else /* U_EBCDIC_FAMILY */ {
12661cb0ef41Sopenharmony_ci                tempTable.stripForCompare=ucnv_io_stripEBCDICForCompare;
12671cb0ef41Sopenharmony_ci            }
12681cb0ef41Sopenharmony_ci
12691cb0ef41Sopenharmony_ci            /*
12701cb0ef41Sopenharmony_ci             * Sort unique aliases+mapped names.
12711cb0ef41Sopenharmony_ci             *
12721cb0ef41Sopenharmony_ci             * We need to sort the list again by outCharset strings because they
12731cb0ef41Sopenharmony_ci             * sort differently for different charset families.
12741cb0ef41Sopenharmony_ci             * First we set up a temporary table with the string indexes and
12751cb0ef41Sopenharmony_ci             * sorting indexes and sort that.
12761cb0ef41Sopenharmony_ci             * Then we permutate and copy/swap the actual values.
12771cb0ef41Sopenharmony_ci             */
12781cb0ef41Sopenharmony_ci            p=inTable+offsets[aliasListIndex];
12791cb0ef41Sopenharmony_ci            q=outTable+offsets[aliasListIndex];
12801cb0ef41Sopenharmony_ci
12811cb0ef41Sopenharmony_ci            p2=inTable+offsets[untaggedConvArrayIndex];
12821cb0ef41Sopenharmony_ci            q2=outTable+offsets[untaggedConvArrayIndex];
12831cb0ef41Sopenharmony_ci
12841cb0ef41Sopenharmony_ci            for(i=0; i<count; ++i) {
12851cb0ef41Sopenharmony_ci                tempTable.rows[i].strIndex=ds->readUInt16(p[i]);
12861cb0ef41Sopenharmony_ci                tempTable.rows[i].sortIndex=(uint16_t)i;
12871cb0ef41Sopenharmony_ci            }
12881cb0ef41Sopenharmony_ci
12891cb0ef41Sopenharmony_ci            uprv_sortArray(tempTable.rows, (int32_t)count, sizeof(TempRow),
12901cb0ef41Sopenharmony_ci                           io_compareRows, &tempTable,
12911cb0ef41Sopenharmony_ci                           false, pErrorCode);
12921cb0ef41Sopenharmony_ci
12931cb0ef41Sopenharmony_ci            if(U_SUCCESS(*pErrorCode)) {
12941cb0ef41Sopenharmony_ci                /* copy/swap/permutate items */
12951cb0ef41Sopenharmony_ci                if(p!=q) {
12961cb0ef41Sopenharmony_ci                    for(i=0; i<count; ++i) {
12971cb0ef41Sopenharmony_ci                        oldIndex=tempTable.rows[i].sortIndex;
12981cb0ef41Sopenharmony_ci                        ds->swapArray16(ds, p+oldIndex, 2, q+i, pErrorCode);
12991cb0ef41Sopenharmony_ci                        ds->swapArray16(ds, p2+oldIndex, 2, q2+i, pErrorCode);
13001cb0ef41Sopenharmony_ci                    }
13011cb0ef41Sopenharmony_ci                } else {
13021cb0ef41Sopenharmony_ci                    /*
13031cb0ef41Sopenharmony_ci                     * If we swap in-place, then the permutation must use another
13041cb0ef41Sopenharmony_ci                     * temporary array (tempTable.resort)
13051cb0ef41Sopenharmony_ci                     * before the results are copied to the outBundle.
13061cb0ef41Sopenharmony_ci                     */
13071cb0ef41Sopenharmony_ci                    uint16_t *r=tempTable.resort;
13081cb0ef41Sopenharmony_ci
13091cb0ef41Sopenharmony_ci                    for(i=0; i<count; ++i) {
13101cb0ef41Sopenharmony_ci                        oldIndex=tempTable.rows[i].sortIndex;
13111cb0ef41Sopenharmony_ci                        ds->swapArray16(ds, p+oldIndex, 2, r+i, pErrorCode);
13121cb0ef41Sopenharmony_ci                    }
13131cb0ef41Sopenharmony_ci                    uprv_memcpy(q, r, 2*(size_t)count);
13141cb0ef41Sopenharmony_ci
13151cb0ef41Sopenharmony_ci                    for(i=0; i<count; ++i) {
13161cb0ef41Sopenharmony_ci                        oldIndex=tempTable.rows[i].sortIndex;
13171cb0ef41Sopenharmony_ci                        ds->swapArray16(ds, p2+oldIndex, 2, r+i, pErrorCode);
13181cb0ef41Sopenharmony_ci                    }
13191cb0ef41Sopenharmony_ci                    uprv_memcpy(q2, r, 2*(size_t)count);
13201cb0ef41Sopenharmony_ci                }
13211cb0ef41Sopenharmony_ci            }
13221cb0ef41Sopenharmony_ci
13231cb0ef41Sopenharmony_ci            if(tempTable.rows!=rows) {
13241cb0ef41Sopenharmony_ci                uprv_free(tempTable.rows);
13251cb0ef41Sopenharmony_ci            }
13261cb0ef41Sopenharmony_ci
13271cb0ef41Sopenharmony_ci            if(U_FAILURE(*pErrorCode)) {
13281cb0ef41Sopenharmony_ci                udata_printError(ds, "ucnv_swapAliases().uprv_sortArray(%u items) failed\n",
13291cb0ef41Sopenharmony_ci                                 count);
13301cb0ef41Sopenharmony_ci                return 0;
13311cb0ef41Sopenharmony_ci            }
13321cb0ef41Sopenharmony_ci
13331cb0ef41Sopenharmony_ci            /* swap remaining 16-bit values */
13341cb0ef41Sopenharmony_ci            ds->swapArray16(ds,
13351cb0ef41Sopenharmony_ci                            inTable+offsets[converterListIndex],
13361cb0ef41Sopenharmony_ci                            2*(int32_t)(offsets[aliasListIndex]-offsets[converterListIndex]),
13371cb0ef41Sopenharmony_ci                            outTable+offsets[converterListIndex],
13381cb0ef41Sopenharmony_ci                            pErrorCode);
13391cb0ef41Sopenharmony_ci            ds->swapArray16(ds,
13401cb0ef41Sopenharmony_ci                            inTable+offsets[taggedAliasArrayIndex],
13411cb0ef41Sopenharmony_ci                            2*(int32_t)(offsets[stringTableIndex]-offsets[taggedAliasArrayIndex]),
13421cb0ef41Sopenharmony_ci                            outTable+offsets[taggedAliasArrayIndex],
13431cb0ef41Sopenharmony_ci                            pErrorCode);
13441cb0ef41Sopenharmony_ci        }
13451cb0ef41Sopenharmony_ci    }
13461cb0ef41Sopenharmony_ci
13471cb0ef41Sopenharmony_ci    return headerSize+2*(int32_t)topOffset;
13481cb0ef41Sopenharmony_ci}
13491cb0ef41Sopenharmony_ci
13501cb0ef41Sopenharmony_ci#endif
13511cb0ef41Sopenharmony_ci
13521cb0ef41Sopenharmony_ci
13531cb0ef41Sopenharmony_ci/*
13541cb0ef41Sopenharmony_ci * Hey, Emacs, please set the following:
13551cb0ef41Sopenharmony_ci *
13561cb0ef41Sopenharmony_ci * Local Variables:
13571cb0ef41Sopenharmony_ci * indent-tabs-mode: nil
13581cb0ef41Sopenharmony_ci * End:
13591cb0ef41Sopenharmony_ci *
13601cb0ef41Sopenharmony_ci */
1361