unames.cpp 67 KB

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