16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 1999-2013, International Business Machines
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org******************************************************************************
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   file name:  unames.c
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   encoding:   US-ASCII
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   tab size:   8 (not used)
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   indentation:4
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created on: 1999oct04
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created by: Markus W. Scherer
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/putil.h"
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uchar.h"
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/udata.h"
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf.h"
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf16.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ustr_imp.h"
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "umutex.h"
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cstring.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucln_cmn.h"
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "udataswp.h"
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uprops.h"
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* prototypes ------------------------------------------------------------- */
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const char DATA_NAME[] = "unames";
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const char DATA_TYPE[] = "icu";
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define GROUP_SHIFT 5
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define LINES_PER_GROUP (1L<<GROUP_SHIFT)
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define GROUP_MASK (LINES_PER_GROUP-1)
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * This struct was replaced by explicitly accessing equivalent
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * fields from triples of uint16_t.
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * The Group struct was padded to 8 bytes on compilers for early ARM CPUs,
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * which broke the assumption that sizeof(Group)==6 and that the ++ operator
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * would advance by 6 bytes (3 uint16_t).
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * We can't just change the data structure because it's loaded from a data file,
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * and we don't want to make it less compact, so we changed the access code.
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * For details see ICU tickets 6331 and 6008.
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtypedef struct {
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t groupMSB,
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             offsetHigh, offsetLow; / * avoid padding * /
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} Group;
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenum {
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GROUP_MSB,
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GROUP_OFFSET_HIGH,
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GROUP_OFFSET_LOW,
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GROUP_LENGTH
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Get the 32-bit group offset.
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param group (const uint16_t *) pointer to a Group triple of uint16_t
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return group offset (int32_t)
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define GET_GROUP_OFFSET(group) ((int32_t)(group)[GROUP_OFFSET_HIGH]<<16|(group)[GROUP_OFFSET_LOW])
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define NEXT_GROUP(group) ((group)+GROUP_LENGTH)
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define PREV_GROUP(group) ((group)-GROUP_LENGTH)
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtypedef struct {
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t start, end;
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t type, variant;
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t size;
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} AlgorithmicRange;
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtypedef struct {
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t tokenStringOffset, groupsOffset, groupStringOffset, algNamesOffset;
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} UCharNames;
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Get the groups table from a UCharNames struct.
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * The groups table consists of one uint16_t groupCount followed by
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * groupCount groups. Each group is a triple of uint16_t, see GROUP_LENGTH
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * and the comment for the old struct Group above.
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param names (const UCharNames *) pointer to the UCharNames indexes
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return (const uint16_t *) pointer to the groups table
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define GET_GROUPS(names) (const uint16_t *)((const char *)names+names->groupsOffset)
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtypedef struct {
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *otherName;
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 code;
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} FindName;
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define DO_FIND_NAME NULL
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UDataMemory *uCharNamesData=NULL;
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UCharNames *uCharNames=NULL;
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic icu::UInitOnce gCharNamesInitOnce = U_INITONCE_INITIALIZER;
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Maximum length of character names (regular & 1.0).
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t gMaxNameLength=0;
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Set of chars used in character names (regular & 1.0).
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Chars are platform-dependent (can be EBCDIC).
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic uint32_t gNameSet[8]={ 0 };
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define U_NONCHARACTER_CODE_POINT U_CHAR_CATEGORY_COUNT
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define U_LEAD_SURROGATE U_CHAR_CATEGORY_COUNT + 1
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define U_TRAIL_SURROGATE U_CHAR_CATEGORY_COUNT + 2
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define U_CHAR_EXTENDED_CATEGORY_COUNT (U_CHAR_CATEGORY_COUNT + 3)
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const char * const charCatNames[U_CHAR_EXTENDED_CATEGORY_COUNT] = {
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "unassigned",
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "uppercase letter",
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "lowercase letter",
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "titlecase letter",
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "modifier letter",
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "other letter",
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "non spacing mark",
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "enclosing mark",
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "combining spacing mark",
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "decimal digit number",
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "letter number",
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "other number",
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "space separator",
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "line separator",
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "paragraph separator",
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "control",
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "format",
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "private use area",
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "surrogate",
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "dash punctuation",
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "start punctuation",
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "end punctuation",
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "connector punctuation",
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "other punctuation",
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "math symbol",
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "currency symbol",
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "modifier symbol",
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "other symbol",
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "initial punctuation",
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "final punctuation",
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "noncharacter",
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "lead surrogate",
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "trail surrogate"
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* implementation ----------------------------------------------------------- */
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool U_CALLCONV unames_cleanup(void)
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(uCharNamesData) {
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udata_close(uCharNamesData);
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uCharNamesData = NULL;
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(uCharNames) {
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uCharNames = NULL;
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    gCharNamesInitOnce.reset();
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    gMaxNameLength=0;
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool U_CALLCONV
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgisAcceptable(void * /*context*/,
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             const char * /*type*/, const char * /*name*/,
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             const UDataInfo *pInfo) {
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (UBool)(
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->size>=20 &&
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->charsetFamily==U_CHARSET_FAMILY &&
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[0]==0x75 &&   /* dataFormat="unam" */
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[1]==0x6e &&
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[2]==0x61 &&
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[3]==0x6d &&
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->formatVersion[0]==1);
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void U_CALLCONV
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgloadCharNames(UErrorCode &status) {
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_ASSERT(uCharNamesData == NULL);
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_ASSERT(uCharNames == NULL);
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uCharNamesData = udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, &status);
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(status)) {
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uCharNamesData = NULL;
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uCharNames = (UCharNames *)udata_getMemory(uCharNamesData);
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ucln_common_registerCleanup(UCLN_COMMON_UNAMES, unames_cleanup);
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgisDataLoaded(UErrorCode *pErrorCode) {
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    umtx_initOnce(gCharNamesInitOnce, &loadCharNames, *pErrorCode);
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return U_SUCCESS(*pErrorCode);
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define WRITE_CHAR(buffer, bufferLength, bufferPos, c) { \
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((bufferLength)>0) { \
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *(buffer)++=c; \
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        --(bufferLength); \
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } \
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ++(bufferPos); \
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define U_ISO_COMMENT U_CHAR_NAME_CHOICE_COUNT
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Important: expandName() and compareName() are almost the same -
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * apply fixes to both.
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * UnicodeData.txt uses ';' as a field separator, so no
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * field can contain ';' as part of its contents.
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * In unames.dat, it is marked as token[';']==-1 only if the
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * semicolon is used in the data file - which is iff we
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * have Unicode 1.0 names or ISO comments or aliases.
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * So, it will be token[';']==-1 if we store U1.0 names/ISO comments/aliases
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * although we know that it will never be part of a name.
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic uint16_t
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgexpandName(UCharNames *names,
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org           const uint8_t *name, uint16_t nameLength, UCharNameChoice nameChoice,
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org           char *buffer, uint16_t bufferLength) {
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t *tokens=(uint16_t *)names+8;
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t token, tokenCount=*tokens++, bufferPos=0;
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t *tokenStrings=(uint8_t *)names+names->tokenStringOffset;
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t c;
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * skip the modern name if it is not requested _and_
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * if the semicolon byte value is a character, not a token number
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) {
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int fieldIndex= nameChoice==U_ISO_COMMENT ? 2 : nameChoice;
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            do {
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                while(nameLength>0) {
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    --nameLength;
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(*name++==';') {
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        break;
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } while(--fieldIndex>0);
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * the semicolon byte value is a token number, therefore
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * only modern names are stored in unames.dat and there is no
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * such requested alternate name here
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            nameLength=0;
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* write each letter directly, and write a token word per token */
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(nameLength>0) {
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        --nameLength;
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=*name++;
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c>=tokenCount) {
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(c!=';') {
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* implicit letter */
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                WRITE_CHAR(buffer, bufferLength, bufferPos, c);
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* finished */
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            token=tokens[c];
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(token==(uint16_t)(-2)) {
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* this is a lead byte for a double-byte token */
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                token=tokens[c<<8|*name++];
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                --nameLength;
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(token==(uint16_t)(-1)) {
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(c!=';') {
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* explicit letter */
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    WRITE_CHAR(buffer, bufferLength, bufferPos, c);
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* stop, but skip the semicolon if we are seeking
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       extended names and there was no 2.0 name but there
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       is a 1.0 name. */
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(!bufferPos && nameChoice == U_EXTENDED_CHAR_NAME) {
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if ((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) {
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            continue;
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* finished */
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* write token word */
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                uint8_t *tokenString=tokenStrings+token;
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                while((c=*tokenString++)!=0) {
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    WRITE_CHAR(buffer, bufferLength, bufferPos, c);
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* zero-terminate */
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(bufferLength>0) {
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *buffer=0;
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return bufferPos;
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * compareName() is almost the same as expandName() except that it compares
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * the currently expanded name to an input name.
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * It returns the match/no match result as soon as possible.
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgcompareName(UCharNames *names,
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const uint8_t *name, uint16_t nameLength, UCharNameChoice nameChoice,
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const char *otherName) {
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t *tokens=(uint16_t *)names+8;
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t token, tokenCount=*tokens++;
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t *tokenStrings=(uint8_t *)names+names->tokenStringOffset;
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t c;
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *origOtherName = otherName;
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * skip the modern name if it is not requested _and_
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * if the semicolon byte value is a character, not a token number
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) {
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int fieldIndex= nameChoice==U_ISO_COMMENT ? 2 : nameChoice;
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            do {
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                while(nameLength>0) {
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    --nameLength;
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(*name++==';') {
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        break;
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } while(--fieldIndex>0);
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * the semicolon byte value is a token number, therefore
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * only modern names are stored in unames.dat and there is no
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * such requested alternate name here
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            nameLength=0;
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* compare each letter directly, and compare a token word per token */
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(nameLength>0) {
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        --nameLength;
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=*name++;
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c>=tokenCount) {
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(c!=';') {
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* implicit letter */
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if((char)c!=*otherName++) {
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return FALSE;
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* finished */
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            token=tokens[c];
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(token==(uint16_t)(-2)) {
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* this is a lead byte for a double-byte token */
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                token=tokens[c<<8|*name++];
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                --nameLength;
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(token==(uint16_t)(-1)) {
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(c!=';') {
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* explicit letter */
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if((char)c!=*otherName++) {
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        return FALSE;
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* stop, but skip the semicolon if we are seeking
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       extended names and there was no 2.0 name but there
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       is a 1.0 name. */
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(otherName == origOtherName && nameChoice == U_EXTENDED_CHAR_NAME) {
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if ((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) {
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            continue;
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* finished */
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* write token word */
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                uint8_t *tokenString=tokenStrings+token;
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                while((c=*tokenString++)!=0) {
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if((char)c!=*otherName++) {
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        return FALSE;
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* complete match? */
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (UBool)(*otherName==0);
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic uint8_t getCharCat(UChar32 cp) {
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t cat;
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_IS_UNICODE_NONCHAR(cp)) {
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return U_NONCHARACTER_CODE_POINT;
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if ((cat = u_charType(cp)) == U_SURROGATE) {
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cat = U_IS_LEAD(cp) ? U_LEAD_SURROGATE : U_TRAIL_SURROGATE;
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return cat;
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const char *getCharCatName(UChar32 cp) {
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t cat = getCharCat(cp);
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Return unknown if the table of names above is not up to
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org       date. */
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cat >= LENGTHOF(charCatNames)) {
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return "unknown";
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return charCatNames[cat];
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic uint16_t getExtName(uint32_t code, char *buffer, uint16_t bufferLength) {
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *catname = getCharCatName(code);
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t length = 0;
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 cp;
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int ndigits, i;
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    WRITE_CHAR(buffer, bufferLength, length, '<');
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while (catname[length - 1]) {
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        WRITE_CHAR(buffer, bufferLength, length, catname[length - 1]);
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    WRITE_CHAR(buffer, bufferLength, length, '-');
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (cp = code, ndigits = 0; cp; ++ndigits, cp >>= 4)
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ;
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ndigits < 4)
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ndigits = 4;
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (cp = code, i = ndigits; (cp || i > 0) && bufferLength; cp >>= 4, bufferLength--) {
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint8_t v = (uint8_t)(cp & 0xf);
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        buffer[--i] = (v < 10 ? '0' + v : 'A' + v - 10);
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    buffer += ndigits;
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    length += ndigits;
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    WRITE_CHAR(buffer, bufferLength, length, '>');
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return length;
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * getGroup() does a binary search for the group that contains the
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Unicode code point "code".
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * The return value is always a valid Group* that may contain "code"
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * or else is the highest group before "code".
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * If the lowest group is after "code", then that one is returned.
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const uint16_t *
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orggetGroup(UCharNames *names, uint32_t code) {
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint16_t *groups=GET_GROUPS(names);
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t groupMSB=(uint16_t)(code>>GROUP_SHIFT),
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             start=0,
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             limit=*groups++,
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             number;
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* binary search for the group of names that contains the one for code */
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(start<limit-1) {
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        number=(uint16_t)((start+limit)/2);
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(groupMSB<groups[number*GROUP_LENGTH+GROUP_MSB]) {
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            limit=number;
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start=number;
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* return this regardless of whether it is an exact match */
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return groups+start*GROUP_LENGTH;
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * expandGroupLengths() reads a block of compressed lengths of 32 strings and
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * expands them into offsets and lengths for each string.
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Lengths are stored with a variable-width encoding in consecutive nibbles:
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * If a nibble<0xc, then it is the length itself (0=empty string).
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * If a nibble>=0xc, then it forms a length value with the following nibble.
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Calculation see below.
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * The offsets and lengths arrays must be at least 33 (one more) long because
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * there is no check here at the end if the last nibble is still used.
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const uint8_t *
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgexpandGroupLengths(const uint8_t *s,
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   uint16_t offsets[LINES_PER_GROUP+1], uint16_t lengths[LINES_PER_GROUP+1]) {
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* read the lengths of the 32 strings in this group and get each string's offset */
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t i=0, offset=0, length=0;
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t lengthByte;
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* all 32 lengths must be read to get the offset of the first group string */
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(i<LINES_PER_GROUP) {
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        lengthByte=*s++;
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* read even nibble - MSBs of lengthByte */
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>=12) {
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* double-nibble length spread across two bytes */
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=(uint16_t)(((length&0x3)<<4|lengthByte>>4)+12);
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lengthByte&=0xf;
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if((lengthByte /* &0xf0 */)>=0xc0) {
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* double-nibble length spread across this one byte */
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=(uint16_t)((lengthByte&0x3f)+12);
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* single-nibble length in MSBs */
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=(uint16_t)(lengthByte>>4);
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lengthByte&=0xf;
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *offsets++=offset;
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *lengths++=length;
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        offset+=length;
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++i;
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* read odd nibble - LSBs of lengthByte */
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((lengthByte&0xf0)==0) {
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* this nibble was not consumed for a double-nibble length above */
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=lengthByte;
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length<12) {
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* single-nibble length in LSBs */
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *offsets++=offset;
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *lengths++=length;
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                offset+=length;
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ++i;
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=0;   /* prevent double-nibble detection in the next iteration */
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* now, s is at the first group string */
5636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return s;
5646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic uint16_t
5676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgexpandGroupName(UCharNames *names, const uint16_t *group,
5686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                uint16_t lineNumber, UCharNameChoice nameChoice,
5696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                char *buffer, uint16_t bufferLength) {
5706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t offsets[LINES_PER_GROUP+2], lengths[LINES_PER_GROUP+2];
5716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint8_t *s=(uint8_t *)names+names->groupStringOffset+GET_GROUP_OFFSET(group);
5726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    s=expandGroupLengths(s, offsets, lengths);
5736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return expandName(names, s+offsets[lineNumber], lengths[lineNumber], nameChoice,
5746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                      buffer, bufferLength);
5756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic uint16_t
5786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orggetName(UCharNames *names, uint32_t code, UCharNameChoice nameChoice,
5796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char *buffer, uint16_t bufferLength) {
5806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint16_t *group=getGroup(names, code);
5816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((uint16_t)(code>>GROUP_SHIFT)==group[GROUP_MSB]) {
5826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return expandGroupName(names, group, (uint16_t)(code&GROUP_MASK), nameChoice,
5836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                               buffer, bufferLength);
5846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
5856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* group not found */
5866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* zero-terminate */
5876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(bufferLength>0) {
5886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *buffer=0;
5896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
5916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
5956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * enumGroupNames() enumerates all the names in a 32-group
5966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * and either calls the enumerator function or finds a given input name.
5976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
5986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
5996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenumGroupNames(UCharNames *names, const uint16_t *group,
6006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UChar32 start, UChar32 end,
6016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UEnumCharNamesFn *fn, void *context,
6026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UCharNameChoice nameChoice) {
6036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t offsets[LINES_PER_GROUP+2], lengths[LINES_PER_GROUP+2];
6046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint8_t *s=(uint8_t *)names+names->groupStringOffset+GET_GROUP_OFFSET(group);
6056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    s=expandGroupLengths(s, offsets, lengths);
6076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(fn!=DO_FIND_NAME) {
6086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char buffer[200];
6096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t length;
6106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(start<=end) {
6126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=expandName(names, s+offsets[start&GROUP_MASK], lengths[start&GROUP_MASK], nameChoice, buffer, sizeof(buffer));
6136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (!length && nameChoice == U_EXTENDED_CHAR_NAME) {
6146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                buffer[length = getExtName(start, buffer, sizeof(buffer))] = 0;
6156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* here, we assume that the buffer is large enough */
6176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length>0) {
6186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(!fn(context, start, nameChoice, buffer, length)) {
6196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return FALSE;
6206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++start;
6236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
6256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *otherName=((FindName *)context)->otherName;
6266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(start<=end) {
6276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(compareName(names, s+offsets[start&GROUP_MASK], lengths[start&GROUP_MASK], nameChoice, otherName)) {
6286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ((FindName *)context)->code=start;
6296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return FALSE;
6306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++start;
6326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
6356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
6386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * enumExtNames enumerate extended names.
6396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * It only needs to do it if it is called with a real function and not
6406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * with the dummy DO_FIND_NAME, because u_charFromName() does a check
6416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * for extended names by itself.
6426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
6436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
6446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenumExtNames(UChar32 start, UChar32 end,
6456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UEnumCharNamesFn *fn, void *context)
6466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(fn!=DO_FIND_NAME) {
6486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char buffer[200];
6496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t length;
6506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(start<=end) {
6526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            buffer[length = getExtName(start, buffer, sizeof(buffer))] = 0;
6536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* here, we assume that the buffer is large enough */
6546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length>0) {
6556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(!fn(context, start, U_EXTENDED_CHAR_NAME, buffer, length)) {
6566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return FALSE;
6576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++start;
6606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
6646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
6676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenumNames(UCharNames *names,
6686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          UChar32 start, UChar32 limit,
6696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          UEnumCharNamesFn *fn, void *context,
6706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          UCharNameChoice nameChoice) {
6716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t startGroupMSB, endGroupMSB, groupCount;
6726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint16_t *group, *groupLimit;
6736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    startGroupMSB=(uint16_t)(start>>GROUP_SHIFT);
6756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    endGroupMSB=(uint16_t)((limit-1)>>GROUP_SHIFT);
6766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* find the group that contains start, or the highest before it */
6786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    group=getGroup(names, start);
6796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(startGroupMSB<group[GROUP_MSB] && nameChoice==U_EXTENDED_CHAR_NAME) {
6816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* enumerate synthetic names between start and the group start */
6826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar32 extLimit=((UChar32)group[GROUP_MSB]<<GROUP_SHIFT);
6836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(extLimit>limit) {
6846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            extLimit=limit;
6856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(!enumExtNames(start, extLimit-1, fn, context)) {
6876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
6886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        start=extLimit;
6906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(startGroupMSB==endGroupMSB) {
6936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(startGroupMSB==group[GROUP_MSB]) {
6946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* if start and limit-1 are in the same group, then enumerate only in that one */
6956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return enumGroupNames(names, group, start, limit-1, fn, context, nameChoice);
6966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
6986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const uint16_t *groups=GET_GROUPS(names);
6996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        groupCount=*groups++;
7006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        groupLimit=groups+groupCount*GROUP_LENGTH;
7016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(startGroupMSB==group[GROUP_MSB]) {
7036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* enumerate characters in the partial start group */
7046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if((start&GROUP_MASK)!=0) {
7056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(!enumGroupNames(names, group,
7066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                   start, ((UChar32)startGroupMSB<<GROUP_SHIFT)+LINES_PER_GROUP-1,
7076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                   fn, context, nameChoice)) {
7086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return FALSE;
7096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
7106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                group=NEXT_GROUP(group); /* continue with the next group */
7116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(startGroupMSB>group[GROUP_MSB]) {
7136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* make sure that we start enumerating with the first group after start */
7146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const uint16_t *nextGroup=NEXT_GROUP(group);
7156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (nextGroup < groupLimit && nextGroup[GROUP_MSB] > startGroupMSB && nameChoice == U_EXTENDED_CHAR_NAME) {
7166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UChar32 end = nextGroup[GROUP_MSB] << GROUP_SHIFT;
7176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (end > limit) {
7186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    end = limit;
7196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
7206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (!enumExtNames(start, end - 1, fn, context)) {
7216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return FALSE;
7226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
7236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            group=nextGroup;
7256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* enumerate entire groups between the start- and end-groups */
7286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(group<groupLimit && group[GROUP_MSB]<endGroupMSB) {
7296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const uint16_t *nextGroup;
7306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start=(UChar32)group[GROUP_MSB]<<GROUP_SHIFT;
7316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(!enumGroupNames(names, group, start, start+LINES_PER_GROUP-1, fn, context, nameChoice)) {
7326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return FALSE;
7336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            nextGroup=NEXT_GROUP(group);
7356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (nextGroup < groupLimit && nextGroup[GROUP_MSB] > group[GROUP_MSB] + 1 && nameChoice == U_EXTENDED_CHAR_NAME) {
7366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UChar32 end = nextGroup[GROUP_MSB] << GROUP_SHIFT;
7376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (end > limit) {
7386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    end = limit;
7396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
7406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (!enumExtNames((group[GROUP_MSB] + 1) << GROUP_SHIFT, end - 1, fn, context)) {
7416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return FALSE;
7426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
7436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            group=nextGroup;
7456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* enumerate within the end group (group[GROUP_MSB]==endGroupMSB) */
7486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(group<groupLimit && group[GROUP_MSB]==endGroupMSB) {
7496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return enumGroupNames(names, group, (limit-1)&~GROUP_MASK, limit-1, fn, context, nameChoice);
7506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if (nameChoice == U_EXTENDED_CHAR_NAME && group == groupLimit) {
7516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UChar32 next = (PREV_GROUP(group)[GROUP_MSB] + 1) << GROUP_SHIFT;
7526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (next > start) {
7536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                start = next;
7546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
7566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return TRUE;
7576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* we have not found a group, which means everything is made of
7616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org       extended names. */
7626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (nameChoice == U_EXTENDED_CHAR_NAME) {
7636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (limit > UCHAR_MAX_VALUE + 1) {
7646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            limit = UCHAR_MAX_VALUE + 1;
7656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return enumExtNames(start, limit - 1, fn, context);
7676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
7706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic uint16_t
7736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgwriteFactorSuffix(const uint16_t *factors, uint16_t count,
7746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  const char *s, /* suffix elements */
7756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  uint32_t code,
7766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  uint16_t indexes[8], /* output fields from here */
7776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  const char *elementBases[8], const char *elements[8],
7786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  char *buffer, uint16_t bufferLength) {
7796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t i, factor, bufferPos=0;
7806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char c;
7816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* write elements according to the factors */
7836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
7856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * the factorized elements are determined by modulo arithmetic
7866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * with the factors of this algorithm
7876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
7886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * note that for fewer operations, count is decremented here
7896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
7906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    --count;
7916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(i=count; i>0; --i) {
7926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        factor=factors[i];
7936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        indexes[i]=(uint16_t)(code%factor);
7946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        code/=factor;
7956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
7976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * we don't need to calculate the last modulus because start<=code<=end
7986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * guarantees here that code<=factors[0]
7996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
8006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    indexes[0]=(uint16_t)code;
8016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* write each element */
8036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
8046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(elementBases!=NULL) {
8056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *elementBases++=s;
8066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* skip indexes[i] strings */
8096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        factor=indexes[i];
8106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(factor>0) {
8116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while(*s++!=0) {}
8126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            --factor;
8136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(elements!=NULL) {
8156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *elements++=s;
8166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* write element */
8196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while((c=*s++)!=0) {
8206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            WRITE_CHAR(buffer, bufferLength, bufferPos, c);
8216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* we do not need to perform the rest of this loop for i==count - break here */
8246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(i>=count) {
8256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
8266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* skip the rest of the strings for this factors[i] */
8296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        factor=(uint16_t)(factors[i]-indexes[i]-1);
8306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(factor>0) {
8316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while(*s++!=0) {}
8326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            --factor;
8336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++i;
8366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* zero-terminate */
8396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(bufferLength>0) {
8406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *buffer=0;
8416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return bufferPos;
8446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
8476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Important:
8486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Parts of findAlgName() are almost the same as some of getAlgName().
8496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Fixes must be applied to both.
8506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
8516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic uint16_t
8526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orggetAlgName(AlgorithmicRange *range, uint32_t code, UCharNameChoice nameChoice,
8536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char *buffer, uint16_t bufferLength) {
8546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t bufferPos=0;
8556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Only the normative character name can be algorithmic. */
8576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
8586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* zero-terminate */
8596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(bufferLength>0) {
8606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *buffer=0;
8616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
8636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(range->type) {
8666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case 0: {
8676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* name = prefix hex-digits */
8686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *s=(const char *)(range+1);
8696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char c;
8706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t i, count;
8726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy prefix */
8746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while((c=*s++)!=0) {
8756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            WRITE_CHAR(buffer, bufferLength, bufferPos, c);
8766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* write hexadecimal code point value */
8796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        count=range->variant;
8806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* zero-terminate */
8826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(count<bufferLength) {
8836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            buffer[count]=0;
8846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(i=count; i>0;) {
8876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(--i<bufferLength) {
8886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c=(char)(code&0xf);
8896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(c<10) {
8906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    c+='0';
8916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
8926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    c+='A'-10;
8936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                buffer[i]=c;
8956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            code>>=4;
8976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        bufferPos+=count;
9006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
9016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case 1: {
9036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* name = prefix factorized-elements */
9046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t indexes[8];
9056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const uint16_t *factors=(const uint16_t *)(range+1);
9066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t count=range->variant;
9076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *s=(const char *)(factors+count);
9086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char c;
9096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy prefix */
9116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while((c=*s++)!=0) {
9126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            WRITE_CHAR(buffer, bufferLength, bufferPos, c);
9136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        bufferPos+=writeFactorSuffix(factors, count,
9166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     s, code-range->start, indexes, NULL, NULL, buffer, bufferLength);
9176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
9186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
9206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* undefined type */
9216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* zero-terminate */
9226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(bufferLength>0) {
9236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *buffer=0;
9246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
9266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return bufferPos;
9296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
9326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Important: enumAlgNames() and findAlgName() are almost the same.
9336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Any fix must be applied to both.
9346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
9356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
9366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenumAlgNames(AlgorithmicRange *range,
9376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UChar32 start, UChar32 limit,
9386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UEnumCharNamesFn *fn, void *context,
9396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UCharNameChoice nameChoice) {
9406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char buffer[200];
9416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t length;
9426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
9446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
9456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(range->type) {
9486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case 0: {
9496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char *s, *end;
9506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char c;
9516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* get the full name of the start character */
9536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=getAlgName(range, (uint32_t)start, nameChoice, buffer, sizeof(buffer));
9546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length<=0) {
9556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return TRUE;
9566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* call the enumerator function with this first character */
9596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(!fn(context, start, nameChoice, buffer, length)) {
9606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
9616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* go to the end of the name; all these names have the same length */
9646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        end=buffer;
9656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(*end!=0) {
9666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++end;
9676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* enumerate the rest of the names */
9706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(++start<limit) {
9716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* increment the hexadecimal number on a character-basis */
9726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            s=end;
9736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for (;;) {
9746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c=*--s;
9756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(('0'<=c && c<'9') || ('A'<=c && c<'F')) {
9766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *s=(char)(c+1);
9776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
9786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else if(c=='9') {
9796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *s='A';
9806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
9816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else if(c=='F') {
9826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *s='0';
9836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(!fn(context, start, nameChoice, buffer, length)) {
9876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return FALSE;
9886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
9916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case 1: {
9936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t indexes[8];
9946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *elementBases[8], *elements[8];
9956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const uint16_t *factors=(const uint16_t *)(range+1);
9966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t count=range->variant;
9976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *s=(const char *)(factors+count);
9986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char *suffix, *t;
9996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t prefixLength, i, idx;
10006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char c;
10026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* name = prefix factorized-elements */
10046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy prefix */
10066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        suffix=buffer;
10076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        prefixLength=0;
10086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while((c=*s++)!=0) {
10096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *suffix++=c;
10106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++prefixLength;
10116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* append the suffix of the start character */
10146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=(uint16_t)(prefixLength+writeFactorSuffix(factors, count,
10156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                              s, (uint32_t)start-range->start,
10166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                              indexes, elementBases, elements,
10176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                              suffix, (uint16_t)(sizeof(buffer)-prefixLength)));
10186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* call the enumerator function with this first character */
10206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(!fn(context, start, nameChoice, buffer, length)) {
10216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
10226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* enumerate the rest of the names */
10256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(++start<limit) {
10266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* increment the indexes in lexical order bound by the factors */
10276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            i=count;
10286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for (;;) {
10296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                idx=(uint16_t)(indexes[--i]+1);
10306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(idx<factors[i]) {
10316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* skip one index and its element string */
10326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    indexes[i]=idx;
10336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    s=elements[i];
10346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    while(*s++!=0) {
10356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
10366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    elements[i]=s;
10376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
10386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
10396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* reset this index to 0 and its element string to the first one */
10406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    indexes[i]=0;
10416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    elements[i]=elementBases[i];
10426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
10436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
10446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* to make matters a little easier, just append all elements to the suffix */
10466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            t=suffix;
10476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=prefixLength;
10486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for(i=0; i<count; ++i) {
10496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                s=elements[i];
10506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                while((c=*s++)!=0) {
10516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *t++=c;
10526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ++length;
10536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
10546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
10556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* zero-terminate */
10566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *t=0;
10576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(!fn(context, start, nameChoice, buffer, length)) {
10596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return FALSE;
10606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
10616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
10636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
10656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* undefined type */
10666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
10676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
10706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
10736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * findAlgName() is almost the same as enumAlgNames() except that it
10746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * returns the code point for a name if it fits into the range.
10756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * It returns 0xffff otherwise.
10766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
10776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UChar32
10786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfindAlgName(AlgorithmicRange *range, UCharNameChoice nameChoice, const char *otherName) {
10796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 code;
10806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
10826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0xffff;
10836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(range->type) {
10866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case 0: {
10876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* name = prefix hex-digits */
10886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *s=(const char *)(range+1);
10896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char c;
10906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t i, count;
10926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* compare prefix */
10946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while((c=*s++)!=0) {
10956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if((char)c!=*otherName++) {
10966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0xffff;
10976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
10986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* read hexadecimal code point value */
11016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        count=range->variant;
11026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        code=0;
11036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(i=0; i<count; ++i) {
11046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c=*otherName++;
11056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if('0'<=c && c<='9') {
11066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                code=(code<<4)|(c-'0');
11076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if('A'<=c && c<='F') {
11086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                code=(code<<4)|(c-'A'+10);
11096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
11106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0xffff;
11116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* does it fit into the range? */
11156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(*otherName==0 && range->start<=(uint32_t)code && (uint32_t)code<=range->end) {
11166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return code;
11176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
11196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case 1: {
11216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char buffer[64];
11226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t indexes[8];
11236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *elementBases[8], *elements[8];
11246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const uint16_t *factors=(const uint16_t *)(range+1);
11256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t count=range->variant;
11266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *s=(const char *)(factors+count), *t;
11276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar32 start, limit;
11286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t i, idx;
11296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char c;
11316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* name = prefix factorized-elements */
11336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* compare prefix */
11356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while((c=*s++)!=0) {
11366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if((char)c!=*otherName++) {
11376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0xffff;
11386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        start=(UChar32)range->start;
11426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit=(UChar32)(range->end+1);
11436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* initialize the suffix elements for enumeration; indexes should all be set to 0 */
11456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        writeFactorSuffix(factors, count, s, 0,
11466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                          indexes, elementBases, elements, buffer, sizeof(buffer));
11476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* compare the first suffix */
11496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(0==uprv_strcmp(otherName, buffer)) {
11506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return start;
11516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* enumerate and compare the rest of the suffixes */
11546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(++start<limit) {
11556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* increment the indexes in lexical order bound by the factors */
11566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            i=count;
11576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for (;;) {
11586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                idx=(uint16_t)(indexes[--i]+1);
11596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(idx<factors[i]) {
11606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* skip one index and its element string */
11616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    indexes[i]=idx;
11626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    s=elements[i];
11636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    while(*s++!=0) {}
11646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    elements[i]=s;
11656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
11666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
11676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* reset this index to 0 and its element string to the first one */
11686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    indexes[i]=0;
11696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    elements[i]=elementBases[i];
11706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
11716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* to make matters a little easier, just compare all elements of the suffix */
11746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            t=otherName;
11756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for(i=0; i<count; ++i) {
11766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                s=elements[i];
11776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                while((c=*s++)!=0) {
11786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(c!=*t++) {
11796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        s=""; /* does not match */
11806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        i=99;
11816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
11826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
11836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(i<99 && *t==0) {
11856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return start;
11866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
11896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
11916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* undefined type */
11926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
11936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return 0xffff;
11966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* sets of name characters, maximum name lengths ---------------------------- */
11996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define SET_ADD(set, c) ((set)[(uint8_t)c>>5]|=((uint32_t)1<<((uint8_t)c&0x1f)))
12016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define SET_CONTAINS(set, c) (((set)[(uint8_t)c>>5]&((uint32_t)1<<((uint8_t)c&0x1f)))!=0)
12026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
12046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgcalcStringSetLength(uint32_t set[8], const char *s) {
12056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length=0;
12066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char c;
12076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while((c=*s++)!=0) {
12096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        SET_ADD(set, c);
12106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++length;
12116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return length;
12136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
12166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgcalcAlgNameSetsLengths(int32_t maxNameLength) {
12176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    AlgorithmicRange *range;
12186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *p;
12196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t rangeCount;
12206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
12216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* enumerate algorithmic ranges */
12236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    p=(uint32_t *)((uint8_t *)uCharNames+uCharNames->algNamesOffset);
12246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    rangeCount=*p;
12256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    range=(AlgorithmicRange *)(p+1);
12266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(rangeCount>0) {
12276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        switch(range->type) {
12286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case 0:
12296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* name = prefix + (range->variant times) hex-digits */
12306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* prefix */
12316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=calcStringSetLength(gNameSet, (const char *)(range+1))+range->variant;
12326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length>maxNameLength) {
12336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                maxNameLength=length;
12346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
12356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
12366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case 1: {
12376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* name = prefix factorized-elements */
12386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const uint16_t *factors=(const uint16_t *)(range+1);
12396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const char *s;
12406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t i, count=range->variant, factor, factorLength, maxFactorLength;
12416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* prefix length */
12436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            s=(const char *)(factors+count);
12446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=calcStringSetLength(gNameSet, s);
12456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            s+=length+1; /* start of factor suffixes */
12466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* get the set and maximum factor suffix length for each factor */
12486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for(i=0; i<count; ++i) {
12496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                maxFactorLength=0;
12506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                for(factor=factors[i]; factor>0; --factor) {
12516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    factorLength=calcStringSetLength(gNameSet, s);
12526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    s+=factorLength+1;
12536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(factorLength>maxFactorLength) {
12546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        maxFactorLength=factorLength;
12556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
12566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
12576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                length+=maxFactorLength;
12586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
12596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length>maxNameLength) {
12616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                maxNameLength=length;
12626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
12636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
12646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
12656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        default:
12666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* unknown type */
12676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
12686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
12696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        range=(AlgorithmicRange *)((uint8_t *)range+range->size);
12716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        --rangeCount;
12726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return maxNameLength;
12746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
12776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgcalcExtNameSetsLengths(int32_t maxNameLength) {
12786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, length;
12796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(i=0; i<LENGTHOF(charCatNames); ++i) {
12816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
12826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * for each category, count the length of the category name
12836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * plus 9=
12846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 2 for <>
12856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 1 for -
12866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 6 for most hex digits per code point
12876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
12886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=9+calcStringSetLength(gNameSet, charCatNames[i]);
12896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>maxNameLength) {
12906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            maxNameLength=length;
12916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
12926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return maxNameLength;
12946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
12976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgcalcNameSetLength(const uint16_t *tokens, uint16_t tokenCount, const uint8_t *tokenStrings, int8_t *tokenLengths,
12986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  uint32_t set[8],
12996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  const uint8_t **pLine, const uint8_t *lineLimit) {
13006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint8_t *line=*pLine;
13016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length=0, tokenLength;
13026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t c, token;
13036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(line!=lineLimit && (c=*line++)!=(uint8_t)';') {
13056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c>=tokenCount) {
13066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* implicit letter */
13076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            SET_ADD(set, c);
13086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++length;
13096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
13106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            token=tokens[c];
13116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(token==(uint16_t)(-2)) {
13126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* this is a lead byte for a double-byte token */
13136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c=c<<8|*line++;
13146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                token=tokens[c];
13156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(token==(uint16_t)(-1)) {
13176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* explicit letter */
13186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                SET_ADD(set, c);
13196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ++length;
13206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
13216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* count token word */
13226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(tokenLengths!=NULL) {
13236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* use cached token length */
13246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    tokenLength=tokenLengths[c];
13256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(tokenLength==0) {
13266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        tokenLength=calcStringSetLength(set, (const char *)tokenStrings+token);
13276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        tokenLengths[c]=(int8_t)tokenLength;
13286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
13296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
13306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    tokenLength=calcStringSetLength(set, (const char *)tokenStrings+token);
13316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
13326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                length+=tokenLength;
13336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
13356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *pLine=line;
13386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return length;
13396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
13406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
13426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgcalcGroupNameSetsLengths(int32_t maxNameLength) {
13436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t offsets[LINES_PER_GROUP+2], lengths[LINES_PER_GROUP+2];
13446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t *tokens=(uint16_t *)uCharNames+8;
13466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t tokenCount=*tokens++;
13476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t *tokenStrings=(uint8_t *)uCharNames+uCharNames->tokenStringOffset;
13486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int8_t *tokenLengths;
13506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint16_t *group;
13526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint8_t *s, *line, *lineLimit;
13536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t groupCount, lineNumber, length;
13556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    tokenLengths=(int8_t *)uprv_malloc(tokenCount);
13576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(tokenLengths!=NULL) {
13586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memset(tokenLengths, 0, tokenCount);
13596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    group=GET_GROUPS(uCharNames);
13626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    groupCount=*group++;
13636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* enumerate all groups */
13656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(groupCount>0) {
13666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        s=(uint8_t *)uCharNames+uCharNames->groupStringOffset+GET_GROUP_OFFSET(group);
13676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        s=expandGroupLengths(s, offsets, lengths);
13686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* enumerate all lines in each group */
13706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(lineNumber=0; lineNumber<LINES_PER_GROUP; ++lineNumber) {
13716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            line=s+offsets[lineNumber];
13726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=lengths[lineNumber];
13736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length==0) {
13746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                continue;
13756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lineLimit=line+length;
13786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* read regular name */
13806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=calcNameSetLength(tokens, tokenCount, tokenStrings, tokenLengths, gNameSet, &line, lineLimit);
13816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length>maxNameLength) {
13826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                maxNameLength=length;
13836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(line==lineLimit) {
13856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                continue;
13866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* read Unicode 1.0 name */
13896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=calcNameSetLength(tokens, tokenCount, tokenStrings, tokenLengths, gNameSet, &line, lineLimit);
13906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length>maxNameLength) {
13916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                maxNameLength=length;
13926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(line==lineLimit) {
13946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                continue;
13956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* read ISO comment */
13986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*length=calcNameSetLength(tokens, tokenCount, tokenStrings, tokenLengths, gISOCommentSet, &line, lineLimit);*/
13996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        group=NEXT_GROUP(group);
14026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        --groupCount;
14036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(tokenLengths!=NULL) {
14066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(tokenLengths);
14076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set gMax... - name length last for threading */
14106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    gMaxNameLength=maxNameLength;
14116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
14126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
14146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgcalcNameSetsLengths(UErrorCode *pErrorCode) {
14156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    static const char extChars[]="0123456789ABCDEF<>-";
14166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, maxNameLength;
14176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(gMaxNameLength!=0) {
14196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
14206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!isDataLoaded(pErrorCode)) {
14236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
14246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set hex digits, used in various names, and <>-, used in extended names */
14276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(i=0; i<(int32_t)sizeof(extChars)-1; ++i) {
14286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        SET_ADD(gNameSet, extChars[i]);
14296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set sets and lengths from algorithmic names */
14326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    maxNameLength=calcAlgNameSetsLengths(0);
14336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set sets and lengths from extended names */
14356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    maxNameLength=calcExtNameSetsLengths(maxNameLength);
14366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set sets and lengths from group names, set global maximum values */
14386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    calcGroupNameSetsLengths(maxNameLength);
14396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
14416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
14426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* public API --------------------------------------------------------------- */
14446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
14466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_charName(UChar32 code, UCharNameChoice nameChoice,
14476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org           char *buffer, int32_t bufferLength,
14486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org           UErrorCode *pErrorCode) {
14496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    AlgorithmicRange *algRange;
14506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *p;
14516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t i;
14526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
14536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check the argument values */
14556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
14566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
14576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(nameChoice>=U_CHAR_NAME_CHOICE_COUNT ||
14586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              bufferLength<0 || (bufferLength>0 && buffer==NULL)
14596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
14606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
14616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
14626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((uint32_t)code>UCHAR_MAX_VALUE || !isDataLoaded(pErrorCode)) {
14656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return u_terminateChars(buffer, bufferLength, 0, pErrorCode);
14666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    length=0;
14696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* try algorithmic names first */
14716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    p=(uint32_t *)((uint8_t *)uCharNames+uCharNames->algNamesOffset);
14726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    i=*p;
14736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    algRange=(AlgorithmicRange *)(p+1);
14746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(i>0) {
14756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(algRange->start<=(uint32_t)code && (uint32_t)code<=algRange->end) {
14766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=getAlgName(algRange, (uint32_t)code, nameChoice, buffer, (uint16_t)bufferLength);
14776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
14786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        algRange=(AlgorithmicRange *)((uint8_t *)algRange+algRange->size);
14806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        --i;
14816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(i==0) {
14846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (nameChoice == U_EXTENDED_CHAR_NAME) {
14856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length = getName(uCharNames, (uint32_t )code, U_EXTENDED_CHAR_NAME, buffer, (uint16_t) bufferLength);
14866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (!length) {
14876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* extended character name */
14886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                length = getExtName((uint32_t) code, buffer, (uint16_t) bufferLength);
14896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
14906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
14916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* normal character name */
14926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=getName(uCharNames, (uint32_t)code, nameChoice, buffer, (uint16_t)bufferLength);
14936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_terminateChars(buffer, bufferLength, length, pErrorCode);
14976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
14986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
15006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_getISOComment(UChar32 /*c*/,
15016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                char *dest, int32_t destCapacity,
15026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UErrorCode *pErrorCode) {
15036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check the argument values */
15046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
15056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
15066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(destCapacity<0 || (destCapacity>0 && dest==NULL)) {
15076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
15086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
15096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_terminateChars(dest, destCapacity, 0, pErrorCode);
15126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
15136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UChar32 U_EXPORT2
15156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_charFromName(UCharNameChoice nameChoice,
15166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               const char *name,
15176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UErrorCode *pErrorCode) {
15186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char upper[120], lower[120];
15196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    FindName findName;
15206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    AlgorithmicRange *algRange;
15216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *p;
15226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t i;
15236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 cp = 0;
15246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char c0;
15256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 error = 0xffff;     /* Undefined, but use this for backwards compatibility. */
15266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
15286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return error;
15296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nameChoice>=U_CHAR_NAME_CHOICE_COUNT || name==NULL || *name==0) {
15326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
15336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return error;
15346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!isDataLoaded(pErrorCode)) {
15376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return error;
15386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* construct the uppercase and lowercase of the name first */
15416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(i=0; i<sizeof(upper); ++i) {
15426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((c0=*name++)!=0) {
15436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            upper[i]=uprv_toupper(c0);
15446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lower[i]=uprv_tolower(c0);
15456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
15466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            upper[i]=lower[i]=0;
15476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
15486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
15496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(i==sizeof(upper)) {
15516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* name too long, there is no such character */
15526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode = U_ILLEGAL_CHAR_FOUND;
15536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return error;
15546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* try extended names first */
15576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (lower[0] == '<') {
15586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (nameChoice == U_EXTENDED_CHAR_NAME) {
15596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (lower[--i] == '>') {
15606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                for (--i; lower[i] && lower[i] != '-'; --i) {
15616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
15626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (lower[i] == '-') { /* We've got a category. */
15646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    uint32_t cIdx;
15656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    lower[i] = 0;
15676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    for (++i; lower[i] != '>'; ++i) {
15696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (lower[i] >= '0' && lower[i] <= '9') {
15706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            cp = (cp << 4) + lower[i] - '0';
15716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        } else if (lower[i] >= 'a' && lower[i] <= 'f') {
15726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            cp = (cp << 4) + lower[i] - 'a' + 10;
15736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        } else {
15746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            *pErrorCode = U_ILLEGAL_CHAR_FOUND;
15756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            return error;
15766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
15776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
15786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* Now validate the category name.
15806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       We could use a binary search, or a trie, if
15816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       we really wanted to. */
15826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    for (lower[i] = 0, cIdx = 0; cIdx < LENGTHOF(charCatNames); ++cIdx) {
15846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (!uprv_strcmp(lower + 1, charCatNames[cIdx])) {
15866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            if (getCharCat(cp) == cIdx) {
15876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                return cp;
15886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            }
15896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            break;
15906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
15916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
15926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
15936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
15946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
15956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode = U_ILLEGAL_CHAR_FOUND;
15976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return error;
15986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* try algorithmic names now */
16016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    p=(uint32_t *)((uint8_t *)uCharNames+uCharNames->algNamesOffset);
16026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    i=*p;
16036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    algRange=(AlgorithmicRange *)(p+1);
16046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(i>0) {
16056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((cp=findAlgName(algRange, nameChoice, upper))!=0xffff) {
16066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return cp;
16076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
16086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        algRange=(AlgorithmicRange *)((uint8_t *)algRange+algRange->size);
16096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        --i;
16106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* normal character name */
16136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    findName.otherName=upper;
16146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    findName.code=error;
16156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    enumNames(uCharNames, 0, UCHAR_MAX_VALUE + 1, DO_FIND_NAME, &findName, nameChoice);
16166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (findName.code == error) {
16176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *pErrorCode = U_ILLEGAL_CHAR_FOUND;
16186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return findName.code;
16206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
16216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
16236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_enumCharNames(UChar32 start, UChar32 limit,
16246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UEnumCharNamesFn *fn,
16256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                void *context,
16266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UCharNameChoice nameChoice,
16276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UErrorCode *pErrorCode) {
16286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    AlgorithmicRange *algRange;
16296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *p;
16306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t i;
16316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
16336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
16346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nameChoice>=U_CHAR_NAME_CHOICE_COUNT || fn==NULL) {
16376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
16386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
16396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((uint32_t) limit > UCHAR_MAX_VALUE + 1) {
16426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit = UCHAR_MAX_VALUE + 1;
16436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((uint32_t)start>=(uint32_t)limit) {
16456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
16466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!isDataLoaded(pErrorCode)) {
16496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
16506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* interleave the data-driven ones with the algorithmic ones */
16536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* iterate over all algorithmic ranges; assume that they are in ascending order */
16546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    p=(uint32_t *)((uint8_t *)uCharNames+uCharNames->algNamesOffset);
16556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    i=*p;
16566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    algRange=(AlgorithmicRange *)(p+1);
16576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(i>0) {
16586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* enumerate the character names before the current algorithmic range */
16596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* here: start<limit */
16606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((uint32_t)start<algRange->start) {
16616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if((uint32_t)limit<=algRange->start) {
16626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                enumNames(uCharNames, start, limit, fn, context, nameChoice);
16636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
16646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
16656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(!enumNames(uCharNames, start, (UChar32)algRange->start, fn, context, nameChoice)) {
16666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
16676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
16686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start=(UChar32)algRange->start;
16696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
16706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* enumerate the character names in the current algorithmic range */
16716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* here: algRange->start<=start<limit */
16726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((uint32_t)start<=algRange->end) {
16736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if((uint32_t)limit<=(algRange->end+1)) {
16746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                enumAlgNames(algRange, start, limit, fn, context, nameChoice);
16756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
16766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
16776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(!enumAlgNames(algRange, start, (UChar32)algRange->end+1, fn, context, nameChoice)) {
16786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
16796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
16806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start=(UChar32)algRange->end+1;
16816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
16826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* continue to the next algorithmic range (here: start<limit) */
16836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        algRange=(AlgorithmicRange *)((uint8_t *)algRange+algRange->size);
16846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        --i;
16856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* enumerate the character names after the last algorithmic range */
16876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    enumNames(uCharNames, start, limit, fn, context, nameChoice);
16886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
16896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
16916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orguprv_getMaxCharNameLength() {
16926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode errorCode=U_ZERO_ERROR;
16936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(calcNameSetsLengths(&errorCode)) {
16946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return gMaxNameLength;
16956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
16966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
16976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
16996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
17016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Converts the char set cset into a Unicode set uset.
17026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param cset Set of 256 bit flags corresponding to a set of chars.
17036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param uset USet to receive characters. Existing contents are deleted.
17046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
17056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
17066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgcharSetToUSet(uint32_t cset[8], const USetAdder *sa) {
17076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar us[256];
17086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char cs[256];
17096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, length;
17116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode errorCode;
17126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    errorCode=U_ZERO_ERROR;
17146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!calcNameSetsLengths(&errorCode)) {
17166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
17176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
17186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* build a char string with all chars that are used in character names */
17206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    length=0;
17216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(i=0; i<256; ++i) {
17226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(SET_CONTAINS(cset, i)) {
17236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cs[length++]=(char)i;
17246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
17256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
17266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* convert the char string to a UChar string */
17286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    u_charsToUChars(cs, us, length);
17296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* add each UChar to the USet */
17316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(i=0; i<length; ++i) {
17326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(us[i]!=0 || cs[i]==0) { /* non-invariant chars become (UChar)0 */
17336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sa->add(sa->set, us[i]);
17346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
17356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
17366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
17376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
17396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Fills set with characters that are used in Unicode character names.
17406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param set USet to receive characters.
17416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
17426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
17436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orguprv_getCharNameCharacters(const USetAdder *sa) {
17446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    charSetToUSet(gNameSet, sa);
17456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
17466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* data swapping ------------------------------------------------------------ */
17486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
17506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * The token table contains non-negative entries for token bytes,
17516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * and -1 for bytes that represent themselves in the data file's charset.
17526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * -2 entries are used for lead bytes.
17536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
17546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Direct bytes (-1 entries) must be translated from the input charset family
17556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * to the output charset family.
17566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * makeTokenMap() writes a permutation mapping for this.
17576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Use it once for single-/lead-byte tokens and once more for all trail byte
17586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * tokens. (';' is an unused trail byte marked with -1.)
17596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
17606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
17616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgmakeTokenMap(const UDataSwapper *ds,
17626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             int16_t tokens[], uint16_t tokenCount,
17636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             uint8_t map[256],
17646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UErrorCode *pErrorCode) {
17656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool usedOutChar[256];
17666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint16_t i, j;
17676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t c1, c2;
17686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
17706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
17716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
17726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(ds->inCharset==ds->outCharset) {
17746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* Same charset family: identity permutation */
17756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(i=0; i<256; ++i) {
17766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            map[i]=(uint8_t)i;
17776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
17786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
17796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memset(map, 0, 256);
17806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memset(usedOutChar, 0, 256);
17816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(tokenCount>256) {
17836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tokenCount=256;
17846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
17856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* set the direct bytes (byte 0 always maps to itself) */
17876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(i=1; i<tokenCount; ++i) {
17886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(tokens[i]==-1) {
17896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* convert the direct byte character */
17906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c1=(uint8_t)i;
17916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ds->swapInvChars(ds, &c1, 1, &c2, pErrorCode);
17926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(U_FAILURE(*pErrorCode)) {
17936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    udata_printError(ds, "unames/makeTokenMap() finds variant character 0x%02x used (input charset family %d)\n",
17946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     i, ds->inCharset);
17956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return;
17966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
17976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* enter the converted character into the map and mark it used */
17996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                map[c1]=c2;
18006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                usedOutChar[c2]=TRUE;
18016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
18026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
18036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* set the mappings for the rest of the permutation */
18056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(i=j=1; i<tokenCount; ++i) {
18066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* set mappings that were not set for direct bytes */
18076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(map[i]==0) {
18086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* set an output byte value that was not used as an output byte above */
18096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                while(usedOutChar[j]) {
18106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ++j;
18116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
18126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                map[i]=(uint8_t)j++;
18136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
18146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
18156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
18176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * leave mappings at tokenCount and above unset if tokenCount<256
18186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * because they won't be used
18196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
18206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
18226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
18246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orguchar_swapNames(const UDataSwapper *ds,
18256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                const void *inData, int32_t length, void *outData,
18266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UErrorCode *pErrorCode) {
18276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UDataInfo *pInfo;
18286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t headerSize;
18296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint8_t *inBytes;
18316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t *outBytes;
18326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t tokenStringOffset, groupsOffset, groupStringOffset, algNamesOffset,
18346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             offset, i, count, stringsCount;
18356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const AlgorithmicRange *inRange;
18376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    AlgorithmicRange *outRange;
18386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* udata_swapDataHeader checks the arguments */
18406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
18416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
18426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
18436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check data format and format version */
18466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pInfo=(const UDataInfo *)((const char *)inData+4);
18476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!(
18486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[0]==0x75 &&   /* dataFormat="unam" */
18496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[1]==0x6e &&
18506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[2]==0x61 &&
18516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[3]==0x6d &&
18526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->formatVersion[0]==1
18536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    )) {
18546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udata_printError(ds, "uchar_swapNames(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as unames.icu\n",
18556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         pInfo->dataFormat[0], pInfo->dataFormat[1],
18566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         pInfo->dataFormat[2], pInfo->dataFormat[3],
18576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         pInfo->formatVersion[0]);
18586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_UNSUPPORTED_ERROR;
18596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
18606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    inBytes=(const uint8_t *)inData+headerSize;
18636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    outBytes=(uint8_t *)outData+headerSize;
18646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length<0) {
18656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        algNamesOffset=ds->readUInt32(((const uint32_t *)inBytes)[3]);
18666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
18676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length-=headerSize;
18686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( length<20 ||
18696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            (uint32_t)length<(algNamesOffset=ds->readUInt32(((const uint32_t *)inBytes)[3]))
18706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
18716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            udata_printError(ds, "uchar_swapNames(): too few bytes (%d after header) for unames.icu\n",
18726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             length);
18736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
18746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
18756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
18766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length<0) {
18796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* preflighting: iterate through algorithmic ranges */
18806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        offset=algNamesOffset;
18816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        count=ds->readUInt32(*((const uint32_t *)(inBytes+offset)));
18826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        offset+=4;
18836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(i=0; i<count; ++i) {
18856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            inRange=(const AlgorithmicRange *)(inBytes+offset);
18866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            offset+=ds->readUInt16(inRange->size);
18876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
18886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
18896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap data */
18906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const uint16_t *p;
18916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t *q, *temp;
18926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int16_t tokens[512];
18946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint16_t tokenCount;
18956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint8_t map[256], trailMap[256];
18976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy the data for inaccessible bytes */
18996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(inBytes!=outBytes) {
19006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memcpy(outBytes, inBytes, length);
19016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* the initial 4 offsets first */
19046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        tokenStringOffset=ds->readUInt32(((const uint32_t *)inBytes)[0]);
19056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        groupsOffset=ds->readUInt32(((const uint32_t *)inBytes)[1]);
19066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        groupStringOffset=ds->readUInt32(((const uint32_t *)inBytes)[2]);
19076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ds->swapArray32(ds, inBytes, 16, outBytes, pErrorCode);
19086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
19106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * now the tokens table
19116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * it needs to be permutated along with the compressed name strings
19126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
19136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=(const uint16_t *)(inBytes+16);
19146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        q=(uint16_t *)(outBytes+16);
19156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* read and swap the tokenCount */
19176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        tokenCount=ds->readUInt16(*p);
19186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ds->swapArray16(ds, p, 2, q, pErrorCode);
19196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++p;
19206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++q;
19216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* read the first 512 tokens and make the token maps */
19236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(tokenCount<=512) {
19246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            count=tokenCount;
19256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
19266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            count=512;
19276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(i=0; i<count; ++i) {
19296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tokens[i]=udata_readInt16(ds, p[i]);
19306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(; i<512; ++i) {
19326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tokens[i]=0; /* fill the rest of the tokens array if tokenCount<512 */
19336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        makeTokenMap(ds, tokens, tokenCount, map, pErrorCode);
19356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        makeTokenMap(ds, tokens+256, (uint16_t)(tokenCount>256 ? tokenCount-256 : 0), trailMap, pErrorCode);
19366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(*pErrorCode)) {
19376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
19386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
19416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * swap and permutate the tokens
19426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * go through a temporary array to support in-place swapping
19436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
19446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        temp=(uint16_t *)uprv_malloc(tokenCount*2);
19456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(temp==NULL) {
19466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            udata_printError(ds, "out of memory swapping %u unames.icu tokens\n",
19476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             tokenCount);
19486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
19496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
19506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap and permutate single-/lead-byte tokens */
19536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(i=0; i<tokenCount && i<256; ++i) {
19546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ds->swapArray16(ds, p+i, 2, temp+map[i], pErrorCode);
19556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap and permutate trail-byte tokens */
19586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(; i<tokenCount; ++i) {
19596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ds->swapArray16(ds, p+i, 2, temp+(i&0xffffff00)+trailMap[i&0xff], pErrorCode);
19606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy the result into the output and free the temporary array */
19636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memcpy(q, temp, tokenCount*2);
19646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(temp);
19656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
19676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * swap the token strings but not a possible padding byte after
19686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * the terminating NUL of the last string
19696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
19706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udata_swapInvStringBlock(ds, inBytes+tokenStringOffset, (int32_t)(groupsOffset-tokenStringOffset),
19716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                    outBytes+tokenStringOffset, pErrorCode);
19726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(*pErrorCode)) {
19736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            udata_printError(ds, "uchar_swapNames(token strings) failed\n");
19746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
19756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap the group table */
19786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        count=ds->readUInt16(*((const uint16_t *)(inBytes+groupsOffset)));
19796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ds->swapArray16(ds, inBytes+groupsOffset, (int32_t)((1+count*3)*2),
19806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           outBytes+groupsOffset, pErrorCode);
19816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
19836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * swap the group strings
19846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * swap the string bytes but not the nibble-encoded string lengths
19856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
19866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(ds->inCharset!=ds->outCharset) {
19876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uint16_t offsets[LINES_PER_GROUP+1], lengths[LINES_PER_GROUP+1];
19886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const uint8_t *inStrings, *nextInStrings;
19906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uint8_t *outStrings;
19916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uint8_t c;
19936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            inStrings=inBytes+groupStringOffset;
19956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            outStrings=outBytes+groupStringOffset;
19966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stringsCount=algNamesOffset-groupStringOffset;
19986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* iterate through string groups until only a few padding bytes are left */
20006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while(stringsCount>32) {
20016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                nextInStrings=expandGroupLengths(inStrings, offsets, lengths);
20026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* move past the length bytes */
20046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                stringsCount-=(uint32_t)(nextInStrings-inStrings);
20056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                outStrings+=nextInStrings-inStrings;
20066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                inStrings=nextInStrings;
20076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                count=offsets[31]+lengths[31]; /* total number of string bytes in this group */
20096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                stringsCount-=count;
20106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* swap the string bytes using map[] and trailMap[] */
20126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                while(count>0) {
20136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    c=*inStrings++;
20146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *outStrings++=map[c];
20156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(tokens[c]!=-2) {
20166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        --count;
20176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    } else {
20186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /* token lead byte: swap the trail byte, too */
20196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        *outStrings++=trailMap[*inStrings++];
20206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        count-=2;
20216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
20226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
20236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
20246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
20256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap the algorithmic ranges */
20276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        offset=algNamesOffset;
20286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        count=ds->readUInt32(*((const uint32_t *)(inBytes+offset)));
20296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ds->swapArray32(ds, inBytes+offset, 4, outBytes+offset, pErrorCode);
20306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        offset+=4;
20316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(i=0; i<count; ++i) {
20336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(offset>(uint32_t)length) {
20346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                udata_printError(ds, "uchar_swapNames(): too few bytes (%d after header) for unames.icu algorithmic range %u\n",
20356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 length, i);
20366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
20376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
20386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
20396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            inRange=(const AlgorithmicRange *)(inBytes+offset);
20416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            outRange=(AlgorithmicRange *)(outBytes+offset);
20426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            offset+=ds->readUInt16(inRange->size);
20436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ds->swapArray32(ds, inRange, 8, outRange, pErrorCode);
20456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ds->swapArray16(ds, &inRange->size, 2, &outRange->size, pErrorCode);
20466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            switch(inRange->type) {
20476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case 0:
20486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* swap prefix string */
20496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ds->swapInvChars(ds, inRange+1, (int32_t)uprv_strlen((const char *)(inRange+1)),
20506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                    outRange+1, pErrorCode);
20516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(U_FAILURE(*pErrorCode)) {
20526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    udata_printError(ds, "uchar_swapNames(prefix string of algorithmic range %u) failed\n",
20536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     i);
20546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return 0;
20556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
20566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
20576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            case 1:
20586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                {
20596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* swap factors and the prefix and factor strings */
20606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    uint32_t factorsCount;
20616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    factorsCount=inRange->variant;
20636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    p=(const uint16_t *)(inRange+1);
20646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    q=(uint16_t *)(outRange+1);
20656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ds->swapArray16(ds, p, (int32_t)(factorsCount*2), q, pErrorCode);
20666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* swap the strings, up to the last terminating NUL */
20686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    p+=factorsCount;
20696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    q+=factorsCount;
20706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    stringsCount=(uint32_t)((inBytes+offset)-(const uint8_t *)p);
20716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    while(stringsCount>0 && ((const uint8_t *)p)[stringsCount-1]!=0) {
20726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        --stringsCount;
20736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
20746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ds->swapInvChars(ds, p, (int32_t)stringsCount, q, pErrorCode);
20756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
20766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
20776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            default:
20786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                udata_printError(ds, "uchar_swapNames(): unknown type %u of algorithmic range %u\n",
20796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 inRange->type, i);
20806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_UNSUPPORTED_ERROR;
20816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
20826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
20836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
20846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
20856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return headerSize+(int32_t)offset;
20876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
20886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END
20906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
20926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Hey, Emacs, please set the following:
20936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
20946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Local Variables:
20956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * indent-tabs-mode: nil
20966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * End:
20976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
20986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
2099