OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ******************************************************************************* |
| 3 * |
| 4 * Copyright (C) 2001-2010, International Business Machines |
| 5 * Corporation and others. All Rights Reserved. |
| 6 * |
| 7 ******************************************************************************* |
| 8 * file name: ucaelems.cpp |
| 9 * encoding: US-ASCII |
| 10 * tab size: 8 (not used) |
| 11 * indentation:4 |
| 12 * |
| 13 * created 02/22/2001 |
| 14 * created by: Vladimir Weinstein |
| 15 * |
| 16 * This program reads the Franctional UCA table and generates |
| 17 * internal format for UCA table as well as inverse UCA table. |
| 18 * It then writes binary files containing the data: ucadata.dat |
| 19 * & invuca.dat |
| 20 * |
| 21 * date name comments |
| 22 * 03/02/2001 synwee added setMaxExpansion |
| 23 * 03/07/2001 synwee merged UCA's maxexpansion and tailoring's |
| 24 */ |
| 25 |
| 26 #include "unicode/utypes.h" |
| 27 |
| 28 #if !UCONFIG_NO_COLLATION |
| 29 |
| 30 #include "unicode/uchar.h" |
| 31 #include "unicode/unistr.h" |
| 32 #include "unicode/ucoleitr.h" |
| 33 #include "unicode/normlzr.h" |
| 34 #include "normalizer2impl.h" |
| 35 #include "ucol_elm.h" |
| 36 #include "ucol_tok.h" |
| 37 #include "ucol_cnt.h" |
| 38 #include "unicode/caniter.h" |
| 39 #include "cmemory.h" |
| 40 |
| 41 U_NAMESPACE_USE |
| 42 |
| 43 static uint32_t uprv_uca_processContraction(CntTable *contractions, UCAElements
*element, uint32_t existingCE, UErrorCode *status); |
| 44 |
| 45 U_CDECL_BEGIN |
| 46 static int32_t U_CALLCONV |
| 47 prefixLookupHash(const UHashTok e) { |
| 48 UCAElements *element = (UCAElements *)e.pointer; |
| 49 UChar buf[256]; |
| 50 UHashTok key; |
| 51 key.pointer = buf; |
| 52 uprv_memcpy(buf, element->cPoints, element->cSize*sizeof(UChar)); |
| 53 buf[element->cSize] = 0; |
| 54 //key.pointer = element->cPoints; |
| 55 //element->cPoints[element->cSize] = 0; |
| 56 return uhash_hashUChars(key); |
| 57 } |
| 58 |
| 59 static int8_t U_CALLCONV |
| 60 prefixLookupComp(const UHashTok e1, const UHashTok e2) { |
| 61 UCAElements *element1 = (UCAElements *)e1.pointer; |
| 62 UCAElements *element2 = (UCAElements *)e2.pointer; |
| 63 |
| 64 UChar buf1[256]; |
| 65 UHashTok key1; |
| 66 key1.pointer = buf1; |
| 67 uprv_memcpy(buf1, element1->cPoints, element1->cSize*sizeof(UChar)); |
| 68 buf1[element1->cSize] = 0; |
| 69 |
| 70 UChar buf2[256]; |
| 71 UHashTok key2; |
| 72 key2.pointer = buf2; |
| 73 uprv_memcpy(buf2, element2->cPoints, element2->cSize*sizeof(UChar)); |
| 74 buf2[element2->cSize] = 0; |
| 75 |
| 76 return uhash_compareUChars(key1, key2); |
| 77 } |
| 78 U_CDECL_END |
| 79 |
| 80 static int32_t uprv_uca_addExpansion(ExpansionTable *expansions, uint32_t value,
UErrorCode *status) { |
| 81 if(U_FAILURE(*status)) { |
| 82 return 0; |
| 83 } |
| 84 if(expansions->CEs == NULL) { |
| 85 expansions->CEs = (uint32_t *)uprv_malloc(INIT_EXP_TABLE_SIZE*sizeof(uin
t32_t)); |
| 86 /* test for NULL */ |
| 87 if (expansions->CEs == NULL) { |
| 88 *status = U_MEMORY_ALLOCATION_ERROR; |
| 89 return 0; |
| 90 } |
| 91 expansions->size = INIT_EXP_TABLE_SIZE; |
| 92 expansions->position = 0; |
| 93 } |
| 94 |
| 95 if(expansions->position == expansions->size) { |
| 96 uint32_t *newData = (uint32_t *)uprv_realloc(expansions->CEs, 2*expansio
ns->size*sizeof(uint32_t)); |
| 97 if(newData == NULL) { |
| 98 #ifdef UCOL_DEBUG |
| 99 fprintf(stderr, "out of memory for expansions\n"); |
| 100 #endif |
| 101 *status = U_MEMORY_ALLOCATION_ERROR; |
| 102 return -1; |
| 103 } |
| 104 expansions->CEs = newData; |
| 105 expansions->size *= 2; |
| 106 } |
| 107 |
| 108 expansions->CEs[expansions->position] = value; |
| 109 return(expansions->position++); |
| 110 } |
| 111 |
| 112 U_CAPI tempUCATable* U_EXPORT2 |
| 113 uprv_uca_initTempTable(UCATableHeader *image, UColOptionSet *opts, const UCollat
or *UCA, UColCETags initTag, UColCETags supplementaryInitTag, UErrorCode *status
) { |
| 114 MaxJamoExpansionTable *maxjet; |
| 115 MaxExpansionTable *maxet; |
| 116 tempUCATable *t = (tempUCATable *)uprv_malloc(sizeof(tempUCATable)); |
| 117 /* test for NULL */ |
| 118 if (t == NULL) { |
| 119 *status = U_MEMORY_ALLOCATION_ERROR; |
| 120 return NULL; |
| 121 } |
| 122 uprv_memset(t, 0, sizeof(tempUCATable)); |
| 123 |
| 124 maxet = (MaxExpansionTable *)uprv_malloc(sizeof(MaxExpansionTable)); |
| 125 if (maxet == NULL) { |
| 126 goto allocation_failure; |
| 127 } |
| 128 uprv_memset(maxet, 0, sizeof(MaxExpansionTable)); |
| 129 t->maxExpansions = maxet; |
| 130 |
| 131 maxjet = (MaxJamoExpansionTable *)uprv_malloc(sizeof(MaxJamoExpansionTable))
; |
| 132 if (maxjet == NULL) { |
| 133 goto allocation_failure; |
| 134 } |
| 135 uprv_memset(maxjet, 0, sizeof(MaxJamoExpansionTable)); |
| 136 t->maxJamoExpansions = maxjet; |
| 137 |
| 138 t->image = image; |
| 139 t->options = opts; |
| 140 |
| 141 t->UCA = UCA; |
| 142 t->expansions = (ExpansionTable *)uprv_malloc(sizeof(ExpansionTable)); |
| 143 /* test for NULL */ |
| 144 if (t->expansions == NULL) { |
| 145 goto allocation_failure; |
| 146 } |
| 147 uprv_memset(t->expansions, 0, sizeof(ExpansionTable)); |
| 148 |
| 149 t->mapping = utrie_open(NULL, NULL, UCOL_ELM_TRIE_CAPACITY, |
| 150 UCOL_SPECIAL_FLAG | (initTag<<24), |
| 151 UCOL_SPECIAL_FLAG | (supplementaryInitTag << 24), |
| 152 TRUE); // Do your own mallocs for the structure, array and have linear L
atin 1 |
| 153 if (U_FAILURE(*status)) { |
| 154 goto allocation_failure; |
| 155 } |
| 156 t->prefixLookup = uhash_open(prefixLookupHash, prefixLookupComp, NULL, statu
s); |
| 157 if (U_FAILURE(*status)) { |
| 158 goto allocation_failure; |
| 159 } |
| 160 uhash_setValueDeleter(t->prefixLookup, uhash_freeBlock); |
| 161 |
| 162 t->contractions = uprv_cnttab_open(t->mapping, status); |
| 163 if (U_FAILURE(*status)) { |
| 164 goto cleanup; |
| 165 } |
| 166 |
| 167 /* copy UCA's maxexpansion and merge as we go along */ |
| 168 if (UCA != NULL) { |
| 169 /* adding an extra initial value for easier manipulation */ |
| 170 maxet->size = (int32_t)(UCA->lastEndExpansionCE - UCA->endExp
ansionCE) + 2; |
| 171 maxet->position = maxet->size - 1; |
| 172 maxet->endExpansionCE = |
| 173 (uint32_t *)uprv_malloc(sizeof(uint32_t) * maxet->size); |
| 174 /* test for NULL */ |
| 175 if (maxet->endExpansionCE == NULL) { |
| 176 goto allocation_failure; |
| 177 } |
| 178 maxet->expansionCESize = |
| 179 (uint8_t *)uprv_malloc(sizeof(uint8_t) * maxet->size); |
| 180 /* test for NULL */ |
| 181 if (maxet->expansionCESize == NULL) { |
| 182 goto allocation_failure; |
| 183 } |
| 184 /* initialized value */ |
| 185 *(maxet->endExpansionCE) = 0; |
| 186 *(maxet->expansionCESize) = 0; |
| 187 uprv_memcpy(maxet->endExpansionCE + 1, UCA->endExpansionCE, |
| 188 sizeof(uint32_t) * (maxet->size - 1)); |
| 189 uprv_memcpy(maxet->expansionCESize + 1, UCA->expansionCESize, |
| 190 sizeof(uint8_t) * (maxet->size - 1)); |
| 191 } |
| 192 else { |
| 193 maxet->size = 0; |
| 194 } |
| 195 maxjet->endExpansionCE = NULL; |
| 196 maxjet->isV = NULL; |
| 197 maxjet->size = 0; |
| 198 maxjet->position = 0; |
| 199 maxjet->maxLSize = 1; |
| 200 maxjet->maxVSize = 1; |
| 201 maxjet->maxTSize = 1; |
| 202 |
| 203 t->unsafeCP = (uint8_t *)uprv_malloc(UCOL_UNSAFECP_TABLE_SIZE); |
| 204 /* test for NULL */ |
| 205 if (t->unsafeCP == NULL) { |
| 206 goto allocation_failure; |
| 207 } |
| 208 t->contrEndCP = (uint8_t *)uprv_malloc(UCOL_UNSAFECP_TABLE_SIZE); |
| 209 /* test for NULL */ |
| 210 if (t->contrEndCP == NULL) { |
| 211 goto allocation_failure; |
| 212 } |
| 213 uprv_memset(t->unsafeCP, 0, UCOL_UNSAFECP_TABLE_SIZE); |
| 214 uprv_memset(t->contrEndCP, 0, UCOL_UNSAFECP_TABLE_SIZE); |
| 215 t->cmLookup = NULL; |
| 216 return t; |
| 217 |
| 218 allocation_failure: |
| 219 *status = U_MEMORY_ALLOCATION_ERROR; |
| 220 cleanup: |
| 221 uprv_uca_closeTempTable(t); |
| 222 return NULL; |
| 223 } |
| 224 |
| 225 static tempUCATable* U_EXPORT2 |
| 226 uprv_uca_cloneTempTable(tempUCATable *t, UErrorCode *status) { |
| 227 if(U_FAILURE(*status)) { |
| 228 return NULL; |
| 229 } |
| 230 |
| 231 tempUCATable *r = (tempUCATable *)uprv_malloc(sizeof(tempUCATable)); |
| 232 /* test for NULL */ |
| 233 if (r == NULL) { |
| 234 *status = U_MEMORY_ALLOCATION_ERROR; |
| 235 return NULL; |
| 236 } |
| 237 uprv_memset(r, 0, sizeof(tempUCATable)); |
| 238 |
| 239 /* mapping */ |
| 240 if(t->mapping != NULL) { |
| 241 /*r->mapping = ucmpe32_clone(t->mapping, status);*/ |
| 242 r->mapping = utrie_clone(NULL, t->mapping, NULL, 0); |
| 243 } |
| 244 |
| 245 // a hashing clone function would be very nice. We have none currently... |
| 246 // However, we should be good, as closing should not produce any prefixed el
ements. |
| 247 r->prefixLookup = NULL; // prefixes are not used in closing |
| 248 |
| 249 /* expansions */ |
| 250 if(t->expansions != NULL) { |
| 251 r->expansions = (ExpansionTable *)uprv_malloc(sizeof(ExpansionTable)); |
| 252 /* test for NULL */ |
| 253 if (r->expansions == NULL) { |
| 254 *status = U_MEMORY_ALLOCATION_ERROR; |
| 255 goto cleanup; |
| 256 } |
| 257 r->expansions->position = t->expansions->position; |
| 258 r->expansions->size = t->expansions->size; |
| 259 if(t->expansions->CEs != NULL) { |
| 260 r->expansions->CEs = (uint32_t *)uprv_malloc(sizeof(uint32_t)*t->exp
ansions->size); |
| 261 /* test for NULL */ |
| 262 if (r->expansions->CEs == NULL) { |
| 263 *status = U_MEMORY_ALLOCATION_ERROR; |
| 264 goto cleanup; |
| 265 } |
| 266 uprv_memcpy(r->expansions->CEs, t->expansions->CEs, sizeof(uint32_t)
*t->expansions->position); |
| 267 } else { |
| 268 r->expansions->CEs = NULL; |
| 269 } |
| 270 } |
| 271 |
| 272 if(t->contractions != NULL) { |
| 273 r->contractions = uprv_cnttab_clone(t->contractions, status); |
| 274 // Check for cloning failure. |
| 275 if (r->contractions == NULL) { |
| 276 *status = U_MEMORY_ALLOCATION_ERROR; |
| 277 goto cleanup; |
| 278 } |
| 279 r->contractions->mapping = r->mapping; |
| 280 } |
| 281 |
| 282 if(t->maxExpansions != NULL) { |
| 283 r->maxExpansions = (MaxExpansionTable *)uprv_malloc(sizeof(MaxExpansionT
able)); |
| 284 /* test for NULL */ |
| 285 if (r->maxExpansions == NULL) { |
| 286 *status = U_MEMORY_ALLOCATION_ERROR; |
| 287 goto cleanup; |
| 288 } |
| 289 r->maxExpansions->size = t->maxExpansions->size; |
| 290 r->maxExpansions->position = t->maxExpansions->position; |
| 291 if(t->maxExpansions->endExpansionCE != NULL) { |
| 292 r->maxExpansions->endExpansionCE = (uint32_t *)uprv_malloc(sizeof(ui
nt32_t)*t->maxExpansions->size); |
| 293 /* test for NULL */ |
| 294 if (r->maxExpansions->endExpansionCE == NULL) { |
| 295 *status = U_MEMORY_ALLOCATION_ERROR; |
| 296 goto cleanup; |
| 297 } |
| 298 uprv_memset(r->maxExpansions->endExpansionCE, 0xDB, sizeof(uint32_t)
*t->maxExpansions->size); |
| 299 uprv_memcpy(r->maxExpansions->endExpansionCE, t->maxExpansions->endE
xpansionCE, t->maxExpansions->position*sizeof(uint32_t)); |
| 300 } else { |
| 301 r->maxExpansions->endExpansionCE = NULL; |
| 302 } |
| 303 if(t->maxExpansions->expansionCESize != NULL) { |
| 304 r->maxExpansions->expansionCESize = (uint8_t *)uprv_malloc(sizeof(ui
nt8_t)*t->maxExpansions->size); |
| 305 /* test for NULL */ |
| 306 if (r->maxExpansions->expansionCESize == NULL) { |
| 307 *status = U_MEMORY_ALLOCATION_ERROR; |
| 308 goto cleanup; |
| 309 } |
| 310 uprv_memset(r->maxExpansions->expansionCESize, 0xDB, sizeof(uint8_t)
*t->maxExpansions->size); |
| 311 uprv_memcpy(r->maxExpansions->expansionCESize, t->maxExpansions->exp
ansionCESize, t->maxExpansions->position*sizeof(uint8_t)); |
| 312 } else { |
| 313 r->maxExpansions->expansionCESize = NULL; |
| 314 } |
| 315 } |
| 316 |
| 317 if(t->maxJamoExpansions != NULL) { |
| 318 r->maxJamoExpansions = (MaxJamoExpansionTable *)uprv_malloc(sizeof(MaxJa
moExpansionTable)); |
| 319 /* test for NULL */ |
| 320 if (r->maxJamoExpansions == NULL) { |
| 321 *status = U_MEMORY_ALLOCATION_ERROR; |
| 322 goto cleanup; |
| 323 } |
| 324 r->maxJamoExpansions->size = t->maxJamoExpansions->size; |
| 325 r->maxJamoExpansions->position = t->maxJamoExpansions->position; |
| 326 r->maxJamoExpansions->maxLSize = t->maxJamoExpansions->maxLSize; |
| 327 r->maxJamoExpansions->maxVSize = t->maxJamoExpansions->maxVSize; |
| 328 r->maxJamoExpansions->maxTSize = t->maxJamoExpansions->maxTSize; |
| 329 if(t->maxJamoExpansions->size != 0) { |
| 330 r->maxJamoExpansions->endExpansionCE = (uint32_t *)uprv_malloc(sizeo
f(uint32_t)*t->maxJamoExpansions->size); |
| 331 /* test for NULL */ |
| 332 if (r->maxJamoExpansions->endExpansionCE == NULL) { |
| 333 *status = U_MEMORY_ALLOCATION_ERROR; |
| 334 goto cleanup; |
| 335 } |
| 336 uprv_memcpy(r->maxJamoExpansions->endExpansionCE, t->maxJamoExpansio
ns->endExpansionCE, t->maxJamoExpansions->position*sizeof(uint32_t)); |
| 337 r->maxJamoExpansions->isV = (UBool *)uprv_malloc(sizeof(UBool)*t->ma
xJamoExpansions->size); |
| 338 /* test for NULL */ |
| 339 if (r->maxJamoExpansions->isV == NULL) { |
| 340 *status = U_MEMORY_ALLOCATION_ERROR; |
| 341 goto cleanup; |
| 342 } |
| 343 uprv_memcpy(r->maxJamoExpansions->isV, t->maxJamoExpansions->isV, t-
>maxJamoExpansions->position*sizeof(UBool)); |
| 344 } else { |
| 345 r->maxJamoExpansions->endExpansionCE = NULL; |
| 346 r->maxJamoExpansions->isV = NULL; |
| 347 } |
| 348 } |
| 349 |
| 350 if(t->unsafeCP != NULL) { |
| 351 r->unsafeCP = (uint8_t *)uprv_malloc(UCOL_UNSAFECP_TABLE_SIZE); |
| 352 /* test for NULL */ |
| 353 if (r->unsafeCP == NULL) { |
| 354 *status = U_MEMORY_ALLOCATION_ERROR; |
| 355 goto cleanup; |
| 356 } |
| 357 uprv_memcpy(r->unsafeCP, t->unsafeCP, UCOL_UNSAFECP_TABLE_SIZE); |
| 358 } |
| 359 |
| 360 if(t->contrEndCP != NULL) { |
| 361 r->contrEndCP = (uint8_t *)uprv_malloc(UCOL_UNSAFECP_TABLE_SIZE); |
| 362 /* test for NULL */ |
| 363 if (r->contrEndCP == NULL) { |
| 364 *status = U_MEMORY_ALLOCATION_ERROR; |
| 365 goto cleanup; |
| 366 } |
| 367 uprv_memcpy(r->contrEndCP, t->contrEndCP, UCOL_UNSAFECP_TABLE_SIZE); |
| 368 } |
| 369 |
| 370 r->UCA = t->UCA; |
| 371 r->image = t->image; |
| 372 r->options = t->options; |
| 373 |
| 374 return r; |
| 375 cleanup: |
| 376 uprv_uca_closeTempTable(t); |
| 377 return NULL; |
| 378 } |
| 379 |
| 380 |
| 381 U_CAPI void U_EXPORT2 |
| 382 uprv_uca_closeTempTable(tempUCATable *t) { |
| 383 if(t != NULL) { |
| 384 if (t->expansions != NULL) { |
| 385 uprv_free(t->expansions->CEs); |
| 386 uprv_free(t->expansions); |
| 387 } |
| 388 if(t->contractions != NULL) { |
| 389 uprv_cnttab_close(t->contractions); |
| 390 } |
| 391 if (t->mapping != NULL) { |
| 392 utrie_close(t->mapping); |
| 393 } |
| 394 |
| 395 if(t->prefixLookup != NULL) { |
| 396 uhash_close(t->prefixLookup); |
| 397 } |
| 398 |
| 399 if (t->maxExpansions != NULL) { |
| 400 uprv_free(t->maxExpansions->endExpansionCE); |
| 401 uprv_free(t->maxExpansions->expansionCESize); |
| 402 uprv_free(t->maxExpansions); |
| 403 } |
| 404 |
| 405 if (t->maxJamoExpansions->size > 0) { |
| 406 uprv_free(t->maxJamoExpansions->endExpansionCE); |
| 407 uprv_free(t->maxJamoExpansions->isV); |
| 408 } |
| 409 uprv_free(t->maxJamoExpansions); |
| 410 |
| 411 uprv_free(t->unsafeCP); |
| 412 uprv_free(t->contrEndCP); |
| 413 |
| 414 if (t->cmLookup != NULL) { |
| 415 uprv_free(t->cmLookup->cPoints); |
| 416 uprv_free(t->cmLookup); |
| 417 } |
| 418 |
| 419 uprv_free(t); |
| 420 } |
| 421 } |
| 422 |
| 423 /** |
| 424 * Looks for the maximum length of all expansion sequences ending with the same |
| 425 * collation element. The size required for maxexpansion and maxsize is |
| 426 * returned if the arrays are too small. |
| 427 * @param endexpansion the last expansion collation element to be added |
| 428 * @param expansionsize size of the expansion |
| 429 * @param maxexpansion data structure to store the maximum expansion data. |
| 430 * @param status error status |
| 431 * @returns size of the maxexpansion and maxsize used. |
| 432 */ |
| 433 static int uprv_uca_setMaxExpansion(uint32_t endexpansion, |
| 434 uint8_t expansionsize, |
| 435 MaxExpansionTable *maxexpansion, |
| 436 UErrorCode *status) |
| 437 { |
| 438 if (maxexpansion->size == 0) { |
| 439 /* we'll always make the first element 0, for easier manipulation */ |
| 440 maxexpansion->endExpansionCE = |
| 441 (uint32_t *)uprv_malloc(INIT_EXP_TABLE_SIZE * sizeof(int32_t)); |
| 442 /* test for NULL */ |
| 443 if (maxexpansion->endExpansionCE == NULL) { |
| 444 *status = U_MEMORY_ALLOCATION_ERROR; |
| 445 return 0; |
| 446 } |
| 447 *(maxexpansion->endExpansionCE) = 0; |
| 448 maxexpansion->expansionCESize = |
| 449 (uint8_t *)uprv_malloc(INIT_EXP_TABLE_SIZE * sizeof(uint8_t)); |
| 450 /* test for NULL */; |
| 451 if (maxexpansion->expansionCESize == NULL) { |
| 452 *status = U_MEMORY_ALLOCATION_ERROR; |
| 453 return 0; |
| 454 } |
| 455 *(maxexpansion->expansionCESize) = 0; |
| 456 maxexpansion->size = INIT_EXP_TABLE_SIZE; |
| 457 maxexpansion->position = 0; |
| 458 } |
| 459 |
| 460 if (maxexpansion->position + 1 == maxexpansion->size) { |
| 461 uint32_t *neweece = (uint32_t *)uprv_realloc(maxexpansion->endExpansionC
E, |
| 462 2 * maxexpansion->size * sizeof(uint32_t)); |
| 463 if (neweece == NULL) { |
| 464 *status = U_MEMORY_ALLOCATION_ERROR; |
| 465 return 0; |
| 466 } |
| 467 maxexpansion->endExpansionCE = neweece; |
| 468 |
| 469 uint8_t *neweces = (uint8_t *)uprv_realloc(maxexpansion->expansionCESiz
e, |
| 470 2 * maxexpansion->size * sizeof(uint8_t)); |
| 471 if (neweces == NULL) { |
| 472 *status = U_MEMORY_ALLOCATION_ERROR; |
| 473 return 0; |
| 474 } |
| 475 maxexpansion->expansionCESize = neweces; |
| 476 maxexpansion->size *= 2; |
| 477 } |
| 478 |
| 479 uint32_t *pendexpansionce = maxexpansion->endExpansionCE; |
| 480 uint8_t *pexpansionsize = maxexpansion->expansionCESize; |
| 481 int pos = maxexpansion->position; |
| 482 |
| 483 uint32_t *start = pendexpansionce; |
| 484 uint32_t *limit = pendexpansionce + pos; |
| 485 |
| 486 /* using binary search to determine if last expansion element is |
| 487 already in the array */ |
| 488 uint32_t *mid; |
| 489 int result = -1; |
| 490 while (start < limit - 1) { |
| 491 mid = start + ((limit - start) >> 1); |
| 492 if (endexpansion <= *mid) { |
| 493 limit = mid; |
| 494 } |
| 495 else { |
| 496 start = mid; |
| 497 } |
| 498 } |
| 499 |
| 500 if (*start == endexpansion) { |
| 501 result = (int)(start - pendexpansionce); |
| 502 } |
| 503 else if (*limit == endexpansion) { |
| 504 result = (int)(limit - pendexpansionce); |
| 505 } |
| 506 |
| 507 if (result > -1) { |
| 508 /* found the ce in expansion, we'll just modify the size if it is |
| 509 smaller */ |
| 510 uint8_t *currentsize = pexpansionsize + result; |
| 511 if (*currentsize < expansionsize) { |
| 512 *currentsize = expansionsize; |
| 513 } |
| 514 } |
| 515 else { |
| 516 /* we'll need to squeeze the value into the array. |
| 517 initial implementation. */ |
| 518 /* shifting the subarray down by 1 */ |
| 519 int shiftsize = (int)((pendexpansionce + pos) - start); |
| 520 uint32_t *shiftpos = start + 1; |
| 521 uint8_t *sizeshiftpos = pexpansionsize + (shiftpos - pendexpansionce); |
| 522 |
| 523 /* okay need to rearrange the array into sorted order */ |
| 524 if (shiftsize == 0 /*|| *(pendexpansionce + pos) < endexpansion*/) { /*
the commented part is actually both redundant and dangerous */ |
| 525 *(pendexpansionce + pos + 1) = endexpansion; |
| 526 *(pexpansionsize + pos + 1) = expansionsize; |
| 527 } |
| 528 else { |
| 529 uprv_memmove(shiftpos + 1, shiftpos, shiftsize * sizeof(int32_t)); |
| 530 uprv_memmove(sizeshiftpos + 1, sizeshiftpos, |
| 531 shiftsize * sizeof(uint8_t)); |
| 532 *shiftpos = endexpansion; |
| 533 *sizeshiftpos = expansionsize; |
| 534 } |
| 535 maxexpansion->position ++; |
| 536 |
| 537 #ifdef UCOL_DEBUG |
| 538 int temp; |
| 539 UBool found = FALSE; |
| 540 for (temp = 0; temp < maxexpansion->position; temp ++) { |
| 541 if (pendexpansionce[temp] >= pendexpansionce[temp + 1]) { |
| 542 fprintf(stderr, "expansions %d\n", temp); |
| 543 } |
| 544 if (pendexpansionce[temp] == endexpansion) { |
| 545 found =TRUE; |
| 546 if (pexpansionsize[temp] < expansionsize) { |
| 547 fprintf(stderr, "expansions size %d\n", temp); |
| 548 } |
| 549 } |
| 550 } |
| 551 if (pendexpansionce[temp] == endexpansion) { |
| 552 found =TRUE; |
| 553 if (pexpansionsize[temp] < expansionsize) { |
| 554 fprintf(stderr, "expansions size %d\n", temp); |
| 555 } |
| 556 } |
| 557 if (!found) |
| 558 fprintf(stderr, "expansion not found %d\n", temp); |
| 559 #endif |
| 560 } |
| 561 |
| 562 return maxexpansion->position; |
| 563 } |
| 564 |
| 565 /** |
| 566 * Sets the maximum length of all jamo expansion sequences ending with the same |
| 567 * collation element. The size required for maxexpansion and maxsize is |
| 568 * returned if the arrays are too small. |
| 569 * @param ch the jamo codepoint |
| 570 * @param endexpansion the last expansion collation element to be added |
| 571 * @param expansionsize size of the expansion |
| 572 * @param maxexpansion data structure to store the maximum expansion data. |
| 573 * @param status error status |
| 574 * @returns size of the maxexpansion and maxsize used. |
| 575 */ |
| 576 static int uprv_uca_setMaxJamoExpansion(UChar ch, |
| 577 uint32_t endexpansion, |
| 578 uint8_t expansionsize, |
| 579 MaxJamoExpansionTable *maxexpansion, |
| 580 UErrorCode *status) |
| 581 { |
| 582 UBool isV = TRUE; |
| 583 if (((uint32_t)ch - 0x1100) <= (0x1112 - 0x1100)) { |
| 584 /* determines L for Jamo, doesn't need to store this since it is never |
| 585 at the end of a expansion */ |
| 586 if (maxexpansion->maxLSize < expansionsize) { |
| 587 maxexpansion->maxLSize = expansionsize; |
| 588 } |
| 589 return maxexpansion->position; |
| 590 } |
| 591 |
| 592 if (((uint32_t)ch - 0x1161) <= (0x1175 - 0x1161)) { |
| 593 /* determines V for Jamo */ |
| 594 if (maxexpansion->maxVSize < expansionsize) { |
| 595 maxexpansion->maxVSize = expansionsize; |
| 596 } |
| 597 } |
| 598 |
| 599 if (((uint32_t)ch - 0x11A8) <= (0x11C2 - 0x11A8)) { |
| 600 isV = FALSE; |
| 601 /* determines T for Jamo */ |
| 602 if (maxexpansion->maxTSize < expansionsize) { |
| 603 maxexpansion->maxTSize = expansionsize; |
| 604 } |
| 605 } |
| 606 |
| 607 if (maxexpansion->size == 0) { |
| 608 /* we'll always make the first element 0, for easier manipulation */ |
| 609 maxexpansion->endExpansionCE = |
| 610 (uint32_t *)uprv_malloc(INIT_EXP_TABLE_SIZE * sizeof(uint32_t)); |
| 611 /* test for NULL */; |
| 612 if (maxexpansion->endExpansionCE == NULL) { |
| 613 *status = U_MEMORY_ALLOCATION_ERROR; |
| 614 return 0; |
| 615 } |
| 616 *(maxexpansion->endExpansionCE) = 0; |
| 617 maxexpansion->isV = |
| 618 (UBool *)uprv_malloc(INIT_EXP_TABLE_SIZE * sizeof(UBool)); |
| 619 /* test for NULL */; |
| 620 if (maxexpansion->isV == NULL) { |
| 621 *status = U_MEMORY_ALLOCATION_ERROR; |
| 622 uprv_free(maxexpansion->endExpansionCE); |
| 623 maxexpansion->endExpansionCE = NULL; |
| 624 return 0; |
| 625 } |
| 626 *(maxexpansion->isV) = 0; |
| 627 maxexpansion->size = INIT_EXP_TABLE_SIZE; |
| 628 maxexpansion->position = 0; |
| 629 } |
| 630 |
| 631 if (maxexpansion->position + 1 == maxexpansion->size) { |
| 632 maxexpansion->size *= 2; |
| 633 maxexpansion->endExpansionCE = (uint32_t *)uprv_realloc(maxexpansion->en
dExpansionCE, |
| 634 maxexpansion->size * sizeof(uint32_t)); |
| 635 if (maxexpansion->endExpansionCE == NULL) { |
| 636 #ifdef UCOL_DEBUG |
| 637 fprintf(stderr, "out of memory for maxExpansions\n"); |
| 638 #endif |
| 639 *status = U_MEMORY_ALLOCATION_ERROR; |
| 640 return 0; |
| 641 } |
| 642 maxexpansion->isV = (UBool *)uprv_realloc(maxexpansion->isV, |
| 643 maxexpansion->size * sizeof(UBool)); |
| 644 if (maxexpansion->isV == NULL) { |
| 645 #ifdef UCOL_DEBUG |
| 646 fprintf(stderr, "out of memory for maxExpansions\n"); |
| 647 #endif |
| 648 *status = U_MEMORY_ALLOCATION_ERROR; |
| 649 uprv_free(maxexpansion->endExpansionCE); |
| 650 maxexpansion->endExpansionCE = NULL; |
| 651 return 0; |
| 652 } |
| 653 } |
| 654 |
| 655 uint32_t *pendexpansionce = maxexpansion->endExpansionCE; |
| 656 int pos = maxexpansion->position; |
| 657 |
| 658 while (pos > 0) { |
| 659 pos --; |
| 660 if (*(pendexpansionce + pos) == endexpansion) { |
| 661 return maxexpansion->position; |
| 662 } |
| 663 } |
| 664 |
| 665 *(pendexpansionce + maxexpansion->position) = endexpansion; |
| 666 *(maxexpansion->isV + maxexpansion->position) = isV; |
| 667 maxexpansion->position ++; |
| 668 |
| 669 return maxexpansion->position; |
| 670 } |
| 671 |
| 672 |
| 673 static void ContrEndCPSet(uint8_t *table, UChar c) { |
| 674 uint32_t hash; |
| 675 uint8_t *htByte; |
| 676 |
| 677 hash = c; |
| 678 if (hash >= UCOL_UNSAFECP_TABLE_SIZE*8) { |
| 679 hash = (hash & UCOL_UNSAFECP_TABLE_MASK) + 256; |
| 680 } |
| 681 htByte = &table[hash>>3]; |
| 682 *htByte |= (1 << (hash & 7)); |
| 683 } |
| 684 |
| 685 |
| 686 static void unsafeCPSet(uint8_t *table, UChar c) { |
| 687 uint32_t hash; |
| 688 uint8_t *htByte; |
| 689 |
| 690 hash = c; |
| 691 if (hash >= UCOL_UNSAFECP_TABLE_SIZE*8) { |
| 692 if (hash >= 0xd800 && hash <= 0xf8ff) { |
| 693 /* Part of a surrogate, or in private use area. */ |
| 694 /* These don't go in the table */ |
| 695 return; |
| 696 } |
| 697 hash = (hash & UCOL_UNSAFECP_TABLE_MASK) + 256; |
| 698 } |
| 699 htByte = &table[hash>>3]; |
| 700 *htByte |= (1 << (hash & 7)); |
| 701 } |
| 702 |
| 703 static void |
| 704 uprv_uca_createCMTable(tempUCATable *t, int32_t noOfCM, UErrorCode *status) { |
| 705 t->cmLookup = (CombinClassTable *)uprv_malloc(sizeof(CombinClassTable)); |
| 706 if (t->cmLookup==NULL) { |
| 707 *status = U_MEMORY_ALLOCATION_ERROR; |
| 708 return; |
| 709 } |
| 710 t->cmLookup->cPoints=(UChar *)uprv_malloc(noOfCM*sizeof(UChar)); |
| 711 if (t->cmLookup->cPoints ==NULL) { |
| 712 uprv_free(t->cmLookup); |
| 713 t->cmLookup = NULL; |
| 714 *status = U_MEMORY_ALLOCATION_ERROR; |
| 715 return; |
| 716 } |
| 717 |
| 718 t->cmLookup->size=noOfCM; |
| 719 uprv_memset(t->cmLookup->index, 0, sizeof(t->cmLookup->index)); |
| 720 |
| 721 return; |
| 722 } |
| 723 |
| 724 static void |
| 725 uprv_uca_copyCMTable(tempUCATable *t, UChar *cm, uint16_t *index) { |
| 726 int32_t count=0; |
| 727 |
| 728 for (int32_t i=0; i<256; ++i) { |
| 729 if (index[i]>0) { |
| 730 // cPoints is ordered by combining class value. |
| 731 uprv_memcpy(t->cmLookup->cPoints+count, cm+(i<<8), index[i]*sizeof(U
Char)); |
| 732 count += index[i]; |
| 733 } |
| 734 t->cmLookup->index[i]=count; |
| 735 } |
| 736 return; |
| 737 } |
| 738 |
| 739 /* 1. to the UnsafeCP hash table, add all chars with combining class != 0 */ |
| 740 /* 2. build combining marks table for all chars with combining class != 0 */ |
| 741 static void uprv_uca_unsafeCPAddCCNZ(tempUCATable *t, UErrorCode *status) { |
| 742 |
| 743 UChar c; |
| 744 uint16_t fcd; // Hi byte is lead combining class. |
| 745 // lo byte is trailing combing class. |
| 746 const uint16_t *fcdTrieIndex; |
| 747 UChar32 fcdHighStart; |
| 748 UBool buildCMTable = (t->cmLookup==NULL); // flag for building combining cla
ss table |
| 749 UChar *cm=NULL; |
| 750 uint16_t index[256]; |
| 751 int32_t count=0; |
| 752 fcdTrieIndex = unorm_getFCDTrieIndex(fcdHighStart, status); |
| 753 if (U_FAILURE(*status)) { |
| 754 return; |
| 755 } |
| 756 |
| 757 if (buildCMTable) { |
| 758 if (cm==NULL) { |
| 759 cm = (UChar *)uprv_malloc(sizeof(UChar)*UCOL_MAX_CM_TAB); |
| 760 if (cm==NULL) { |
| 761 *status = U_MEMORY_ALLOCATION_ERROR; |
| 762 return; |
| 763 } |
| 764 } |
| 765 uprv_memset(index, 0, sizeof(index)); |
| 766 } |
| 767 for (c=0; c<0xffff; c++) { |
| 768 fcd = unorm_getFCD16(fcdTrieIndex, c); |
| 769 if (fcd >= 0x100 || // if the leading combining class(c) >
0 || |
| 770 (UTF_IS_LEAD(c) && fcd != 0)) {// c is a leading surrogate with s
ome FCD data |
| 771 if (buildCMTable) { |
| 772 uint32_t cClass = fcd & 0xff; |
| 773 //uint32_t temp=(cClass<<8)+index[cClass]; |
| 774 cm[(cClass<<8)+index[cClass]] = c; // |
| 775 index[cClass]++; |
| 776 count++; |
| 777 } |
| 778 unsafeCPSet(t->unsafeCP, c); |
| 779 } |
| 780 } |
| 781 |
| 782 // copy to cm table |
| 783 if (buildCMTable) { |
| 784 uprv_uca_createCMTable(t, count, status); |
| 785 if(U_FAILURE(*status)) { |
| 786 if (cm!=NULL) { |
| 787 uprv_free(cm); |
| 788 } |
| 789 return; |
| 790 } |
| 791 uprv_uca_copyCMTable(t, cm, index); |
| 792 } |
| 793 |
| 794 if(t->prefixLookup != NULL) { |
| 795 int32_t i = -1; |
| 796 const UHashElement *e = NULL; |
| 797 UCAElements *element = NULL; |
| 798 UChar NFCbuf[256]; |
| 799 uint32_t NFCbufLen = 0; |
| 800 while((e = uhash_nextElement(t->prefixLookup, &i)) != NULL) { |
| 801 element = (UCAElements *)e->value.pointer; |
| 802 // codepoints here are in the NFD form. We need to add the |
| 803 // first code point of the NFC form to unsafe, because |
| 804 // strcoll needs to backup over them. |
| 805 NFCbufLen = unorm_normalize(element->cPoints, element->cSize, UNORM_
NFC, 0, |
| 806 NFCbuf, 256, status); |
| 807 unsafeCPSet(t->unsafeCP, NFCbuf[0]); |
| 808 } |
| 809 } |
| 810 |
| 811 if (cm!=NULL) { |
| 812 uprv_free(cm); |
| 813 } |
| 814 } |
| 815 |
| 816 static uint32_t uprv_uca_addPrefix(tempUCATable *t, uint32_t CE, |
| 817 UCAElements *element, UErrorCode *status) |
| 818 { |
| 819 // currently the longest prefix we're supporting in Japanese is two characte
rs |
| 820 // long. Although this table could quite easily mimic complete contraction s
tuff |
| 821 // there is no good reason to make a general solution, as it would require s
ome |
| 822 // error prone messing. |
| 823 CntTable *contractions = t->contractions; |
| 824 UChar32 cp; |
| 825 uint32_t cpsize = 0; |
| 826 UChar *oldCP = element->cPoints; |
| 827 uint32_t oldCPSize = element->cSize; |
| 828 |
| 829 |
| 830 contractions->currentTag = SPEC_PROC_TAG; |
| 831 |
| 832 // here, we will normalize & add prefix to the table. |
| 833 uint32_t j = 0; |
| 834 #ifdef UCOL_DEBUG |
| 835 for(j=0; j<element->cSize; j++) { |
| 836 fprintf(stdout, "CP: %04X ", element->cPoints[j]); |
| 837 } |
| 838 fprintf(stdout, "El: %08X Pref: ", CE); |
| 839 for(j=0; j<element->prefixSize; j++) { |
| 840 fprintf(stdout, "%04X ", element->prefix[j]); |
| 841 } |
| 842 fprintf(stdout, "%08X ", element->mapCE); |
| 843 #endif |
| 844 |
| 845 for (j = 1; j<element->prefixSize; j++) { /* First add NFD prefix chars to
unsafe CP hash table */ |
| 846 // Unless it is a trail surrogate, which is handled algoritmically and |
| 847 // shouldn't take up space in the table. |
| 848 if(!(UTF_IS_TRAIL(element->prefix[j]))) { |
| 849 unsafeCPSet(t->unsafeCP, element->prefix[j]); |
| 850 } |
| 851 } |
| 852 |
| 853 UChar tempPrefix = 0; |
| 854 |
| 855 for(j = 0; j < /*nfcSize*/element->prefixSize/2; j++) { // prefixes are goin
g to be looked up backwards |
| 856 // therefore, we will promptly reverse the prefix buffer... |
| 857 tempPrefix = *(/*nfcBuffer*/element->prefix+element->prefixSize-j-1); |
| 858 *(/*nfcBuffer*/element->prefix+element->prefixSize-j-1) = element->prefi
x[j]; |
| 859 element->prefix[j] = tempPrefix; |
| 860 } |
| 861 |
| 862 #ifdef UCOL_DEBUG |
| 863 fprintf(stdout, "Reversed: "); |
| 864 for(j=0; j<element->prefixSize; j++) { |
| 865 fprintf(stdout, "%04X ", element->prefix[j]); |
| 866 } |
| 867 fprintf(stdout, "%08X\n", element->mapCE); |
| 868 #endif |
| 869 |
| 870 // the first codepoint is also unsafe, as it forms a 'contraction' with the
prefix |
| 871 if(!(UTF_IS_TRAIL(element->cPoints[0]))) { |
| 872 unsafeCPSet(t->unsafeCP, element->cPoints[0]); |
| 873 } |
| 874 |
| 875 // Maybe we need this... To handle prefixes completely in the forward direct
ion... |
| 876 //if(element->cSize == 1) { |
| 877 // if(!(UTF_IS_TRAIL(element->cPoints[0]))) { |
| 878 // ContrEndCPSet(t->contrEndCP, element->cPoints[0]); |
| 879 // } |
| 880 //} |
| 881 |
| 882 element->cPoints = element->prefix; |
| 883 element->cSize = element->prefixSize; |
| 884 |
| 885 // Add the last char of the contraction to the contraction-end hash table. |
| 886 // unless it is a trail surrogate, which is handled algorithmically and |
| 887 // shouldn't be in the table |
| 888 if(!(UTF_IS_TRAIL(element->cPoints[element->cSize -1]))) { |
| 889 ContrEndCPSet(t->contrEndCP, element->cPoints[element->cSize -1]); |
| 890 } |
| 891 |
| 892 // First we need to check if contractions starts with a surrogate |
| 893 UTF_NEXT_CHAR(element->cPoints, cpsize, element->cSize, cp); |
| 894 |
| 895 // If there are any Jamos in the contraction, we should turn on special |
| 896 // processing for Jamos |
| 897 if(UCOL_ISJAMO(element->prefix[0])) { |
| 898 t->image->jamoSpecial = TRUE; |
| 899 } |
| 900 /* then we need to deal with it */ |
| 901 /* we could aready have something in table - or we might not */ |
| 902 |
| 903 if(!isPrefix(CE)) { |
| 904 /* if it wasn't contraction, we wouldn't end up here*/ |
| 905 int32_t firstContractionOffset = 0; |
| 906 firstContractionOffset = uprv_cnttab_addContraction(contractions, UPRV_C
NTTAB_NEWELEMENT, 0, CE, status); |
| 907 uint32_t newCE = uprv_uca_processContraction(contractions, element, UCOL
_NOT_FOUND, status); |
| 908 uprv_cnttab_addContraction(contractions, firstContractionOffset, *elemen
t->prefix, newCE, status); |
| 909 uprv_cnttab_addContraction(contractions, firstContractionOffset, 0xFFFF,
CE, status); |
| 910 CE = constructContractCE(SPEC_PROC_TAG, firstContractionOffset); |
| 911 } else { /* we are adding to existing contraction */ |
| 912 /* there were already some elements in the table, so we need to add a ne
w contraction */ |
| 913 /* Two things can happen here: either the codepoint is already in the ta
ble, or it is not */ |
| 914 int32_t position = uprv_cnttab_findCP(contractions, CE, *element->prefix
, status); |
| 915 if(position > 0) { /* if it is we just continue down the chain */ |
| 916 uint32_t eCE = uprv_cnttab_getCE(contractions, CE, position, status)
; |
| 917 uint32_t newCE = uprv_uca_processContraction(contractions, element,
eCE, status); |
| 918 uprv_cnttab_setContraction(contractions, CE, position, *(element->pr
efix), newCE, status); |
| 919 } else { /* if it isn't, we will have to create a new s
equence */ |
| 920 uprv_uca_processContraction(contractions, element, UCOL_NOT_FOUND, s
tatus); |
| 921 uprv_cnttab_insertContraction(contractions, CE, *(element->prefix),
element->mapCE, status); |
| 922 } |
| 923 } |
| 924 |
| 925 element->cPoints = oldCP; |
| 926 element->cSize = oldCPSize; |
| 927 |
| 928 return CE; |
| 929 } |
| 930 |
| 931 // Note regarding surrogate handling: We are interested only in the single |
| 932 // or leading surrogates in a contraction. If a surrogate is somewhere else |
| 933 // in the contraction, it is going to be handled as a pair of code units, |
| 934 // as it doesn't affect the performance AND handling surrogates specially |
| 935 // would complicate code way too much. |
| 936 static uint32_t uprv_uca_addContraction(tempUCATable *t, uint32_t CE, |
| 937 UCAElements *element, UErrorCode *status
) |
| 938 { |
| 939 CntTable *contractions = t->contractions; |
| 940 UChar32 cp; |
| 941 uint32_t cpsize = 0; |
| 942 |
| 943 contractions->currentTag = CONTRACTION_TAG; |
| 944 |
| 945 // First we need to check if contractions starts with a surrogate |
| 946 UTF_NEXT_CHAR(element->cPoints, cpsize, element->cSize, cp); |
| 947 |
| 948 if(cpsize<element->cSize) { // This is a real contraction, if there are othe
r characters after the first |
| 949 uint32_t j = 0; |
| 950 for (j=1; j<element->cSize; j++) { /* First add contraction chars to u
nsafe CP hash table */ |
| 951 // Unless it is a trail surrogate, which is handled algoritmically a
nd |
| 952 // shouldn't take up space in the table. |
| 953 if(!(UTF_IS_TRAIL(element->cPoints[j]))) { |
| 954 unsafeCPSet(t->unsafeCP, element->cPoints[j]); |
| 955 } |
| 956 } |
| 957 // Add the last char of the contraction to the contraction-end hash tabl
e. |
| 958 // unless it is a trail surrogate, which is handled algorithmically and |
| 959 // shouldn't be in the table |
| 960 if(!(UTF_IS_TRAIL(element->cPoints[element->cSize -1]))) { |
| 961 ContrEndCPSet(t->contrEndCP, element->cPoints[element->cSize -1]); |
| 962 } |
| 963 |
| 964 // If there are any Jamos in the contraction, we should turn on special |
| 965 // processing for Jamos |
| 966 if(UCOL_ISJAMO(element->cPoints[0])) { |
| 967 t->image->jamoSpecial = TRUE; |
| 968 } |
| 969 /* then we need to deal with it */ |
| 970 /* we could aready have something in table - or we might not */ |
| 971 element->cPoints+=cpsize; |
| 972 element->cSize-=cpsize; |
| 973 if(!isContraction(CE)) { |
| 974 /* if it wasn't contraction, we wouldn't end up here*/ |
| 975 int32_t firstContractionOffset = 0; |
| 976 firstContractionOffset = uprv_cnttab_addContraction(contractions, UP
RV_CNTTAB_NEWELEMENT, 0, CE, status); |
| 977 uint32_t newCE = uprv_uca_processContraction(contractions, element,
UCOL_NOT_FOUND, status); |
| 978 uprv_cnttab_addContraction(contractions, firstContractionOffset, *el
ement->cPoints, newCE, status); |
| 979 uprv_cnttab_addContraction(contractions, firstContractionOffset, 0xF
FFF, CE, status); |
| 980 CE = constructContractCE(CONTRACTION_TAG, firstContractionOffset); |
| 981 } else { /* we are adding to existing contraction */ |
| 982 /* there were already some elements in the table, so we need to add
a new contraction */ |
| 983 /* Two things can happen here: either the codepoint is already in th
e table, or it is not */ |
| 984 int32_t position = uprv_cnttab_findCP(contractions, CE, *element->cP
oints, status); |
| 985 if(position > 0) { /* if it is we just continue down the chain
*/ |
| 986 uint32_t eCE = uprv_cnttab_getCE(contractions, CE, position, sta
tus); |
| 987 uint32_t newCE = uprv_uca_processContraction(contractions, eleme
nt, eCE, status); |
| 988 uprv_cnttab_setContraction(contractions, CE, position, *(element
->cPoints), newCE, status); |
| 989 } else { /* if it isn't, we will have to create a n
ew sequence */ |
| 990 uint32_t newCE = uprv_uca_processContraction(contractions, eleme
nt, UCOL_NOT_FOUND, status); |
| 991 uprv_cnttab_insertContraction(contractions, CE, *(element->cPoin
ts), newCE, status); |
| 992 } |
| 993 } |
| 994 element->cPoints-=cpsize; |
| 995 element->cSize+=cpsize; |
| 996 /*ucmpe32_set(t->mapping, cp, CE);*/ |
| 997 utrie_set32(t->mapping, cp, CE); |
| 998 } else if(!isContraction(CE)) { /* this is just a surrogate, and there is no
contraction */ |
| 999 /*ucmpe32_set(t->mapping, cp, element->mapCE);*/ |
| 1000 utrie_set32(t->mapping, cp, element->mapCE); |
| 1001 } else { /* fill out the first stage of the contraction with the surrogate C
E */ |
| 1002 uprv_cnttab_changeContraction(contractions, CE, 0, element->mapCE, statu
s); |
| 1003 uprv_cnttab_changeContraction(contractions, CE, 0xFFFF, element->mapCE,
status); |
| 1004 } |
| 1005 return CE; |
| 1006 } |
| 1007 |
| 1008 |
| 1009 static uint32_t uprv_uca_processContraction(CntTable *contractions, UCAElements
*element, uint32_t existingCE, UErrorCode *status) { |
| 1010 int32_t firstContractionOffset = 0; |
| 1011 // uint32_t contractionElement = UCOL_NOT_FOUND; |
| 1012 |
| 1013 if(U_FAILURE(*status)) { |
| 1014 return UCOL_NOT_FOUND; |
| 1015 } |
| 1016 |
| 1017 /* end of recursion */ |
| 1018 if(element->cSize == 1) { |
| 1019 if(isCntTableElement(existingCE) && ((UColCETags)getCETag(existingCE) ==
contractions->currentTag)) { |
| 1020 uprv_cnttab_changeContraction(contractions, existingCE, 0, element->
mapCE, status); |
| 1021 uprv_cnttab_changeContraction(contractions, existingCE, 0xFFFF, elem
ent->mapCE, status); |
| 1022 return existingCE; |
| 1023 } else { |
| 1024 return element->mapCE; /*can't do just that. existingCe might be a c
ontraction, meaning that we need to do another step */ |
| 1025 } |
| 1026 } |
| 1027 |
| 1028 /* this recursion currently feeds on the only element we have... We will hav
e to copy it in order to accomodate */ |
| 1029 /* for both backward and forward cycles */ |
| 1030 |
| 1031 /* we encountered either an empty space or a non-contraction element */ |
| 1032 /* this means we are constructing a new contraction sequence */ |
| 1033 element->cPoints++; |
| 1034 element->cSize--; |
| 1035 if(!isCntTableElement(existingCE)) { |
| 1036 /* if it wasn't contraction, we wouldn't end up here*/ |
| 1037 firstContractionOffset = uprv_cnttab_addContraction(contractions, UPRV_C
NTTAB_NEWELEMENT, 0, existingCE, status); |
| 1038 uint32_t newCE = uprv_uca_processContraction(contractions, element, UCOL
_NOT_FOUND, status); |
| 1039 uprv_cnttab_addContraction(contractions, firstContractionOffset, *elemen
t->cPoints, newCE, status); |
| 1040 uprv_cnttab_addContraction(contractions, firstContractionOffset, 0xFFFF,
existingCE, status); |
| 1041 existingCE = constructContractCE(contractions->currentTag, firstContrac
tionOffset); |
| 1042 } else { /* we are adding to existing contraction */ |
| 1043 /* there were already some elements in the table, so we need to add a ne
w contraction */ |
| 1044 /* Two things can happen here: either the codepoint is already in the ta
ble, or it is not */ |
| 1045 int32_t position = uprv_cnttab_findCP(contractions, existingCE, *element
->cPoints, status); |
| 1046 if(position > 0) { /* if it is we just continue down the chain */ |
| 1047 uint32_t eCE = uprv_cnttab_getCE(contractions, existingCE, position,
status); |
| 1048 uint32_t newCE = uprv_uca_processContraction(contractions, element,
eCE, status); |
| 1049 uprv_cnttab_setContraction(contractions, existingCE, position, *(ele
ment->cPoints), newCE, status); |
| 1050 } else { /* if it isn't, we will have to create a new s
equence */ |
| 1051 uint32_t newCE = uprv_uca_processContraction(contractions, element,
UCOL_NOT_FOUND, status); |
| 1052 uprv_cnttab_insertContraction(contractions, existingCE, *(element->c
Points), newCE, status); |
| 1053 } |
| 1054 } |
| 1055 element->cPoints--; |
| 1056 element->cSize++; |
| 1057 return existingCE; |
| 1058 } |
| 1059 |
| 1060 static uint32_t uprv_uca_finalizeAddition(tempUCATable *t, UCAElements *element,
UErrorCode *status) { |
| 1061 uint32_t CE = UCOL_NOT_FOUND; |
| 1062 // This should add a completely ignorable element to the |
| 1063 // unsafe table, so that backward iteration will skip |
| 1064 // over it when treating contractions. |
| 1065 uint32_t i = 0; |
| 1066 if(element->mapCE == 0) { |
| 1067 for(i = 0; i < element->cSize; i++) { |
| 1068 if(!UTF_IS_TRAIL(element->cPoints[i])) { |
| 1069 unsafeCPSet(t->unsafeCP, element->cPoints[i]); |
| 1070 } |
| 1071 } |
| 1072 } |
| 1073 if(element->cSize > 1) { /* we're adding a contraction */ |
| 1074 uint32_t i = 0; |
| 1075 UChar32 cp; |
| 1076 |
| 1077 UTF_NEXT_CHAR(element->cPoints, i, element->cSize, cp); |
| 1078 /*CE = ucmpe32_get(t->mapping, cp);*/ |
| 1079 CE = utrie_get32(t->mapping, cp, NULL); |
| 1080 |
| 1081 CE = uprv_uca_addContraction(t, CE, element, status); |
| 1082 } else { /* easy case, */ |
| 1083 /*CE = ucmpe32_get(t->mapping, element->cPoints[0]);*/ |
| 1084 CE = utrie_get32(t->mapping, element->cPoints[0], NULL); |
| 1085 |
| 1086 if( CE != UCOL_NOT_FOUND) { |
| 1087 if(isCntTableElement(CE) /*isContraction(CE)*/) { /* adding a non co
ntraction element (thai, expansion, single) to already existing contraction */ |
| 1088 if(!isPrefix(element->mapCE)) { // we cannot reenter prefix elem
ents - as we are going to create a dead loop |
| 1089 // Only expansions and regular CEs can go here... Contractio
ns will never happen in this place |
| 1090 uprv_cnttab_setContraction(t->contractions, CE, 0, 0, elemen
t->mapCE, status); |
| 1091 /* This loop has to change the CE at the end of contraction
REDO!*/ |
| 1092 uprv_cnttab_changeLastCE(t->contractions, CE, element->mapCE
, status); |
| 1093 } |
| 1094 } else { |
| 1095 /*ucmpe32_set(t->mapping, element->cPoints[0], element->mapCE);*
/ |
| 1096 utrie_set32(t->mapping, element->cPoints[0], element->mapCE); |
| 1097 if ((element->prefixSize!=0) && (!isSpecial(CE) || (getCETag(CE)
!=IMPLICIT_TAG))) { |
| 1098 UCAElements *origElem = (UCAElements *)uprv_malloc(sizeof(UC
AElements)); |
| 1099 /* test for NULL */ |
| 1100 if (origElem== NULL) { |
| 1101 *status = U_MEMORY_ALLOCATION_ERROR; |
| 1102 return 0; |
| 1103 } |
| 1104 /* copy the original UCA value */ |
| 1105 origElem->prefixSize = 0; |
| 1106 origElem->prefix = NULL; |
| 1107 origElem->cPoints = origElem->uchars; |
| 1108 origElem->cPoints[0] = element->cPoints[0]; |
| 1109 origElem->cSize = 1; |
| 1110 origElem->CEs[0]=CE; |
| 1111 origElem->mapCE=CE; |
| 1112 origElem->noOfCEs=1; |
| 1113 uprv_uca_finalizeAddition(t, origElem, status); |
| 1114 uprv_free(origElem); |
| 1115 } |
| 1116 #ifdef UCOL_DEBUG |
| 1117 fprintf(stderr, "Warning - trying to overwrite existing data %08
X for cp %04X with %08X\n", CE, element->cPoints[0], element->CEs[0]); |
| 1118 //*status = U_ILLEGAL_ARGUMENT_ERROR; |
| 1119 #endif |
| 1120 } |
| 1121 } else { |
| 1122 /*ucmpe32_set(t->mapping, element->cPoints[0], element->mapCE);*/ |
| 1123 utrie_set32(t->mapping, element->cPoints[0], element->mapCE); |
| 1124 } |
| 1125 } |
| 1126 return CE; |
| 1127 } |
| 1128 |
| 1129 /* This adds a read element, while testing for existence */ |
| 1130 U_CAPI uint32_t U_EXPORT2 |
| 1131 uprv_uca_addAnElement(tempUCATable *t, UCAElements *element, UErrorCode *status)
{ |
| 1132 U_NAMESPACE_USE |
| 1133 |
| 1134 ExpansionTable *expansions = t->expansions; |
| 1135 |
| 1136 uint32_t i = 1; |
| 1137 uint32_t expansion = 0; |
| 1138 uint32_t CE; |
| 1139 |
| 1140 if(U_FAILURE(*status)) { |
| 1141 return 0xFFFF; |
| 1142 } |
| 1143 |
| 1144 element->mapCE = 0; // clear mapCE so that we can catch expansions |
| 1145 |
| 1146 if(element->noOfCEs == 1) { |
| 1147 element->mapCE = element->CEs[0]; |
| 1148 } else { |
| 1149 /* ICU 2.1 long primaries */ |
| 1150 /* unfortunately, it looks like we have to look for a long primary here
*/ |
| 1151 /* since in canonical closure we are going to hit some long primaries fr
om */ |
| 1152 /* the first phase, and they will come back as continuations/expansions
*/ |
| 1153 /* destroying the effect of the previous opitimization */ |
| 1154 /* A long primary is a three byte primary with starting secondaries and
tertiaries */ |
| 1155 /* It can appear in long runs of only primary differences (like east Asi
an tailorings) */ |
| 1156 /* also, it should not be an expansion, as expansions would break with t
his */ |
| 1157 // This part came in from ucol_bld.cpp |
| 1158 //if(tok->expansion == 0 |
| 1159 //&& noOfBytes[0] == 3 && noOfBytes[1] == 1 && noOfBytes[2] == 1 |
| 1160 //&& CEparts[1] == (UCOL_BYTE_COMMON << 24) && CEparts[2] == (UCOL_BYTE_
COMMON << 24)) { |
| 1161 /* we will construct a special CE that will go unchanged to the table */ |
| 1162 if(element->noOfCEs == 2 // a two CE expansion |
| 1163 && isContinuation(element->CEs[1]) // which is a continuation |
| 1164 && (element->CEs[1] & (~(0xFF << 24 | UCOL_CONTINUATION_MARKER))) ==
0 // that has only primaries in continuation, |
| 1165 && (((element->CEs[0]>>8) & 0xFF) == UCOL_BYTE_COMMON) // a common s
econdary |
| 1166 && ((element->CEs[0] & 0xFF) == UCOL_BYTE_COMMON) // and a common te
rtiary |
| 1167 ) |
| 1168 { |
| 1169 #ifdef UCOL_DEBUG |
| 1170 fprintf(stdout, "Long primary %04X\n", element->cPoints[0]); |
| 1171 #endif |
| 1172 element->mapCE = UCOL_SPECIAL_FLAG | (LONG_PRIMARY_TAG<<24) // a lon
g primary special |
| 1173 | ((element->CEs[0]>>8) & 0xFFFF00) // first and second byte of
primary |
| 1174 | ((element->CEs[1]>>24) & 0xFF); // third byte of primary |
| 1175 } |
| 1176 else { |
| 1177 expansion = (uint32_t)(UCOL_SPECIAL_FLAG | (EXPANSION_TAG<<UCOL_TAG_
SHIFT) |
| 1178 | (((uprv_uca_addExpansion(expansions, element->CEs[0], status)+
(headersize>>2))<<4) |
| 1179 & 0xFFFFF0)); |
| 1180 |
| 1181 for(i = 1; i<element->noOfCEs; i++) { |
| 1182 uprv_uca_addExpansion(expansions, element->CEs[i], status); |
| 1183 } |
| 1184 if(element->noOfCEs <= 0xF) { |
| 1185 expansion |= element->noOfCEs; |
| 1186 } else { |
| 1187 uprv_uca_addExpansion(expansions, 0, status); |
| 1188 } |
| 1189 element->mapCE = expansion; |
| 1190 uprv_uca_setMaxExpansion(element->CEs[element->noOfCEs - 1], |
| 1191 (uint8_t)element->noOfCEs, |
| 1192 t->maxExpansions, |
| 1193 status); |
| 1194 if(UCOL_ISJAMO(element->cPoints[0])) { |
| 1195 t->image->jamoSpecial = TRUE; |
| 1196 uprv_uca_setMaxJamoExpansion(element->cPoints[0], |
| 1197 element->CEs[element->noOfCEs - 1], |
| 1198 (uint8_t)element->noOfCEs, |
| 1199 t->maxJamoExpansions, |
| 1200 status); |
| 1201 } |
| 1202 if (U_FAILURE(*status)) { |
| 1203 return 0; |
| 1204 } |
| 1205 } |
| 1206 } |
| 1207 |
| 1208 // We treat digits differently - they are "uber special" and should be |
| 1209 // processed differently if numeric collation is on. |
| 1210 UChar32 uniChar = 0; |
| 1211 //printElement(element); |
| 1212 if ((element->cSize == 2) && U16_IS_LEAD(element->cPoints[0])){ |
| 1213 uniChar = U16_GET_SUPPLEMENTARY(element->cPoints[0], element->cPoints[1]
); |
| 1214 } else if (element->cSize == 1){ |
| 1215 uniChar = element->cPoints[0]; |
| 1216 } |
| 1217 |
| 1218 // Here, we either have one normal CE OR mapCE is set. Therefore, we stuff o
nly |
| 1219 // one element to the expansion buffer. When we encounter a digit and we don
't |
| 1220 // do numeric collation, we will just pick the CE we have and break out of c
ase |
| 1221 // (see ucol.cpp ucol_prv_getSpecialCE && ucol_prv_getSpecialPrevCE). If we
picked |
| 1222 // a special, further processing will occur. If it's a simple CE, we'll retu
rn due |
| 1223 // to how the loop is constructed. |
| 1224 if (uniChar != 0 && u_isdigit(uniChar)){ |
| 1225 expansion = (uint32_t)(UCOL_SPECIAL_FLAG | (DIGIT_TAG<<UCOL_TAG_SHIFT) |
1); // prepare the element |
| 1226 if(element->mapCE) { // if there is an expansion, we'll pick it here |
| 1227 expansion |= ((uprv_uca_addExpansion(expansions, element->mapCE, sta
tus)+(headersize>>2))<<4); |
| 1228 } else { |
| 1229 expansion |= ((uprv_uca_addExpansion(expansions, element->CEs[0], st
atus)+(headersize>>2))<<4); |
| 1230 } |
| 1231 element->mapCE = expansion; |
| 1232 |
| 1233 // Need to go back to the beginning of the digit string if in the middle
! |
| 1234 if(uniChar <= 0xFFFF) { // supplementaries are always unsafe. API takes
UChars |
| 1235 unsafeCPSet(t->unsafeCP, (UChar)uniChar); |
| 1236 } |
| 1237 } |
| 1238 |
| 1239 // here we want to add the prefix structure. |
| 1240 // I will try to process it as a reverse contraction, if possible. |
| 1241 // prefix buffer is already reversed. |
| 1242 |
| 1243 if(element->prefixSize!=0) { |
| 1244 // We keep the seen prefix starter elements in a hashtable |
| 1245 // we need it to be able to distinguish between the simple |
| 1246 // codepoints and prefix starters. Also, we need to use it |
| 1247 // for canonical closure. |
| 1248 |
| 1249 UCAElements *composed = (UCAElements *)uprv_malloc(sizeof(UCAElements)); |
| 1250 /* test for NULL */ |
| 1251 if (composed == NULL) { |
| 1252 *status = U_MEMORY_ALLOCATION_ERROR; |
| 1253 return 0; |
| 1254 } |
| 1255 uprv_memcpy(composed, element, sizeof(UCAElements)); |
| 1256 composed->cPoints = composed->uchars; |
| 1257 composed->prefix = composed->prefixChars; |
| 1258 |
| 1259 composed->prefixSize = unorm_normalize(element->prefix, element->prefixS
ize, UNORM_NFC, 0, composed->prefix, 128, status); |
| 1260 |
| 1261 |
| 1262 if(t->prefixLookup != NULL) { |
| 1263 UCAElements *uCE = (UCAElements *)uhash_get(t->prefixLookup, element
); |
| 1264 if(uCE != NULL) { // there is already a set of code points here |
| 1265 element->mapCE = uprv_uca_addPrefix(t, uCE->mapCE, element, stat
us); |
| 1266 } else { // no code points, so this spot is clean |
| 1267 element->mapCE = uprv_uca_addPrefix(t, UCOL_NOT_FOUND, element,
status); |
| 1268 uCE = (UCAElements *)uprv_malloc(sizeof(UCAElements)); |
| 1269 /* test for NULL */ |
| 1270 if (uCE == NULL) { |
| 1271 *status = U_MEMORY_ALLOCATION_ERROR; |
| 1272 return 0; |
| 1273 } |
| 1274 uprv_memcpy(uCE, element, sizeof(UCAElements)); |
| 1275 uCE->cPoints = uCE->uchars; |
| 1276 uhash_put(t->prefixLookup, uCE, uCE, status); |
| 1277 } |
| 1278 if(composed->prefixSize != element->prefixSize || uprv_memcmp(compos
ed->prefix, element->prefix, element->prefixSize)) { |
| 1279 // do it! |
| 1280 composed->mapCE = uprv_uca_addPrefix(t, element->mapCE, composed
, status); |
| 1281 } |
| 1282 } |
| 1283 uprv_free(composed); |
| 1284 } |
| 1285 |
| 1286 // We need to use the canonical iterator here |
| 1287 // the way we do it is to generate the canonically equivalent strings |
| 1288 // for the contraction and then add the sequences that pass FCD check |
| 1289 if(element->cSize > 1 && !(element->cSize==2 && UTF16_IS_LEAD(element->cPoin
ts[0]) && UTF16_IS_TRAIL(element->cPoints[1]))) { // this is a contraction, we s
hould check whether a composed form should also be included |
| 1290 UnicodeString source(element->cPoints, element->cSize); |
| 1291 CanonicalIterator it(source, *status); |
| 1292 source = it.next(); |
| 1293 while(!source.isBogus()) { |
| 1294 if(Normalizer::quickCheck(source, UNORM_FCD, *status) != UNORM_NO) { |
| 1295 element->cSize = source.extract(element->cPoints, 128, *status); |
| 1296 uprv_uca_finalizeAddition(t, element, status); |
| 1297 } |
| 1298 source = it.next(); |
| 1299 } |
| 1300 CE = element->mapCE; |
| 1301 } else { |
| 1302 CE = uprv_uca_finalizeAddition(t, element, status); |
| 1303 } |
| 1304 |
| 1305 return CE; |
| 1306 } |
| 1307 |
| 1308 |
| 1309 /*void uprv_uca_getMaxExpansionJamo(CompactEIntArray *mapping, */ |
| 1310 static void uprv_uca_getMaxExpansionJamo(UNewTrie *mapping, |
| 1311 MaxExpansionTable *maxexpansion, |
| 1312 MaxJamoExpansionTable *maxjamoexpansion
, |
| 1313 UBool jamospecial, |
| 1314 UErrorCode *status) |
| 1315 { |
| 1316 const uint32_t VBASE = 0x1161; |
| 1317 const uint32_t TBASE = 0x11A8; |
| 1318 const uint32_t VCOUNT = 21; |
| 1319 const uint32_t TCOUNT = 28; |
| 1320 |
| 1321 uint32_t v = VBASE + VCOUNT - 1; |
| 1322 uint32_t t = TBASE + TCOUNT - 1; |
| 1323 uint32_t ce; |
| 1324 |
| 1325 while (v >= VBASE) { |
| 1326 /*ce = ucmpe32_get(mapping, v);*/ |
| 1327 ce = utrie_get32(mapping, v, NULL); |
| 1328 if (ce < UCOL_SPECIAL_FLAG) { |
| 1329 uprv_uca_setMaxExpansion(ce, 2, maxexpansion, status); |
| 1330 } |
| 1331 v --; |
| 1332 } |
| 1333 |
| 1334 while (t >= TBASE) |
| 1335 { |
| 1336 /*ce = ucmpe32_get(mapping, t);*/ |
| 1337 ce = utrie_get32(mapping, t, NULL); |
| 1338 if (ce < UCOL_SPECIAL_FLAG) { |
| 1339 uprv_uca_setMaxExpansion(ce, 3, maxexpansion, status); |
| 1340 } |
| 1341 t --; |
| 1342 } |
| 1343 /* According to the docs, 99% of the time, the Jamo will not be special */ |
| 1344 if (jamospecial) { |
| 1345 /* gets the max expansion in all unicode characters */ |
| 1346 int count = maxjamoexpansion->position; |
| 1347 uint8_t maxTSize = (uint8_t)(maxjamoexpansion->maxLSize + |
| 1348 maxjamoexpansion->maxVSize + |
| 1349 maxjamoexpansion->maxTSize); |
| 1350 uint8_t maxVSize = (uint8_t)(maxjamoexpansion->maxLSize + |
| 1351 maxjamoexpansion->maxVSize); |
| 1352 |
| 1353 while (count > 0) { |
| 1354 count --; |
| 1355 if (*(maxjamoexpansion->isV + count) == TRUE) { |
| 1356 uprv_uca_setMaxExpansion( |
| 1357 *(maxjamoexpansion->endExpansionCE + count), |
| 1358 maxVSize, maxexpansion, status); |
| 1359 } |
| 1360 else { |
| 1361 uprv_uca_setMaxExpansion( |
| 1362 *(maxjamoexpansion->endExpansionCE + count), |
| 1363 maxTSize, maxexpansion, status); |
| 1364 } |
| 1365 } |
| 1366 } |
| 1367 } |
| 1368 |
| 1369 U_CDECL_BEGIN |
| 1370 static inline uint32_t U_CALLCONV |
| 1371 getFoldedValue(UNewTrie *trie, UChar32 start, int32_t offset) |
| 1372 { |
| 1373 uint32_t value; |
| 1374 uint32_t tag; |
| 1375 UChar32 limit; |
| 1376 UBool inBlockZero; |
| 1377 |
| 1378 limit=start+0x400; |
| 1379 while(start<limit) { |
| 1380 value=utrie_get32(trie, start, &inBlockZero); |
| 1381 tag = getCETag(value); |
| 1382 if(inBlockZero == TRUE) { |
| 1383 start+=UTRIE_DATA_BLOCK_LENGTH; |
| 1384 } else if(!(isSpecial(value) && (tag == IMPLICIT_TAG || tag == NOT_FOUND
_TAG))) { |
| 1385 /* These are values that are starting in either UCA (IMPLICIT_TAG) o
r in the |
| 1386 * tailorings (NOT_FOUND_TAG). Presence of these tags means that ther
e is |
| 1387 * nothing in this position and that it should be skipped. |
| 1388 */ |
| 1389 #ifdef UCOL_DEBUG |
| 1390 static int32_t count = 1; |
| 1391 fprintf(stdout, "%i, Folded %08X, value %08X\n", count++, start, val
ue); |
| 1392 #endif |
| 1393 return (uint32_t)(UCOL_SPECIAL_FLAG | (SURROGATE_TAG<<24) | offset); |
| 1394 } else { |
| 1395 ++start; |
| 1396 } |
| 1397 } |
| 1398 return 0; |
| 1399 } |
| 1400 U_CDECL_END |
| 1401 |
| 1402 #ifdef UCOL_DEBUG |
| 1403 // This is a debug function to print the contents of a trie. |
| 1404 // It is used in conjuction with the code around utrie_unserialize call |
| 1405 UBool enumRange(const void *context, UChar32 start, UChar32 limit, uint32_t valu
e) { |
| 1406 if(start<0x10000) { |
| 1407 fprintf(stdout, "%08X, %08X, %08X\n", start, limit, value); |
| 1408 } else { |
| 1409 fprintf(stdout, "%08X=%04X %04X, %08X=%04X %04X, %08X\n", start, UTF16_L
EAD(start), UTF16_TRAIL(start), limit, UTF16_LEAD(limit), UTF16_TRAIL(limit), va
lue); |
| 1410 } |
| 1411 return TRUE; |
| 1412 } |
| 1413 |
| 1414 int32_t |
| 1415 myGetFoldingOffset(uint32_t data) { |
| 1416 if(data > UCOL_NOT_FOUND && getCETag(data) == SURROGATE_TAG) { |
| 1417 return (data&0xFFFFFF); |
| 1418 } else { |
| 1419 return 0; |
| 1420 } |
| 1421 } |
| 1422 #endif |
| 1423 |
| 1424 U_CAPI UCATableHeader* U_EXPORT2 |
| 1425 uprv_uca_assembleTable(tempUCATable *t, UErrorCode *status) { |
| 1426 /*CompactEIntArray *mapping = t->mapping;*/ |
| 1427 UNewTrie *mapping = t->mapping; |
| 1428 ExpansionTable *expansions = t->expansions; |
| 1429 CntTable *contractions = t->contractions; |
| 1430 MaxExpansionTable *maxexpansion = t->maxExpansions; |
| 1431 |
| 1432 if(U_FAILURE(*status)) { |
| 1433 return NULL; |
| 1434 } |
| 1435 |
| 1436 uint32_t beforeContractions = (uint32_t)((headersize+paddedsize(expansions->
position*sizeof(uint32_t)))/sizeof(UChar)); |
| 1437 |
| 1438 int32_t contractionsSize = 0; |
| 1439 contractionsSize = uprv_cnttab_constructTable(contractions, beforeContractio
ns, status); |
| 1440 |
| 1441 /* the following operation depends on the trie data. Therefore, we have to d
o it before */ |
| 1442 /* the trie is compacted */ |
| 1443 /* sets jamo expansions */ |
| 1444 uprv_uca_getMaxExpansionJamo(mapping, maxexpansion, t->maxJamoExpansions, |
| 1445 t->image->jamoSpecial, status); |
| 1446 |
| 1447 /*ucmpe32_compact(mapping);*/ |
| 1448 /*UMemoryStream *ms = uprv_mstrm_openNew(8192);*/ |
| 1449 /*int32_t mappingSize = ucmpe32_flattenMem(mapping, ms);*/ |
| 1450 /*const uint8_t *flattened = uprv_mstrm_getBuffer(ms, &mappingSize);*/ |
| 1451 |
| 1452 // After setting the jamo expansions, compact the trie and get the needed si
ze |
| 1453 int32_t mappingSize = utrie_serialize(mapping, NULL, 0, getFoldedValue /*get
FoldedValue*/, FALSE, status); |
| 1454 |
| 1455 uint32_t tableOffset = 0; |
| 1456 uint8_t *dataStart; |
| 1457 |
| 1458 /* TODO: LATIN1 array is now in the utrie - it should be removed from the ca
lculation */ |
| 1459 |
| 1460 uint32_t toAllocate =(uint32_t)(headersize+
|
| 1461 paddedsize(expansions->position*sizeof(uint32_t))+ |
| 1462 paddedsize(mappingSize)+ |
| 1463 paddedsize(contractionsSize*(sizeof(UChar)+sizeof(uint32_t)))+ |
| 1464 //paddedsize(0x100*sizeof(uint32_t)) /* Latin1 is now included in the t
rie */ |
| 1465 /* maxexpansion array */ |
| 1466 + paddedsize(maxexpansion->position * sizeof(uint32_t)) + |
| 1467 /* maxexpansion size array */ |
| 1468 paddedsize(maxexpansion->position * sizeof(uint8_t)) + |
| 1469 paddedsize(UCOL_UNSAFECP_TABLE_SIZE) + /* Unsafe chars */ |
| 1470 paddedsize(UCOL_UNSAFECP_TABLE_SIZE)); /* Contraction Ending chars *
/ |
| 1471 |
| 1472 |
| 1473 dataStart = (uint8_t *)uprv_malloc(toAllocate); |
| 1474 /* test for NULL */ |
| 1475 if (dataStart == NULL) { |
| 1476 *status = U_MEMORY_ALLOCATION_ERROR; |
| 1477 return NULL; |
| 1478 } |
| 1479 |
| 1480 UCATableHeader *myData = (UCATableHeader *)dataStart; |
| 1481 // Please, do reset all the fields! |
| 1482 uprv_memset(dataStart, 0, toAllocate); |
| 1483 // Make sure we know this is reset |
| 1484 myData->magic = UCOL_HEADER_MAGIC; |
| 1485 myData->isBigEndian = U_IS_BIG_ENDIAN; |
| 1486 myData->charSetFamily = U_CHARSET_FAMILY; |
| 1487 myData->formatVersion[0] = UCA_FORMAT_VERSION_0; |
| 1488 myData->formatVersion[1] = UCA_FORMAT_VERSION_1; |
| 1489 myData->formatVersion[2] = UCA_FORMAT_VERSION_2; |
| 1490 myData->formatVersion[3] = UCA_FORMAT_VERSION_3; |
| 1491 myData->jamoSpecial = t->image->jamoSpecial; |
| 1492 |
| 1493 // Don't copy stuff from UCA header! |
| 1494 //uprv_memcpy(myData, t->image, sizeof(UCATableHeader)); |
| 1495 |
| 1496 myData->contractionSize = contractionsSize; |
| 1497 |
| 1498 tableOffset += (uint32_t)(paddedsize(sizeof(UCATableHeader))); |
| 1499 |
| 1500 myData->options = tableOffset; |
| 1501 uprv_memcpy(dataStart+tableOffset, t->options, sizeof(UColOptionSet)); |
| 1502 tableOffset += (uint32_t)(paddedsize(sizeof(UColOptionSet))); |
| 1503 |
| 1504 /* copy expansions */ |
| 1505 /*myData->expansion = (uint32_t *)dataStart+tableOffset;*/ |
| 1506 myData->expansion = tableOffset; |
| 1507 uprv_memcpy(dataStart+tableOffset, expansions->CEs, expansions->position*siz
eof(uint32_t)); |
| 1508 tableOffset += (uint32_t)(paddedsize(expansions->position*sizeof(uint32_t)))
; |
| 1509 |
| 1510 /* contractions block */ |
| 1511 if(contractionsSize != 0) { |
| 1512 /* copy contraction index */ |
| 1513 /*myData->contractionIndex = (UChar *)(dataStart+tableOffset);*/ |
| 1514 myData->contractionIndex = tableOffset; |
| 1515 uprv_memcpy(dataStart+tableOffset, contractions->codePoints, contraction
sSize*sizeof(UChar)); |
| 1516 tableOffset += (uint32_t)(paddedsize(contractionsSize*sizeof(UChar))); |
| 1517 |
| 1518 /* copy contraction collation elements */ |
| 1519 /*myData->contractionCEs = (uint32_t *)(dataStart+tableOffset);*/ |
| 1520 myData->contractionCEs = tableOffset; |
| 1521 uprv_memcpy(dataStart+tableOffset, contractions->CEs, contractionsSize*s
izeof(uint32_t)); |
| 1522 tableOffset += (uint32_t)(paddedsize(contractionsSize*sizeof(uint32_t)))
; |
| 1523 } else { |
| 1524 myData->contractionIndex = 0; |
| 1525 myData->contractionCEs = 0; |
| 1526 } |
| 1527 |
| 1528 /* copy mapping table */ |
| 1529 /*myData->mappingPosition = dataStart+tableOffset;*/ |
| 1530 /*myData->mappingPosition = tableOffset;*/ |
| 1531 /*uprv_memcpy(dataStart+tableOffset, flattened, mappingSize);*/ |
| 1532 |
| 1533 myData->mappingPosition = tableOffset; |
| 1534 utrie_serialize(mapping, dataStart+tableOffset, toAllocate-tableOffset, getF
oldedValue, FALSE, status); |
| 1535 #ifdef UCOL_DEBUG |
| 1536 // This is debug code to dump the contents of the trie. It needs two functio
ns defined above |
| 1537 { |
| 1538 UTrie UCAt = { 0 }; |
| 1539 uint32_t trieWord; |
| 1540 utrie_unserialize(&UCAt, dataStart+tableOffset, 9999999, status); |
| 1541 UCAt.getFoldingOffset = myGetFoldingOffset; |
| 1542 if(U_SUCCESS(*status)) { |
| 1543 utrie_enum(&UCAt, NULL, enumRange, NULL); |
| 1544 } |
| 1545 trieWord = UTRIE_GET32_FROM_LEAD(&UCAt, 0xDC01); |
| 1546 } |
| 1547 #endif |
| 1548 tableOffset += paddedsize(mappingSize); |
| 1549 |
| 1550 |
| 1551 int32_t i = 0; |
| 1552 |
| 1553 /* copy max expansion table */ |
| 1554 myData->endExpansionCE = tableOffset; |
| 1555 myData->endExpansionCECount = maxexpansion->position - 1; |
| 1556 /* not copying the first element which is a dummy */ |
| 1557 uprv_memcpy(dataStart + tableOffset, maxexpansion->endExpansionCE + 1, |
| 1558 (maxexpansion->position - 1) * sizeof(uint32_t)); |
| 1559 tableOffset += (uint32_t)(paddedsize((maxexpansion->position)* sizeof(uint32
_t))); |
| 1560 myData->expansionCESize = tableOffset; |
| 1561 uprv_memcpy(dataStart + tableOffset, maxexpansion->expansionCESize + 1, |
| 1562 (maxexpansion->position - 1) * sizeof(uint8_t)); |
| 1563 tableOffset += (uint32_t)(paddedsize((maxexpansion->position)* sizeof(uint8_
t))); |
| 1564 |
| 1565 /* Unsafe chars table. Finish it off, then copy it. */ |
| 1566 uprv_uca_unsafeCPAddCCNZ(t, status); |
| 1567 if (t->UCA != 0) { /* Or in unsafebits from UCA, making a combi
ned table. */ |
| 1568 for (i=0; i<UCOL_UNSAFECP_TABLE_SIZE; i++) { |
| 1569 t->unsafeCP[i] |= t->UCA->unsafeCP[i]; |
| 1570 } |
| 1571 } |
| 1572 myData->unsafeCP = tableOffset; |
| 1573 uprv_memcpy(dataStart + tableOffset, t->unsafeCP, UCOL_UNSAFECP_TABLE_SIZE); |
| 1574 tableOffset += paddedsize(UCOL_UNSAFECP_TABLE_SIZE); |
| 1575 |
| 1576 |
| 1577 /* Finish building Contraction Ending chars hash table and then copy it out.
*/ |
| 1578 if (t->UCA != 0) { /* Or in unsafebits from UCA, making a combi
ned table. */ |
| 1579 for (i=0; i<UCOL_UNSAFECP_TABLE_SIZE; i++) { |
| 1580 t->contrEndCP[i] |= t->UCA->contrEndCP[i]; |
| 1581 } |
| 1582 } |
| 1583 myData->contrEndCP = tableOffset; |
| 1584 uprv_memcpy(dataStart + tableOffset, t->contrEndCP, UCOL_UNSAFECP_TABLE_SIZE
); |
| 1585 tableOffset += paddedsize(UCOL_UNSAFECP_TABLE_SIZE); |
| 1586 |
| 1587 if(tableOffset != toAllocate) { |
| 1588 #ifdef UCOL_DEBUG |
| 1589 fprintf(stderr, "calculation screwup!!! Expected to write %i but wrote %
i instead!!!\n", toAllocate, tableOffset); |
| 1590 #endif |
| 1591 *status = U_INTERNAL_PROGRAM_ERROR; |
| 1592 uprv_free(dataStart); |
| 1593 return 0; |
| 1594 } |
| 1595 |
| 1596 myData->size = tableOffset; |
| 1597 /* This should happen upon ressurection */ |
| 1598 /*const uint8_t *mapPosition = (uint8_t*)myData+myData->mappingPosition;*/ |
| 1599 /*uprv_mstrm_close(ms);*/ |
| 1600 return myData; |
| 1601 } |
| 1602 |
| 1603 |
| 1604 struct enumStruct { |
| 1605 tempUCATable *t; |
| 1606 UCollator *tempColl; |
| 1607 UCollationElements* colEl; |
| 1608 const Normalizer2Impl *nfcImpl; |
| 1609 UnicodeSet *closed; |
| 1610 int32_t noOfClosures; |
| 1611 UErrorCode *status; |
| 1612 }; |
| 1613 U_CDECL_BEGIN |
| 1614 static UBool U_CALLCONV |
| 1615 _enumCategoryRangeClosureCategory(const void *context, UChar32 start, UChar32 li
mit, UCharCategory type) { |
| 1616 |
| 1617 if (type != U_UNASSIGNED && type != U_PRIVATE_USE_CHAR) { // if the range is
assigned - we might ommit more categories later |
| 1618 UErrorCode *status = ((enumStruct *)context)->status; |
| 1619 tempUCATable *t = ((enumStruct *)context)->t; |
| 1620 UCollator *tempColl = ((enumStruct *)context)->tempColl; |
| 1621 UCollationElements* colEl = ((enumStruct *)context)->colEl; |
| 1622 UCAElements el; |
| 1623 UChar decompBuffer[4]; |
| 1624 const UChar *decomp; |
| 1625 int32_t noOfDec = 0; |
| 1626 |
| 1627 UChar32 u32 = 0; |
| 1628 UChar comp[2]; |
| 1629 uint32_t len = 0; |
| 1630 |
| 1631 for(u32 = start; u32 < limit; u32++) { |
| 1632 decomp = ((enumStruct *)context)->nfcImpl-> |
| 1633 getDecomposition(u32, decompBuffer, noOfDec); |
| 1634 //if((noOfDec = unorm_normalize(comp, len, UNORM_NFD, 0, decomp, 256
, status)) > 1 |
| 1635 //|| (noOfDec == 1 && *decomp != (UChar)u32)) |
| 1636 if(decomp != NULL) |
| 1637 { |
| 1638 len = 0; |
| 1639 U16_APPEND_UNSAFE(comp, len, u32); |
| 1640 if(ucol_strcoll(tempColl, comp, len, decomp, noOfDec) != UCOL_EQ
UAL) { |
| 1641 #ifdef UCOL_DEBUG |
| 1642 fprintf(stderr, "Closure: U+%04X -> ", u32); |
| 1643 UChar32 c; |
| 1644 int32_t i = 0; |
| 1645 while(i < noOfDec) { |
| 1646 U16_NEXT(decomp, i, noOfDec, c); |
| 1647 fprintf(stderr, "%04X ", c); |
| 1648 } |
| 1649 fprintf(stderr, "\n"); |
| 1650 // print CEs for code point vs. decomposition |
| 1651 fprintf(stderr, "U+%04X CEs: ", u32); |
| 1652 UCollationElements *iter = ucol_openElements(tempColl, comp,
len, status); |
| 1653 int32_t ce; |
| 1654 while((ce = ucol_next(iter, status)) != UCOL_NULLORDER) { |
| 1655 fprintf(stderr, "%08X ", ce); |
| 1656 } |
| 1657 fprintf(stderr, "\nDecomp CEs: "); |
| 1658 ucol_setText(iter, decomp, noOfDec, status); |
| 1659 while((ce = ucol_next(iter, status)) != UCOL_NULLORDER) { |
| 1660 fprintf(stderr, "%08X ", ce); |
| 1661 } |
| 1662 fprintf(stderr, "\n"); |
| 1663 ucol_closeElements(iter); |
| 1664 #endif |
| 1665 if(((enumStruct *)context)->closed != NULL) { |
| 1666 ((enumStruct *)context)->closed->add(u32); |
| 1667 } |
| 1668 ((enumStruct *)context)->noOfClosures++; |
| 1669 el.cPoints = (UChar *)decomp; |
| 1670 el.cSize = noOfDec; |
| 1671 el.noOfCEs = 0; |
| 1672 el.prefix = el.prefixChars; |
| 1673 el.prefixSize = 0; |
| 1674 |
| 1675 UCAElements *prefix=(UCAElements *)uhash_get(t->prefixLookup
, &el); |
| 1676 el.cPoints = comp; |
| 1677 el.cSize = len; |
| 1678 el.prefix = el.prefixChars; |
| 1679 el.prefixSize = 0; |
| 1680 if(prefix == NULL) { |
| 1681 el.noOfCEs = 0; |
| 1682 ucol_setText(colEl, decomp, noOfDec, status); |
| 1683 while((el.CEs[el.noOfCEs] = ucol_next(colEl, status)) !=
(uint32_t)UCOL_NULLORDER) { |
| 1684 el.noOfCEs++; |
| 1685 } |
| 1686 } else { |
| 1687 el.noOfCEs = 1; |
| 1688 el.CEs[0] = prefix->mapCE; |
| 1689 // This character uses a prefix. We have to add it |
| 1690 // to the unsafe table, as it decomposed form is already |
| 1691 // in. In Japanese, this happens for \u309e & \u30fe |
| 1692 // Since unsafeCPSet is static in ucol_elm, we are going |
| 1693 // to wrap it up in the uprv_uca_unsafeCPAddCCNZ functio
n |
| 1694 } |
| 1695 uprv_uca_addAnElement(t, &el, status); |
| 1696 } |
| 1697 } |
| 1698 } |
| 1699 } |
| 1700 return TRUE; |
| 1701 } |
| 1702 U_CDECL_END |
| 1703 |
| 1704 static void |
| 1705 uprv_uca_setMapCE(tempUCATable *t, UCAElements *element, UErrorCode *status) { |
| 1706 uint32_t expansion = 0; |
| 1707 int32_t j; |
| 1708 |
| 1709 ExpansionTable *expansions = t->expansions; |
| 1710 if(element->noOfCEs == 2 // a two CE expansion |
| 1711 && isContinuation(element->CEs[1]) // which is a continuation |
| 1712 && (element->CEs[1] & (~(0xFF << 24 | UCOL_CONTINUATION_MARKER))) == 0 /
/ that has only primaries in continuation, |
| 1713 && (((element->CEs[0]>>8) & 0xFF) == UCOL_BYTE_COMMON) // a common secon
dary |
| 1714 && ((element->CEs[0] & 0xFF) == UCOL_BYTE_COMMON) // and a common tertia
ry |
| 1715 ) { |
| 1716 element->mapCE = UCOL_SPECIAL_FLAG | (LONG_PRIMARY_TAG<<24) // a lon
g primary special |
| 1717 | ((element->CEs[0]>>8) & 0xFFFF00) // first and second byte of
primary |
| 1718 | ((element->CEs[1]>>24) & 0xFF); // third byte of primary |
| 1719 } else { |
| 1720 expansion = (uint32_t)(UCOL_SPECIAL_FLAG | (EXPANSION_TAG<<UCOL_TAG_
SHIFT) |
| 1721 | (((uprv_uca_addExpansion(expansions, element->CEs[0], status)+
(headersize>>2))<<4) |
| 1722 & 0xFFFFF0)); |
| 1723 |
| 1724 for(j = 1; j<(int32_t)element->noOfCEs; j++) { |
| 1725 uprv_uca_addExpansion(expansions, element->CEs[j], status); |
| 1726 } |
| 1727 if(element->noOfCEs <= 0xF) { |
| 1728 expansion |= element->noOfCEs; |
| 1729 } else { |
| 1730 uprv_uca_addExpansion(expansions, 0, status); |
| 1731 } |
| 1732 element->mapCE = expansion; |
| 1733 uprv_uca_setMaxExpansion(element->CEs[element->noOfCEs - 1], |
| 1734 (uint8_t)element->noOfCEs, |
| 1735 t->maxExpansions, |
| 1736 status); |
| 1737 } |
| 1738 } |
| 1739 |
| 1740 static void |
| 1741 uprv_uca_addFCD4AccentedContractions(tempUCATable *t, |
| 1742 UCollationElements* colEl, |
| 1743 UChar *data, |
| 1744 int32_t len, |
| 1745 UCAElements *el, |
| 1746 UErrorCode *status) { |
| 1747 UChar decomp[256], comp[256]; |
| 1748 int32_t decLen, compLen; |
| 1749 |
| 1750 decLen = unorm_normalize(data, len, UNORM_NFD, 0, decomp, 256, status); |
| 1751 compLen = unorm_normalize(data, len, UNORM_NFC, 0, comp, 256, status); |
| 1752 decomp[decLen] = comp[compLen] = 0; |
| 1753 |
| 1754 el->cPoints = decomp; |
| 1755 el->cSize = decLen; |
| 1756 el->noOfCEs = 0; |
| 1757 el->prefixSize = 0; |
| 1758 el->prefix = el->prefixChars; |
| 1759 |
| 1760 UCAElements *prefix=(UCAElements *)uhash_get(t->prefixLookup, el); |
| 1761 el->cPoints = comp; |
| 1762 el->cSize = compLen; |
| 1763 el->prefix = el->prefixChars; |
| 1764 el->prefixSize = 0; |
| 1765 if(prefix == NULL) { |
| 1766 el->noOfCEs = 0; |
| 1767 ucol_setText(colEl, decomp, decLen, status); |
| 1768 while((el->CEs[el->noOfCEs] = ucol_next(colEl, status)) != (uint32_t)UCO
L_NULLORDER) { |
| 1769 el->noOfCEs++; |
| 1770 } |
| 1771 uprv_uca_setMapCE(t, el, status); |
| 1772 uprv_uca_addAnElement(t, el, status); |
| 1773 } |
| 1774 } |
| 1775 |
| 1776 static void |
| 1777 uprv_uca_addMultiCMContractions(tempUCATable *t, |
| 1778 UCollationElements* colEl, |
| 1779 tempTailorContext *c, |
| 1780 UCAElements *el, |
| 1781 UErrorCode *status) { |
| 1782 CombinClassTable *cmLookup = t->cmLookup; |
| 1783 UChar newDecomp[256]; |
| 1784 int32_t maxComp, newDecLen; |
| 1785 UChar32 fcdHighStart; |
| 1786 const uint16_t *fcdTrieIndex = unorm_getFCDTrieIndex(fcdHighStart, status); |
| 1787 if (U_FAILURE(*status)) { |
| 1788 return; |
| 1789 } |
| 1790 int16_t curClass = (unorm_getFCD16(fcdTrieIndex, c->tailoringCM) & 0xff); |
| 1791 CompData *precomp = c->precomp; |
| 1792 int32_t compLen = c->compLen; |
| 1793 UChar *comp = c->comp; |
| 1794 maxComp = c->precompLen; |
| 1795 |
| 1796 for (int32_t j=0; j < maxComp; j++) { |
| 1797 int32_t count=0; |
| 1798 do { |
| 1799 if ( count == 0 ) { // Decompose the saved precomposed char. |
| 1800 UChar temp[2]; |
| 1801 temp[0]=precomp[j].cp; |
| 1802 temp[1]=0; |
| 1803 newDecLen = unorm_normalize(temp, 1, UNORM_NFD, 0, |
| 1804 newDecomp, sizeof(newDecomp)/sizeof(UChar), status); |
| 1805 newDecomp[newDecLen++] = cmLookup->cPoints[c->cmPos]; |
| 1806 } |
| 1807 else { // swap 2 combining marks when they are equal. |
| 1808 uprv_memcpy(newDecomp, c->decomp, sizeof(UChar)*(c->decompLen)); |
| 1809 newDecLen = c->decompLen; |
| 1810 newDecomp[newDecLen++] = precomp[j].cClass; |
| 1811 } |
| 1812 newDecomp[newDecLen] = 0; |
| 1813 compLen = unorm_normalize(newDecomp, newDecLen, UNORM_NFC, 0, |
| 1814 comp, 256, status); |
| 1815 if (compLen==1) { |
| 1816 comp[compLen++] = newDecomp[newDecLen++] = c->tailoringCM; |
| 1817 comp[compLen] = newDecomp[newDecLen] = 0; |
| 1818 el->cPoints = newDecomp; |
| 1819 el->cSize = newDecLen; |
| 1820 |
| 1821 UCAElements *prefix=(UCAElements *)uhash_get(t->prefixLookup, el
); |
| 1822 el->cPoints = c->comp; |
| 1823 el->cSize = compLen; |
| 1824 el->prefix = el->prefixChars; |
| 1825 el->prefixSize = 0; |
| 1826 if(prefix == NULL) { |
| 1827 el->noOfCEs = 0; |
| 1828 ucol_setText(colEl, newDecomp, newDecLen, status); |
| 1829 while((el->CEs[el->noOfCEs] = ucol_next(colEl, status)) != (
uint32_t)UCOL_NULLORDER) { |
| 1830 el->noOfCEs++; |
| 1831 } |
| 1832 uprv_uca_setMapCE(t, el, status); |
| 1833 uprv_uca_finalizeAddition(t, el, status); |
| 1834 |
| 1835 // Save the current precomposed char and its class to find a
ny |
| 1836 // other combining mark combinations. |
| 1837 precomp[c->precompLen].cp=comp[0]; |
| 1838 precomp[c->precompLen].cClass = curClass; |
| 1839 c->precompLen++; |
| 1840 } |
| 1841 } |
| 1842 } while (++count<2 && (precomp[j].cClass == curClass)); |
| 1843 } |
| 1844 |
| 1845 } |
| 1846 |
| 1847 static void |
| 1848 uprv_uca_addTailCanonicalClosures(tempUCATable *t, |
| 1849 UCollationElements* colEl, |
| 1850 UChar baseCh, |
| 1851 UChar cMark, |
| 1852 UCAElements *el, |
| 1853 UErrorCode *status) { |
| 1854 CombinClassTable *cmLookup = t->cmLookup; |
| 1855 UChar32 fcdHighStart; |
| 1856 const uint16_t *fcdTrieIndex = unorm_getFCDTrieIndex(fcdHighStart, status); |
| 1857 if (U_FAILURE(*status)) { |
| 1858 return; |
| 1859 } |
| 1860 int16_t maxIndex = (unorm_getFCD16(fcdTrieIndex, cMark) & 0xff ); |
| 1861 UCAElements element; |
| 1862 uint16_t *index; |
| 1863 UChar decomp[256]; |
| 1864 UChar comp[256]; |
| 1865 CompData precomp[256]; // precomposed array |
| 1866 int32_t precompLen = 0; // count for precomp |
| 1867 int32_t i, len, decompLen, curClass, replacedPos; |
| 1868 tempTailorContext c; |
| 1869 |
| 1870 if ( cmLookup == NULL ) { |
| 1871 return; |
| 1872 } |
| 1873 index = cmLookup->index; |
| 1874 int32_t cClass=(unorm_getFCD16(fcdTrieIndex, cMark) & 0xff); |
| 1875 maxIndex = (int32_t)index[(unorm_getFCD16(fcdTrieIndex, cMark) & 0xff)-1]; |
| 1876 c.comp = comp; |
| 1877 c.decomp = decomp; |
| 1878 c.precomp = precomp; |
| 1879 c.tailoringCM = cMark; |
| 1880 |
| 1881 if (cClass>0) { |
| 1882 maxIndex = (int32_t)index[cClass-1]; |
| 1883 } |
| 1884 else { |
| 1885 maxIndex=0; |
| 1886 } |
| 1887 decomp[0]=baseCh; |
| 1888 for ( i=0; i<maxIndex ; i++ ) { |
| 1889 decomp[1] = cmLookup->cPoints[i]; |
| 1890 decomp[2]=0; |
| 1891 decompLen=2; |
| 1892 len = unorm_normalize(decomp, decompLen, UNORM_NFC, 0, comp, 256, status
); |
| 1893 if (len==1) { |
| 1894 // Save the current precomposed char and its class to find any |
| 1895 // other combining mark combinations. |
| 1896 precomp[precompLen].cp=comp[0]; |
| 1897 curClass = precomp[precompLen].cClass = |
| 1898 index[unorm_getFCD16(fcdTrieIndex, decomp[1]) & 0xff]; |
| 1899 precompLen++; |
| 1900 replacedPos=0; |
| 1901 for (decompLen=0; decompLen< (int32_t)el->cSize; decompLen++) { |
| 1902 decomp[decompLen] = el->cPoints[decompLen]; |
| 1903 if (decomp[decompLen]==cMark) { |
| 1904 replacedPos = decompLen; // record the position for later u
se |
| 1905 } |
| 1906 } |
| 1907 if ( replacedPos != 0 ) { |
| 1908 decomp[replacedPos]=cmLookup->cPoints[i]; |
| 1909 } |
| 1910 decomp[decompLen] = 0; |
| 1911 len = unorm_normalize(decomp, decompLen, UNORM_NFC, 0, comp, 256, st
atus); |
| 1912 comp[len++] = decomp[decompLen++] = cMark; |
| 1913 comp[len] = decomp[decompLen] = 0; |
| 1914 element.cPoints = decomp; |
| 1915 element.cSize = decompLen; |
| 1916 element.noOfCEs = 0; |
| 1917 element.prefix = el->prefixChars; |
| 1918 element.prefixSize = 0; |
| 1919 |
| 1920 UCAElements *prefix=(UCAElements *)uhash_get(t->prefixLookup, &eleme
nt); |
| 1921 element.cPoints = comp; |
| 1922 element.cSize = len; |
| 1923 element.prefix = el->prefixChars; |
| 1924 element.prefixSize = 0; |
| 1925 if(prefix == NULL) { |
| 1926 element.noOfCEs = 0; |
| 1927 ucol_setText(colEl, decomp, decompLen, status); |
| 1928 while((element.CEs[element.noOfCEs] = ucol_next(colEl, status))
!= (uint32_t)UCOL_NULLORDER) { |
| 1929 element.noOfCEs++; |
| 1930 } |
| 1931 uprv_uca_setMapCE(t, &element, status); |
| 1932 uprv_uca_finalizeAddition(t, &element, status); |
| 1933 } |
| 1934 |
| 1935 // This is a fix for tailoring contractions with accented |
| 1936 // character at the end of contraction string. |
| 1937 if ((len>2) && |
| 1938 (unorm_getFCD16(fcdTrieIndex, comp[len-2]) & 0xff00)==0) { |
| 1939 uprv_uca_addFCD4AccentedContractions(t, colEl, comp, len, &eleme
nt, status); |
| 1940 } |
| 1941 |
| 1942 if (precompLen >1) { |
| 1943 c.compLen = len; |
| 1944 c.decompLen = decompLen; |
| 1945 c.precompLen = precompLen; |
| 1946 c.cmPos = i; |
| 1947 uprv_uca_addMultiCMContractions(t, colEl, &c, &element, status); |
| 1948 precompLen = c.precompLen; |
| 1949 } |
| 1950 } |
| 1951 } |
| 1952 } |
| 1953 |
| 1954 U_CFUNC int32_t U_EXPORT2 |
| 1955 uprv_uca_canonicalClosure(tempUCATable *t, |
| 1956 UColTokenParser *src, |
| 1957 UnicodeSet *closed, |
| 1958 UErrorCode *status) |
| 1959 { |
| 1960 enumStruct context; |
| 1961 context.closed = closed; |
| 1962 context.noOfClosures = 0; |
| 1963 UCAElements el; |
| 1964 UColToken *tok; |
| 1965 uint32_t i = 0, j = 0; |
| 1966 UChar baseChar, firstCM; |
| 1967 UChar32 fcdHighStart; |
| 1968 const uint16_t *fcdTrieIndex = unorm_getFCDTrieIndex(fcdHighStart, status); |
| 1969 context.nfcImpl=Normalizer2Factory::getNFCImpl(*status); |
| 1970 if(U_FAILURE(*status)) { |
| 1971 return 0; |
| 1972 } |
| 1973 |
| 1974 UCollator *tempColl = NULL; |
| 1975 tempUCATable *tempTable = uprv_uca_cloneTempTable(t, status); |
| 1976 // Check for null pointer |
| 1977 if (U_FAILURE(*status)) { |
| 1978 return 0; |
| 1979 } |
| 1980 |
| 1981 UCATableHeader *tempData = uprv_uca_assembleTable(tempTable, status); |
| 1982 tempColl = ucol_initCollator(tempData, 0, t->UCA, status); |
| 1983 if ( tempTable->cmLookup != NULL ) { |
| 1984 t->cmLookup = tempTable->cmLookup; // copy over to t |
| 1985 tempTable->cmLookup = NULL; |
| 1986 } |
| 1987 uprv_uca_closeTempTable(tempTable); |
| 1988 |
| 1989 if(U_SUCCESS(*status)) { |
| 1990 tempColl->ucaRules = NULL; |
| 1991 tempColl->actualLocale = NULL; |
| 1992 tempColl->validLocale = NULL; |
| 1993 tempColl->requestedLocale = NULL; |
| 1994 tempColl->hasRealData = TRUE; |
| 1995 tempColl->freeImageOnClose = TRUE; |
| 1996 } else if(tempData != 0) { |
| 1997 uprv_free(tempData); |
| 1998 } |
| 1999 |
| 2000 /* produce canonical closure */ |
| 2001 UCollationElements* colEl = ucol_openElements(tempColl, NULL, 0, status); |
| 2002 // Check for null pointer |
| 2003 if (U_FAILURE(*status)) { |
| 2004 return 0; |
| 2005 } |
| 2006 context.t = t; |
| 2007 context.tempColl = tempColl; |
| 2008 context.colEl = colEl; |
| 2009 context.status = status; |
| 2010 u_enumCharTypes(_enumCategoryRangeClosureCategory, &context); |
| 2011 |
| 2012 if ( (src==NULL) || !src->buildCCTabFlag ) { |
| 2013 ucol_closeElements(colEl); |
| 2014 ucol_close(tempColl); |
| 2015 return context.noOfClosures; // no extra contraction needed to add |
| 2016 } |
| 2017 |
| 2018 for (i=0; i < src->resultLen; i++) { |
| 2019 baseChar = firstCM= (UChar)0; |
| 2020 tok = src->lh[i].first; |
| 2021 while (tok != NULL && U_SUCCESS(*status)) { |
| 2022 el.prefix = el.prefixChars; |
| 2023 el.cPoints = el.uchars; |
| 2024 if(tok->prefix != 0) { |
| 2025 el.prefixSize = tok->prefix>>24; |
| 2026 uprv_memcpy(el.prefix, src->source + (tok->prefix & 0x00FFFFFF),
el.prefixSize*sizeof(UChar)); |
| 2027 |
| 2028 el.cSize = (tok->source >> 24)-(tok->prefix>>24); |
| 2029 uprv_memcpy(el.uchars, (tok->source & 0x00FFFFFF)+(tok->prefix>>
24) + src->source, el.cSize*sizeof(UChar)); |
| 2030 } else { |
| 2031 el.prefixSize = 0; |
| 2032 *el.prefix = 0; |
| 2033 |
| 2034 el.cSize = (tok->source >> 24); |
| 2035 uprv_memcpy(el.uchars, (tok->source & 0x00FFFFFF) + src->source,
el.cSize*sizeof(UChar)); |
| 2036 } |
| 2037 if(src->UCA != NULL) { |
| 2038 for(j = 0; j<el.cSize; j++) { |
| 2039 int16_t fcd = unorm_getFCD16(fcdTrieIndex, el.cPoints[j]); |
| 2040 if ( (fcd & 0xff) == 0 ) { |
| 2041 baseChar = el.cPoints[j]; // last base character |
| 2042 firstCM=0; // reset combining mark value |
| 2043 } |
| 2044 else { |
| 2045 if ( (baseChar!=0) && (firstCM==0) ) { |
| 2046 firstCM = el.cPoints[j]; // first combining mark |
| 2047 } |
| 2048 } |
| 2049 } |
| 2050 } |
| 2051 if ( (baseChar!= (UChar)0) && (firstCM != (UChar)0) ) { |
| 2052 // find all the canonical rules |
| 2053 uprv_uca_addTailCanonicalClosures(t, colEl, baseChar, firstCM, &
el, status); |
| 2054 } |
| 2055 tok = tok->next; |
| 2056 } |
| 2057 } |
| 2058 ucol_closeElements(colEl); |
| 2059 ucol_close(tempColl); |
| 2060 |
| 2061 return context.noOfClosures; |
| 2062 } |
| 2063 |
| 2064 #endif /* #if !UCONFIG_NO_COLLATION */ |
OLD | NEW |