1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 2003-2015, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
10 * file name: ucol_swp.cpp
12 * tab size: 8 (not used)
15 * created on: 2003sep10
16 * created by: Markus W. Scherer
18 * Swap collation binaries.
21 #include "unicode/udata.h" /* UDataInfo */
26 #include "ucol_data.h"
29 /* swapping ----------------------------------------------------------------- */
32 * This performs data swapping for a folded trie (see utrie.c for details).
35 U_CAPI
int32_t U_EXPORT2
36 utrie_swap(const UDataSwapper
*ds
,
37 const void *inData
, int32_t length
, void *outData
,
38 UErrorCode
*pErrorCode
) {
39 const UTrieHeader
*inTrie
;
44 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
47 if(ds
==NULL
|| inData
==NULL
|| (length
>=0 && outData
==NULL
)) {
48 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
52 /* setup and swapping */
53 if(length
>=0 && (uint32_t)length
<sizeof(UTrieHeader
)) {
54 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
58 inTrie
=(const UTrieHeader
*)inData
;
59 trie
.signature
=ds
->readUInt32(inTrie
->signature
);
60 trie
.options
=ds
->readUInt32(inTrie
->options
);
61 trie
.indexLength
=udata_readInt32(ds
, inTrie
->indexLength
);
62 trie
.dataLength
=udata_readInt32(ds
, inTrie
->dataLength
);
64 if( trie
.signature
!=0x54726965 ||
65 (trie
.options
&UTRIE_OPTIONS_SHIFT_MASK
)!=UTRIE_SHIFT
||
66 ((trie
.options
>>UTRIE_OPTIONS_INDEX_SHIFT
)&UTRIE_OPTIONS_SHIFT_MASK
)!=UTRIE_INDEX_SHIFT
||
67 trie
.indexLength
<UTRIE_BMP_INDEX_LENGTH
||
68 (trie
.indexLength
&(UTRIE_SURROGATE_BLOCK_COUNT
-1))!=0 ||
69 trie
.dataLength
<UTRIE_DATA_BLOCK_LENGTH
||
70 (trie
.dataLength
&(UTRIE_DATA_GRANULARITY
-1))!=0 ||
71 ((trie
.options
&UTRIE_OPTIONS_LATIN1_IS_LINEAR
)!=0 && trie
.dataLength
<(UTRIE_DATA_BLOCK_LENGTH
+0x100))
73 *pErrorCode
=U_INVALID_FORMAT_ERROR
; /* not a UTrie */
77 dataIs32
=(UBool
)((trie
.options
&UTRIE_OPTIONS_DATA_IS_32_BIT
)!=0);
78 size
=sizeof(UTrieHeader
)+trie
.indexLength
*2+trie
.dataLength
*(dataIs32
?4:2);
84 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
88 outTrie
=(UTrieHeader
*)outData
;
91 ds
->swapArray32(ds
, inTrie
, sizeof(UTrieHeader
), outTrie
, pErrorCode
);
93 /* swap the index and the data */
95 ds
->swapArray16(ds
, inTrie
+1, trie
.indexLength
*2, outTrie
+1, pErrorCode
);
96 ds
->swapArray32(ds
, (const uint16_t *)(inTrie
+1)+trie
.indexLength
, trie
.dataLength
*4,
97 (uint16_t *)(outTrie
+1)+trie
.indexLength
, pErrorCode
);
99 ds
->swapArray16(ds
, inTrie
+1, (trie
.indexLength
+trie
.dataLength
)*2, outTrie
+1, pErrorCode
);
106 #if !UCONFIG_NO_COLLATION
108 U_CAPI UBool U_EXPORT2
109 ucol_looksLikeCollationBinary(const UDataSwapper
*ds
,
110 const void *inData
, int32_t length
) {
111 if(ds
==NULL
|| inData
==NULL
|| length
<-1) {
115 // First check for format version 4+ which has a standard data header.
116 UErrorCode errorCode
=U_ZERO_ERROR
;
117 (void)udata_swapDataHeader(ds
, inData
, -1, NULL
, &errorCode
);
118 if(U_SUCCESS(errorCode
)) {
119 const UDataInfo
&info
=*(const UDataInfo
*)((const char *)inData
+4);
120 if(info
.dataFormat
[0]==0x55 && // dataFormat="UCol"
121 info
.dataFormat
[1]==0x43 &&
122 info
.dataFormat
[2]==0x6f &&
123 info
.dataFormat
[3]==0x6c) {
128 // Else check for format version 3.
129 const UCATableHeader
*inHeader
=(const UCATableHeader
*)inData
;
132 * The collation binary must contain at least the UCATableHeader,
133 * starting with its size field.
134 * sizeof(UCATableHeader)==42*4 in ICU 2.8
135 * check the length against the header size before reading the size field
137 UCATableHeader header
;
138 uprv_memset(&header
, 0, sizeof(header
));
140 header
.size
=udata_readInt32(ds
, inHeader
->size
);
141 } else if((length
<(42*4) || length
<(header
.size
=udata_readInt32(ds
, inHeader
->size
)))) {
145 header
.magic
=ds
->readUInt32(inHeader
->magic
);
147 header
.magic
==UCOL_HEADER_MAGIC
&&
148 inHeader
->formatVersion
[0]==3 /*&&
149 inHeader->formatVersion[1]>=0*/
154 if(inHeader
->isBigEndian
!=ds
->inIsBigEndian
|| inHeader
->charSetFamily
!=ds
->inCharset
) {
163 /* swap a header-less collation formatVersion=3 binary, inside a resource bundle or ucadata.icu */
165 swapFormatVersion3(const UDataSwapper
*ds
,
166 const void *inData
, int32_t length
, void *outData
,
167 UErrorCode
*pErrorCode
) {
168 const uint8_t *inBytes
;
171 const UCATableHeader
*inHeader
;
172 UCATableHeader
*outHeader
;
173 UCATableHeader header
;
177 /* argument checking in case we were not called from ucol_swap() */
178 if(U_FAILURE(*pErrorCode
)) {
181 if(ds
==NULL
|| inData
==NULL
|| length
<-1 || (length
>0 && outData
==NULL
)) {
182 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
186 inBytes
=(const uint8_t *)inData
;
187 outBytes
=(uint8_t *)outData
;
189 inHeader
=(const UCATableHeader
*)inData
;
190 outHeader
=(UCATableHeader
*)outData
;
193 * The collation binary must contain at least the UCATableHeader,
194 * starting with its size field.
195 * sizeof(UCATableHeader)==42*4 in ICU 2.8
196 * check the length against the header size before reading the size field
198 uprv_memset(&header
, 0, sizeof(header
));
200 header
.size
=udata_readInt32(ds
, inHeader
->size
);
201 } else if((length
<(42*4) || length
<(header
.size
=udata_readInt32(ds
, inHeader
->size
)))) {
202 udata_printError(ds
, "ucol_swap(formatVersion=3): too few bytes (%d after header) for collation data\n",
204 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
208 header
.magic
=ds
->readUInt32(inHeader
->magic
);
210 header
.magic
==UCOL_HEADER_MAGIC
&&
211 inHeader
->formatVersion
[0]==3 /*&&
212 inHeader->formatVersion[1]>=0*/
214 udata_printError(ds
, "ucol_swap(formatVersion=3): magic 0x%08x or format version %02x.%02x is not a collation binary\n",
216 inHeader
->formatVersion
[0], inHeader
->formatVersion
[1]);
217 *pErrorCode
=U_UNSUPPORTED_ERROR
;
221 if(inHeader
->isBigEndian
!=ds
->inIsBigEndian
|| inHeader
->charSetFamily
!=ds
->inCharset
) {
222 udata_printError(ds
, "ucol_swap(formatVersion=3): endianness %d or charset %d does not match the swapper\n",
223 inHeader
->isBigEndian
, inHeader
->charSetFamily
);
224 *pErrorCode
=U_INVALID_FORMAT_ERROR
;
229 /* copy everything, takes care of data that needs no swapping */
230 if(inBytes
!=outBytes
) {
231 uprv_memcpy(outBytes
, inBytes
, header
.size
);
234 /* swap the necessary pieces in the order of their occurrence in the data */
236 /* read more of the UCATableHeader (the size field was read above) */
237 header
.options
= ds
->readUInt32(inHeader
->options
);
238 header
.UCAConsts
= ds
->readUInt32(inHeader
->UCAConsts
);
239 header
.contractionUCACombos
= ds
->readUInt32(inHeader
->contractionUCACombos
);
240 header
.mappingPosition
= ds
->readUInt32(inHeader
->mappingPosition
);
241 header
.expansion
= ds
->readUInt32(inHeader
->expansion
);
242 header
.contractionIndex
= ds
->readUInt32(inHeader
->contractionIndex
);
243 header
.contractionCEs
= ds
->readUInt32(inHeader
->contractionCEs
);
244 header
.contractionSize
= ds
->readUInt32(inHeader
->contractionSize
);
245 header
.endExpansionCE
= ds
->readUInt32(inHeader
->endExpansionCE
);
246 header
.expansionCESize
= ds
->readUInt32(inHeader
->expansionCESize
);
247 header
.endExpansionCECount
= udata_readInt32(ds
, inHeader
->endExpansionCECount
);
248 header
.contractionUCACombosSize
=udata_readInt32(ds
, inHeader
->contractionUCACombosSize
);
249 header
.scriptToLeadByte
= ds
->readUInt32(inHeader
->scriptToLeadByte
);
250 header
.leadByteToScript
= ds
->readUInt32(inHeader
->leadByteToScript
);
252 /* swap the 32-bit integers in the header */
253 ds
->swapArray32(ds
, inHeader
, (int32_t)((const char *)&inHeader
->jamoSpecial
-(const char *)inHeader
),
254 outHeader
, pErrorCode
);
255 ds
->swapArray32(ds
, &(inHeader
->scriptToLeadByte
), sizeof(header
.scriptToLeadByte
) + sizeof(header
.leadByteToScript
),
256 &(outHeader
->scriptToLeadByte
), pErrorCode
);
257 /* set the output platform properties */
258 outHeader
->isBigEndian
=ds
->outIsBigEndian
;
259 outHeader
->charSetFamily
=ds
->outCharset
;
261 /* swap the options */
262 if(header
.options
!=0) {
263 ds
->swapArray32(ds
, inBytes
+header
.options
, header
.expansion
-header
.options
,
264 outBytes
+header
.options
, pErrorCode
);
267 /* swap the expansions */
268 if(header
.mappingPosition
!=0 && header
.expansion
!=0) {
269 if(header
.contractionIndex
!=0) {
270 /* expansions bounded by contractions */
271 count
=header
.contractionIndex
-header
.expansion
;
273 /* no contractions: expansions bounded by the main trie */
274 count
=header
.mappingPosition
-header
.expansion
;
276 ds
->swapArray32(ds
, inBytes
+header
.expansion
, (int32_t)count
,
277 outBytes
+header
.expansion
, pErrorCode
);
280 /* swap the contractions */
281 if(header
.contractionSize
!=0) {
282 /* contractionIndex: UChar[] */
283 ds
->swapArray16(ds
, inBytes
+header
.contractionIndex
, header
.contractionSize
*2,
284 outBytes
+header
.contractionIndex
, pErrorCode
);
286 /* contractionCEs: CEs[] */
287 ds
->swapArray32(ds
, inBytes
+header
.contractionCEs
, header
.contractionSize
*4,
288 outBytes
+header
.contractionCEs
, pErrorCode
);
291 /* swap the main trie */
292 if(header
.mappingPosition
!=0) {
293 count
=header
.endExpansionCE
-header
.mappingPosition
;
294 utrie_swap(ds
, inBytes
+header
.mappingPosition
, (int32_t)count
,
295 outBytes
+header
.mappingPosition
, pErrorCode
);
298 /* swap the max expansion table */
299 if(header
.endExpansionCECount
!=0) {
300 ds
->swapArray32(ds
, inBytes
+header
.endExpansionCE
, header
.endExpansionCECount
*4,
301 outBytes
+header
.endExpansionCE
, pErrorCode
);
304 /* expansionCESize, unsafeCP, contrEndCP: uint8_t[], no need to swap */
306 /* swap UCA constants */
307 if(header
.UCAConsts
!=0) {
309 * if UCAConsts!=0 then contractionUCACombos because we are swapping
310 * the UCA data file, and we know that the UCA contains contractions
312 ds
->swapArray32(ds
, inBytes
+header
.UCAConsts
, header
.contractionUCACombos
-header
.UCAConsts
,
313 outBytes
+header
.UCAConsts
, pErrorCode
);
316 /* swap UCA contractions */
317 if(header
.contractionUCACombosSize
!=0) {
318 count
=header
.contractionUCACombosSize
*inHeader
->contractionUCACombosWidth
*U_SIZEOF_UCHAR
;
319 ds
->swapArray16(ds
, inBytes
+header
.contractionUCACombos
, (int32_t)count
,
320 outBytes
+header
.contractionUCACombos
, pErrorCode
);
323 /* swap the script to lead bytes */
324 if(header
.scriptToLeadByte
!=0) {
325 int indexCount
= ds
->readUInt16(*((uint16_t*)(inBytes
+header
.scriptToLeadByte
))); // each entry = 2 * uint16
326 int dataCount
= ds
->readUInt16(*((uint16_t*)(inBytes
+header
.scriptToLeadByte
+ 2))); // each entry = uint16
327 ds
->swapArray16(ds
, inBytes
+header
.scriptToLeadByte
,
328 4 + (4 * indexCount
) + (2 * dataCount
),
329 outBytes
+header
.scriptToLeadByte
, pErrorCode
);
332 /* swap the lead byte to scripts */
333 if(header
.leadByteToScript
!=0) {
334 int indexCount
= ds
->readUInt16(*((uint16_t*)(inBytes
+header
.leadByteToScript
))); // each entry = uint16
335 int dataCount
= ds
->readUInt16(*((uint16_t*)(inBytes
+header
.leadByteToScript
+ 2))); // each entry = uint16
336 ds
->swapArray16(ds
, inBytes
+header
.leadByteToScript
,
337 4 + (2 * indexCount
) + (2 * dataCount
),
338 outBytes
+header
.leadByteToScript
, pErrorCode
);
345 // swap formatVersion 4 or 5 ----------------------------------------------- ***
347 // The following are copied from CollationDataReader, trading an awkward copy of constants
348 // for an awkward relocation of the i18n collationdatareader.h file into the common library.
349 // Keep them in sync!
352 IX_INDEXES_LENGTH
, // 0
357 IX_JAMO_CE32S_START
, // 4
358 IX_REORDER_CODES_OFFSET
,
359 IX_REORDER_TABLE_OFFSET
,
362 IX_RESERVED8_OFFSET
, // 8
364 IX_RESERVED10_OFFSET
,
367 IX_ROOT_ELEMENTS_OFFSET
, // 12
369 IX_UNSAFE_BWD_OFFSET
,
370 IX_FAST_LATIN_TABLE_OFFSET
,
372 IX_SCRIPTS_OFFSET
, // 16
373 IX_COMPRESSIBLE_BYTES_OFFSET
,
374 IX_RESERVED18_OFFSET
,
379 swapFormatVersion4(const UDataSwapper
*ds
,
380 const void *inData
, int32_t length
, void *outData
,
381 UErrorCode
&errorCode
) {
382 if(U_FAILURE(errorCode
)) { return 0; }
384 const uint8_t *inBytes
=(const uint8_t *)inData
;
385 uint8_t *outBytes
=(uint8_t *)outData
;
387 const int32_t *inIndexes
=(const int32_t *)inBytes
;
388 int32_t indexes
[IX_TOTAL_SIZE
+1];
390 // Need at least IX_INDEXES_LENGTH and IX_OPTIONS.
391 if(0<=length
&& length
<8) {
392 udata_printError(ds
, "ucol_swap(formatVersion=4): too few bytes "
393 "(%d after header) for collation data\n",
395 errorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
399 int32_t indexesLength
=indexes
[0]=udata_readInt32(ds
, inIndexes
[0]);
400 if(0<=length
&& length
<(indexesLength
*4)) {
401 udata_printError(ds
, "ucol_swap(formatVersion=4): too few bytes "
402 "(%d after header) for collation data\n",
404 errorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
408 for(int32_t i
=1; i
<=IX_TOTAL_SIZE
&& i
<indexesLength
; ++i
) {
409 indexes
[i
]=udata_readInt32(ds
, inIndexes
[i
]);
411 for(int32_t i
=indexesLength
; i
<=IX_TOTAL_SIZE
; ++i
) {
414 inIndexes
=NULL
; // Make sure we do not accidentally use these instead of indexes[].
416 // Get the total length of the data.
418 if(indexesLength
>IX_TOTAL_SIZE
) {
419 size
=indexes
[IX_TOTAL_SIZE
];
420 } else if(indexesLength
>IX_REORDER_CODES_OFFSET
) {
421 size
=indexes
[indexesLength
-1];
423 size
=indexesLength
*4;
425 if(length
<0) { return size
; }
428 udata_printError(ds
, "ucol_swap(formatVersion=4): too few bytes "
429 "(%d after header) for collation data\n",
431 errorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
435 // Copy the data for inaccessible bytes and arrays of bytes.
436 if(inBytes
!=outBytes
) {
437 uprv_memcpy(outBytes
, inBytes
, size
);
440 // Swap the int32_t indexes[].
441 ds
->swapArray32(ds
, inBytes
, indexesLength
* 4, outBytes
, &errorCode
);
443 // The following is a modified version of CollationDataReader::read().
444 // Here we use indexes[] not inIndexes[] because
445 // the inIndexes[] may not be in this machine's endianness.
446 int32_t index
; // one of the indexes[] slots
447 int32_t offset
; // byte offset for the index part
448 // int32_t length; // number of bytes in the index part
450 index
= IX_REORDER_CODES_OFFSET
;
451 offset
= indexes
[index
];
452 length
= indexes
[index
+ 1] - offset
;
454 ds
->swapArray32(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
457 // Skip the IX_REORDER_TABLE_OFFSET byte array.
459 index
= IX_TRIE_OFFSET
;
460 offset
= indexes
[index
];
461 length
= indexes
[index
+ 1] - offset
;
463 utrie2_swap(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
466 index
= IX_RESERVED8_OFFSET
;
467 offset
= indexes
[index
];
468 length
= indexes
[index
+ 1] - offset
;
470 udata_printError(ds
, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED8_OFFSET\n", length
);
471 errorCode
= U_UNSUPPORTED_ERROR
;
475 index
= IX_CES_OFFSET
;
476 offset
= indexes
[index
];
477 length
= indexes
[index
+ 1] - offset
;
479 ds
->swapArray64(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
482 index
= IX_RESERVED10_OFFSET
;
483 offset
= indexes
[index
];
484 length
= indexes
[index
+ 1] - offset
;
486 udata_printError(ds
, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED10_OFFSET\n", length
);
487 errorCode
= U_UNSUPPORTED_ERROR
;
491 index
= IX_CE32S_OFFSET
;
492 offset
= indexes
[index
];
493 length
= indexes
[index
+ 1] - offset
;
495 ds
->swapArray32(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
498 index
= IX_ROOT_ELEMENTS_OFFSET
;
499 offset
= indexes
[index
];
500 length
= indexes
[index
+ 1] - offset
;
502 ds
->swapArray32(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
505 index
= IX_CONTEXTS_OFFSET
;
506 offset
= indexes
[index
];
507 length
= indexes
[index
+ 1] - offset
;
509 ds
->swapArray16(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
512 index
= IX_UNSAFE_BWD_OFFSET
;
513 offset
= indexes
[index
];
514 length
= indexes
[index
+ 1] - offset
;
516 ds
->swapArray16(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
519 index
= IX_FAST_LATIN_TABLE_OFFSET
;
520 offset
= indexes
[index
];
521 length
= indexes
[index
+ 1] - offset
;
523 ds
->swapArray16(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
526 index
= IX_SCRIPTS_OFFSET
;
527 offset
= indexes
[index
];
528 length
= indexes
[index
+ 1] - offset
;
530 ds
->swapArray16(ds
, inBytes
+ offset
, length
, outBytes
+ offset
, &errorCode
);
533 // Skip the IX_COMPRESSIBLE_BYTES_OFFSET byte array.
535 index
= IX_RESERVED18_OFFSET
;
536 offset
= indexes
[index
];
537 length
= indexes
[index
+ 1] - offset
;
539 udata_printError(ds
, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED18_OFFSET\n", length
);
540 errorCode
= U_UNSUPPORTED_ERROR
;
549 /* swap ICU collation data like ucadata.icu */
550 U_CAPI
int32_t U_EXPORT2
551 ucol_swap(const UDataSwapper
*ds
,
552 const void *inData
, int32_t length
, void *outData
,
553 UErrorCode
*pErrorCode
) {
554 if(U_FAILURE(*pErrorCode
)) { return 0; }
556 /* udata_swapDataHeader checks the arguments */
557 int32_t headerSize
=udata_swapDataHeader(ds
, inData
, length
, outData
, pErrorCode
);
558 if(U_FAILURE(*pErrorCode
)) {
559 // Try to swap the old format version which did not have a standard data header.
560 *pErrorCode
=U_ZERO_ERROR
;
561 return swapFormatVersion3(ds
, inData
, length
, outData
, pErrorCode
);
564 /* check data format and format version */
565 const UDataInfo
&info
=*(const UDataInfo
*)((const char *)inData
+4);
567 info
.dataFormat
[0]==0x55 && // dataFormat="UCol"
568 info
.dataFormat
[1]==0x43 &&
569 info
.dataFormat
[2]==0x6f &&
570 info
.dataFormat
[3]==0x6c &&
571 (3<=info
.formatVersion
[0] && info
.formatVersion
[0]<=5)
573 udata_printError(ds
, "ucol_swap(): data format %02x.%02x.%02x.%02x "
574 "(format version %02x.%02x) is not recognized as collation data\n",
575 info
.dataFormat
[0], info
.dataFormat
[1],
576 info
.dataFormat
[2], info
.dataFormat
[3],
577 info
.formatVersion
[0], info
.formatVersion
[1]);
578 *pErrorCode
=U_UNSUPPORTED_ERROR
;
582 inData
=(const char *)inData
+headerSize
;
583 if(length
>=0) { length
-=headerSize
; }
584 outData
=(char *)outData
+headerSize
;
585 int32_t collationSize
;
586 if(info
.formatVersion
[0]>=4) {
587 collationSize
=swapFormatVersion4(ds
, inData
, length
, outData
, *pErrorCode
);
589 collationSize
=swapFormatVersion3(ds
, inData
, length
, outData
, pErrorCode
);
591 if(U_SUCCESS(*pErrorCode
)) {
592 return headerSize
+collationSize
;
598 /* swap inverse UCA collation data (invuca.icu) */
599 U_CAPI
int32_t U_EXPORT2
600 ucol_swapInverseUCA(const UDataSwapper
*ds
,
601 const void *inData
, int32_t length
, void *outData
,
602 UErrorCode
*pErrorCode
) {
603 const UDataInfo
*pInfo
;
606 const uint8_t *inBytes
;
609 const InverseUCATableHeader
*inHeader
;
610 InverseUCATableHeader
*outHeader
;
611 InverseUCATableHeader header
={ 0,0,0,0,0,{0,0,0,0},{0,0,0,0,0,0,0,0} };
613 /* udata_swapDataHeader checks the arguments */
614 headerSize
=udata_swapDataHeader(ds
, inData
, length
, outData
, pErrorCode
);
615 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
619 /* check data format and format version */
620 pInfo
=(const UDataInfo
*)((const char *)inData
+4);
622 pInfo
->dataFormat
[0]==0x49 && /* dataFormat="InvC" */
623 pInfo
->dataFormat
[1]==0x6e &&
624 pInfo
->dataFormat
[2]==0x76 &&
625 pInfo
->dataFormat
[3]==0x43 &&
626 pInfo
->formatVersion
[0]==2 &&
627 pInfo
->formatVersion
[1]>=1
629 udata_printError(ds
, "ucol_swapInverseUCA(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not an inverse UCA collation file\n",
630 pInfo
->dataFormat
[0], pInfo
->dataFormat
[1],
631 pInfo
->dataFormat
[2], pInfo
->dataFormat
[3],
632 pInfo
->formatVersion
[0], pInfo
->formatVersion
[1]);
633 *pErrorCode
=U_UNSUPPORTED_ERROR
;
637 inBytes
=(const uint8_t *)inData
+headerSize
;
638 outBytes
=(uint8_t *)outData
+headerSize
;
640 inHeader
=(const InverseUCATableHeader
*)inBytes
;
641 outHeader
=(InverseUCATableHeader
*)outBytes
;
644 * The inverse UCA collation binary must contain at least the InverseUCATableHeader,
645 * starting with its size field.
646 * sizeof(UCATableHeader)==8*4 in ICU 2.8
647 * check the length against the header size before reading the size field
650 header
.byteSize
=udata_readInt32(ds
, inHeader
->byteSize
);
652 ((length
-headerSize
)<(8*4) ||
653 (uint32_t)(length
-headerSize
)<(header
.byteSize
=udata_readInt32(ds
, inHeader
->byteSize
)))
655 udata_printError(ds
, "ucol_swapInverseUCA(): too few bytes (%d after header) for inverse UCA collation data\n",
657 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
662 /* copy everything, takes care of data that needs no swapping */
663 if(inBytes
!=outBytes
) {
664 uprv_memcpy(outBytes
, inBytes
, header
.byteSize
);
667 /* swap the necessary pieces in the order of their occurrence in the data */
669 /* read more of the InverseUCATableHeader (the byteSize field was read above) */
670 header
.tableSize
= ds
->readUInt32(inHeader
->tableSize
);
671 header
.contsSize
= ds
->readUInt32(inHeader
->contsSize
);
672 header
.table
= ds
->readUInt32(inHeader
->table
);
673 header
.conts
= ds
->readUInt32(inHeader
->conts
);
675 /* swap the 32-bit integers in the header */
676 ds
->swapArray32(ds
, inHeader
, 5*4, outHeader
, pErrorCode
);
678 /* swap the inverse table; tableSize counts uint32_t[3] rows */
679 ds
->swapArray32(ds
, inBytes
+header
.table
, header
.tableSize
*3*4,
680 outBytes
+header
.table
, pErrorCode
);
682 /* swap the continuation table; contsSize counts UChars */
683 ds
->swapArray16(ds
, inBytes
+header
.conts
, header
.contsSize
*U_SIZEOF_UCHAR
,
684 outBytes
+header
.conts
, pErrorCode
);
687 return headerSize
+header
.byteSize
;
690 #endif /* #if !UCONFIG_NO_COLLATION */