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