2 *******************************************************************************
4 * Copyright (C) 2003-2015, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: ucol_swp.cpp
10 * tab size: 8 (not used)
13 * created on: 2003sep10
14 * created by: Markus W. Scherer
16 * Swap collation binaries.
19 #include "unicode/udata.h" /* UDataInfo */
24 #include "ucol_data.h"
27 /* swapping ----------------------------------------------------------------- */
30 * This performs data swapping for a folded trie (see utrie.c for details).
33 U_CAPI
int32_t U_EXPORT2
34 utrie_swap(const UDataSwapper
*ds
,
35 const void *inData
, int32_t length
, void *outData
,
36 UErrorCode
*pErrorCode
) {
37 const UTrieHeader
*inTrie
;
42 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
45 if(ds
==NULL
|| inData
==NULL
|| (length
>=0 && outData
==NULL
)) {
46 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
50 /* setup and swapping */
51 if(length
>=0 && (uint32_t)length
<sizeof(UTrieHeader
)) {
52 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
56 inTrie
=(const UTrieHeader
*)inData
;
57 trie
.signature
=ds
->readUInt32(inTrie
->signature
);
58 trie
.options
=ds
->readUInt32(inTrie
->options
);
59 trie
.indexLength
=udata_readInt32(ds
, inTrie
->indexLength
);
60 trie
.dataLength
=udata_readInt32(ds
, inTrie
->dataLength
);
62 if( trie
.signature
!=0x54726965 ||
63 (trie
.options
&UTRIE_OPTIONS_SHIFT_MASK
)!=UTRIE_SHIFT
||
64 ((trie
.options
>>UTRIE_OPTIONS_INDEX_SHIFT
)&UTRIE_OPTIONS_SHIFT_MASK
)!=UTRIE_INDEX_SHIFT
||
65 trie
.indexLength
<UTRIE_BMP_INDEX_LENGTH
||
66 (trie
.indexLength
&(UTRIE_SURROGATE_BLOCK_COUNT
-1))!=0 ||
67 trie
.dataLength
<UTRIE_DATA_BLOCK_LENGTH
||
68 (trie
.dataLength
&(UTRIE_DATA_GRANULARITY
-1))!=0 ||
69 ((trie
.options
&UTRIE_OPTIONS_LATIN1_IS_LINEAR
)!=0 && trie
.dataLength
<(UTRIE_DATA_BLOCK_LENGTH
+0x100))
71 *pErrorCode
=U_INVALID_FORMAT_ERROR
; /* not a UTrie */
75 dataIs32
=(UBool
)((trie
.options
&UTRIE_OPTIONS_DATA_IS_32_BIT
)!=0);
76 size
=sizeof(UTrieHeader
)+trie
.indexLength
*2+trie
.dataLength
*(dataIs32
?4:2);
82 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
86 outTrie
=(UTrieHeader
*)outData
;
89 ds
->swapArray32(ds
, inTrie
, sizeof(UTrieHeader
), outTrie
, pErrorCode
);
91 /* swap the index and the data */
93 ds
->swapArray16(ds
, inTrie
+1, trie
.indexLength
*2, outTrie
+1, pErrorCode
);
94 ds
->swapArray32(ds
, (const uint16_t *)(inTrie
+1)+trie
.indexLength
, trie
.dataLength
*4,
95 (uint16_t *)(outTrie
+1)+trie
.indexLength
, pErrorCode
);
97 ds
->swapArray16(ds
, inTrie
+1, (trie
.indexLength
+trie
.dataLength
)*2, outTrie
+1, pErrorCode
);
104 #if !UCONFIG_NO_COLLATION
106 U_CAPI UBool U_EXPORT2
107 ucol_looksLikeCollationBinary(const UDataSwapper
*ds
,
108 const void *inData
, int32_t length
) {
109 if(ds
==NULL
|| inData
==NULL
|| length
<-1) {
113 // First check for format version 4+ which has a standard data header.
114 UErrorCode errorCode
=U_ZERO_ERROR
;
115 (void)udata_swapDataHeader(ds
, inData
, -1, NULL
, &errorCode
);
116 if(U_SUCCESS(errorCode
)) {
117 const UDataInfo
&info
=*(const UDataInfo
*)((const char *)inData
+4);
118 if(info
.dataFormat
[0]==0x55 && // dataFormat="UCol"
119 info
.dataFormat
[1]==0x43 &&
120 info
.dataFormat
[2]==0x6f &&
121 info
.dataFormat
[3]==0x6c) {
126 // Else check for format version 3.
127 const UCATableHeader
*inHeader
=(const UCATableHeader
*)inData
;
130 * The collation binary must contain at least the UCATableHeader,
131 * starting with its size field.
132 * sizeof(UCATableHeader)==42*4 in ICU 2.8
133 * check the length against the header size before reading the size field
135 UCATableHeader header
;
136 uprv_memset(&header
, 0, sizeof(header
));
138 header
.size
=udata_readInt32(ds
, inHeader
->size
);
139 } else if((length
<(42*4) || length
<(header
.size
=udata_readInt32(ds
, inHeader
->size
)))) {
143 header
.magic
=ds
->readUInt32(inHeader
->magic
);
145 header
.magic
==UCOL_HEADER_MAGIC
&&
146 inHeader
->formatVersion
[0]==3 /*&&
147 inHeader->formatVersion[1]>=0*/
152 if(inHeader
->isBigEndian
!=ds
->inIsBigEndian
|| inHeader
->charSetFamily
!=ds
->inCharset
) {
161 /* swap a header-less collation formatVersion=3 binary, inside a resource bundle or ucadata.icu */
163 swapFormatVersion3(const UDataSwapper
*ds
,
164 const void *inData
, int32_t length
, void *outData
,
165 UErrorCode
*pErrorCode
) {
166 const uint8_t *inBytes
;
169 const UCATableHeader
*inHeader
;
170 UCATableHeader
*outHeader
;
171 UCATableHeader header
;
175 /* argument checking in case we were not called from ucol_swap() */
176 if(U_FAILURE(*pErrorCode
)) {
179 if(ds
==NULL
|| inData
==NULL
|| length
<-1 || (length
>0 && outData
==NULL
)) {
180 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
184 inBytes
=(const uint8_t *)inData
;
185 outBytes
=(uint8_t *)outData
;
187 inHeader
=(const UCATableHeader
*)inData
;
188 outHeader
=(UCATableHeader
*)outData
;
191 * The collation binary must contain at least the UCATableHeader,
192 * starting with its size field.
193 * sizeof(UCATableHeader)==42*4 in ICU 2.8
194 * check the length against the header size before reading the size field
196 uprv_memset(&header
, 0, sizeof(header
));
198 header
.size
=udata_readInt32(ds
, inHeader
->size
);
199 } else if((length
<(42*4) || length
<(header
.size
=udata_readInt32(ds
, inHeader
->size
)))) {
200 udata_printError(ds
, "ucol_swap(formatVersion=3): too few bytes (%d after header) for collation data\n",
202 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
206 header
.magic
=ds
->readUInt32(inHeader
->magic
);
208 header
.magic
==UCOL_HEADER_MAGIC
&&
209 inHeader
->formatVersion
[0]==3 /*&&
210 inHeader->formatVersion[1]>=0*/
212 udata_printError(ds
, "ucol_swap(formatVersion=3): magic 0x%08x or format version %02x.%02x is not a collation binary\n",
214 inHeader
->formatVersion
[0], inHeader
->formatVersion
[1]);
215 *pErrorCode
=U_UNSUPPORTED_ERROR
;
219 if(inHeader
->isBigEndian
!=ds
->inIsBigEndian
|| inHeader
->charSetFamily
!=ds
->inCharset
) {
220 udata_printError(ds
, "ucol_swap(formatVersion=3): endianness %d or charset %d does not match the swapper\n",
221 inHeader
->isBigEndian
, inHeader
->charSetFamily
);
222 *pErrorCode
=U_INVALID_FORMAT_ERROR
;
227 /* copy everything, takes care of data that needs no swapping */
228 if(inBytes
!=outBytes
) {
229 uprv_memcpy(outBytes
, inBytes
, header
.size
);
232 /* swap the necessary pieces in the order of their occurrence in the data */
234 /* read more of the UCATableHeader (the size field was read above) */
235 header
.options
= ds
->readUInt32(inHeader
->options
);
236 header
.UCAConsts
= ds
->readUInt32(inHeader
->UCAConsts
);
237 header
.contractionUCACombos
= ds
->readUInt32(inHeader
->contractionUCACombos
);
238 header
.mappingPosition
= ds
->readUInt32(inHeader
->mappingPosition
);
239 header
.expansion
= ds
->readUInt32(inHeader
->expansion
);
240 header
.contractionIndex
= ds
->readUInt32(inHeader
->contractionIndex
);
241 header
.contractionCEs
= ds
->readUInt32(inHeader
->contractionCEs
);
242 header
.contractionSize
= ds
->readUInt32(inHeader
->contractionSize
);
243 header
.endExpansionCE
= ds
->readUInt32(inHeader
->endExpansionCE
);
244 header
.expansionCESize
= ds
->readUInt32(inHeader
->expansionCESize
);
245 header
.endExpansionCECount
= udata_readInt32(ds
, inHeader
->endExpansionCECount
);
246 header
.contractionUCACombosSize
=udata_readInt32(ds
, inHeader
->contractionUCACombosSize
);
247 header
.scriptToLeadByte
= ds
->readUInt32(inHeader
->scriptToLeadByte
);
248 header
.leadByteToScript
= ds
->readUInt32(inHeader
->leadByteToScript
);
250 /* swap the 32-bit integers in the header */
251 ds
->swapArray32(ds
, inHeader
, (int32_t)((const char *)&inHeader
->jamoSpecial
-(const char *)inHeader
),
252 outHeader
, pErrorCode
);
253 ds
->swapArray32(ds
, &(inHeader
->scriptToLeadByte
), sizeof(header
.scriptToLeadByte
) + sizeof(header
.leadByteToScript
),
254 &(outHeader
->scriptToLeadByte
), pErrorCode
);
255 /* set the output platform properties */
256 outHeader
->isBigEndian
=ds
->outIsBigEndian
;
257 outHeader
->charSetFamily
=ds
->outCharset
;
259 /* swap the options */
260 if(header
.options
!=0) {
261 ds
->swapArray32(ds
, inBytes
+header
.options
, header
.expansion
-header
.options
,
262 outBytes
+header
.options
, pErrorCode
);
265 /* swap the expansions */
266 if(header
.mappingPosition
!=0 && header
.expansion
!=0) {
267 if(header
.contractionIndex
!=0) {
268 /* expansions bounded by contractions */
269 count
=header
.contractionIndex
-header
.expansion
;
271 /* no contractions: expansions bounded by the main trie */
272 count
=header
.mappingPosition
-header
.expansion
;
274 ds
->swapArray32(ds
, inBytes
+header
.expansion
, (int32_t)count
,
275 outBytes
+header
.expansion
, pErrorCode
);
278 /* swap the contractions */
279 if(header
.contractionSize
!=0) {
280 /* contractionIndex: UChar[] */
281 ds
->swapArray16(ds
, inBytes
+header
.contractionIndex
, header
.contractionSize
*2,
282 outBytes
+header
.contractionIndex
, pErrorCode
);
284 /* contractionCEs: CEs[] */
285 ds
->swapArray32(ds
, inBytes
+header
.contractionCEs
, header
.contractionSize
*4,
286 outBytes
+header
.contractionCEs
, pErrorCode
);
289 /* swap the main trie */
290 if(header
.mappingPosition
!=0) {
291 count
=header
.endExpansionCE
-header
.mappingPosition
;
292 utrie_swap(ds
, inBytes
+header
.mappingPosition
, (int32_t)count
,
293 outBytes
+header
.mappingPosition
, pErrorCode
);
296 /* swap the max expansion table */
297 if(header
.endExpansionCECount
!=0) {
298 ds
->swapArray32(ds
, inBytes
+header
.endExpansionCE
, header
.endExpansionCECount
*4,
299 outBytes
+header
.endExpansionCE
, pErrorCode
);
302 /* expansionCESize, unsafeCP, contrEndCP: uint8_t[], no need to swap */
304 /* swap UCA constants */
305 if(header
.UCAConsts
!=0) {
307 * if UCAConsts!=0 then contractionUCACombos because we are swapping
308 * the UCA data file, and we know that the UCA contains contractions
310 ds
->swapArray32(ds
, inBytes
+header
.UCAConsts
, header
.contractionUCACombos
-header
.UCAConsts
,
311 outBytes
+header
.UCAConsts
, pErrorCode
);
314 /* swap UCA contractions */
315 if(header
.contractionUCACombosSize
!=0) {
316 count
=header
.contractionUCACombosSize
*inHeader
->contractionUCACombosWidth
*U_SIZEOF_UCHAR
;
317 ds
->swapArray16(ds
, inBytes
+header
.contractionUCACombos
, (int32_t)count
,
318 outBytes
+header
.contractionUCACombos
, pErrorCode
);
321 /* swap the script to lead bytes */
322 if(header
.scriptToLeadByte
!=0) {
323 int indexCount
= ds
->readUInt16(*((uint16_t*)(inBytes
+header
.scriptToLeadByte
))); // each entry = 2 * uint16
324 int dataCount
= ds
->readUInt16(*((uint16_t*)(inBytes
+header
.scriptToLeadByte
+ 2))); // each entry = uint16
325 ds
->swapArray16(ds
, inBytes
+header
.scriptToLeadByte
,
326 4 + (4 * indexCount
) + (2 * dataCount
),
327 outBytes
+header
.scriptToLeadByte
, pErrorCode
);
330 /* swap the lead byte to scripts */
331 if(header
.leadByteToScript
!=0) {
332 int indexCount
= ds
->readUInt16(*((uint16_t*)(inBytes
+header
.leadByteToScript
))); // each entry = uint16
333 int dataCount
= ds
->readUInt16(*((uint16_t*)(inBytes
+header
.leadByteToScript
+ 2))); // each entry = uint16
334 ds
->swapArray16(ds
, inBytes
+header
.leadByteToScript
,
335 4 + (2 * indexCount
) + (2 * dataCount
),
336 outBytes
+header
.leadByteToScript
, pErrorCode
);
343 // swap formatVersion 4 or 5 ----------------------------------------------- ***
345 // The following are copied from CollationDataReader, trading an awkward copy of constants
346 // for an awkward relocation of the i18n collationdatareader.h file into the common library.
347 // Keep them in sync!
350 IX_INDEXES_LENGTH
, // 0
355 IX_JAMO_CE32S_START
, // 4
356 IX_REORDER_CODES_OFFSET
,
357 IX_REORDER_TABLE_OFFSET
,
360 IX_RESERVED8_OFFSET
, // 8
362 IX_RESERVED10_OFFSET
,
365 IX_ROOT_ELEMENTS_OFFSET
, // 12
367 IX_UNSAFE_BWD_OFFSET
,
368 IX_FAST_LATIN_TABLE_OFFSET
,
370 IX_SCRIPTS_OFFSET
, // 16
371 IX_COMPRESSIBLE_BYTES_OFFSET
,
372 IX_RESERVED18_OFFSET
,
377 swapFormatVersion4(const UDataSwapper
*ds
,
378 const void *inData
, int32_t length
, void *outData
,
379 UErrorCode
&errorCode
) {
380 if(U_FAILURE(errorCode
)) { return 0; }
382 const uint8_t *inBytes
=(const uint8_t *)inData
;
383 uint8_t *outBytes
=(uint8_t *)outData
;
385 const int32_t *inIndexes
=(const int32_t *)inBytes
;
386 int32_t indexes
[IX_TOTAL_SIZE
+1];
388 // Need at least IX_INDEXES_LENGTH and IX_OPTIONS.
389 if(0<=length
&& length
<8) {
390 udata_printError(ds
, "ucol_swap(formatVersion=4): too few bytes "
391 "(%d after header) for collation data\n",
393 errorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
397 int32_t indexesLength
=indexes
[0]=udata_readInt32(ds
, inIndexes
[0]);
398 if(0<=length
&& length
<(indexesLength
*4)) {
399 udata_printError(ds
, "ucol_swap(formatVersion=4): too few bytes "
400 "(%d after header) for collation data\n",
402 errorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
406 for(int32_t i
=1; i
<=IX_TOTAL_SIZE
&& i
<indexesLength
; ++i
) {
407 indexes
[i
]=udata_readInt32(ds
, inIndexes
[i
]);
409 for(int32_t i
=indexesLength
; i
<=IX_TOTAL_SIZE
; ++i
) {
412 inIndexes
=NULL
; // Make sure we do not accidentally use these instead of indexes[].
414 // Get the total length of the data.
416 if(indexesLength
>IX_TOTAL_SIZE
) {
417 size
=indexes
[IX_TOTAL_SIZE
];
418 } else if(indexesLength
>IX_REORDER_CODES_OFFSET
) {
419 size
=indexes
[indexesLength
-1];
421 size
=indexesLength
*4;
423 if(length
<0) { return size
; }
426 udata_printError(ds
, "ucol_swap(formatVersion=4): too few bytes "
427 "(%d after header) for collation data\n",
429 errorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
433 // Copy the data for inaccessible bytes and arrays of bytes.
434 if(inBytes
!=outBytes
) {
435 uprv_memcpy(outBytes
, inBytes
, size
);
438 // Swap the int32_t indexes[].
439 ds
->swapArray32(ds
, inBytes
, indexesLength
* 4, outBytes
, &errorCode
);
441 // The following is a modified version of CollationDataReader::read().
442 // Here we use indexes[] not inIndexes[] because
443 // the inIndexes[] may not be in this machine's endianness.
444 int32_t index
; // one of the indexes[] slots
445 int32_t offset
; // byte offset for the index part
446 // int32_t length; // number of bytes in the index part
448 index
= IX_REORDER_CODES_OFFSET
;
449 offset
= indexes
[index
];
450 length
= indexes
[index
+ 1] - offset
;
452 ds
->swapArray32(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
455 // Skip the IX_REORDER_TABLE_OFFSET byte array.
457 index
= IX_TRIE_OFFSET
;
458 offset
= indexes
[index
];
459 length
= indexes
[index
+ 1] - offset
;
461 utrie2_swap(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
464 index
= IX_RESERVED8_OFFSET
;
465 offset
= indexes
[index
];
466 length
= indexes
[index
+ 1] - offset
;
468 udata_printError(ds
, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED8_OFFSET\n", length
);
469 errorCode
= U_UNSUPPORTED_ERROR
;
473 index
= IX_CES_OFFSET
;
474 offset
= indexes
[index
];
475 length
= indexes
[index
+ 1] - offset
;
477 ds
->swapArray64(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
480 index
= IX_RESERVED10_OFFSET
;
481 offset
= indexes
[index
];
482 length
= indexes
[index
+ 1] - offset
;
484 udata_printError(ds
, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED10_OFFSET\n", length
);
485 errorCode
= U_UNSUPPORTED_ERROR
;
489 index
= IX_CE32S_OFFSET
;
490 offset
= indexes
[index
];
491 length
= indexes
[index
+ 1] - offset
;
493 ds
->swapArray32(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
496 index
= IX_ROOT_ELEMENTS_OFFSET
;
497 offset
= indexes
[index
];
498 length
= indexes
[index
+ 1] - offset
;
500 ds
->swapArray32(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
503 index
= IX_CONTEXTS_OFFSET
;
504 offset
= indexes
[index
];
505 length
= indexes
[index
+ 1] - offset
;
507 ds
->swapArray16(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
510 index
= IX_UNSAFE_BWD_OFFSET
;
511 offset
= indexes
[index
];
512 length
= indexes
[index
+ 1] - offset
;
514 ds
->swapArray16(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
517 index
= IX_FAST_LATIN_TABLE_OFFSET
;
518 offset
= indexes
[index
];
519 length
= indexes
[index
+ 1] - offset
;
521 ds
->swapArray16(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
524 index
= IX_SCRIPTS_OFFSET
;
525 offset
= indexes
[index
];
526 length
= indexes
[index
+ 1] - offset
;
528 ds
->swapArray16(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
531 // Skip the IX_COMPRESSIBLE_BYTES_OFFSET byte array.
533 index
= IX_RESERVED18_OFFSET
;
534 offset
= indexes
[index
];
535 length
= indexes
[index
+ 1] - offset
;
537 udata_printError(ds
, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED18_OFFSET\n", length
);
538 errorCode
= U_UNSUPPORTED_ERROR
;
547 /* swap ICU collation data like ucadata.icu */
548 U_CAPI
int32_t U_EXPORT2
549 ucol_swap(const UDataSwapper
*ds
,
550 const void *inData
, int32_t length
, void *outData
,
551 UErrorCode
*pErrorCode
) {
552 if(U_FAILURE(*pErrorCode
)) { return 0; }
554 /* udata_swapDataHeader checks the arguments */
555 int32_t headerSize
=udata_swapDataHeader(ds
, inData
, length
, outData
, pErrorCode
);
556 if(U_FAILURE(*pErrorCode
)) {
557 // Try to swap the old format version which did not have a standard data header.
558 *pErrorCode
=U_ZERO_ERROR
;
559 return swapFormatVersion3(ds
, inData
, length
, outData
, pErrorCode
);
562 /* check data format and format version */
563 const UDataInfo
&info
=*(const UDataInfo
*)((const char *)inData
+4);
565 info
.dataFormat
[0]==0x55 && // dataFormat="UCol"
566 info
.dataFormat
[1]==0x43 &&
567 info
.dataFormat
[2]==0x6f &&
568 info
.dataFormat
[3]==0x6c &&
569 (3<=info
.formatVersion
[0] && info
.formatVersion
[0]<=5)
571 udata_printError(ds
, "ucol_swap(): data format %02x.%02x.%02x.%02x "
572 "(format version %02x.%02x) is not recognized as collation data\n",
573 info
.dataFormat
[0], info
.dataFormat
[1],
574 info
.dataFormat
[2], info
.dataFormat
[3],
575 info
.formatVersion
[0], info
.formatVersion
[1]);
576 *pErrorCode
=U_UNSUPPORTED_ERROR
;
580 inData
=(const char *)inData
+headerSize
;
581 if(length
>=0) { length
-=headerSize
; }
582 outData
=(char *)outData
+headerSize
;
583 int32_t collationSize
;
584 if(info
.formatVersion
[0]>=4) {
585 collationSize
=swapFormatVersion4(ds
, inData
, length
, outData
, *pErrorCode
);
587 collationSize
=swapFormatVersion3(ds
, inData
, length
, outData
, pErrorCode
);
589 if(U_SUCCESS(*pErrorCode
)) {
590 return headerSize
+collationSize
;
596 /* swap inverse UCA collation data (invuca.icu) */
597 U_CAPI
int32_t U_EXPORT2
598 ucol_swapInverseUCA(const UDataSwapper
*ds
,
599 const void *inData
, int32_t length
, void *outData
,
600 UErrorCode
*pErrorCode
) {
601 const UDataInfo
*pInfo
;
604 const uint8_t *inBytes
;
607 const InverseUCATableHeader
*inHeader
;
608 InverseUCATableHeader
*outHeader
;
609 InverseUCATableHeader header
={ 0,0,0,0,0,{0,0,0,0},{0,0,0,0,0,0,0,0} };
611 /* udata_swapDataHeader checks the arguments */
612 headerSize
=udata_swapDataHeader(ds
, inData
, length
, outData
, pErrorCode
);
613 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
617 /* check data format and format version */
618 pInfo
=(const UDataInfo
*)((const char *)inData
+4);
620 pInfo
->dataFormat
[0]==0x49 && /* dataFormat="InvC" */
621 pInfo
->dataFormat
[1]==0x6e &&
622 pInfo
->dataFormat
[2]==0x76 &&
623 pInfo
->dataFormat
[3]==0x43 &&
624 pInfo
->formatVersion
[0]==2 &&
625 pInfo
->formatVersion
[1]>=1
627 udata_printError(ds
, "ucol_swapInverseUCA(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not an inverse UCA collation file\n",
628 pInfo
->dataFormat
[0], pInfo
->dataFormat
[1],
629 pInfo
->dataFormat
[2], pInfo
->dataFormat
[3],
630 pInfo
->formatVersion
[0], pInfo
->formatVersion
[1]);
631 *pErrorCode
=U_UNSUPPORTED_ERROR
;
635 inBytes
=(const uint8_t *)inData
+headerSize
;
636 outBytes
=(uint8_t *)outData
+headerSize
;
638 inHeader
=(const InverseUCATableHeader
*)inBytes
;
639 outHeader
=(InverseUCATableHeader
*)outBytes
;
642 * The inverse UCA collation binary must contain at least the InverseUCATableHeader,
643 * starting with its size field.
644 * sizeof(UCATableHeader)==8*4 in ICU 2.8
645 * check the length against the header size before reading the size field
648 header
.byteSize
=udata_readInt32(ds
, inHeader
->byteSize
);
650 ((length
-headerSize
)<(8*4) ||
651 (uint32_t)(length
-headerSize
)<(header
.byteSize
=udata_readInt32(ds
, inHeader
->byteSize
)))
653 udata_printError(ds
, "ucol_swapInverseUCA(): too few bytes (%d after header) for inverse UCA collation data\n",
655 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
660 /* copy everything, takes care of data that needs no swapping */
661 if(inBytes
!=outBytes
) {
662 uprv_memcpy(outBytes
, inBytes
, header
.byteSize
);
665 /* swap the necessary pieces in the order of their occurrence in the data */
667 /* read more of the InverseUCATableHeader (the byteSize field was read above) */
668 header
.tableSize
= ds
->readUInt32(inHeader
->tableSize
);
669 header
.contsSize
= ds
->readUInt32(inHeader
->contsSize
);
670 header
.table
= ds
->readUInt32(inHeader
->table
);
671 header
.conts
= ds
->readUInt32(inHeader
->conts
);
673 /* swap the 32-bit integers in the header */
674 ds
->swapArray32(ds
, inHeader
, 5*4, outHeader
, pErrorCode
);
676 /* swap the inverse table; tableSize counts uint32_t[3] rows */
677 ds
->swapArray32(ds
, inBytes
+header
.table
, header
.tableSize
*3*4,
678 outBytes
+header
.table
, pErrorCode
);
680 /* swap the continuation table; contsSize counts UChars */
681 ds
->swapArray16(ds
, inBytes
+header
.conts
, header
.contsSize
*U_SIZEOF_UCHAR
,
682 outBytes
+header
.conts
, pErrorCode
);
685 return headerSize
+header
.byteSize
;
688 #endif /* #if !UCONFIG_NO_COLLATION */