1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
459d709d503bab6e2b61931737e662dd293b40578ccornelius*   Copyright (C) 1999-2013, International Business Machines
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   file name:  unames.c
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   encoding:   US-ASCII
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   tab size:   8 (not used)
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   indentation:4
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   created on: 1999oct04
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   created by: Markus W. Scherer
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uchar.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/udata.h"
2183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#include "unicode/utf.h"
2283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#include "unicode/utf16.h"
2359d709d503bab6e2b61931737e662dd293b40578ccornelius#include "uassert.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr_imp.h"
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_cmn.h"
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "udataswp.h"
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uprops.h"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3259d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_BEGIN
3359d709d503bab6e2b61931737e662dd293b40578ccornelius
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* prototypes ------------------------------------------------------------- */
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DATA_NAME[] = "unames";
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DATA_TYPE[] = "icu";
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GROUP_SHIFT 5
4283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#define LINES_PER_GROUP (1L<<GROUP_SHIFT)
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define GROUP_MASK (LINES_PER_GROUP-1)
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
45b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/*
46b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * This struct was replaced by explicitly accessing equivalent
47b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * fields from triples of uint16_t.
48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * The Group struct was padded to 8 bytes on compilers for early ARM CPUs,
49b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * which broke the assumption that sizeof(Group)==6 and that the ++ operator
50b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * would advance by 6 bytes (3 uint16_t).
51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *
52b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * We can't just change the data structure because it's loaded from a data file,
53b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * and we don't want to make it less compact, so we changed the access code.
54b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *
55b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * For details see ICU tickets 6331 and 6008.
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct {
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t groupMSB,
5850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho             offsetHigh, offsetLow; / * avoid padding * /
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} Group;
60b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */
61b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruenum {
62b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    GROUP_MSB,
63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    GROUP_OFFSET_HIGH,
64b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    GROUP_OFFSET_LOW,
65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    GROUP_LENGTH
66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru};
67b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
68b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/*
69b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Get the 32-bit group offset.
70b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @param group (const uint16_t *) pointer to a Group triple of uint16_t
71b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @return group offset (int32_t)
72b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */
73b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define GET_GROUP_OFFSET(group) ((int32_t)(group)[GROUP_OFFSET_HIGH]<<16|(group)[GROUP_OFFSET_LOW])
74b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
75b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define NEXT_GROUP(group) ((group)+GROUP_LENGTH)
76b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define PREV_GROUP(group) ((group)-GROUP_LENGTH)
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct {
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t start, end;
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t type, variant;
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t size;
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} AlgorithmicRange;
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct {
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t tokenStringOffset, groupsOffset, groupStringOffset, algNamesOffset;
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} UCharNames;
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
88b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/*
89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Get the groups table from a UCharNames struct.
90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * The groups table consists of one uint16_t groupCount followed by
91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * groupCount groups. Each group is a triple of uint16_t, see GROUP_LENGTH
92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * and the comment for the old struct Group above.
93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *
94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @param names (const UCharNames *) pointer to the UCharNames indexes
95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @return (const uint16_t *) pointer to the groups table
96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */
97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define GET_GROUPS(names) (const uint16_t *)((const char *)names+names->groupsOffset)
98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct {
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *otherName;
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar32 code;
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} FindName;
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define DO_FIND_NAME NULL
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UDataMemory *uCharNamesData=NULL;
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UCharNames *uCharNames=NULL;
10859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCharNamesInitOnce = U_INITONCE_INITIALIZER;
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Maximum length of character names (regular & 1.0).
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t gMaxNameLength=0;
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Set of chars used in character names (regular & 1.0).
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Chars are platform-dependent (can be EBCDIC).
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint32_t gNameSet[8]={ 0 };
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_NONCHARACTER_CODE_POINT U_CHAR_CATEGORY_COUNT
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_LEAD_SURROGATE U_CHAR_CATEGORY_COUNT + 1
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_TRAIL_SURROGATE U_CHAR_CATEGORY_COUNT + 2
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_CHAR_EXTENDED_CATEGORY_COUNT (U_CHAR_CATEGORY_COUNT + 3)
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char * const charCatNames[U_CHAR_EXTENDED_CATEGORY_COUNT] = {
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "unassigned",
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "uppercase letter",
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "lowercase letter",
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "titlecase letter",
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "modifier letter",
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "other letter",
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "non spacing mark",
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "enclosing mark",
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "combining spacing mark",
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "decimal digit number",
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "letter number",
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "other number",
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "space separator",
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "line separator",
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "paragraph separator",
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "control",
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "format",
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "private use area",
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "surrogate",
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "dash punctuation",
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "start punctuation",
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "end punctuation",
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "connector punctuation",
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "other punctuation",
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "math symbol",
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "currency symbol",
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "modifier symbol",
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "other symbol",
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "initial punctuation",
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "final punctuation",
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "noncharacter",
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "lead surrogate",
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "trail surrogate"
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* implementation ----------------------------------------------------------- */
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV unames_cleanup(void)
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(uCharNamesData) {
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        udata_close(uCharNamesData);
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uCharNamesData = NULL;
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(uCharNames) {
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uCharNames = NULL;
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
17459d709d503bab6e2b61931737e662dd293b40578ccornelius    gCharNamesInitOnce.reset();
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    gMaxNameLength=0;
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV
18083a171d1a62abf406f7f44ae671823d5ec20db7dCraig CorneliusisAcceptable(void * /*context*/,
18183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius             const char * /*type*/, const char * /*name*/,
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const UDataInfo *pInfo) {
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->size>=20 &&
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->charsetFamily==U_CHARSET_FAMILY &&
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[0]==0x75 &&   /* dataFormat="unam" */
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[1]==0x6e &&
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[2]==0x61 &&
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[3]==0x6d &&
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->formatVersion[0]==1);
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
19459d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV
19559d709d503bab6e2b61931737e662dd293b40578ccorneliusloadCharNames(UErrorCode &status) {
19659d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(uCharNamesData == NULL);
19759d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(uCharNames == NULL);
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
19959d709d503bab6e2b61931737e662dd293b40578ccornelius    uCharNamesData = udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, &status);
20059d709d503bab6e2b61931737e662dd293b40578ccornelius    if(U_FAILURE(status)) {
20159d709d503bab6e2b61931737e662dd293b40578ccornelius        uCharNamesData = NULL;
20259d709d503bab6e2b61931737e662dd293b40578ccornelius    } else {
20359d709d503bab6e2b61931737e662dd293b40578ccornelius        uCharNames = (UCharNames *)udata_getMemory(uCharNamesData);
20459d709d503bab6e2b61931737e662dd293b40578ccornelius    }
20559d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_common_registerCleanup(UCLN_COMMON_UNAMES, unames_cleanup);
20659d709d503bab6e2b61931737e662dd293b40578ccornelius}
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
20959d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic UBool
21059d709d503bab6e2b61931737e662dd293b40578ccorneliusisDataLoaded(UErrorCode *pErrorCode) {
21159d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gCharNamesInitOnce, &loadCharNames, *pErrorCode);
21259d709d503bab6e2b61931737e662dd293b40578ccornelius    return U_SUCCESS(*pErrorCode);
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define WRITE_CHAR(buffer, bufferLength, bufferPos, c) { \
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((bufferLength)>0) { \
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *(buffer)++=c; \
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --(bufferLength); \
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } \
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ++(bufferPos); \
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_ISO_COMMENT U_CHAR_NAME_CHOICE_COUNT
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Important: expandName() and compareName() are almost the same -
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * apply fixes to both.
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * UnicodeData.txt uses ';' as a field separator, so no
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * field can contain ';' as part of its contents.
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * In unames.dat, it is marked as token[';']==-1 only if the
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * semicolon is used in the data file - which is iff we
23350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * have Unicode 1.0 names or ISO comments or aliases.
23450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * So, it will be token[';']==-1 if we store U1.0 names/ISO comments/aliases
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * although we know that it will never be part of a name.
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint16_t
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruexpandName(UCharNames *names,
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           const uint8_t *name, uint16_t nameLength, UCharNameChoice nameChoice,
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           char *buffer, uint16_t bufferLength) {
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t *tokens=(uint16_t *)names+8;
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t token, tokenCount=*tokens++, bufferPos=0;
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t *tokenStrings=(uint8_t *)names+names->tokenStringOffset;
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t c;
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
24650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * skip the modern name if it is not requested _and_
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * if the semicolon byte value is a character, not a token number
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) {
25250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            int fieldIndex= nameChoice==U_ISO_COMMENT ? 2 : nameChoice;
25350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            do {
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while(nameLength>0) {
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    --nameLength;
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(*name++==';') {
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
26050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            } while(--fieldIndex>0);
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * the semicolon byte value is a token number, therefore
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * only modern names are stored in unames.dat and there is no
26550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho             * such requested alternate name here
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            nameLength=0;
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* write each letter directly, and write a token word per token */
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(nameLength>0) {
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --nameLength;
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        c=*name++;
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(c>=tokenCount) {
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(c!=';') {
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* implicit letter */
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                WRITE_CHAR(buffer, bufferLength, bufferPos, c);
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* finished */
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            token=tokens[c];
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(token==(uint16_t)(-2)) {
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* this is a lead byte for a double-byte token */
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                token=tokens[c<<8|*name++];
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                --nameLength;
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(token==(uint16_t)(-1)) {
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(c!=';') {
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* explicit letter */
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    WRITE_CHAR(buffer, bufferLength, bufferPos, c);
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* stop, but skip the semicolon if we are seeking
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       extended names and there was no 2.0 name but there
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       is a 1.0 name. */
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(!bufferPos && nameChoice == U_EXTENDED_CHAR_NAME) {
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if ((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) {
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            continue;
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* finished */
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* write token word */
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uint8_t *tokenString=tokenStrings+token;
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while((c=*tokenString++)!=0) {
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    WRITE_CHAR(buffer, bufferLength, bufferPos, c);
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* zero-terminate */
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(bufferLength>0) {
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *buffer=0;
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return bufferPos;
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * compareName() is almost the same as expandName() except that it compares
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the currently expanded name to an input name.
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * It returns the match/no match result as soon as possible.
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucompareName(UCharNames *names,
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const uint8_t *name, uint16_t nameLength, UCharNameChoice nameChoice,
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const char *otherName) {
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t *tokens=(uint16_t *)names+8;
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t token, tokenCount=*tokens++;
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t *tokenStrings=(uint8_t *)names+names->tokenStringOffset;
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t c;
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *origOtherName = otherName;
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * skip the modern name if it is not requested _and_
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * if the semicolon byte value is a character, not a token number
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) {
34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            int fieldIndex= nameChoice==U_ISO_COMMENT ? 2 : nameChoice;
34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            do {
34850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                while(nameLength>0) {
34950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    --nameLength;
35050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    if(*name++==';') {
35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        break;
35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    }
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            } while(--fieldIndex>0);
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * the semicolon byte value is a token number, therefore
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * only modern names are stored in unames.dat and there is no
35950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho             * such requested alternate name here
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            nameLength=0;
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* compare each letter directly, and compare a token word per token */
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(nameLength>0) {
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --nameLength;
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        c=*name++;
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(c>=tokenCount) {
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(c!=';') {
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* implicit letter */
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if((char)c!=*otherName++) {
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return FALSE;
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* finished */
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            token=tokens[c];
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(token==(uint16_t)(-2)) {
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* this is a lead byte for a double-byte token */
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                token=tokens[c<<8|*name++];
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                --nameLength;
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(token==(uint16_t)(-1)) {
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(c!=';') {
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* explicit letter */
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if((char)c!=*otherName++) {
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        return FALSE;
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* stop, but skip the semicolon if we are seeking
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       extended names and there was no 2.0 name but there
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       is a 1.0 name. */
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(otherName == origOtherName && nameChoice == U_EXTENDED_CHAR_NAME) {
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if ((uint8_t)';'>=tokenCount || tokens[(uint8_t)';']==(uint16_t)(-1)) {
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            continue;
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* finished */
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* write token word */
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uint8_t *tokenString=tokenStrings+token;
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while((c=*tokenString++)!=0) {
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if((char)c!=*otherName++) {
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        return FALSE;
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* complete match? */
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(*otherName==0);
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint8_t getCharCat(UChar32 cp) {
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t cat;
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
42483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius    if (U_IS_UNICODE_NONCHAR(cp)) {
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_NONCHARACTER_CODE_POINT;
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((cat = u_charType(cp)) == U_SURROGATE) {
42983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        cat = U_IS_LEAD(cp) ? U_LEAD_SURROGATE : U_TRAIL_SURROGATE;
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return cat;
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char *getCharCatName(UChar32 cp) {
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t cat = getCharCat(cp);
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Return unknown if the table of names above is not up to
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       date. */
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (cat >= LENGTHOF(charCatNames)) {
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return "unknown";
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return charCatNames[cat];
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint16_t getExtName(uint32_t code, char *buffer, uint16_t bufferLength) {
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *catname = getCharCatName(code);
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t length = 0;
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar32 cp;
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int ndigits, i;
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    WRITE_CHAR(buffer, bufferLength, length, '<');
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (catname[length - 1]) {
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        WRITE_CHAR(buffer, bufferLength, length, catname[length - 1]);
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    WRITE_CHAR(buffer, bufferLength, length, '-');
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (cp = code, ndigits = 0; cp; ++ndigits, cp >>= 4)
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ;
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (ndigits < 4)
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ndigits = 4;
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (cp = code, i = ndigits; (cp || i > 0) && bufferLength; cp >>= 4, bufferLength--) {
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint8_t v = (uint8_t)(cp & 0xf);
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        buffer[--i] = (v < 10 ? '0' + v : 'A' + v - 10);
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    buffer += ndigits;
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    length += ndigits;
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    WRITE_CHAR(buffer, bufferLength, length, '>');
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return length;
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * getGroup() does a binary search for the group that contains the
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Unicode code point "code".
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The return value is always a valid Group* that may contain "code"
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * or else is the highest group before "code".
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * If the lowest group is after "code", then that one is returned.
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const uint16_t *
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerugetGroup(UCharNames *names, uint32_t code) {
484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint16_t *groups=GET_GROUPS(names);
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t groupMSB=(uint16_t)(code>>GROUP_SHIFT),
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             start=0,
487b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             limit=*groups++,
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             number;
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* binary search for the group of names that contains the one for code */
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(start<limit-1) {
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        number=(uint16_t)((start+limit)/2);
493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(groupMSB<groups[number*GROUP_LENGTH+GROUP_MSB]) {
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            limit=number;
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            start=number;
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* return this regardless of whether it is an exact match */
501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return groups+start*GROUP_LENGTH;
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * expandGroupLengths() reads a block of compressed lengths of 32 strings and
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * expands them into offsets and lengths for each string.
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Lengths are stored with a variable-width encoding in consecutive nibbles:
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * If a nibble<0xc, then it is the length itself (0=empty string).
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * If a nibble>=0xc, then it forms a length value with the following nibble.
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Calculation see below.
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The offsets and lengths arrays must be at least 33 (one more) long because
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * there is no check here at the end if the last nibble is still used.
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const uint8_t *
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruexpandGroupLengths(const uint8_t *s,
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   uint16_t offsets[LINES_PER_GROUP+1], uint16_t lengths[LINES_PER_GROUP+1]) {
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* read the lengths of the 32 strings in this group and get each string's offset */
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t i=0, offset=0, length=0;
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t lengthByte;
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* all 32 lengths must be read to get the offset of the first group string */
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(i<LINES_PER_GROUP) {
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        lengthByte=*s++;
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* read even nibble - MSBs of lengthByte */
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(length>=12) {
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* double-nibble length spread across two bytes */
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=(uint16_t)(((length&0x3)<<4|lengthByte>>4)+12);
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            lengthByte&=0xf;
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if((lengthByte /* &0xf0 */)>=0xc0) {
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* double-nibble length spread across this one byte */
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=(uint16_t)((lengthByte&0x3f)+12);
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* single-nibble length in MSBs */
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=(uint16_t)(lengthByte>>4);
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            lengthByte&=0xf;
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *offsets++=offset;
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *lengths++=length;
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset+=length;
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++i;
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* read odd nibble - LSBs of lengthByte */
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((lengthByte&0xf0)==0) {
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* this nibble was not consumed for a double-nibble length above */
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=lengthByte;
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(length<12) {
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* single-nibble length in LSBs */
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *offsets++=offset;
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *lengths++=length;
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                offset+=length;
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++i;
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=0;   /* prevent double-nibble detection in the next iteration */
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* now, s is at the first group string */
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return s;
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint16_t
567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruexpandGroupName(UCharNames *names, const uint16_t *group,
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uint16_t lineNumber, UCharNameChoice nameChoice,
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                char *buffer, uint16_t bufferLength) {
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t offsets[LINES_PER_GROUP+2], lengths[LINES_PER_GROUP+2];
571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint8_t *s=(uint8_t *)names+names->groupStringOffset+GET_GROUP_OFFSET(group);
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    s=expandGroupLengths(s, offsets, lengths);
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return expandName(names, s+offsets[lineNumber], lengths[lineNumber], nameChoice,
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                      buffer, bufferLength);
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint16_t
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerugetName(UCharNames *names, uint32_t code, UCharNameChoice nameChoice,
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char *buffer, uint16_t bufferLength) {
580b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint16_t *group=getGroup(names, code);
581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if((uint16_t)(code>>GROUP_SHIFT)==group[GROUP_MSB]) {
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return expandGroupName(names, group, (uint16_t)(code&GROUP_MASK), nameChoice,
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               buffer, bufferLength);
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* group not found */
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* zero-terminate */
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(bufferLength>0) {
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *buffer=0;
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * enumGroupNames() enumerates all the names in a 32-group
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * and either calls the enumerator function or finds a given input name.
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool
599b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruenumGroupNames(UCharNames *names, const uint16_t *group,
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               UChar32 start, UChar32 end,
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               UEnumCharNamesFn *fn, void *context,
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               UCharNameChoice nameChoice) {
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t offsets[LINES_PER_GROUP+2], lengths[LINES_PER_GROUP+2];
604b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint8_t *s=(uint8_t *)names+names->groupStringOffset+GET_GROUP_OFFSET(group);
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    s=expandGroupLengths(s, offsets, lengths);
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fn!=DO_FIND_NAME) {
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char buffer[200];
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t length;
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(start<=end) {
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=expandName(names, s+offsets[start&GROUP_MASK], lengths[start&GROUP_MASK], nameChoice, buffer, sizeof(buffer));
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!length && nameChoice == U_EXTENDED_CHAR_NAME) {
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                buffer[length = getExtName(start, buffer, sizeof(buffer))] = 0;
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* here, we assume that the buffer is large enough */
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(length>0) {
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(!fn(context, start, nameChoice, buffer, length)) {
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return FALSE;
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++start;
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *otherName=((FindName *)context)->otherName;
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(start<=end) {
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(compareName(names, s+offsets[start&GROUP_MASK], lengths[start&GROUP_MASK], nameChoice, otherName)) {
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ((FindName *)context)->code=start;
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++start;
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * enumExtNames enumerate extended names.
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * It only needs to do it if it is called with a real function and not
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * with the dummy DO_FIND_NAME, because u_charFromName() does a check
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * for extended names by itself.
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruenumExtNames(UChar32 start, UChar32 end,
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UEnumCharNamesFn *fn, void *context)
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fn!=DO_FIND_NAME) {
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char buffer[200];
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t length;
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(start<=end) {
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            buffer[length = getExtName(start, buffer, sizeof(buffer))] = 0;
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* here, we assume that the buffer is large enough */
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(length>0) {
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(!fn(context, start, U_EXTENDED_CHAR_NAME, buffer, length)) {
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return FALSE;
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++start;
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruenumNames(UCharNames *names,
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          UChar32 start, UChar32 limit,
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          UEnumCharNamesFn *fn, void *context,
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          UCharNameChoice nameChoice) {
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t startGroupMSB, endGroupMSB, groupCount;
672b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint16_t *group, *groupLimit;
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startGroupMSB=(uint16_t)(start>>GROUP_SHIFT);
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endGroupMSB=(uint16_t)((limit-1)>>GROUP_SHIFT);
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* find the group that contains start, or the highest before it */
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    group=getGroup(names, start);
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
68083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius    if(startGroupMSB<group[GROUP_MSB] && nameChoice==U_EXTENDED_CHAR_NAME) {
68183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        /* enumerate synthetic names between start and the group start */
68283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        UChar32 extLimit=((UChar32)group[GROUP_MSB]<<GROUP_SHIFT);
68383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        if(extLimit>limit) {
68483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius            extLimit=limit;
68583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        }
68683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        if(!enumExtNames(start, extLimit-1, fn, context)) {
68783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius            return FALSE;
68883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        }
68983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        start=extLimit;
69083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius    }
69183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(startGroupMSB==endGroupMSB) {
693b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(startGroupMSB==group[GROUP_MSB]) {
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* if start and limit-1 are in the same group, then enumerate only in that one */
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return enumGroupNames(names, group, start, limit-1, fn, context, nameChoice);
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
698b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        const uint16_t *groups=GET_GROUPS(names);
699b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        groupCount=*groups++;
700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        groupLimit=groups+groupCount*GROUP_LENGTH;
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
702b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(startGroupMSB==group[GROUP_MSB]) {
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* enumerate characters in the partial start group */
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if((start&GROUP_MASK)!=0) {
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(!enumGroupNames(names, group,
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   start, ((UChar32)startGroupMSB<<GROUP_SHIFT)+LINES_PER_GROUP-1,
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fn, context, nameChoice)) {
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return FALSE;
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
710b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                group=NEXT_GROUP(group); /* continue with the next group */
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else if(startGroupMSB>group[GROUP_MSB]) {
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* make sure that we start enumerating with the first group after start */
714b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            const uint16_t *nextGroup=NEXT_GROUP(group);
715b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (nextGroup < groupLimit && nextGroup[GROUP_MSB] > startGroupMSB && nameChoice == U_EXTENDED_CHAR_NAME) {
716b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UChar32 end = nextGroup[GROUP_MSB] << GROUP_SHIFT;
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (end > limit) {
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    end = limit;
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (!enumExtNames(start, end - 1, fn, context)) {
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return FALSE;
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
724b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            group=nextGroup;
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* enumerate entire groups between the start- and end-groups */
728b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        while(group<groupLimit && group[GROUP_MSB]<endGroupMSB) {
729b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            const uint16_t *nextGroup;
730b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            start=(UChar32)group[GROUP_MSB]<<GROUP_SHIFT;
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(!enumGroupNames(names, group, start, start+LINES_PER_GROUP-1, fn, context, nameChoice)) {
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
734b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            nextGroup=NEXT_GROUP(group);
735b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (nextGroup < groupLimit && nextGroup[GROUP_MSB] > group[GROUP_MSB] + 1 && nameChoice == U_EXTENDED_CHAR_NAME) {
736b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UChar32 end = nextGroup[GROUP_MSB] << GROUP_SHIFT;
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (end > limit) {
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    end = limit;
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
740b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (!enumExtNames((group[GROUP_MSB] + 1) << GROUP_SHIFT, end - 1, fn, context)) {
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return FALSE;
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
744b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            group=nextGroup;
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
747b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /* enumerate within the end group (group[GROUP_MSB]==endGroupMSB) */
748b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if(group<groupLimit && group[GROUP_MSB]==endGroupMSB) {
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return enumGroupNames(names, group, (limit-1)&~GROUP_MASK, limit-1, fn, context, nameChoice);
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (nameChoice == U_EXTENDED_CHAR_NAME && group == groupLimit) {
751b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UChar32 next = (PREV_GROUP(group)[GROUP_MSB] + 1) << GROUP_SHIFT;
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (next > start) {
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                start = next;
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return TRUE;
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* we have not found a group, which means everything is made of
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       extended names. */
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (nameChoice == U_EXTENDED_CHAR_NAME) {
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (limit > UCHAR_MAX_VALUE + 1) {
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            limit = UCHAR_MAX_VALUE + 1;
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return enumExtNames(start, limit - 1, fn, context);
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint16_t
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruwriteFactorSuffix(const uint16_t *factors, uint16_t count,
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const char *s, /* suffix elements */
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  uint32_t code,
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  uint16_t indexes[8], /* output fields from here */
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const char *elementBases[8], const char *elements[8],
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  char *buffer, uint16_t bufferLength) {
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t i, factor, bufferPos=0;
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char c;
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* write elements according to the factors */
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * the factorized elements are determined by modulo arithmetic
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * with the factors of this algorithm
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * note that for fewer operations, count is decremented here
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    --count;
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=count; i>0; --i) {
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        factor=factors[i];
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        indexes[i]=(uint16_t)(code%factor);
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        code/=factor;
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * we don't need to calculate the last modulus because start<=code<=end
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * guarantees here that code<=factors[0]
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    indexes[0]=(uint16_t)code;
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* write each element */
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(;;) {
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(elementBases!=NULL) {
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *elementBases++=s;
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* skip indexes[i] strings */
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        factor=indexes[i];
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(factor>0) {
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(*s++!=0) {}
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            --factor;
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(elements!=NULL) {
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *elements++=s;
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* write element */
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while((c=*s++)!=0) {
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            WRITE_CHAR(buffer, bufferLength, bufferPos, c);
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* we do not need to perform the rest of this loop for i==count - break here */
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(i>=count) {
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* skip the rest of the strings for this factors[i] */
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        factor=(uint16_t)(factors[i]-indexes[i]-1);
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(factor>0) {
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(*s++!=0) {}
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            --factor;
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++i;
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* zero-terminate */
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(bufferLength>0) {
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *buffer=0;
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return bufferPos;
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Important:
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Parts of findAlgName() are almost the same as some of getAlgName().
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Fixes must be applied to both.
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint16_t
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerugetAlgName(AlgorithmicRange *range, uint32_t code, UCharNameChoice nameChoice,
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char *buffer, uint16_t bufferLength) {
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t bufferPos=0;
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
85650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* Only the normative character name can be algorithmic. */
85750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* zero-terminate */
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(bufferLength>0) {
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *buffer=0;
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch(range->type) {
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 0: {
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* name = prefix hex-digits */
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *s=(const char *)(range+1);
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char c;
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t i, count;
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* copy prefix */
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while((c=*s++)!=0) {
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            WRITE_CHAR(buffer, bufferLength, bufferPos, c);
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* write hexadecimal code point value */
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=range->variant;
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* zero-terminate */
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(count<bufferLength) {
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            buffer[count]=0;
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=count; i>0;) {
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(--i<bufferLength) {
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                c=(char)(code&0xf);
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(c<10) {
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    c+='0';
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    c+='A'-10;
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                buffer[i]=c;
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            code>>=4;
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        bufferPos+=count;
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 1: {
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* name = prefix factorized-elements */
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t indexes[8];
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const uint16_t *factors=(const uint16_t *)(range+1);
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t count=range->variant;
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *s=(const char *)(factors+count);
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char c;
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* copy prefix */
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while((c=*s++)!=0) {
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            WRITE_CHAR(buffer, bufferLength, bufferPos, c);
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        bufferPos+=writeFactorSuffix(factors, count,
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     s, code-range->start, indexes, NULL, NULL, buffer, bufferLength);
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* undefined type */
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* zero-terminate */
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(bufferLength>0) {
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *buffer=0;
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return bufferPos;
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Important: enumAlgNames() and findAlgName() are almost the same.
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Any fix must be applied to both.
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruenumAlgNames(AlgorithmicRange *range,
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar32 start, UChar32 limit,
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UEnumCharNamesFn *fn, void *context,
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UCharNameChoice nameChoice) {
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char buffer[200];
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t length;
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
94350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch(range->type) {
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 0: {
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char *s, *end;
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char c;
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* get the full name of the start character */
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length=getAlgName(range, (uint32_t)start, nameChoice, buffer, sizeof(buffer));
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(length<=0) {
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return TRUE;
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* call the enumerator function with this first character */
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(!fn(context, start, nameChoice, buffer, length)) {
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* go to the end of the name; all these names have the same length */
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        end=buffer;
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(*end!=0) {
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++end;
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* enumerate the rest of the names */
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(++start<limit) {
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* increment the hexadecimal number on a character-basis */
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s=end;
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for (;;) {
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                c=*--s;
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(('0'<=c && c<'9') || ('A'<=c && c<'F')) {
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *s=(char)(c+1);
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else if(c=='9') {
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *s='A';
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else if(c=='F') {
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *s='0';
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(!fn(context, start, nameChoice, buffer, length)) {
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 1: {
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t indexes[8];
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *elementBases[8], *elements[8];
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const uint16_t *factors=(const uint16_t *)(range+1);
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t count=range->variant;
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *s=(const char *)(factors+count);
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char *suffix, *t;
999b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uint16_t prefixLength, i, idx;
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char c;
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* name = prefix factorized-elements */
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* copy prefix */
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        suffix=buffer;
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        prefixLength=0;
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while((c=*s++)!=0) {
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *suffix++=c;
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++prefixLength;
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* append the suffix of the start character */
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length=(uint16_t)(prefixLength+writeFactorSuffix(factors, count,
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                              s, (uint32_t)start-range->start,
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                              indexes, elementBases, elements,
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                              suffix, (uint16_t)(sizeof(buffer)-prefixLength)));
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* call the enumerator function with this first character */
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(!fn(context, start, nameChoice, buffer, length)) {
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* enumerate the rest of the names */
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(++start<limit) {
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* increment the indexes in lexical order bound by the factors */
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            i=count;
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for (;;) {
1029b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                idx=(uint16_t)(indexes[--i]+1);
1030b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if(idx<factors[i]) {
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* skip one index and its element string */
1032b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    indexes[i]=idx;
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    s=elements[i];
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    while(*s++!=0) {
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    elements[i]=s;
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* reset this index to 0 and its element string to the first one */
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    indexes[i]=0;
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    elements[i]=elementBases[i];
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* to make matters a little easier, just append all elements to the suffix */
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            t=suffix;
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=prefixLength;
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<count; ++i) {
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                s=elements[i];
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while((c=*s++)!=0) {
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *t++=c;
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ++length;
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* zero-terminate */
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *t=0;
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(!fn(context, start, nameChoice, buffer, length)) {
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* undefined type */
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * findAlgName() is almost the same as enumAlgNames() except that it
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * returns the code point for a name if it fits into the range.
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * It returns 0xffff otherwise.
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UChar32
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufindAlgName(AlgorithmicRange *range, UCharNameChoice nameChoice, const char *otherName) {
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar32 code;
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
108150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(nameChoice!=U_UNICODE_CHAR_NAME && nameChoice!=U_EXTENDED_CHAR_NAME) {
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0xffff;
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch(range->type) {
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 0: {
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* name = prefix hex-digits */
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *s=(const char *)(range+1);
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char c;
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t i, count;
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* compare prefix */
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while((c=*s++)!=0) {
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if((char)c!=*otherName++) {
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0xffff;
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* read hexadecimal code point value */
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=range->variant;
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        code=0;
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; i<count; ++i) {
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            c=*otherName++;
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if('0'<=c && c<='9') {
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                code=(code<<4)|(c-'0');
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else if('A'<=c && c<='F') {
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                code=(code<<4)|(c-'A'+10);
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0xffff;
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* does it fit into the range? */
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(*otherName==0 && range->start<=(uint32_t)code && (uint32_t)code<=range->end) {
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return code;
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 1: {
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char buffer[64];
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t indexes[8];
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *elementBases[8], *elements[8];
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const uint16_t *factors=(const uint16_t *)(range+1);
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t count=range->variant;
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *s=(const char *)(factors+count), *t;
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar32 start, limit;
1128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uint16_t i, idx;
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char c;
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* name = prefix factorized-elements */
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* compare prefix */
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while((c=*s++)!=0) {
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if((char)c!=*otherName++) {
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0xffff;
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        start=(UChar32)range->start;
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        limit=(UChar32)(range->end+1);
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* initialize the suffix elements for enumeration; indexes should all be set to 0 */
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        writeFactorSuffix(factors, count, s, 0,
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          indexes, elementBases, elements, buffer, sizeof(buffer));
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* compare the first suffix */
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(0==uprv_strcmp(otherName, buffer)) {
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return start;
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* enumerate and compare the rest of the suffixes */
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(++start<limit) {
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* increment the indexes in lexical order bound by the factors */
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            i=count;
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for (;;) {
1158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                idx=(uint16_t)(indexes[--i]+1);
1159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if(idx<factors[i]) {
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* skip one index and its element string */
1161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    indexes[i]=idx;
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    s=elements[i];
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    while(*s++!=0) {}
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    elements[i]=s;
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* reset this index to 0 and its element string to the first one */
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    indexes[i]=0;
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    elements[i]=elementBases[i];
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* to make matters a little easier, just compare all elements of the suffix */
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            t=otherName;
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<count; ++i) {
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                s=elements[i];
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while((c=*s++)!=0) {
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(c!=*t++) {
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        s=""; /* does not match */
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        i=99;
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(i<99 && *t==0) {
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return start;
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* undefined type */
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0xffff;
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* sets of name characters, maximum name lengths ---------------------------- */
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define SET_ADD(set, c) ((set)[(uint8_t)c>>5]|=((uint32_t)1<<((uint8_t)c&0x1f)))
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define SET_CONTAINS(set, c) (((set)[(uint8_t)c>>5]&((uint32_t)1<<((uint8_t)c&0x1f)))!=0)
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucalcStringSetLength(uint32_t set[8], const char *s) {
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length=0;
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char c;
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while((c=*s++)!=0) {
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SET_ADD(set, c);
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++length;
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return length;
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucalcAlgNameSetsLengths(int32_t maxNameLength) {
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    AlgorithmicRange *range;
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t *p;
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t rangeCount;
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length;
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* enumerate algorithmic ranges */
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    p=(uint32_t *)((uint8_t *)uCharNames+uCharNames->algNamesOffset);
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rangeCount=*p;
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    range=(AlgorithmicRange *)(p+1);
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(rangeCount>0) {
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        switch(range->type) {
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case 0:
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* name = prefix + (range->variant times) hex-digits */
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* prefix */
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=calcStringSetLength(gNameSet, (const char *)(range+1))+range->variant;
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(length>maxNameLength) {
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                maxNameLength=length;
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case 1: {
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* name = prefix factorized-elements */
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const uint16_t *factors=(const uint16_t *)(range+1);
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const char *s;
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t i, count=range->variant, factor, factorLength, maxFactorLength;
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* prefix length */
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s=(const char *)(factors+count);
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=calcStringSetLength(gNameSet, s);
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s+=length+1; /* start of factor suffixes */
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* get the set and maximum factor suffix length for each factor */
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<count; ++i) {
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                maxFactorLength=0;
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(factor=factors[i]; factor>0; --factor) {
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    factorLength=calcStringSetLength(gNameSet, s);
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    s+=factorLength+1;
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(factorLength>maxFactorLength) {
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        maxFactorLength=factorLength;
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                length+=maxFactorLength;
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(length>maxNameLength) {
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                maxNameLength=length;
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* unknown type */
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        range=(AlgorithmicRange *)((uint8_t *)range+range->size);
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --rangeCount;
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return maxNameLength;
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucalcExtNameSetsLengths(int32_t maxNameLength) {
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i, length;
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0; i<LENGTHOF(charCatNames); ++i) {
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * for each category, count the length of the category name
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * plus 9=
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * 2 for <>
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * 1 for -
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * 6 for most hex digits per code point
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length=9+calcStringSetLength(gNameSet, charCatNames[i]);
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(length>maxNameLength) {
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            maxNameLength=length;
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return maxNameLength;
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucalcNameSetLength(const uint16_t *tokens, uint16_t tokenCount, const uint8_t *tokenStrings, int8_t *tokenLengths,
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  uint32_t set[8],
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const uint8_t **pLine, const uint8_t *lineLimit) {
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const uint8_t *line=*pLine;
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length=0, tokenLength;
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t c, token;
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(line!=lineLimit && (c=*line++)!=(uint8_t)';') {
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(c>=tokenCount) {
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* implicit letter */
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            SET_ADD(set, c);
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++length;
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            token=tokens[c];
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(token==(uint16_t)(-2)) {
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* this is a lead byte for a double-byte token */
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                c=c<<8|*line++;
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                token=tokens[c];
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(token==(uint16_t)(-1)) {
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* explicit letter */
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                SET_ADD(set, c);
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++length;
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* count token word */
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(tokenLengths!=NULL) {
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* use cached token length */
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    tokenLength=tokenLengths[c];
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(tokenLength==0) {
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        tokenLength=calcStringSetLength(set, (const char *)tokenStrings+token);
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        tokenLengths[c]=(int8_t)tokenLength;
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    tokenLength=calcStringSetLength(set, (const char *)tokenStrings+token);
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                length+=tokenLength;
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *pLine=line;
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return length;
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucalcGroupNameSetsLengths(int32_t maxNameLength) {
1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t offsets[LINES_PER_GROUP+2], lengths[LINES_PER_GROUP+2];
1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t *tokens=(uint16_t *)uCharNames+8;
1346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t tokenCount=*tokens++;
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t *tokenStrings=(uint8_t *)uCharNames+uCharNames->tokenStringOffset;
1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t *tokenLengths;
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint16_t *group;
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const uint8_t *s, *line, *lineLimit;
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t groupCount, lineNumber, length;
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    tokenLengths=(int8_t *)uprv_malloc(tokenCount);
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(tokenLengths!=NULL) {
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memset(tokenLengths, 0, tokenCount);
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    group=GET_GROUPS(uCharNames);
1362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    groupCount=*group++;
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* enumerate all groups */
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(groupCount>0) {
1366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        s=(uint8_t *)uCharNames+uCharNames->groupStringOffset+GET_GROUP_OFFSET(group);
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        s=expandGroupLengths(s, offsets, lengths);
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* enumerate all lines in each group */
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(lineNumber=0; lineNumber<LINES_PER_GROUP; ++lineNumber) {
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            line=s+offsets[lineNumber];
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=lengths[lineNumber];
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(length==0) {
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            lineLimit=line+length;
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* read regular name */
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=calcNameSetLength(tokens, tokenCount, tokenStrings, tokenLengths, gNameSet, &line, lineLimit);
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(length>maxNameLength) {
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                maxNameLength=length;
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(line==lineLimit) {
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* read Unicode 1.0 name */
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=calcNameSetLength(tokens, tokenCount, tokenStrings, tokenLengths, gNameSet, &line, lineLimit);
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(length>maxNameLength) {
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                maxNameLength=length;
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(line==lineLimit) {
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* read ISO comment */
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*length=calcNameSetLength(tokens, tokenCount, tokenStrings, tokenLengths, gISOCommentSet, &line, lineLimit);*/
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        group=NEXT_GROUP(group);
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --groupCount;
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(tokenLengths!=NULL) {
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(tokenLengths);
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* set gMax... - name length last for threading */
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    gMaxNameLength=maxNameLength;
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucalcNameSetsLengths(UErrorCode *pErrorCode) {
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static const char extChars[]="0123456789ABCDEF<>-";
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i, maxNameLength;
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(gMaxNameLength!=0) {
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!isDataLoaded(pErrorCode)) {
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* set hex digits, used in various names, and <>-, used in extended names */
142783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius    for(i=0; i<(int32_t)sizeof(extChars)-1; ++i) {
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SET_ADD(gNameSet, extChars[i]);
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* set sets and lengths from algorithmic names */
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    maxNameLength=calcAlgNameSetsLengths(0);
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* set sets and lengths from extended names */
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    maxNameLength=calcExtNameSetsLengths(maxNameLength);
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* set sets and lengths from group names, set global maximum values */
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    calcGroupNameSetsLengths(maxNameLength);
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1443fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END
1444fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* public API --------------------------------------------------------------- */
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1447fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_USE
1448fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruu_charName(UChar32 code, UCharNameChoice nameChoice,
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           char *buffer, int32_t bufferLength,
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           UErrorCode *pErrorCode) {
1453fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius     AlgorithmicRange *algRange;
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t *p;
1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t i;
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length;
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* check the argument values */
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(nameChoice>=U_CHAR_NAME_CHOICE_COUNT ||
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              bufferLength<0 || (bufferLength>0 && buffer==NULL)
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ) {
1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((uint32_t)code>UCHAR_MAX_VALUE || !isDataLoaded(pErrorCode)) {
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return u_terminateChars(buffer, bufferLength, 0, pErrorCode);
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    length=0;
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* try algorithmic names first */
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    p=(uint32_t *)((uint8_t *)uCharNames+uCharNames->algNamesOffset);
1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    i=*p;
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    algRange=(AlgorithmicRange *)(p+1);
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(i>0) {
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(algRange->start<=(uint32_t)code && (uint32_t)code<=algRange->end) {
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=getAlgName(algRange, (uint32_t)code, nameChoice, buffer, (uint16_t)bufferLength);
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        algRange=(AlgorithmicRange *)((uint8_t *)algRange+algRange->size);
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --i;
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(i==0) {
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (nameChoice == U_EXTENDED_CHAR_NAME) {
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length = getName(uCharNames, (uint32_t )code, U_EXTENDED_CHAR_NAME, buffer, (uint16_t) bufferLength);
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!length) {
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* extended character name */
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                length = getExtName((uint32_t) code, buffer, (uint16_t) bufferLength);
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* normal character name */
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=getName(uCharNames, (uint32_t)code, nameChoice, buffer, (uint16_t)bufferLength);
1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_terminateChars(buffer, bufferLength, length, pErrorCode);
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
150483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Corneliusu_getISOComment(UChar32 /*c*/,
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                char *dest, int32_t destCapacity,
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode *pErrorCode) {
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* check the argument values */
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(destCapacity<0 || (destCapacity>0 && dest==NULL)) {
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
151583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius    return u_terminateChars(dest, destCapacity, 0, pErrorCode);
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UChar32 U_EXPORT2
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruu_charFromName(UCharNameChoice nameChoice,
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               const char *name,
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               UErrorCode *pErrorCode) {
1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char upper[120], lower[120];
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FindName findName;
1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    AlgorithmicRange *algRange;
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t *p;
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t i;
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar32 cp = 0;
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char c0;
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar32 error = 0xffff;     /* Undefined, but use this for backwards compatibility. */
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return error;
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(nameChoice>=U_CHAR_NAME_CHOICE_COUNT || name==NULL || *name==0) {
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return error;
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!isDataLoaded(pErrorCode)) {
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return error;
1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* construct the uppercase and lowercase of the name first */
1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0; i<sizeof(upper); ++i) {
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((c0=*name++)!=0) {
1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            upper[i]=uprv_toupper(c0);
1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            lower[i]=uprv_tolower(c0);
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            upper[i]=lower[i]=0;
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(i==sizeof(upper)) {
1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* name too long, there is no such character */
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode = U_ILLEGAL_CHAR_FOUND;
1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return error;
1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* try extended names first */
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (lower[0] == '<') {
1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (nameChoice == U_EXTENDED_CHAR_NAME) {
1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (lower[--i] == '>') {
1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for (--i; lower[i] && lower[i] != '-'; --i) {
1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (lower[i] == '-') { /* We've got a category. */
1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uint32_t cIdx;
1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    lower[i] = 0;
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    for (++i; lower[i] != '>'; ++i) {
1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (lower[i] >= '0' && lower[i] <= '9') {
1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            cp = (cp << 4) + lower[i] - '0';
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else if (lower[i] >= 'a' && lower[i] <= 'f') {
1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            cp = (cp << 4) + lower[i] - 'a' + 10;
1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else {
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            *pErrorCode = U_ILLEGAL_CHAR_FOUND;
1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            return error;
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* Now validate the category name.
1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       We could use a binary search, or a trie, if
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       we really wanted to. */
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    for (lower[i] = 0, cIdx = 0; cIdx < LENGTHOF(charCatNames); ++cIdx) {
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (!uprv_strcmp(lower + 1, charCatNames[cIdx])) {
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (getCharCat(cp) == cIdx) {
1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                return cp;
1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            break;
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode = U_ILLEGAL_CHAR_FOUND;
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return error;
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* try algorithmic names now */
1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    p=(uint32_t *)((uint8_t *)uCharNames+uCharNames->algNamesOffset);
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    i=*p;
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    algRange=(AlgorithmicRange *)(p+1);
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(i>0) {
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((cp=findAlgName(algRange, nameChoice, upper))!=0xffff) {
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return cp;
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        algRange=(AlgorithmicRange *)((uint8_t *)algRange+algRange->size);
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --i;
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* normal character name */
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    findName.otherName=upper;
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    findName.code=error;
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enumNames(uCharNames, 0, UCHAR_MAX_VALUE + 1, DO_FIND_NAME, &findName, nameChoice);
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (findName.code == error) {
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         *pErrorCode = U_ILLEGAL_CHAR_FOUND;
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return findName.code;
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruu_enumCharNames(UChar32 start, UChar32 limit,
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UEnumCharNamesFn *fn,
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                void *context,
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UCharNameChoice nameChoice,
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode *pErrorCode) {
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    AlgorithmicRange *algRange;
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t *p;
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t i;
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(nameChoice>=U_CHAR_NAME_CHOICE_COUNT || fn==NULL) {
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((uint32_t) limit > UCHAR_MAX_VALUE + 1) {
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        limit = UCHAR_MAX_VALUE + 1;
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((uint32_t)start>=(uint32_t)limit) {
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!isDataLoaded(pErrorCode)) {
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* interleave the data-driven ones with the algorithmic ones */
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* iterate over all algorithmic ranges; assume that they are in ascending order */
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    p=(uint32_t *)((uint8_t *)uCharNames+uCharNames->algNamesOffset);
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    i=*p;
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    algRange=(AlgorithmicRange *)(p+1);
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(i>0) {
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* enumerate the character names before the current algorithmic range */
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* here: start<limit */
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((uint32_t)start<algRange->start) {
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if((uint32_t)limit<=algRange->start) {
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                enumNames(uCharNames, start, limit, fn, context, nameChoice);
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(!enumNames(uCharNames, start, (UChar32)algRange->start, fn, context, nameChoice)) {
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            start=(UChar32)algRange->start;
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* enumerate the character names in the current algorithmic range */
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* here: algRange->start<=start<limit */
1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((uint32_t)start<=algRange->end) {
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if((uint32_t)limit<=(algRange->end+1)) {
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                enumAlgNames(algRange, start, limit, fn, context, nameChoice);
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(!enumAlgNames(algRange, start, (UChar32)algRange->end+1, fn, context, nameChoice)) {
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            start=(UChar32)algRange->end+1;
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* continue to the next algorithmic range (here: start<limit) */
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        algRange=(AlgorithmicRange *)((uint8_t *)algRange+algRange->size);
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --i;
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* enumerate the character names after the last algorithmic range */
1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enumNames(uCharNames, start, limit, fn, context, nameChoice);
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_getMaxCharNameLength() {
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode errorCode=U_ZERO_ERROR;
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(calcNameSetsLengths(&errorCode)) {
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return gMaxNameLength;
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Converts the char set cset into a Unicode set uset.
1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param cset Set of 256 bit flags corresponding to a set of chars.
1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param uset USet to receive characters. Existing contents are deleted.
1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucharSetToUSet(uint32_t cset[8], const USetAdder *sa) {
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar us[256];
1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char cs[256];
1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i, length;
1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode errorCode;
1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    errorCode=U_ZERO_ERROR;
1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!calcNameSetsLengths(&errorCode)) {
1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* build a char string with all chars that are used in character names */
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    length=0;
1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0; i<256; ++i) {
1726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(SET_CONTAINS(cset, i)) {
1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cs[length++]=(char)i;
1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* convert the char string to a UChar string */
1732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_charsToUChars(cs, us, length);
1733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* add each UChar to the USet */
1735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0; i<length; ++i) {
1736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(us[i]!=0 || cs[i]==0) { /* non-invariant chars become (UChar)0 */
1737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            sa->add(sa->set, us[i]);
1738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Fills set with characters that are used in Unicode character names.
1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param set USet to receive characters.
1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_getCharNameCharacters(const USetAdder *sa) {
1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    charSetToUSet(gNameSet, sa);
1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* data swapping ------------------------------------------------------------ */
1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The token table contains non-negative entries for token bytes,
1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * and -1 for bytes that represent themselves in the data file's charset.
1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * -2 entries are used for lead bytes.
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Direct bytes (-1 entries) must be translated from the input charset family
1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * to the output charset family.
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * makeTokenMap() writes a permutation mapping for this.
1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Use it once for single-/lead-byte tokens and once more for all trail byte
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * tokens. (';' is an unused trail byte marked with -1.)
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerumakeTokenMap(const UDataSwapper *ds,
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int16_t tokens[], uint16_t tokenCount,
1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             uint8_t map[256],
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UErrorCode *pErrorCode) {
1769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool usedOutChar[256];
1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint16_t i, j;
1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t c1, c2;
1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(ds->inCharset==ds->outCharset) {
1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Same charset family: identity permutation */
1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; i<256; ++i) {
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            map[i]=(uint8_t)i;
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memset(map, 0, 256);
1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memset(usedOutChar, 0, 256);
1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(tokenCount>256) {
1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            tokenCount=256;
1788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* set the direct bytes (byte 0 always maps to itself) */
1791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=1; i<tokenCount; ++i) {
1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(tokens[i]==-1) {
1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* convert the direct byte character */
1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                c1=(uint8_t)i;
1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ds->swapInvChars(ds, &c1, 1, &c2, pErrorCode);
1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(U_FAILURE(*pErrorCode)) {
1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    udata_printError(ds, "unames/makeTokenMap() finds variant character 0x%02x used (input charset family %d)\n",
1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     i, ds->inCharset);
1799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return;
1800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* enter the converted character into the map and mark it used */
1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                map[c1]=c2;
1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                usedOutChar[c2]=TRUE;
1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* set the mappings for the rest of the permutation */
1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=j=1; i<tokenCount; ++i) {
1810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* set mappings that were not set for direct bytes */
1811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(map[i]==0) {
1812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* set an output byte value that was not used as an output byte above */
1813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while(usedOutChar[j]) {
1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ++j;
1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                map[i]=(uint8_t)j++;
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * leave mappings at tokenCount and above unset if tokenCount<256
1822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * because they won't be used
1823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuchar_swapNames(const UDataSwapper *ds,
1829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                const void *inData, int32_t length, void *outData,
1830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode *pErrorCode) {
1831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UDataInfo *pInfo;
1832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t headerSize;
1833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const uint8_t *inBytes;
1835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint8_t *outBytes;
1836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t tokenStringOffset, groupsOffset, groupStringOffset, algNamesOffset,
1838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             offset, i, count, stringsCount;
1839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const AlgorithmicRange *inRange;
1841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    AlgorithmicRange *outRange;
1842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* udata_swapDataHeader checks the arguments */
1844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
1845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* check data format and format version */
1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pInfo=(const UDataInfo *)((const char *)inData+4);
1851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!(
1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[0]==0x75 &&   /* dataFormat="unam" */
1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[1]==0x6e &&
1854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[2]==0x61 &&
1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[3]==0x6d &&
1856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->formatVersion[0]==1
1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    )) {
1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        udata_printError(ds, "uchar_swapNames(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as unames.icu\n",
1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         pInfo->dataFormat[0], pInfo->dataFormat[1],
1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         pInfo->dataFormat[2], pInfo->dataFormat[3],
1861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         pInfo->formatVersion[0]);
1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_UNSUPPORTED_ERROR;
1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    inBytes=(const uint8_t *)inData+headerSize;
1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    outBytes=(uint8_t *)outData+headerSize;
1868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length<0) {
1869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        algNamesOffset=ds->readUInt32(((const uint32_t *)inBytes)[3]);
1870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length-=headerSize;
1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if( length<20 ||
1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (uint32_t)length<(algNamesOffset=ds->readUInt32(((const uint32_t *)inBytes)[3]))
1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ) {
1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            udata_printError(ds, "uchar_swapNames(): too few bytes (%d after header) for unames.icu\n",
1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             length);
1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length<0) {
1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* preflighting: iterate through algorithmic ranges */
1884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset=algNamesOffset;
1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=ds->readUInt32(*((const uint32_t *)(inBytes+offset)));
1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset+=4;
1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; i<count; ++i) {
1889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            inRange=(const AlgorithmicRange *)(inBytes+offset);
1890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            offset+=ds->readUInt16(inRange->size);
1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap data */
1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const uint16_t *p;
1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t *q, *temp;
1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int16_t tokens[512];
1898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint16_t tokenCount;
1899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint8_t map[256], trailMap[256];
1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* copy the data for inaccessible bytes */
1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(inBytes!=outBytes) {
1904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_memcpy(outBytes, inBytes, length);
1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* the initial 4 offsets first */
1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tokenStringOffset=ds->readUInt32(((const uint32_t *)inBytes)[0]);
1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        groupsOffset=ds->readUInt32(((const uint32_t *)inBytes)[1]);
1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        groupStringOffset=ds->readUInt32(((const uint32_t *)inBytes)[2]);
1911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray32(ds, inBytes, 16, outBytes, pErrorCode);
1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * now the tokens table
1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * it needs to be permutated along with the compressed name strings
1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
1917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        p=(const uint16_t *)(inBytes+16);
1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        q=(uint16_t *)(outBytes+16);
1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* read and swap the tokenCount */
1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tokenCount=ds->readUInt16(*p);
1922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray16(ds, p, 2, q, pErrorCode);
1923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++p;
1924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++q;
1925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* read the first 512 tokens and make the token maps */
1927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(tokenCount<=512) {
1928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            count=tokenCount;
1929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            count=512;
1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; i<count; ++i) {
1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            tokens[i]=udata_readInt16(ds, p[i]);
1934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(; i<512; ++i) {
1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            tokens[i]=0; /* fill the rest of the tokens array if tokenCount<512 */
1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        makeTokenMap(ds, tokens, tokenCount, map, pErrorCode);
1939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        makeTokenMap(ds, tokens+256, (uint16_t)(tokenCount>256 ? tokenCount-256 : 0), trailMap, pErrorCode);
1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(*pErrorCode)) {
1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
1942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * swap and permutate the tokens
1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * go through a temporary array to support in-place swapping
1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
1948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        temp=(uint16_t *)uprv_malloc(tokenCount*2);
1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(temp==NULL) {
1950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            udata_printError(ds, "out of memory swapping %u unames.icu tokens\n",
1951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             tokenCount);
1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
1953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap and permutate single-/lead-byte tokens */
1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; i<tokenCount && i<256; ++i) {
1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ds->swapArray16(ds, p+i, 2, temp+map[i], pErrorCode);
1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap and permutate trail-byte tokens */
1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(; i<tokenCount; ++i) {
1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ds->swapArray16(ds, p+i, 2, temp+(i&0xffffff00)+trailMap[i&0xff], pErrorCode);
1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* copy the result into the output and free the temporary array */
1967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memcpy(q, temp, tokenCount*2);
1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(temp);
1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * swap the token strings but not a possible padding byte after
1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * the terminating NUL of the last string
1973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
1974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        udata_swapInvStringBlock(ds, inBytes+tokenStringOffset, (int32_t)(groupsOffset-tokenStringOffset),
1975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    outBytes+tokenStringOffset, pErrorCode);
1976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(*pErrorCode)) {
1977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            udata_printError(ds, "uchar_swapNames(token strings) failed\n");
1978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
1979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap the group table */
1982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=ds->readUInt16(*((const uint16_t *)(inBytes+groupsOffset)));
1983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray16(ds, inBytes+groupsOffset, (int32_t)((1+count*3)*2),
1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           outBytes+groupsOffset, pErrorCode);
1985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * swap the group strings
1988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * swap the string bytes but not the nibble-encoded string lengths
1989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
1990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(ds->inCharset!=ds->outCharset) {
1991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uint16_t offsets[LINES_PER_GROUP+1], lengths[LINES_PER_GROUP+1];
1992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const uint8_t *inStrings, *nextInStrings;
1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uint8_t *outStrings;
1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uint8_t c;
1997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            inStrings=inBytes+groupStringOffset;
1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            outStrings=outBytes+groupStringOffset;
2000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            stringsCount=algNamesOffset-groupStringOffset;
2002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* iterate through string groups until only a few padding bytes are left */
2004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(stringsCount>32) {
2005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                nextInStrings=expandGroupLengths(inStrings, offsets, lengths);
2006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* move past the length bytes */
2008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                stringsCount-=(uint32_t)(nextInStrings-inStrings);
2009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                outStrings+=nextInStrings-inStrings;
2010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                inStrings=nextInStrings;
2011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                count=offsets[31]+lengths[31]; /* total number of string bytes in this group */
2013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                stringsCount-=count;
2014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* swap the string bytes using map[] and trailMap[] */
2016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while(count>0) {
2017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    c=*inStrings++;
2018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *outStrings++=map[c];
2019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(tokens[c]!=-2) {
2020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        --count;
2021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
2022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        /* token lead byte: swap the trail byte, too */
2023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        *outStrings++=trailMap[*inStrings++];
2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        count-=2;
2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap the algorithmic ranges */
2031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset=algNamesOffset;
2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=ds->readUInt32(*((const uint32_t *)(inBytes+offset)));
2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray32(ds, inBytes+offset, 4, outBytes+offset, pErrorCode);
2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset+=4;
2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; i<count; ++i) {
2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(offset>(uint32_t)length) {
2038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                udata_printError(ds, "uchar_swapNames(): too few bytes (%d after header) for unames.icu algorithmic range %u\n",
2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 length, i);
2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
2041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0;
2042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            inRange=(const AlgorithmicRange *)(inBytes+offset);
2045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            outRange=(AlgorithmicRange *)(outBytes+offset);
2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            offset+=ds->readUInt16(inRange->size);
2047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ds->swapArray32(ds, inRange, 8, outRange, pErrorCode);
2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ds->swapArray16(ds, &inRange->size, 2, &outRange->size, pErrorCode);
2050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            switch(inRange->type) {
2051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            case 0:
2052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* swap prefix string */
2053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ds->swapInvChars(ds, inRange+1, (int32_t)uprv_strlen((const char *)(inRange+1)),
2054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    outRange+1, pErrorCode);
2055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(U_FAILURE(*pErrorCode)) {
2056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    udata_printError(ds, "uchar_swapNames(prefix string of algorithmic range %u) failed\n",
2057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     i);
2058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return 0;
2059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
2061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            case 1:
2062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* swap factors and the prefix and factor strings */
2064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uint32_t factorsCount;
2065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    factorsCount=inRange->variant;
2067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    p=(const uint16_t *)(inRange+1);
2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    q=(uint16_t *)(outRange+1);
2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ds->swapArray16(ds, p, (int32_t)(factorsCount*2), q, pErrorCode);
2070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* swap the strings, up to the last terminating NUL */
2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    p+=factorsCount;
2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    q+=factorsCount;
2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    stringsCount=(uint32_t)((inBytes+offset)-(const uint8_t *)p);
2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    while(stringsCount>0 && ((const uint8_t *)p)[stringsCount-1]!=0) {
2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        --stringsCount;
2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ds->swapInvChars(ds, p, (int32_t)stringsCount, q, pErrorCode);
2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            default:
2082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                udata_printError(ds, "uchar_swapNames(): unknown type %u of algorithmic range %u\n",
2083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 inRange->type, i);
2084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *pErrorCode=U_UNSUPPORTED_ERROR;
2085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0;
2086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return headerSize+(int32_t)offset;
2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Hey, Emacs, please set the following:
2095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
2096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Local Variables:
2097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * indent-tabs-mode: nil
2098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * End:
2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
2101