intl/icu/source/common/ucol_swp.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 *******************************************************************************
michael@0 3 *
michael@0 4 * Copyright (C) 2003-2012, International Business Machines
michael@0 5 * Corporation and others. All Rights Reserved.
michael@0 6 *
michael@0 7 *******************************************************************************
michael@0 8 * file name: ucol_swp.cpp
michael@0 9 * encoding: US-ASCII
michael@0 10 * tab size: 8 (not used)
michael@0 11 * indentation:4
michael@0 12 *
michael@0 13 * created on: 2003sep10
michael@0 14 * created by: Markus W. Scherer
michael@0 15 *
michael@0 16 * Swap collation binaries.
michael@0 17 */
michael@0 18
michael@0 19 #include "unicode/udata.h" /* UDataInfo */
michael@0 20 #include "utrie.h"
michael@0 21 #include "udataswp.h"
michael@0 22 #include "cmemory.h"
michael@0 23 #include "ucol_data.h"
michael@0 24 #include "ucol_swp.h"
michael@0 25
michael@0 26 /* swapping ----------------------------------------------------------------- */
michael@0 27
michael@0 28 /*
michael@0 29 * This performs data swapping for a folded trie (see utrie.c for details).
michael@0 30 */
michael@0 31
michael@0 32 U_CAPI int32_t U_EXPORT2
michael@0 33 utrie_swap(const UDataSwapper *ds,
michael@0 34 const void *inData, int32_t length, void *outData,
michael@0 35 UErrorCode *pErrorCode) {
michael@0 36 const UTrieHeader *inTrie;
michael@0 37 UTrieHeader trie;
michael@0 38 int32_t size;
michael@0 39 UBool dataIs32;
michael@0 40
michael@0 41 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 42 return 0;
michael@0 43 }
michael@0 44 if(ds==NULL || inData==NULL || (length>=0 && outData==NULL)) {
michael@0 45 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 46 return 0;
michael@0 47 }
michael@0 48
michael@0 49 /* setup and swapping */
michael@0 50 if(length>=0 && (uint32_t)length<sizeof(UTrieHeader)) {
michael@0 51 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
michael@0 52 return 0;
michael@0 53 }
michael@0 54
michael@0 55 inTrie=(const UTrieHeader *)inData;
michael@0 56 trie.signature=ds->readUInt32(inTrie->signature);
michael@0 57 trie.options=ds->readUInt32(inTrie->options);
michael@0 58 trie.indexLength=udata_readInt32(ds, inTrie->indexLength);
michael@0 59 trie.dataLength=udata_readInt32(ds, inTrie->dataLength);
michael@0 60
michael@0 61 if( trie.signature!=0x54726965 ||
michael@0 62 (trie.options&UTRIE_OPTIONS_SHIFT_MASK)!=UTRIE_SHIFT ||
michael@0 63 ((trie.options>>UTRIE_OPTIONS_INDEX_SHIFT)&UTRIE_OPTIONS_SHIFT_MASK)!=UTRIE_INDEX_SHIFT ||
michael@0 64 trie.indexLength<UTRIE_BMP_INDEX_LENGTH ||
michael@0 65 (trie.indexLength&(UTRIE_SURROGATE_BLOCK_COUNT-1))!=0 ||
michael@0 66 trie.dataLength<UTRIE_DATA_BLOCK_LENGTH ||
michael@0 67 (trie.dataLength&(UTRIE_DATA_GRANULARITY-1))!=0 ||
michael@0 68 ((trie.options&UTRIE_OPTIONS_LATIN1_IS_LINEAR)!=0 && trie.dataLength<(UTRIE_DATA_BLOCK_LENGTH+0x100))
michael@0 69 ) {
michael@0 70 *pErrorCode=U_INVALID_FORMAT_ERROR; /* not a UTrie */
michael@0 71 return 0;
michael@0 72 }
michael@0 73
michael@0 74 dataIs32=(UBool)((trie.options&UTRIE_OPTIONS_DATA_IS_32_BIT)!=0);
michael@0 75 size=sizeof(UTrieHeader)+trie.indexLength*2+trie.dataLength*(dataIs32?4:2);
michael@0 76
michael@0 77 if(length>=0) {
michael@0 78 UTrieHeader *outTrie;
michael@0 79
michael@0 80 if(length<size) {
michael@0 81 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
michael@0 82 return 0;
michael@0 83 }
michael@0 84
michael@0 85 outTrie=(UTrieHeader *)outData;
michael@0 86
michael@0 87 /* swap the header */
michael@0 88 ds->swapArray32(ds, inTrie, sizeof(UTrieHeader), outTrie, pErrorCode);
michael@0 89
michael@0 90 /* swap the index and the data */
michael@0 91 if(dataIs32) {
michael@0 92 ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode);
michael@0 93 ds->swapArray32(ds, (const uint16_t *)(inTrie+1)+trie.indexLength, trie.dataLength*4,
michael@0 94 (uint16_t *)(outTrie+1)+trie.indexLength, pErrorCode);
michael@0 95 } else {
michael@0 96 ds->swapArray16(ds, inTrie+1, (trie.indexLength+trie.dataLength)*2, outTrie+1, pErrorCode);
michael@0 97 }
michael@0 98 }
michael@0 99
michael@0 100 return size;
michael@0 101 }
michael@0 102
michael@0 103 #if !UCONFIG_NO_COLLATION
michael@0 104
michael@0 105 /* Modified copy of the beginning of ucol_swapBinary(). */
michael@0 106 U_CAPI UBool U_EXPORT2
michael@0 107 ucol_looksLikeCollationBinary(const UDataSwapper *ds,
michael@0 108 const void *inData, int32_t length) {
michael@0 109 const UCATableHeader *inHeader;
michael@0 110 UCATableHeader header;
michael@0 111
michael@0 112 if(ds==NULL || inData==NULL || length<-1) {
michael@0 113 return FALSE;
michael@0 114 }
michael@0 115
michael@0 116 inHeader=(const UCATableHeader *)inData;
michael@0 117
michael@0 118 /*
michael@0 119 * The collation binary must contain at least the UCATableHeader,
michael@0 120 * starting with its size field.
michael@0 121 * sizeof(UCATableHeader)==42*4 in ICU 2.8
michael@0 122 * check the length against the header size before reading the size field
michael@0 123 */
michael@0 124 uprv_memset(&header, 0, sizeof(header));
michael@0 125 if(length<0) {
michael@0 126 header.size=udata_readInt32(ds, inHeader->size);
michael@0 127 } else if((length<(42*4) || length<(header.size=udata_readInt32(ds, inHeader->size)))) {
michael@0 128 return FALSE;
michael@0 129 }
michael@0 130
michael@0 131 header.magic=ds->readUInt32(inHeader->magic);
michael@0 132 if(!(
michael@0 133 header.magic==UCOL_HEADER_MAGIC &&
michael@0 134 inHeader->formatVersion[0]==3 /*&&
michael@0 135 inHeader->formatVersion[1]>=0*/
michael@0 136 )) {
michael@0 137 return FALSE;
michael@0 138 }
michael@0 139
michael@0 140 if(inHeader->isBigEndian!=ds->inIsBigEndian || inHeader->charSetFamily!=ds->inCharset) {
michael@0 141 return FALSE;
michael@0 142 }
michael@0 143
michael@0 144 return TRUE;
michael@0 145 }
michael@0 146
michael@0 147 /* swap a header-less collation binary, inside a resource bundle or ucadata.icu */
michael@0 148 U_CAPI int32_t U_EXPORT2
michael@0 149 ucol_swapBinary(const UDataSwapper *ds,
michael@0 150 const void *inData, int32_t length, void *outData,
michael@0 151 UErrorCode *pErrorCode) {
michael@0 152 const uint8_t *inBytes;
michael@0 153 uint8_t *outBytes;
michael@0 154
michael@0 155 const UCATableHeader *inHeader;
michael@0 156 UCATableHeader *outHeader;
michael@0 157 UCATableHeader header;
michael@0 158
michael@0 159 uint32_t count;
michael@0 160
michael@0 161 /* argument checking in case we were not called from ucol_swap() */
michael@0 162 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 163 return 0;
michael@0 164 }
michael@0 165 if(ds==NULL || inData==NULL || length<-1 || (length>0 && outData==NULL)) {
michael@0 166 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 167 return 0;
michael@0 168 }
michael@0 169
michael@0 170 inBytes=(const uint8_t *)inData;
michael@0 171 outBytes=(uint8_t *)outData;
michael@0 172
michael@0 173 inHeader=(const UCATableHeader *)inData;
michael@0 174 outHeader=(UCATableHeader *)outData;
michael@0 175
michael@0 176 /*
michael@0 177 * The collation binary must contain at least the UCATableHeader,
michael@0 178 * starting with its size field.
michael@0 179 * sizeof(UCATableHeader)==42*4 in ICU 2.8
michael@0 180 * check the length against the header size before reading the size field
michael@0 181 */
michael@0 182 uprv_memset(&header, 0, sizeof(header));
michael@0 183 if(length<0) {
michael@0 184 header.size=udata_readInt32(ds, inHeader->size);
michael@0 185 } else if((length<(42*4) || length<(header.size=udata_readInt32(ds, inHeader->size)))) {
michael@0 186 udata_printError(ds, "ucol_swapBinary(): too few bytes (%d after header) for collation data\n",
michael@0 187 length);
michael@0 188 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
michael@0 189 return 0;
michael@0 190 }
michael@0 191
michael@0 192 header.magic=ds->readUInt32(inHeader->magic);
michael@0 193 if(!(
michael@0 194 header.magic==UCOL_HEADER_MAGIC &&
michael@0 195 inHeader->formatVersion[0]==3 /*&&
michael@0 196 inHeader->formatVersion[1]>=0*/
michael@0 197 )) {
michael@0 198 udata_printError(ds, "ucol_swapBinary(): magic 0x%08x or format version %02x.%02x is not a collation binary\n",
michael@0 199 header.magic,
michael@0 200 inHeader->formatVersion[0], inHeader->formatVersion[1]);
michael@0 201 *pErrorCode=U_UNSUPPORTED_ERROR;
michael@0 202 return 0;
michael@0 203 }
michael@0 204
michael@0 205 if(inHeader->isBigEndian!=ds->inIsBigEndian || inHeader->charSetFamily!=ds->inCharset) {
michael@0 206 udata_printError(ds, "ucol_swapBinary(): endianness %d or charset %d does not match the swapper\n",
michael@0 207 inHeader->isBigEndian, inHeader->charSetFamily);
michael@0 208 *pErrorCode=U_INVALID_FORMAT_ERROR;
michael@0 209 return 0;
michael@0 210 }
michael@0 211
michael@0 212 if(length>=0) {
michael@0 213 /* copy everything, takes care of data that needs no swapping */
michael@0 214 if(inBytes!=outBytes) {
michael@0 215 uprv_memcpy(outBytes, inBytes, header.size);
michael@0 216 }
michael@0 217
michael@0 218 /* swap the necessary pieces in the order of their occurrence in the data */
michael@0 219
michael@0 220 /* read more of the UCATableHeader (the size field was read above) */
michael@0 221 header.options= ds->readUInt32(inHeader->options);
michael@0 222 header.UCAConsts= ds->readUInt32(inHeader->UCAConsts);
michael@0 223 header.contractionUCACombos= ds->readUInt32(inHeader->contractionUCACombos);
michael@0 224 header.mappingPosition= ds->readUInt32(inHeader->mappingPosition);
michael@0 225 header.expansion= ds->readUInt32(inHeader->expansion);
michael@0 226 header.contractionIndex= ds->readUInt32(inHeader->contractionIndex);
michael@0 227 header.contractionCEs= ds->readUInt32(inHeader->contractionCEs);
michael@0 228 header.contractionSize= ds->readUInt32(inHeader->contractionSize);
michael@0 229 header.endExpansionCE= ds->readUInt32(inHeader->endExpansionCE);
michael@0 230 header.expansionCESize= ds->readUInt32(inHeader->expansionCESize);
michael@0 231 header.endExpansionCECount= udata_readInt32(ds, inHeader->endExpansionCECount);
michael@0 232 header.contractionUCACombosSize=udata_readInt32(ds, inHeader->contractionUCACombosSize);
michael@0 233 header.scriptToLeadByte= ds->readUInt32(inHeader->scriptToLeadByte);
michael@0 234 header.leadByteToScript= ds->readUInt32(inHeader->leadByteToScript);
michael@0 235
michael@0 236 /* swap the 32-bit integers in the header */
michael@0 237 ds->swapArray32(ds, inHeader, (int32_t)((const char *)&inHeader->jamoSpecial-(const char *)inHeader),
michael@0 238 outHeader, pErrorCode);
michael@0 239 ds->swapArray32(ds, &(inHeader->scriptToLeadByte), sizeof(header.scriptToLeadByte) + sizeof(header.leadByteToScript),
michael@0 240 &(outHeader->scriptToLeadByte), pErrorCode);
michael@0 241 /* set the output platform properties */
michael@0 242 outHeader->isBigEndian=ds->outIsBigEndian;
michael@0 243 outHeader->charSetFamily=ds->outCharset;
michael@0 244
michael@0 245 /* swap the options */
michael@0 246 if(header.options!=0) {
michael@0 247 ds->swapArray32(ds, inBytes+header.options, header.expansion-header.options,
michael@0 248 outBytes+header.options, pErrorCode);
michael@0 249 }
michael@0 250
michael@0 251 /* swap the expansions */
michael@0 252 if(header.mappingPosition!=0 && header.expansion!=0) {
michael@0 253 if(header.contractionIndex!=0) {
michael@0 254 /* expansions bounded by contractions */
michael@0 255 count=header.contractionIndex-header.expansion;
michael@0 256 } else {
michael@0 257 /* no contractions: expansions bounded by the main trie */
michael@0 258 count=header.mappingPosition-header.expansion;
michael@0 259 }
michael@0 260 ds->swapArray32(ds, inBytes+header.expansion, (int32_t)count,
michael@0 261 outBytes+header.expansion, pErrorCode);
michael@0 262 }
michael@0 263
michael@0 264 /* swap the contractions */
michael@0 265 if(header.contractionSize!=0) {
michael@0 266 /* contractionIndex: UChar[] */
michael@0 267 ds->swapArray16(ds, inBytes+header.contractionIndex, header.contractionSize*2,
michael@0 268 outBytes+header.contractionIndex, pErrorCode);
michael@0 269
michael@0 270 /* contractionCEs: CEs[] */
michael@0 271 ds->swapArray32(ds, inBytes+header.contractionCEs, header.contractionSize*4,
michael@0 272 outBytes+header.contractionCEs, pErrorCode);
michael@0 273 }
michael@0 274
michael@0 275 /* swap the main trie */
michael@0 276 if(header.mappingPosition!=0) {
michael@0 277 count=header.endExpansionCE-header.mappingPosition;
michael@0 278 utrie_swap(ds, inBytes+header.mappingPosition, (int32_t)count,
michael@0 279 outBytes+header.mappingPosition, pErrorCode);
michael@0 280 }
michael@0 281
michael@0 282 /* swap the max expansion table */
michael@0 283 if(header.endExpansionCECount!=0) {
michael@0 284 ds->swapArray32(ds, inBytes+header.endExpansionCE, header.endExpansionCECount*4,
michael@0 285 outBytes+header.endExpansionCE, pErrorCode);
michael@0 286 }
michael@0 287
michael@0 288 /* expansionCESize, unsafeCP, contrEndCP: uint8_t[], no need to swap */
michael@0 289
michael@0 290 /* swap UCA constants */
michael@0 291 if(header.UCAConsts!=0) {
michael@0 292 /*
michael@0 293 * if UCAConsts!=0 then contractionUCACombos because we are swapping
michael@0 294 * the UCA data file, and we know that the UCA contains contractions
michael@0 295 */
michael@0 296 count=header.contractionUCACombos-header.UCAConsts;
michael@0 297 ds->swapArray32(ds, inBytes+header.UCAConsts, header.contractionUCACombos-header.UCAConsts,
michael@0 298 outBytes+header.UCAConsts, pErrorCode);
michael@0 299 }
michael@0 300
michael@0 301 /* swap UCA contractions */
michael@0 302 if(header.contractionUCACombosSize!=0) {
michael@0 303 count=header.contractionUCACombosSize*inHeader->contractionUCACombosWidth*U_SIZEOF_UCHAR;
michael@0 304 ds->swapArray16(ds, inBytes+header.contractionUCACombos, (int32_t)count,
michael@0 305 outBytes+header.contractionUCACombos, pErrorCode);
michael@0 306 }
michael@0 307
michael@0 308 /* swap the script to lead bytes */
michael@0 309 if(header.scriptToLeadByte!=0) {
michael@0 310 int indexCount = ds->readUInt16(*((uint16_t*)(inBytes+header.scriptToLeadByte))); // each entry = 2 * uint16
michael@0 311 int dataCount = ds->readUInt16(*((uint16_t*)(inBytes+header.scriptToLeadByte + 2))); // each entry = uint16
michael@0 312 ds->swapArray16(ds, inBytes+header.scriptToLeadByte,
michael@0 313 4 + (4 * indexCount) + (2 * dataCount),
michael@0 314 outBytes+header.scriptToLeadByte, pErrorCode);
michael@0 315 }
michael@0 316
michael@0 317 /* swap the lead byte to scripts */
michael@0 318 if(header.leadByteToScript!=0) {
michael@0 319 int indexCount = ds->readUInt16(*((uint16_t*)(inBytes+header.leadByteToScript))); // each entry = uint16
michael@0 320 int dataCount = ds->readUInt16(*((uint16_t*)(inBytes+header.leadByteToScript + 2))); // each entry = uint16
michael@0 321 ds->swapArray16(ds, inBytes+header.leadByteToScript,
michael@0 322 4 + (2 * indexCount) + (2 * dataCount),
michael@0 323 outBytes+header.leadByteToScript, pErrorCode);
michael@0 324 }
michael@0 325 }
michael@0 326
michael@0 327 return header.size;
michael@0 328 }
michael@0 329
michael@0 330 /* swap ICU collation data like ucadata.icu */
michael@0 331 U_CAPI int32_t U_EXPORT2
michael@0 332 ucol_swap(const UDataSwapper *ds,
michael@0 333 const void *inData, int32_t length, void *outData,
michael@0 334 UErrorCode *pErrorCode) {
michael@0 335
michael@0 336 const UDataInfo *pInfo;
michael@0 337 int32_t headerSize, collationSize;
michael@0 338
michael@0 339 /* udata_swapDataHeader checks the arguments */
michael@0 340 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
michael@0 341 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 342 return 0;
michael@0 343 }
michael@0 344
michael@0 345 /* check data format and format version */
michael@0 346 pInfo=(const UDataInfo *)((const char *)inData+4);
michael@0 347 if(!(
michael@0 348 pInfo->dataFormat[0]==0x55 && /* dataFormat="UCol" */
michael@0 349 pInfo->dataFormat[1]==0x43 &&
michael@0 350 pInfo->dataFormat[2]==0x6f &&
michael@0 351 pInfo->dataFormat[3]==0x6c &&
michael@0 352 pInfo->formatVersion[0]==3 /*&&
michael@0 353 pInfo->formatVersion[1]>=0*/
michael@0 354 )) {
michael@0 355 udata_printError(ds, "ucol_swap(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not a collation file\n",
michael@0 356 pInfo->dataFormat[0], pInfo->dataFormat[1],
michael@0 357 pInfo->dataFormat[2], pInfo->dataFormat[3],
michael@0 358 pInfo->formatVersion[0], pInfo->formatVersion[1]);
michael@0 359 *pErrorCode=U_UNSUPPORTED_ERROR;
michael@0 360 return 0;
michael@0 361 }
michael@0 362
michael@0 363 collationSize=ucol_swapBinary(ds,
michael@0 364 (const char *)inData+headerSize,
michael@0 365 length>=0 ? length-headerSize : -1,
michael@0 366 (char *)outData+headerSize,
michael@0 367 pErrorCode);
michael@0 368 if(U_SUCCESS(*pErrorCode)) {
michael@0 369 return headerSize+collationSize;
michael@0 370 } else {
michael@0 371 return 0;
michael@0 372 }
michael@0 373 }
michael@0 374
michael@0 375 /* swap inverse UCA collation data (invuca.icu) */
michael@0 376 U_CAPI int32_t U_EXPORT2
michael@0 377 ucol_swapInverseUCA(const UDataSwapper *ds,
michael@0 378 const void *inData, int32_t length, void *outData,
michael@0 379 UErrorCode *pErrorCode) {
michael@0 380 const UDataInfo *pInfo;
michael@0 381 int32_t headerSize;
michael@0 382
michael@0 383 const uint8_t *inBytes;
michael@0 384 uint8_t *outBytes;
michael@0 385
michael@0 386 const InverseUCATableHeader *inHeader;
michael@0 387 InverseUCATableHeader *outHeader;
michael@0 388 InverseUCATableHeader header={ 0,0,0,0,0,{0,0,0,0},{0,0,0,0,0,0,0,0} };
michael@0 389
michael@0 390 /* udata_swapDataHeader checks the arguments */
michael@0 391 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
michael@0 392 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 393 return 0;
michael@0 394 }
michael@0 395
michael@0 396 /* check data format and format version */
michael@0 397 pInfo=(const UDataInfo *)((const char *)inData+4);
michael@0 398 if(!(
michael@0 399 pInfo->dataFormat[0]==0x49 && /* dataFormat="InvC" */
michael@0 400 pInfo->dataFormat[1]==0x6e &&
michael@0 401 pInfo->dataFormat[2]==0x76 &&
michael@0 402 pInfo->dataFormat[3]==0x43 &&
michael@0 403 pInfo->formatVersion[0]==2 &&
michael@0 404 pInfo->formatVersion[1]>=1
michael@0 405 )) {
michael@0 406 udata_printError(ds, "ucol_swapInverseUCA(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not an inverse UCA collation file\n",
michael@0 407 pInfo->dataFormat[0], pInfo->dataFormat[1],
michael@0 408 pInfo->dataFormat[2], pInfo->dataFormat[3],
michael@0 409 pInfo->formatVersion[0], pInfo->formatVersion[1]);
michael@0 410 *pErrorCode=U_UNSUPPORTED_ERROR;
michael@0 411 return 0;
michael@0 412 }
michael@0 413
michael@0 414 inBytes=(const uint8_t *)inData+headerSize;
michael@0 415 outBytes=(uint8_t *)outData+headerSize;
michael@0 416
michael@0 417 inHeader=(const InverseUCATableHeader *)inBytes;
michael@0 418 outHeader=(InverseUCATableHeader *)outBytes;
michael@0 419
michael@0 420 /*
michael@0 421 * The inverse UCA collation binary must contain at least the InverseUCATableHeader,
michael@0 422 * starting with its size field.
michael@0 423 * sizeof(UCATableHeader)==8*4 in ICU 2.8
michael@0 424 * check the length against the header size before reading the size field
michael@0 425 */
michael@0 426 if(length<0) {
michael@0 427 header.byteSize=udata_readInt32(ds, inHeader->byteSize);
michael@0 428 } else if(
michael@0 429 ((length-headerSize)<(8*4) ||
michael@0 430 (uint32_t)(length-headerSize)<(header.byteSize=udata_readInt32(ds, inHeader->byteSize)))
michael@0 431 ) {
michael@0 432 udata_printError(ds, "ucol_swapInverseUCA(): too few bytes (%d after header) for inverse UCA collation data\n",
michael@0 433 length);
michael@0 434 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
michael@0 435 return 0;
michael@0 436 }
michael@0 437
michael@0 438 if(length>=0) {
michael@0 439 /* copy everything, takes care of data that needs no swapping */
michael@0 440 if(inBytes!=outBytes) {
michael@0 441 uprv_memcpy(outBytes, inBytes, header.byteSize);
michael@0 442 }
michael@0 443
michael@0 444 /* swap the necessary pieces in the order of their occurrence in the data */
michael@0 445
michael@0 446 /* read more of the InverseUCATableHeader (the byteSize field was read above) */
michael@0 447 header.tableSize= ds->readUInt32(inHeader->tableSize);
michael@0 448 header.contsSize= ds->readUInt32(inHeader->contsSize);
michael@0 449 header.table= ds->readUInt32(inHeader->table);
michael@0 450 header.conts= ds->readUInt32(inHeader->conts);
michael@0 451
michael@0 452 /* swap the 32-bit integers in the header */
michael@0 453 ds->swapArray32(ds, inHeader, 5*4, outHeader, pErrorCode);
michael@0 454
michael@0 455 /* swap the inverse table; tableSize counts uint32_t[3] rows */
michael@0 456 ds->swapArray32(ds, inBytes+header.table, header.tableSize*3*4,
michael@0 457 outBytes+header.table, pErrorCode);
michael@0 458
michael@0 459 /* swap the continuation table; contsSize counts UChars */
michael@0 460 ds->swapArray16(ds, inBytes+header.conts, header.contsSize*U_SIZEOF_UCHAR,
michael@0 461 outBytes+header.conts, pErrorCode);
michael@0 462 }
michael@0 463
michael@0 464 return headerSize+header.byteSize;
michael@0 465 }
michael@0 466
michael@0 467 #endif /* #if !UCONFIG_NO_COLLATION */

mercurial