1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 2005-2009, 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 "sprpimpl.h" 54 #include "propname.h" 55 #include "rbbidata.h" 56 #include "triedict.h" 57 58 /* swapping implementations in i18n */ 59 60 #if !UCONFIG_NO_NORMALIZATION 61 #include "uspoof_impl.h" 62 #endif 63 64 65 /* definitions */ 66 67 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 68 69 /* Unicode properties data swapping ----------------------------------------- */ 70 71 U_CAPI int32_t U_EXPORT2 72 uprops_swap(const UDataSwapper *ds, 73 const void *inData, int32_t length, void *outData, 74 UErrorCode *pErrorCode) { 75 const UDataInfo *pInfo; 76 int32_t headerSize, i; 77 78 int32_t dataIndexes[UPROPS_INDEX_COUNT]; 79 const int32_t *inData32; 80 81 /* udata_swapDataHeader checks the arguments */ 82 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 83 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 84 return 0; 85 } 86 87 /* check data format and format version */ 88 pInfo=(const UDataInfo *)((const char *)inData+4); 89 if(!( 90 pInfo->dataFormat[0]==0x55 && /* dataFormat="UPro" */ 91 pInfo->dataFormat[1]==0x50 && 92 pInfo->dataFormat[2]==0x72 && 93 pInfo->dataFormat[3]==0x6f && 94 (pInfo->formatVersion[0]==3 || pInfo->formatVersion[0]==4 || pInfo->formatVersion[0]==5) && 95 pInfo->formatVersion[2]==UTRIE_SHIFT && 96 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT 97 )) { 98 udata_printError(ds, "uprops_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not a Unicode properties file\n", 99 pInfo->dataFormat[0], pInfo->dataFormat[1], 100 pInfo->dataFormat[2], pInfo->dataFormat[3], 101 pInfo->formatVersion[0]); 102 *pErrorCode=U_UNSUPPORTED_ERROR; 103 return 0; 104 } 105 106 /* the properties file must contain at least the indexes array */ 107 if(length>=0 && (length-headerSize)<(int32_t)sizeof(dataIndexes)) { 108 udata_printError(ds, "uprops_swap(): too few bytes (%d after header) for a Unicode properties file\n", 109 length-headerSize); 110 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 111 return 0; 112 } 113 114 /* read the indexes */ 115 inData32=(const int32_t *)((const char *)inData+headerSize); 116 for(i=0; i<UPROPS_INDEX_COUNT; ++i) { 117 dataIndexes[i]=udata_readInt32(ds, inData32[i]); 118 } 119 120 /* 121 * comments are copied from the data format description in genprops/store.c 122 * indexes[] constants are in uprops.h 123 */ 124 if(length>=0) { 125 int32_t *outData32; 126 127 if((length-headerSize)<(4*dataIndexes[UPROPS_RESERVED_INDEX])) { 128 udata_printError(ds, "uprops_swap(): too few bytes (%d after header) for a Unicode properties file\n", 129 length-headerSize); 130 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 131 return 0; 132 } 133 134 outData32=(int32_t *)((char *)outData+headerSize); 135 136 /* copy everything for inaccessible data (padding) */ 137 if(inData32!=outData32) { 138 uprv_memcpy(outData32, inData32, 4*dataIndexes[UPROPS_RESERVED_INDEX]); 139 } 140 141 /* swap the indexes[16] */ 142 ds->swapArray32(ds, inData32, 4*UPROPS_INDEX_COUNT, outData32, pErrorCode); 143 144 /* 145 * swap the main properties UTrie 146 * PT serialized properties trie, see utrie.h (byte size: 4*(i0-16)) 147 */ 148 utrie_swap(ds, 149 inData32+UPROPS_INDEX_COUNT, 150 4*(dataIndexes[UPROPS_PROPS32_INDEX]-UPROPS_INDEX_COUNT), 151 outData32+UPROPS_INDEX_COUNT, 152 pErrorCode); 153 154 /* 155 * swap the properties and exceptions words 156 * P const uint32_t props32[i1-i0]; 157 * E const uint32_t exceptions[i2-i1]; 158 */ 159 ds->swapArray32(ds, 160 inData32+dataIndexes[UPROPS_PROPS32_INDEX], 161 4*(dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX]-dataIndexes[UPROPS_PROPS32_INDEX]), 162 outData32+dataIndexes[UPROPS_PROPS32_INDEX], 163 pErrorCode); 164 165 /* 166 * swap the UChars 167 * U const UChar uchars[2*(i3-i2)]; 168 */ 169 ds->swapArray16(ds, 170 inData32+dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX], 171 4*(dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX]-dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX]), 172 outData32+dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX], 173 pErrorCode); 174 175 /* 176 * swap the additional UTrie 177 * i3 additionalTrieIndex; -- 32-bit unit index to the additional trie for more properties 178 */ 179 utrie_swap(ds, 180 inData32+dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX], 181 4*(dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX]-dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX]), 182 outData32+dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX], 183 pErrorCode); 184 185 /* 186 * swap the properties vectors 187 * PV const uint32_t propsVectors[(i6-i4)/i5][i5]==uint32_t propsVectors[i6-i4]; 188 */ 189 ds->swapArray32(ds, 190 inData32+dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX], 191 4*(dataIndexes[UPROPS_RESERVED_INDEX]-dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX]), 192 outData32+dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX], 193 pErrorCode); 194 } 195 196 /* i6 reservedItemIndex; -- 32-bit unit index to the top of the properties vectors table */ 197 return headerSize+4*dataIndexes[UPROPS_RESERVED_INDEX]; 198 } 199 200 /* Unicode case mapping data swapping --------------------------------------- */ 201 202 U_CAPI int32_t U_EXPORT2 203 ucase_swap(const UDataSwapper *ds, 204 const void *inData, int32_t length, void *outData, 205 UErrorCode *pErrorCode) { 206 const UDataInfo *pInfo; 207 int32_t headerSize; 208 209 const uint8_t *inBytes; 210 uint8_t *outBytes; 211 212 const int32_t *inIndexes; 213 int32_t indexes[16]; 214 215 int32_t i, offset, count, size; 216 217 /* udata_swapDataHeader checks the arguments */ 218 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 219 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 220 return 0; 221 } 222 223 /* check data format and format version */ 224 pInfo=(const UDataInfo *)((const char *)inData+4); 225 if(!( 226 pInfo->dataFormat[0]==UCASE_FMT_0 && /* dataFormat="cAsE" */ 227 pInfo->dataFormat[1]==UCASE_FMT_1 && 228 pInfo->dataFormat[2]==UCASE_FMT_2 && 229 pInfo->dataFormat[3]==UCASE_FMT_3 && 230 pInfo->formatVersion[0]==1 && 231 pInfo->formatVersion[2]==UTRIE_SHIFT && 232 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT 233 )) { 234 udata_printError(ds, "ucase_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as case mapping data\n", 235 pInfo->dataFormat[0], pInfo->dataFormat[1], 236 pInfo->dataFormat[2], pInfo->dataFormat[3], 237 pInfo->formatVersion[0]); 238 *pErrorCode=U_UNSUPPORTED_ERROR; 239 return 0; 240 } 241 242 inBytes=(const uint8_t *)inData+headerSize; 243 outBytes=(uint8_t *)outData+headerSize; 244 245 inIndexes=(const int32_t *)inBytes; 246 247 if(length>=0) { 248 length-=headerSize; 249 if(length<16*4) { 250 udata_printError(ds, "ucase_swap(): too few bytes (%d after header) for case mapping data\n", 251 length); 252 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 253 return 0; 254 } 255 } 256 257 /* read the first 16 indexes (ICU 3.2/format version 1: UCASE_IX_TOP==16, might grow) */ 258 for(i=0; i<16; ++i) { 259 indexes[i]=udata_readInt32(ds, inIndexes[i]); 260 } 261 262 /* get the total length of the data */ 263 size=indexes[UCASE_IX_LENGTH]; 264 265 if(length>=0) { 266 if(length<size) { 267 udata_printError(ds, "ucase_swap(): too few bytes (%d after header) for all of case mapping data\n", 268 length); 269 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 270 return 0; 271 } 272 273 /* copy the data for inaccessible bytes */ 274 if(inBytes!=outBytes) { 275 uprv_memcpy(outBytes, inBytes, size); 276 } 277 278 offset=0; 279 280 /* swap the int32_t indexes[] */ 281 count=indexes[UCASE_IX_INDEX_TOP]*4; 282 ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode); 283 offset+=count; 284 285 /* swap the UTrie */ 286 count=indexes[UCASE_IX_TRIE_SIZE]; 287 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 288 offset+=count; 289 290 /* swap the uint16_t exceptions[] and unfold[] */ 291 count=(indexes[UCASE_IX_EXC_LENGTH]+indexes[UCASE_IX_UNFOLD_LENGTH])*2; 292 ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 293 offset+=count; 294 295 U_ASSERT(offset==size); 296 } 297 298 return headerSize+size; 299 } 300 301 /* Unicode bidi/shaping data swapping --------------------------------------- */ 302 303 U_CAPI int32_t U_EXPORT2 304 ubidi_swap(const UDataSwapper *ds, 305 const void *inData, int32_t length, void *outData, 306 UErrorCode *pErrorCode) { 307 const UDataInfo *pInfo; 308 int32_t headerSize; 309 310 const uint8_t *inBytes; 311 uint8_t *outBytes; 312 313 const int32_t *inIndexes; 314 int32_t indexes[16]; 315 316 int32_t i, offset, count, size; 317 318 /* udata_swapDataHeader checks the arguments */ 319 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 320 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 321 return 0; 322 } 323 324 /* check data format and format version */ 325 pInfo=(const UDataInfo *)((const char *)inData+4); 326 if(!( 327 pInfo->dataFormat[0]==UBIDI_FMT_0 && /* dataFormat="BiDi" */ 328 pInfo->dataFormat[1]==UBIDI_FMT_1 && 329 pInfo->dataFormat[2]==UBIDI_FMT_2 && 330 pInfo->dataFormat[3]==UBIDI_FMT_3 && 331 pInfo->formatVersion[0]==1 && 332 pInfo->formatVersion[2]==UTRIE_SHIFT && 333 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT 334 )) { 335 udata_printError(ds, "ubidi_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as bidi/shaping data\n", 336 pInfo->dataFormat[0], pInfo->dataFormat[1], 337 pInfo->dataFormat[2], pInfo->dataFormat[3], 338 pInfo->formatVersion[0]); 339 *pErrorCode=U_UNSUPPORTED_ERROR; 340 return 0; 341 } 342 343 inBytes=(const uint8_t *)inData+headerSize; 344 outBytes=(uint8_t *)outData+headerSize; 345 346 inIndexes=(const int32_t *)inBytes; 347 348 if(length>=0) { 349 length-=headerSize; 350 if(length<16*4) { 351 udata_printError(ds, "ubidi_swap(): too few bytes (%d after header) for bidi/shaping data\n", 352 length); 353 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 354 return 0; 355 } 356 } 357 358 /* read the first 16 indexes (ICU 3.4/format version 1: UBIDI_IX_TOP==16, might grow) */ 359 for(i=0; i<16; ++i) { 360 indexes[i]=udata_readInt32(ds, inIndexes[i]); 361 } 362 363 /* get the total length of the data */ 364 size=indexes[UBIDI_IX_LENGTH]; 365 366 if(length>=0) { 367 if(length<size) { 368 udata_printError(ds, "ubidi_swap(): too few bytes (%d after header) for all of bidi/shaping data\n", 369 length); 370 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 371 return 0; 372 } 373 374 /* copy the data for inaccessible bytes */ 375 if(inBytes!=outBytes) { 376 uprv_memcpy(outBytes, inBytes, size); 377 } 378 379 offset=0; 380 381 /* swap the int32_t indexes[] */ 382 count=indexes[UBIDI_IX_INDEX_TOP]*4; 383 ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode); 384 offset+=count; 385 386 /* swap the UTrie */ 387 count=indexes[UBIDI_IX_TRIE_SIZE]; 388 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 389 offset+=count; 390 391 /* swap the uint32_t mirrors[] */ 392 count=indexes[UBIDI_IX_MIRROR_LENGTH]*4; 393 ds->swapArray32(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 394 offset+=count; 395 396 /* just skip the uint8_t jgArray[] */ 397 count=indexes[UBIDI_IX_JG_LIMIT]-indexes[UBIDI_IX_JG_START]; 398 offset+=count; 399 400 U_ASSERT(offset==size); 401 } 402 403 return headerSize+size; 404 } 405 406 /* Unicode normalization data swapping -------------------------------------- */ 407 408 #if !UCONFIG_NO_NORMALIZATION 409 410 U_CAPI int32_t U_EXPORT2 411 unorm_swap(const UDataSwapper *ds, 412 const void *inData, int32_t length, void *outData, 413 UErrorCode *pErrorCode) { 414 const UDataInfo *pInfo; 415 int32_t headerSize; 416 417 const uint8_t *inBytes; 418 uint8_t *outBytes; 419 420 const int32_t *inIndexes; 421 int32_t indexes[32]; 422 423 int32_t i, offset, count, size; 424 425 /* udata_swapDataHeader checks the arguments */ 426 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 427 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 428 return 0; 429 } 430 431 /* check data format and format version */ 432 pInfo=(const UDataInfo *)((const char *)inData+4); 433 if(!( 434 pInfo->dataFormat[0]==0x4e && /* dataFormat="Norm" */ 435 pInfo->dataFormat[1]==0x6f && 436 pInfo->dataFormat[2]==0x72 && 437 pInfo->dataFormat[3]==0x6d && 438 pInfo->formatVersion[0]==2 439 )) { 440 udata_printError(ds, "unorm_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as unorm.icu\n", 441 pInfo->dataFormat[0], pInfo->dataFormat[1], 442 pInfo->dataFormat[2], pInfo->dataFormat[3], 443 pInfo->formatVersion[0]); 444 *pErrorCode=U_UNSUPPORTED_ERROR; 445 return 0; 446 } 447 448 inBytes=(const uint8_t *)inData+headerSize; 449 outBytes=(uint8_t *)outData+headerSize; 450 451 inIndexes=(const int32_t *)inBytes; 452 453 if(length>=0) { 454 length-=headerSize; 455 if(length<32*4) { 456 udata_printError(ds, "unorm_swap(): too few bytes (%d after header) for unorm.icu\n", 457 length); 458 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 459 return 0; 460 } 461 } 462 463 /* read the first 32 indexes (ICU 2.8/format version 2.2: _NORM_INDEX_TOP==32, might grow) */ 464 for(i=0; i<32; ++i) { 465 indexes[i]=udata_readInt32(ds, inIndexes[i]); 466 } 467 468 /* calculate the total length of the data */ 469 size= 470 32*4+ /* size of indexes[] */ 471 indexes[_NORM_INDEX_TRIE_SIZE]+ 472 indexes[_NORM_INDEX_UCHAR_COUNT]*2+ 473 indexes[_NORM_INDEX_COMBINE_DATA_COUNT]*2+ 474 indexes[_NORM_INDEX_FCD_TRIE_SIZE]+ 475 indexes[_NORM_INDEX_AUX_TRIE_SIZE]+ 476 indexes[_NORM_INDEX_CANON_SET_COUNT]*2; 477 478 if(length>=0) { 479 if(length<size) { 480 udata_printError(ds, "unorm_swap(): too few bytes (%d after header) for all of unorm.icu\n", 481 length); 482 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 483 return 0; 484 } 485 486 /* copy the data for inaccessible bytes */ 487 if(inBytes!=outBytes) { 488 uprv_memcpy(outBytes, inBytes, size); 489 } 490 491 offset=0; 492 493 /* swap the indexes[] */ 494 count=32*4; 495 ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode); 496 offset+=count; 497 498 /* swap the main UTrie */ 499 count=indexes[_NORM_INDEX_TRIE_SIZE]; 500 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 501 offset+=count; 502 503 /* swap the uint16_t extraData[] and the uint16_t combiningTable[] */ 504 count=(indexes[_NORM_INDEX_UCHAR_COUNT]+indexes[_NORM_INDEX_COMBINE_DATA_COUNT])*2; 505 ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 506 offset+=count; 507 508 /* swap the FCD UTrie */ 509 count=indexes[_NORM_INDEX_FCD_TRIE_SIZE]; 510 if(count!=0) { 511 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 512 offset+=count; 513 } 514 515 /* swap the aux UTrie */ 516 count=indexes[_NORM_INDEX_AUX_TRIE_SIZE]; 517 if(count!=0) { 518 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 519 offset+=count; 520 } 521 522 /* swap the uint16_t combiningTable[] */ 523 count=indexes[_NORM_INDEX_CANON_SET_COUNT]*2; 524 ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode); 525 offset+=count; 526 } 527 528 return headerSize+size; 529 } 530 531 #endif 532 533 /* Swap 'Test' data from gentest */ 534 U_CAPI int32_t U_EXPORT2 535 test_swap(const UDataSwapper *ds, 536 const void *inData, int32_t length, void *outData, 537 UErrorCode *pErrorCode) { 538 const UDataInfo *pInfo; 539 int32_t headerSize; 540 541 const uint8_t *inBytes; 542 uint8_t *outBytes; 543 544 const int32_t *inIndexes; 545 int32_t indexes[32]; 546 547 int32_t i, offset, count; 548 549 /* udata_swapDataHeader checks the arguments */ 550 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 551 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 552 udata_printError(ds, "test_swap(): data header swap failed %s\n", u_errorName(*pErrorCode)); 553 return 0; 554 } 555 556 /* check data format and format version */ 557 pInfo=(const UDataInfo *)((const char *)inData+4); 558 if(!( 559 pInfo->dataFormat[0]==0x54 && /* dataFormat="Norm" */ 560 pInfo->dataFormat[1]==0x65 && 561 pInfo->dataFormat[2]==0x73 && 562 pInfo->dataFormat[3]==0x74 && 563 pInfo->formatVersion[0]==1 564 )) { 565 udata_printError(ds, "test_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as testdata\n", 566 pInfo->dataFormat[0], pInfo->dataFormat[1], 567 pInfo->dataFormat[2], pInfo->dataFormat[3], 568 pInfo->formatVersion[0]); 569 *pErrorCode=U_UNSUPPORTED_ERROR; 570 return 0; 571 } 572 573 inBytes=(const uint8_t *)inData+headerSize; 574 outBytes=(uint8_t *)outData+headerSize; 575 576 int32_t size16 = 2; // 16bit plus padding 577 int32_t sizeStr = 5; // 4 char inv-str plus null 578 int32_t size = size16 + sizeStr; 579 580 if(length>=0) { 581 if(length<size) { 582 udata_printError(ds, "test_swap(): too few bytes (%d after header, wanted %d) for all of testdata\n", 583 length, size); 584 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 585 return 0; 586 } 587 588 offset =0; 589 /* swap a 1 entry array */ 590 ds->swapArray16(ds, inBytes+offset, size16, outBytes+offset, pErrorCode); 591 offset+=size16; 592 ds->swapInvChars(ds, inBytes+offset, sizeStr, outBytes+offset, pErrorCode); 593 } 594 595 return headerSize+size; 596 } 597 /* swap any data (except a .dat package) ------------------------------------ */ 598 599 static const struct { 600 uint8_t dataFormat[4]; 601 UDataSwapFn *swapFn; 602 } swapFns[]={ 603 { { 0x52, 0x65, 0x73, 0x42 }, ures_swap }, /* dataFormat="ResB" */ 604 #if !UCONFIG_NO_LEGACY_CONVERSION 605 { { 0x63, 0x6e, 0x76, 0x74 }, ucnv_swap }, /* dataFormat="cnvt" */ 606 #endif 607 #if !UCONFIG_NO_CONVERSION 608 { { 0x43, 0x76, 0x41, 0x6c }, ucnv_swapAliases }, /* dataFormat="CvAl" */ 609 #endif 610 #if !UCONFIG_NO_IDNA 611 { { 0x53, 0x50, 0x52, 0x50 }, usprep_swap }, /* dataFormat="SPRP" */ 612 #endif 613 /* insert data formats here, descending by expected frequency of occurrence */ 614 { { 0x55, 0x50, 0x72, 0x6f }, uprops_swap }, /* dataFormat="UPro" */ 615 616 { { UCASE_FMT_0, UCASE_FMT_1, UCASE_FMT_2, UCASE_FMT_3 }, 617 ucase_swap }, /* dataFormat="cAsE" */ 618 619 { { UBIDI_FMT_0, UBIDI_FMT_1, UBIDI_FMT_2, UBIDI_FMT_3 }, 620 ubidi_swap }, /* dataFormat="BiDi" */ 621 622 #if !UCONFIG_NO_NORMALIZATION 623 { { 0x4e, 0x6f, 0x72, 0x6d }, unorm_swap }, /* dataFormat="Norm" */ 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 636 { { 0x43, 0x66, 0x75, 0x20 }, uspoof_swap }, /* dataFormat="Cfu " */ 637 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