1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 2005-2010, International Business Machines 5 * Corporation and others. All Rights Reserved. 6 * 7 ******************************************************************************* 8 * file name: swapimpl.cpp 9 * encoding: US-ASCII 10 * tab size: 8 (not used) 11 * indentation:4 12 * 13 * created on: 2005may05 14 * created by: Markus W. Scherer 15 * 16 * Data file swapping functions moved here from the common library 17 * because some data is hardcoded in ICU4C and needs not be swapped any more. 18 * Moving the functions here simplifies testing (for code coverage) because 19 * we need not jump through hoops (like adding snapshots of these files 20 * to testdata). 21 * 22 * The declarations for these functions remain in the internal header files 23 * in icu/source/common/ 24 */ 25 26 #include "unicode/utypes.h" 27 #include "unicode/putil.h" 28 #include "unicode/udata.h" 29 30 /* Explicit include statement for std_string.h is needed 31 * for compilation on certain platforms. (e.g. AIX/VACPP) 32 */ 33 #include "unicode/std_string.h" 34 35 #include "cmemory.h" 36 #include "cstring.h" 37 #include "uinvchar.h" 38 #include "uassert.h" 39 #include "uarrsort.h" 40 #include "ucmndata.h" 41 #include "udataswp.h" 42 43 /* swapping implementations in common */ 44 45 #include "uresdata.h" 46 #include "ucnv_io.h" 47 #include "uprops.h" 48 #include "ucase.h" 49 #include "ubidi_props.h" 50 #include "ucol_swp.h" 51 #include "ucnv_bld.h" 52 #include "unormimp.h" 53 #include "normalizer2impl.h" 54 #include "sprpimpl.h" 55 #include "propname.h" 56 #include "rbbidata.h" 57 #include "triedict.h" 58 59 /* swapping implementations in i18n */ 60 61 #if !UCONFIG_NO_NORMALIZATION 62 #include "uspoof_impl.h" 63 #endif 64 65 66 /* definitions */ 67 68 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 69 70 /* Unicode properties data swapping ----------------------------------------- */ 71 72 U_CAPI int32_t U_EXPORT2 73 uprops_swap(const UDataSwapper *ds, 74 const void *inData, int32_t length, void *outData, 75 UErrorCode *pErrorCode) { 76 const UDataInfo *pInfo; 77 int32_t headerSize, i; 78 79 int32_t dataIndexes[UPROPS_INDEX_COUNT]; 80 const int32_t *inData32; 81 82 /* udata_swapDataHeader checks the arguments */ 83 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 84 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 85 return 0; 86 } 87 88 /* check data format and format version */ 89 pInfo=(const UDataInfo *)((const char *)inData+4); 90 if(!( 91 pInfo->dataFormat[0]==0x55 && /* dataFormat="UPro" */ 92 pInfo->dataFormat[1]==0x50 && 93 pInfo->dataFormat[2]==0x72 && 94 pInfo->dataFormat[3]==0x6f && 95 (3<=pInfo->formatVersion[0] && pInfo->formatVersion[0]<=6) && 96 pInfo->formatVersion[2]==UTRIE_SHIFT && 97 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT 98 )) { 99 udata_printError(ds, "uprops_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not a Unicode properties file\n", 100 pInfo->dataFormat[0], pInfo->dataFormat[1], 101 pInfo->dataFormat[2], pInfo->dataFormat[3], 102 pInfo->formatVersion[0]); 103 *pErrorCode=U_UNSUPPORTED_ERROR; 104 return 0; 105 } 106 107 /* the properties file must contain at least the indexes array */ 108 if(length>=0 && (length-headerSize)<(int32_t)sizeof(dataIndexes)) { 109 udata_printError(ds, "uprops_swap(): too few bytes (%d after header) for a Unicode properties file\n", 110 length-headerSize); 111 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 112 return 0; 113 } 114 115 /* read the indexes */ 116 inData32=(const int32_t *)((const char *)inData+headerSize); 117 for(i=0; i<UPROPS_INDEX_COUNT; ++i) { 118 dataIndexes[i]=udata_readInt32(ds, inData32[i]); 119 } 120 121 /* 122 * comments are copied from the data format description in genprops/store.c 123 * indexes[] constants are in uprops.h 124 */ 125 if(length>=0) { 126 int32_t *outData32; 127 128 if((length-headerSize)<(4*dataIndexes[UPROPS_RESERVED_INDEX])) { 129 udata_printError(ds, "uprops_swap(): too few bytes (%d after header) for a Unicode properties file\n", 130 length-headerSize); 131 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 132 return 0; 133 } 134 135 outData32=(int32_t *)((char *)outData+headerSize); 136 137 /* copy everything for inaccessible data (padding) */ 138 if(inData32!=outData32) { 139 uprv_memcpy(outData32, inData32, 4*dataIndexes[UPROPS_RESERVED_INDEX]); 140 } 141 142 /* swap the indexes[16] */ 143 ds->swapArray32(ds, inData32, 4*UPROPS_INDEX_COUNT, outData32, pErrorCode); 144 145 /* 146 * swap the main properties UTrie 147 * PT serialized properties trie, see utrie.h (byte size: 4*(i0-16)) 148 */ 149 utrie_swap(ds, 150 inData32+UPROPS_INDEX_COUNT, 151 4*(dataIndexes[UPROPS_PROPS32_INDEX]-UPROPS_INDEX_COUNT), 152 outData32+UPROPS_INDEX_COUNT, 153 pErrorCode); 154 155 /* 156 * swap the properties and exceptions words 157 * P const uint32_t props32[i1-i0]; 158 * E const uint32_t exceptions[i2-i1]; 159 */ 160 ds->swapArray32(ds, 161 inData32+dataIndexes[UPROPS_PROPS32_INDEX], 162 4*(dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX]-dataIndexes[UPROPS_PROPS32_INDEX]), 163 outData32+dataIndexes[UPROPS_PROPS32_INDEX], 164 pErrorCode); 165 166 /* 167 * swap the UChars 168 * U const UChar uchars[2*(i3-i2)]; 169 */ 170 ds->swapArray16(ds, 171 inData32+dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX], 172 4*(dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX]-dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX]), 173 outData32+dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX], 174 pErrorCode); 175 176 /* 177 * swap the additional UTrie 178 * i3 additionalTrieIndex; -- 32-bit unit index to the additional trie for more properties 179 */ 180 utrie_swap(ds, 181 inData32+dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX], 182 4*(dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX]-dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX]), 183 outData32+dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX], 184 pErrorCode); 185 186 /* 187 * swap the properties vectors 188 * PV const uint32_t propsVectors[(i6-i4)/i5][i5]==uint32_t propsVectors[i6-i4]; 189 */ 190 ds->swapArray32(ds, 191 inData32+dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX], 192 4*(dataIndexes[UPROPS_RESERVED_INDEX]-dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX]), 193 outData32+dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX], 194 pErrorCode); 195 } 196 197 /* i6 reservedItemIndex; -- 32-bit unit index to the top of the properties vectors table */ 198 return headerSize+4*dataIndexes[UPROPS_RESERVED_INDEX]; 199 } 200 201 /* Unicode case mapping data swapping --------------------------------------- */ 202 203 U_CAPI int32_t U_EXPORT2 204 ucase_swap(const UDataSwapper *ds, 205 const void *inData, int32_t length, void *outData, 206 UErrorCode *pErrorCode) { 207 const UDataInfo *pInfo; 208 int32_t headerSize; 209 210 const uint8_t *inBytes; 211 uint8_t *outBytes; 212 213 const int32_t *inIndexes; 214 int32_t indexes[16]; 215 216 int32_t i, offset, count, size; 217 218 /* udata_swapDataHeader checks the arguments */ 219 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 220 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 221 return 0; 222 } 223 224 /* check data format and format version */ 225 pInfo=(const UDataInfo *)((const char *)inData+4); 226 if(!( 227 pInfo->dataFormat[0]==UCASE_FMT_0 && /* dataFormat="cAsE" */ 228 pInfo->dataFormat[1]==UCASE_FMT_1 && 229 pInfo->dataFormat[2]==UCASE_FMT_2 && 230 pInfo->dataFormat[3]==UCASE_FMT_3 && 231 pInfo->formatVersion[0]==1 && 232 pInfo->formatVersion[2]==UTRIE_SHIFT && 233 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT 234 )) { 235 udata_printError(ds, "ucase_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as case mapping data\n", 236 pInfo->dataFormat[0], pInfo->dataFormat[1], 237 pInfo->dataFormat[2], pInfo->dataFormat[3], 238 pInfo->formatVersion[0]); 239 *pErrorCode=U_UNSUPPORTED_ERROR; 240 return 0; 241 } 242 243 inBytes=(const uint8_t *)inData+headerSize; 244 outBytes=(uint8_t *)outData+headerSize; 245 246 inIndexes=(const int32_t *)inBytes; 247 248 if(length>=0) { 249 length-=headerSize; 250 if(length<16*4) { 251 udata_printError(ds, "ucase_swap(): too few bytes (%d after header) for case mapping data\n", 252 length); 253 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 254 return 0; 255 } 256 } 257 258 /* read the first 16 indexes (ICU 3.2/format version 1: UCASE_IX_TOP==16, might grow) */ 259 for(i=0; i<16; ++i) { 260 indexes[i]=udata_readInt32(ds, inIndexes[i]); 261 } 262 263 /* get the total length of the data */ 264 size=indexes[UCASE_IX_LENGTH]; 265 266 if(length>=0) { 267 if(length<size) { 268 udata_printError(ds, "ucase_swap(): too few bytes (%d after header) for all of case mapping data\n", 269 length); 270 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 271 return 0; 272 } 273 274 /* copy the data for inaccessible bytes */ 275 if(inBytes!=outBytes) { 276 uprv_memcpy(outBytes, inBytes, size); 277 } 278 279 offset=0; 280 281 /* swap the int32_t indexes[] */ 282 count=indexes[UCASE_IX_INDEX_TOP]*4; 283 ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode); 284 offset+=count; 285 286 /* swap the UTrie */ 287 count=indexes[UCASE_IX_TRIE_SIZE]; 288 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 289 offset+=count; 290 291 /* swap the uint16_t exceptions[] and unfold[] */ 292 count=(indexes[UCASE_IX_EXC_LENGTH]+indexes[UCASE_IX_UNFOLD_LENGTH])*2; 293 ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 294 offset+=count; 295 296 U_ASSERT(offset==size); 297 } 298 299 return headerSize+size; 300 } 301 302 /* Unicode bidi/shaping data swapping --------------------------------------- */ 303 304 U_CAPI int32_t U_EXPORT2 305 ubidi_swap(const UDataSwapper *ds, 306 const void *inData, int32_t length, void *outData, 307 UErrorCode *pErrorCode) { 308 const UDataInfo *pInfo; 309 int32_t headerSize; 310 311 const uint8_t *inBytes; 312 uint8_t *outBytes; 313 314 const int32_t *inIndexes; 315 int32_t indexes[16]; 316 317 int32_t i, offset, count, size; 318 319 /* udata_swapDataHeader checks the arguments */ 320 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 321 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 322 return 0; 323 } 324 325 /* check data format and format version */ 326 pInfo=(const UDataInfo *)((const char *)inData+4); 327 if(!( 328 pInfo->dataFormat[0]==UBIDI_FMT_0 && /* dataFormat="BiDi" */ 329 pInfo->dataFormat[1]==UBIDI_FMT_1 && 330 pInfo->dataFormat[2]==UBIDI_FMT_2 && 331 pInfo->dataFormat[3]==UBIDI_FMT_3 && 332 pInfo->formatVersion[0]==1 && 333 pInfo->formatVersion[2]==UTRIE_SHIFT && 334 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT 335 )) { 336 udata_printError(ds, "ubidi_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as bidi/shaping data\n", 337 pInfo->dataFormat[0], pInfo->dataFormat[1], 338 pInfo->dataFormat[2], pInfo->dataFormat[3], 339 pInfo->formatVersion[0]); 340 *pErrorCode=U_UNSUPPORTED_ERROR; 341 return 0; 342 } 343 344 inBytes=(const uint8_t *)inData+headerSize; 345 outBytes=(uint8_t *)outData+headerSize; 346 347 inIndexes=(const int32_t *)inBytes; 348 349 if(length>=0) { 350 length-=headerSize; 351 if(length<16*4) { 352 udata_printError(ds, "ubidi_swap(): too few bytes (%d after header) for bidi/shaping data\n", 353 length); 354 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 355 return 0; 356 } 357 } 358 359 /* read the first 16 indexes (ICU 3.4/format version 1: UBIDI_IX_TOP==16, might grow) */ 360 for(i=0; i<16; ++i) { 361 indexes[i]=udata_readInt32(ds, inIndexes[i]); 362 } 363 364 /* get the total length of the data */ 365 size=indexes[UBIDI_IX_LENGTH]; 366 367 if(length>=0) { 368 if(length<size) { 369 udata_printError(ds, "ubidi_swap(): too few bytes (%d after header) for all of bidi/shaping data\n", 370 length); 371 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 372 return 0; 373 } 374 375 /* copy the data for inaccessible bytes */ 376 if(inBytes!=outBytes) { 377 uprv_memcpy(outBytes, inBytes, size); 378 } 379 380 offset=0; 381 382 /* swap the int32_t indexes[] */ 383 count=indexes[UBIDI_IX_INDEX_TOP]*4; 384 ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode); 385 offset+=count; 386 387 /* swap the UTrie */ 388 count=indexes[UBIDI_IX_TRIE_SIZE]; 389 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 390 offset+=count; 391 392 /* swap the uint32_t mirrors[] */ 393 count=indexes[UBIDI_IX_MIRROR_LENGTH]*4; 394 ds->swapArray32(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 395 offset+=count; 396 397 /* just skip the uint8_t jgArray[] */ 398 count=indexes[UBIDI_IX_JG_LIMIT]-indexes[UBIDI_IX_JG_START]; 399 offset+=count; 400 401 U_ASSERT(offset==size); 402 } 403 404 return headerSize+size; 405 } 406 407 /* Unicode normalization data swapping -------------------------------------- */ 408 409 #if !UCONFIG_NO_NORMALIZATION 410 411 U_CAPI int32_t U_EXPORT2 412 unorm_swap(const UDataSwapper *ds, 413 const void *inData, int32_t length, void *outData, 414 UErrorCode *pErrorCode) { 415 const UDataInfo *pInfo; 416 int32_t headerSize; 417 418 const uint8_t *inBytes; 419 uint8_t *outBytes; 420 421 const int32_t *inIndexes; 422 int32_t indexes[32]; 423 424 int32_t i, offset, count, size; 425 426 /* udata_swapDataHeader checks the arguments */ 427 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 428 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 429 return 0; 430 } 431 432 /* check data format and format version */ 433 pInfo=(const UDataInfo *)((const char *)inData+4); 434 if(!( 435 pInfo->dataFormat[0]==0x4e && /* dataFormat="Norm" */ 436 pInfo->dataFormat[1]==0x6f && 437 pInfo->dataFormat[2]==0x72 && 438 pInfo->dataFormat[3]==0x6d && 439 pInfo->formatVersion[0]==2 440 )) { 441 udata_printError(ds, "unorm_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as unorm.icu\n", 442 pInfo->dataFormat[0], pInfo->dataFormat[1], 443 pInfo->dataFormat[2], pInfo->dataFormat[3], 444 pInfo->formatVersion[0]); 445 *pErrorCode=U_UNSUPPORTED_ERROR; 446 return 0; 447 } 448 449 inBytes=(const uint8_t *)inData+headerSize; 450 outBytes=(uint8_t *)outData+headerSize; 451 452 inIndexes=(const int32_t *)inBytes; 453 454 if(length>=0) { 455 length-=headerSize; 456 if(length<32*4) { 457 udata_printError(ds, "unorm_swap(): too few bytes (%d after header) for unorm.icu\n", 458 length); 459 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 460 return 0; 461 } 462 } 463 464 /* read the first 32 indexes (ICU 2.8/format version 2.2: _NORM_INDEX_TOP==32, might grow) */ 465 for(i=0; i<32; ++i) { 466 indexes[i]=udata_readInt32(ds, inIndexes[i]); 467 } 468 469 /* calculate the total length of the data */ 470 size= 471 32*4+ /* size of indexes[] */ 472 indexes[_NORM_INDEX_TRIE_SIZE]+ 473 indexes[_NORM_INDEX_UCHAR_COUNT]*2+ 474 indexes[_NORM_INDEX_COMBINE_DATA_COUNT]*2+ 475 indexes[_NORM_INDEX_FCD_TRIE_SIZE]+ 476 indexes[_NORM_INDEX_AUX_TRIE_SIZE]+ 477 indexes[_NORM_INDEX_CANON_SET_COUNT]*2; 478 479 if(length>=0) { 480 if(length<size) { 481 udata_printError(ds, "unorm_swap(): too few bytes (%d after header) for all of unorm.icu\n", 482 length); 483 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 484 return 0; 485 } 486 487 /* copy the data for inaccessible bytes */ 488 if(inBytes!=outBytes) { 489 uprv_memcpy(outBytes, inBytes, size); 490 } 491 492 offset=0; 493 494 /* swap the indexes[] */ 495 count=32*4; 496 ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode); 497 offset+=count; 498 499 /* swap the main UTrie */ 500 count=indexes[_NORM_INDEX_TRIE_SIZE]; 501 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 502 offset+=count; 503 504 /* swap the uint16_t extraData[] and the uint16_t combiningTable[] */ 505 count=(indexes[_NORM_INDEX_UCHAR_COUNT]+indexes[_NORM_INDEX_COMBINE_DATA_COUNT])*2; 506 ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 507 offset+=count; 508 509 /* swap the FCD UTrie */ 510 count=indexes[_NORM_INDEX_FCD_TRIE_SIZE]; 511 if(count!=0) { 512 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 513 offset+=count; 514 } 515 516 /* swap the aux UTrie */ 517 count=indexes[_NORM_INDEX_AUX_TRIE_SIZE]; 518 if(count!=0) { 519 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 520 offset+=count; 521 } 522 523 /* swap the uint16_t combiningTable[] */ 524 count=indexes[_NORM_INDEX_CANON_SET_COUNT]*2; 525 ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 526 offset+=count; 527 } 528 529 return headerSize+size; 530 } 531 532 #endif 533 534 /* Swap 'Test' data from gentest */ 535 U_CAPI int32_t U_EXPORT2 536 test_swap(const UDataSwapper *ds, 537 const void *inData, int32_t length, void *outData, 538 UErrorCode *pErrorCode) { 539 const UDataInfo *pInfo; 540 int32_t headerSize; 541 542 const uint8_t *inBytes; 543 uint8_t *outBytes; 544 545 int32_t offset; 546 547 /* udata_swapDataHeader checks the arguments */ 548 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 549 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 550 udata_printError(ds, "test_swap(): data header swap failed %s\n", u_errorName(*pErrorCode)); 551 return 0; 552 } 553 554 /* check data format and format version */ 555 pInfo=(const UDataInfo *)((const char *)inData+4); 556 if(!( 557 pInfo->dataFormat[0]==0x54 && /* dataFormat="Norm" */ 558 pInfo->dataFormat[1]==0x65 && 559 pInfo->dataFormat[2]==0x73 && 560 pInfo->dataFormat[3]==0x74 && 561 pInfo->formatVersion[0]==1 562 )) { 563 udata_printError(ds, "test_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as testdata\n", 564 pInfo->dataFormat[0], pInfo->dataFormat[1], 565 pInfo->dataFormat[2], pInfo->dataFormat[3], 566 pInfo->formatVersion[0]); 567 *pErrorCode=U_UNSUPPORTED_ERROR; 568 return 0; 569 } 570 571 inBytes=(const uint8_t *)inData+headerSize; 572 outBytes=(uint8_t *)outData+headerSize; 573 574 int32_t size16 = 2; // 16bit plus padding 575 int32_t sizeStr = 5; // 4 char inv-str plus null 576 int32_t size = size16 + sizeStr; 577 578 if(length>=0) { 579 if(length<size) { 580 udata_printError(ds, "test_swap(): too few bytes (%d after header, wanted %d) for all of testdata\n", 581 length, size); 582 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 583 return 0; 584 } 585 586 offset =0; 587 /* swap a 1 entry array */ 588 ds->swapArray16(ds, inBytes+offset, size16, outBytes+offset, pErrorCode); 589 offset+=size16; 590 ds->swapInvChars(ds, inBytes+offset, sizeStr, outBytes+offset, pErrorCode); 591 } 592 593 return headerSize+size; 594 } 595 596 /* swap any data (except a .dat package) ------------------------------------ */ 597 598 static const struct { 599 uint8_t dataFormat[4]; 600 UDataSwapFn *swapFn; 601 } swapFns[]={ 602 { { 0x52, 0x65, 0x73, 0x42 }, ures_swap }, /* dataFormat="ResB" */ 603 #if !UCONFIG_NO_LEGACY_CONVERSION 604 { { 0x63, 0x6e, 0x76, 0x74 }, ucnv_swap }, /* dataFormat="cnvt" */ 605 #endif 606 #if !UCONFIG_NO_CONVERSION 607 { { 0x43, 0x76, 0x41, 0x6c }, ucnv_swapAliases }, /* dataFormat="CvAl" */ 608 #endif 609 #if !UCONFIG_NO_IDNA 610 { { 0x53, 0x50, 0x52, 0x50 }, usprep_swap }, /* dataFormat="SPRP" */ 611 #endif 612 /* insert data formats here, descending by expected frequency of occurrence */ 613 { { 0x55, 0x50, 0x72, 0x6f }, uprops_swap }, /* dataFormat="UPro" */ 614 615 { { UCASE_FMT_0, UCASE_FMT_1, UCASE_FMT_2, UCASE_FMT_3 }, 616 ucase_swap }, /* dataFormat="cAsE" */ 617 618 { { UBIDI_FMT_0, UBIDI_FMT_1, UBIDI_FMT_2, UBIDI_FMT_3 }, 619 ubidi_swap }, /* dataFormat="BiDi" */ 620 621 #if !UCONFIG_NO_NORMALIZATION 622 { { 0x4e, 0x6f, 0x72, 0x6d }, unorm_swap }, /* dataFormat="Norm" */ 623 { { 0x4e, 0x72, 0x6d, 0x32 }, unorm2_swap }, /* dataFormat="Nrm2" */ 624 #endif 625 #if !UCONFIG_NO_COLLATION 626 { { 0x55, 0x43, 0x6f, 0x6c }, ucol_swap }, /* dataFormat="UCol" */ 627 { { 0x49, 0x6e, 0x76, 0x43 }, ucol_swapInverseUCA },/* dataFormat="InvC" */ 628 #endif 629 #if !UCONFIG_NO_BREAK_ITERATION 630 { { 0x42, 0x72, 0x6b, 0x20 }, ubrk_swap }, /* dataFormat="Brk " */ 631 { { 0x54, 0x72, 0x44, 0x63 }, triedict_swap }, /* dataFormat="TrDc " */ 632 #endif 633 { { 0x70, 0x6e, 0x61, 0x6d }, upname_swap }, /* dataFormat="pnam" */ 634 { { 0x75, 0x6e, 0x61, 0x6d }, uchar_swapNames }, /* dataFormat="unam" */ 635 #if !UCONFIG_NO_NORMALIZATION 636 { { 0x43, 0x66, 0x75, 0x20 }, uspoof_swap }, /* dataFormat="Cfu " */ 637 #endif 638 { { 0x54, 0x65, 0x73, 0x74 }, test_swap } /* dataFormat="Test" */ 639 }; 640 641 U_CAPI int32_t U_EXPORT2 642 udata_swap(const UDataSwapper *ds, 643 const void *inData, int32_t length, void *outData, 644 UErrorCode *pErrorCode) { 645 char dataFormatChars[4]; 646 const UDataInfo *pInfo; 647 int32_t headerSize, i, swappedLength; 648 649 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 650 return 0; 651 } 652 653 /* 654 * Preflight the header first; checks for illegal arguments, too. 655 * Do not swap the header right away because the format-specific swapper 656 * will swap it, get the headerSize again, and also use the header 657 * information. Otherwise we would have to pass some of the information 658 * and not be able to use the UDataSwapFn signature. 659 */ 660 headerSize=udata_swapDataHeader(ds, inData, -1, NULL, pErrorCode); 661 662 /* 663 * If we wanted udata_swap() to also handle non-loadable data like a UTrie, 664 * then we could check here for further known magic values and structures. 665 */ 666 if(U_FAILURE(*pErrorCode)) { 667 return 0; /* the data format was not recognized */ 668 } 669 670 pInfo=(const UDataInfo *)((const char *)inData+4); 671 672 { 673 /* convert the data format from ASCII to Unicode to the system charset */ 674 UChar u[4]={ 675 pInfo->dataFormat[0], pInfo->dataFormat[1], 676 pInfo->dataFormat[2], pInfo->dataFormat[3] 677 }; 678 679 if(uprv_isInvariantUString(u, 4)) { 680 u_UCharsToChars(u, dataFormatChars, 4); 681 } else { 682 dataFormatChars[0]=dataFormatChars[1]=dataFormatChars[2]=dataFormatChars[3]='?'; 683 } 684 } 685 686 /* dispatch to the swap function for the dataFormat */ 687 for(i=0; i<LENGTHOF(swapFns); ++i) { 688 if(0==memcmp(swapFns[i].dataFormat, pInfo->dataFormat, 4)) { 689 swappedLength=swapFns[i].swapFn(ds, inData, length, outData, pErrorCode); 690 691 if(U_FAILURE(*pErrorCode)) { 692 udata_printError(ds, "udata_swap(): failure swapping data format %02x.%02x.%02x.%02x (\"%c%c%c%c\") - %s\n", 693 pInfo->dataFormat[0], pInfo->dataFormat[1], 694 pInfo->dataFormat[2], pInfo->dataFormat[3], 695 dataFormatChars[0], dataFormatChars[1], 696 dataFormatChars[2], dataFormatChars[3], 697 u_errorName(*pErrorCode)); 698 } else if(swappedLength<(length-15)) { 699 /* swapped less than expected */ 700 udata_printError(ds, "udata_swap() warning: swapped only %d out of %d bytes - data format %02x.%02x.%02x.%02x (\"%c%c%c%c\")\n", 701 swappedLength, length, 702 pInfo->dataFormat[0], pInfo->dataFormat[1], 703 pInfo->dataFormat[2], pInfo->dataFormat[3], 704 dataFormatChars[0], dataFormatChars[1], 705 dataFormatChars[2], dataFormatChars[3], 706 u_errorName(*pErrorCode)); 707 } 708 709 return swappedLength; 710 } 711 } 712 713 /* the dataFormat was not recognized */ 714 udata_printError(ds, "udata_swap(): unknown data format %02x.%02x.%02x.%02x (\"%c%c%c%c\")\n", 715 pInfo->dataFormat[0], pInfo->dataFormat[1], 716 pInfo->dataFormat[2], pInfo->dataFormat[3], 717 dataFormatChars[0], dataFormatChars[1], 718 dataFormatChars[2], dataFormatChars[3]); 719 720 *pErrorCode=U_UNSUPPORTED_ERROR; 721 return 0; 722 } 723