11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 31cb0ef41Sopenharmony_ci/* 41cb0ef41Sopenharmony_ci******************************************************************************* 51cb0ef41Sopenharmony_ci* 61cb0ef41Sopenharmony_ci* Copyright (C) 2003-2015, International Business Machines 71cb0ef41Sopenharmony_ci* Corporation and others. All Rights Reserved. 81cb0ef41Sopenharmony_ci* 91cb0ef41Sopenharmony_ci******************************************************************************* 101cb0ef41Sopenharmony_ci* file name: ucol_swp.cpp 111cb0ef41Sopenharmony_ci* encoding: UTF-8 121cb0ef41Sopenharmony_ci* tab size: 8 (not used) 131cb0ef41Sopenharmony_ci* indentation:4 141cb0ef41Sopenharmony_ci* 151cb0ef41Sopenharmony_ci* created on: 2003sep10 161cb0ef41Sopenharmony_ci* created by: Markus W. Scherer 171cb0ef41Sopenharmony_ci* 181cb0ef41Sopenharmony_ci* Swap collation binaries. 191cb0ef41Sopenharmony_ci*/ 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci#include "unicode/udata.h" /* UDataInfo */ 221cb0ef41Sopenharmony_ci#include "utrie.h" 231cb0ef41Sopenharmony_ci#include "utrie2.h" 241cb0ef41Sopenharmony_ci#include "udataswp.h" 251cb0ef41Sopenharmony_ci#include "cmemory.h" 261cb0ef41Sopenharmony_ci#include "ucol_data.h" 271cb0ef41Sopenharmony_ci#include "ucol_swp.h" 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci/* swapping ----------------------------------------------------------------- */ 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci#if !UCONFIG_NO_COLLATION 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ciU_CAPI UBool U_EXPORT2 341cb0ef41Sopenharmony_ciucol_looksLikeCollationBinary(const UDataSwapper *ds, 351cb0ef41Sopenharmony_ci const void *inData, int32_t length) { 361cb0ef41Sopenharmony_ci if(ds==nullptr || inData==nullptr || length<-1) { 371cb0ef41Sopenharmony_ci return false; 381cb0ef41Sopenharmony_ci } 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci // First check for format version 4+ which has a standard data header. 411cb0ef41Sopenharmony_ci UErrorCode errorCode=U_ZERO_ERROR; 421cb0ef41Sopenharmony_ci (void)udata_swapDataHeader(ds, inData, -1, nullptr, &errorCode); 431cb0ef41Sopenharmony_ci if(U_SUCCESS(errorCode)) { 441cb0ef41Sopenharmony_ci const UDataInfo &info=*(const UDataInfo *)((const char *)inData+4); 451cb0ef41Sopenharmony_ci if(info.dataFormat[0]==0x55 && // dataFormat="UCol" 461cb0ef41Sopenharmony_ci info.dataFormat[1]==0x43 && 471cb0ef41Sopenharmony_ci info.dataFormat[2]==0x6f && 481cb0ef41Sopenharmony_ci info.dataFormat[3]==0x6c) { 491cb0ef41Sopenharmony_ci return true; 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci // Else check for format version 3. 541cb0ef41Sopenharmony_ci const UCATableHeader *inHeader=(const UCATableHeader *)inData; 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci /* 571cb0ef41Sopenharmony_ci * The collation binary must contain at least the UCATableHeader, 581cb0ef41Sopenharmony_ci * starting with its size field. 591cb0ef41Sopenharmony_ci * sizeof(UCATableHeader)==42*4 in ICU 2.8 601cb0ef41Sopenharmony_ci * check the length against the header size before reading the size field 611cb0ef41Sopenharmony_ci */ 621cb0ef41Sopenharmony_ci UCATableHeader header; 631cb0ef41Sopenharmony_ci uprv_memset(&header, 0, sizeof(header)); 641cb0ef41Sopenharmony_ci if(length<0) { 651cb0ef41Sopenharmony_ci header.size=udata_readInt32(ds, inHeader->size); 661cb0ef41Sopenharmony_ci } else if((length<(42*4) || length<(header.size=udata_readInt32(ds, inHeader->size)))) { 671cb0ef41Sopenharmony_ci return false; 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci header.magic=ds->readUInt32(inHeader->magic); 711cb0ef41Sopenharmony_ci if(!( 721cb0ef41Sopenharmony_ci header.magic==UCOL_HEADER_MAGIC && 731cb0ef41Sopenharmony_ci inHeader->formatVersion[0]==3 /*&& 741cb0ef41Sopenharmony_ci inHeader->formatVersion[1]>=0*/ 751cb0ef41Sopenharmony_ci )) { 761cb0ef41Sopenharmony_ci return false; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci if(inHeader->isBigEndian!=ds->inIsBigEndian || inHeader->charSetFamily!=ds->inCharset) { 801cb0ef41Sopenharmony_ci return false; 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci return true; 841cb0ef41Sopenharmony_ci} 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_cinamespace { 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci/* swap a header-less collation formatVersion=3 binary, inside a resource bundle or ucadata.icu */ 891cb0ef41Sopenharmony_ciint32_t 901cb0ef41Sopenharmony_ciswapFormatVersion3(const UDataSwapper *ds, 911cb0ef41Sopenharmony_ci const void *inData, int32_t length, void *outData, 921cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) { 931cb0ef41Sopenharmony_ci const uint8_t *inBytes; 941cb0ef41Sopenharmony_ci uint8_t *outBytes; 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci const UCATableHeader *inHeader; 971cb0ef41Sopenharmony_ci UCATableHeader *outHeader; 981cb0ef41Sopenharmony_ci UCATableHeader header; 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci uint32_t count; 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci /* argument checking in case we were not called from ucol_swap() */ 1031cb0ef41Sopenharmony_ci if(U_FAILURE(*pErrorCode)) { 1041cb0ef41Sopenharmony_ci return 0; 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci if(ds==nullptr || inData==nullptr || length<-1 || (length>0 && outData==nullptr)) { 1071cb0ef41Sopenharmony_ci *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1081cb0ef41Sopenharmony_ci return 0; 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci inBytes=(const uint8_t *)inData; 1121cb0ef41Sopenharmony_ci outBytes=(uint8_t *)outData; 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci inHeader=(const UCATableHeader *)inData; 1151cb0ef41Sopenharmony_ci outHeader=(UCATableHeader *)outData; 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci /* 1181cb0ef41Sopenharmony_ci * The collation binary must contain at least the UCATableHeader, 1191cb0ef41Sopenharmony_ci * starting with its size field. 1201cb0ef41Sopenharmony_ci * sizeof(UCATableHeader)==42*4 in ICU 2.8 1211cb0ef41Sopenharmony_ci * check the length against the header size before reading the size field 1221cb0ef41Sopenharmony_ci */ 1231cb0ef41Sopenharmony_ci uprv_memset(&header, 0, sizeof(header)); 1241cb0ef41Sopenharmony_ci if(length<0) { 1251cb0ef41Sopenharmony_ci header.size=udata_readInt32(ds, inHeader->size); 1261cb0ef41Sopenharmony_ci } else if((length<(42*4) || length<(header.size=udata_readInt32(ds, inHeader->size)))) { 1271cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(formatVersion=3): too few bytes (%d after header) for collation data\n", 1281cb0ef41Sopenharmony_ci length); 1291cb0ef41Sopenharmony_ci *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 1301cb0ef41Sopenharmony_ci return 0; 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci header.magic=ds->readUInt32(inHeader->magic); 1341cb0ef41Sopenharmony_ci if(!( 1351cb0ef41Sopenharmony_ci header.magic==UCOL_HEADER_MAGIC && 1361cb0ef41Sopenharmony_ci inHeader->formatVersion[0]==3 /*&& 1371cb0ef41Sopenharmony_ci inHeader->formatVersion[1]>=0*/ 1381cb0ef41Sopenharmony_ci )) { 1391cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(formatVersion=3): magic 0x%08x or format version %02x.%02x is not a collation binary\n", 1401cb0ef41Sopenharmony_ci header.magic, 1411cb0ef41Sopenharmony_ci inHeader->formatVersion[0], inHeader->formatVersion[1]); 1421cb0ef41Sopenharmony_ci *pErrorCode=U_UNSUPPORTED_ERROR; 1431cb0ef41Sopenharmony_ci return 0; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci if(inHeader->isBigEndian!=ds->inIsBigEndian || inHeader->charSetFamily!=ds->inCharset) { 1471cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(formatVersion=3): endianness %d or charset %d does not match the swapper\n", 1481cb0ef41Sopenharmony_ci inHeader->isBigEndian, inHeader->charSetFamily); 1491cb0ef41Sopenharmony_ci *pErrorCode=U_INVALID_FORMAT_ERROR; 1501cb0ef41Sopenharmony_ci return 0; 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci if(length>=0) { 1541cb0ef41Sopenharmony_ci /* copy everything, takes care of data that needs no swapping */ 1551cb0ef41Sopenharmony_ci if(inBytes!=outBytes) { 1561cb0ef41Sopenharmony_ci uprv_memcpy(outBytes, inBytes, header.size); 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci /* swap the necessary pieces in the order of their occurrence in the data */ 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci /* read more of the UCATableHeader (the size field was read above) */ 1621cb0ef41Sopenharmony_ci header.options= ds->readUInt32(inHeader->options); 1631cb0ef41Sopenharmony_ci header.UCAConsts= ds->readUInt32(inHeader->UCAConsts); 1641cb0ef41Sopenharmony_ci header.contractionUCACombos= ds->readUInt32(inHeader->contractionUCACombos); 1651cb0ef41Sopenharmony_ci header.mappingPosition= ds->readUInt32(inHeader->mappingPosition); 1661cb0ef41Sopenharmony_ci header.expansion= ds->readUInt32(inHeader->expansion); 1671cb0ef41Sopenharmony_ci header.contractionIndex= ds->readUInt32(inHeader->contractionIndex); 1681cb0ef41Sopenharmony_ci header.contractionCEs= ds->readUInt32(inHeader->contractionCEs); 1691cb0ef41Sopenharmony_ci header.contractionSize= ds->readUInt32(inHeader->contractionSize); 1701cb0ef41Sopenharmony_ci header.endExpansionCE= ds->readUInt32(inHeader->endExpansionCE); 1711cb0ef41Sopenharmony_ci header.expansionCESize= ds->readUInt32(inHeader->expansionCESize); 1721cb0ef41Sopenharmony_ci header.endExpansionCECount= udata_readInt32(ds, inHeader->endExpansionCECount); 1731cb0ef41Sopenharmony_ci header.contractionUCACombosSize=udata_readInt32(ds, inHeader->contractionUCACombosSize); 1741cb0ef41Sopenharmony_ci header.scriptToLeadByte= ds->readUInt32(inHeader->scriptToLeadByte); 1751cb0ef41Sopenharmony_ci header.leadByteToScript= ds->readUInt32(inHeader->leadByteToScript); 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci /* swap the 32-bit integers in the header */ 1781cb0ef41Sopenharmony_ci ds->swapArray32(ds, inHeader, (int32_t)((const char *)&inHeader->jamoSpecial-(const char *)inHeader), 1791cb0ef41Sopenharmony_ci outHeader, pErrorCode); 1801cb0ef41Sopenharmony_ci ds->swapArray32(ds, &(inHeader->scriptToLeadByte), sizeof(header.scriptToLeadByte) + sizeof(header.leadByteToScript), 1811cb0ef41Sopenharmony_ci &(outHeader->scriptToLeadByte), pErrorCode); 1821cb0ef41Sopenharmony_ci /* set the output platform properties */ 1831cb0ef41Sopenharmony_ci outHeader->isBigEndian=ds->outIsBigEndian; 1841cb0ef41Sopenharmony_ci outHeader->charSetFamily=ds->outCharset; 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci /* swap the options */ 1871cb0ef41Sopenharmony_ci if(header.options!=0) { 1881cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes+header.options, header.expansion-header.options, 1891cb0ef41Sopenharmony_ci outBytes+header.options, pErrorCode); 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci /* swap the expansions */ 1931cb0ef41Sopenharmony_ci if(header.mappingPosition!=0 && header.expansion!=0) { 1941cb0ef41Sopenharmony_ci if(header.contractionIndex!=0) { 1951cb0ef41Sopenharmony_ci /* expansions bounded by contractions */ 1961cb0ef41Sopenharmony_ci count=header.contractionIndex-header.expansion; 1971cb0ef41Sopenharmony_ci } else { 1981cb0ef41Sopenharmony_ci /* no contractions: expansions bounded by the main trie */ 1991cb0ef41Sopenharmony_ci count=header.mappingPosition-header.expansion; 2001cb0ef41Sopenharmony_ci } 2011cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes+header.expansion, (int32_t)count, 2021cb0ef41Sopenharmony_ci outBytes+header.expansion, pErrorCode); 2031cb0ef41Sopenharmony_ci } 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci /* swap the contractions */ 2061cb0ef41Sopenharmony_ci if(header.contractionSize!=0) { 2071cb0ef41Sopenharmony_ci /* contractionIndex: char16_t[] */ 2081cb0ef41Sopenharmony_ci ds->swapArray16(ds, inBytes+header.contractionIndex, header.contractionSize*2, 2091cb0ef41Sopenharmony_ci outBytes+header.contractionIndex, pErrorCode); 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_ci /* contractionCEs: CEs[] */ 2121cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes+header.contractionCEs, header.contractionSize*4, 2131cb0ef41Sopenharmony_ci outBytes+header.contractionCEs, pErrorCode); 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci /* swap the main trie */ 2171cb0ef41Sopenharmony_ci if(header.mappingPosition!=0) { 2181cb0ef41Sopenharmony_ci count=header.endExpansionCE-header.mappingPosition; 2191cb0ef41Sopenharmony_ci utrie_swap(ds, inBytes+header.mappingPosition, (int32_t)count, 2201cb0ef41Sopenharmony_ci outBytes+header.mappingPosition, pErrorCode); 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci /* swap the max expansion table */ 2241cb0ef41Sopenharmony_ci if(header.endExpansionCECount!=0) { 2251cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes+header.endExpansionCE, header.endExpansionCECount*4, 2261cb0ef41Sopenharmony_ci outBytes+header.endExpansionCE, pErrorCode); 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci /* expansionCESize, unsafeCP, contrEndCP: uint8_t[], no need to swap */ 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci /* swap UCA constants */ 2321cb0ef41Sopenharmony_ci if(header.UCAConsts!=0) { 2331cb0ef41Sopenharmony_ci /* 2341cb0ef41Sopenharmony_ci * if UCAConsts!=0 then contractionUCACombos because we are swapping 2351cb0ef41Sopenharmony_ci * the UCA data file, and we know that the UCA contains contractions 2361cb0ef41Sopenharmony_ci */ 2371cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes+header.UCAConsts, header.contractionUCACombos-header.UCAConsts, 2381cb0ef41Sopenharmony_ci outBytes+header.UCAConsts, pErrorCode); 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci /* swap UCA contractions */ 2421cb0ef41Sopenharmony_ci if(header.contractionUCACombosSize!=0) { 2431cb0ef41Sopenharmony_ci count=header.contractionUCACombosSize*inHeader->contractionUCACombosWidth*U_SIZEOF_UCHAR; 2441cb0ef41Sopenharmony_ci ds->swapArray16(ds, inBytes+header.contractionUCACombos, (int32_t)count, 2451cb0ef41Sopenharmony_ci outBytes+header.contractionUCACombos, pErrorCode); 2461cb0ef41Sopenharmony_ci } 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci /* swap the script to lead bytes */ 2491cb0ef41Sopenharmony_ci if(header.scriptToLeadByte!=0) { 2501cb0ef41Sopenharmony_ci int indexCount = ds->readUInt16(*((uint16_t*)(inBytes+header.scriptToLeadByte))); // each entry = 2 * uint16 2511cb0ef41Sopenharmony_ci int dataCount = ds->readUInt16(*((uint16_t*)(inBytes+header.scriptToLeadByte + 2))); // each entry = uint16 2521cb0ef41Sopenharmony_ci ds->swapArray16(ds, inBytes+header.scriptToLeadByte, 2531cb0ef41Sopenharmony_ci 4 + (4 * indexCount) + (2 * dataCount), 2541cb0ef41Sopenharmony_ci outBytes+header.scriptToLeadByte, pErrorCode); 2551cb0ef41Sopenharmony_ci } 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ci /* swap the lead byte to scripts */ 2581cb0ef41Sopenharmony_ci if(header.leadByteToScript!=0) { 2591cb0ef41Sopenharmony_ci int indexCount = ds->readUInt16(*((uint16_t*)(inBytes+header.leadByteToScript))); // each entry = uint16 2601cb0ef41Sopenharmony_ci int dataCount = ds->readUInt16(*((uint16_t*)(inBytes+header.leadByteToScript + 2))); // each entry = uint16 2611cb0ef41Sopenharmony_ci ds->swapArray16(ds, inBytes+header.leadByteToScript, 2621cb0ef41Sopenharmony_ci 4 + (2 * indexCount) + (2 * dataCount), 2631cb0ef41Sopenharmony_ci outBytes+header.leadByteToScript, pErrorCode); 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci } 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci return header.size; 2681cb0ef41Sopenharmony_ci} 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci// swap formatVersion 4 or 5 ----------------------------------------------- *** 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci// The following are copied from CollationDataReader, trading an awkward copy of constants 2731cb0ef41Sopenharmony_ci// for an awkward relocation of the i18n collationdatareader.h file into the common library. 2741cb0ef41Sopenharmony_ci// Keep them in sync! 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_cienum { 2771cb0ef41Sopenharmony_ci IX_INDEXES_LENGTH, // 0 2781cb0ef41Sopenharmony_ci IX_OPTIONS, 2791cb0ef41Sopenharmony_ci IX_RESERVED2, 2801cb0ef41Sopenharmony_ci IX_RESERVED3, 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci IX_JAMO_CE32S_START, // 4 2831cb0ef41Sopenharmony_ci IX_REORDER_CODES_OFFSET, 2841cb0ef41Sopenharmony_ci IX_REORDER_TABLE_OFFSET, 2851cb0ef41Sopenharmony_ci IX_TRIE_OFFSET, 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci IX_RESERVED8_OFFSET, // 8 2881cb0ef41Sopenharmony_ci IX_CES_OFFSET, 2891cb0ef41Sopenharmony_ci IX_RESERVED10_OFFSET, 2901cb0ef41Sopenharmony_ci IX_CE32S_OFFSET, 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci IX_ROOT_ELEMENTS_OFFSET, // 12 2931cb0ef41Sopenharmony_ci IX_CONTEXTS_OFFSET, 2941cb0ef41Sopenharmony_ci IX_UNSAFE_BWD_OFFSET, 2951cb0ef41Sopenharmony_ci IX_FAST_LATIN_TABLE_OFFSET, 2961cb0ef41Sopenharmony_ci 2971cb0ef41Sopenharmony_ci IX_SCRIPTS_OFFSET, // 16 2981cb0ef41Sopenharmony_ci IX_COMPRESSIBLE_BYTES_OFFSET, 2991cb0ef41Sopenharmony_ci IX_RESERVED18_OFFSET, 3001cb0ef41Sopenharmony_ci IX_TOTAL_SIZE 3011cb0ef41Sopenharmony_ci}; 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ciint32_t 3041cb0ef41Sopenharmony_ciswapFormatVersion4(const UDataSwapper *ds, 3051cb0ef41Sopenharmony_ci const void *inData, int32_t length, void *outData, 3061cb0ef41Sopenharmony_ci UErrorCode &errorCode) { 3071cb0ef41Sopenharmony_ci if(U_FAILURE(errorCode)) { return 0; } 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci const uint8_t *inBytes=(const uint8_t *)inData; 3101cb0ef41Sopenharmony_ci uint8_t *outBytes=(uint8_t *)outData; 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci const int32_t *inIndexes=(const int32_t *)inBytes; 3131cb0ef41Sopenharmony_ci int32_t indexes[IX_TOTAL_SIZE+1]; 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci // Need at least IX_INDEXES_LENGTH and IX_OPTIONS. 3161cb0ef41Sopenharmony_ci if(0<=length && length<8) { 3171cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(formatVersion=4): too few bytes " 3181cb0ef41Sopenharmony_ci "(%d after header) for collation data\n", 3191cb0ef41Sopenharmony_ci length); 3201cb0ef41Sopenharmony_ci errorCode=U_INDEX_OUTOFBOUNDS_ERROR; 3211cb0ef41Sopenharmony_ci return 0; 3221cb0ef41Sopenharmony_ci } 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci int32_t indexesLength=indexes[0]=udata_readInt32(ds, inIndexes[0]); 3251cb0ef41Sopenharmony_ci if(0<=length && length<(indexesLength*4)) { 3261cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(formatVersion=4): too few bytes " 3271cb0ef41Sopenharmony_ci "(%d after header) for collation data\n", 3281cb0ef41Sopenharmony_ci length); 3291cb0ef41Sopenharmony_ci errorCode=U_INDEX_OUTOFBOUNDS_ERROR; 3301cb0ef41Sopenharmony_ci return 0; 3311cb0ef41Sopenharmony_ci } 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci for(int32_t i=1; i<=IX_TOTAL_SIZE && i<indexesLength; ++i) { 3341cb0ef41Sopenharmony_ci indexes[i]=udata_readInt32(ds, inIndexes[i]); 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci for(int32_t i=indexesLength; i<=IX_TOTAL_SIZE; ++i) { 3371cb0ef41Sopenharmony_ci indexes[i]=-1; 3381cb0ef41Sopenharmony_ci } 3391cb0ef41Sopenharmony_ci inIndexes=nullptr; // Make sure we do not accidentally use these instead of indexes[]. 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci // Get the total length of the data. 3421cb0ef41Sopenharmony_ci int32_t size; 3431cb0ef41Sopenharmony_ci if(indexesLength>IX_TOTAL_SIZE) { 3441cb0ef41Sopenharmony_ci size=indexes[IX_TOTAL_SIZE]; 3451cb0ef41Sopenharmony_ci } else if(indexesLength>IX_REORDER_CODES_OFFSET) { 3461cb0ef41Sopenharmony_ci size=indexes[indexesLength-1]; 3471cb0ef41Sopenharmony_ci } else { 3481cb0ef41Sopenharmony_ci size=indexesLength*4; 3491cb0ef41Sopenharmony_ci } 3501cb0ef41Sopenharmony_ci if(length<0) { return size; } 3511cb0ef41Sopenharmony_ci 3521cb0ef41Sopenharmony_ci if(length<size) { 3531cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(formatVersion=4): too few bytes " 3541cb0ef41Sopenharmony_ci "(%d after header) for collation data\n", 3551cb0ef41Sopenharmony_ci length); 3561cb0ef41Sopenharmony_ci errorCode=U_INDEX_OUTOFBOUNDS_ERROR; 3571cb0ef41Sopenharmony_ci return 0; 3581cb0ef41Sopenharmony_ci } 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci // Copy the data for inaccessible bytes and arrays of bytes. 3611cb0ef41Sopenharmony_ci if(inBytes!=outBytes) { 3621cb0ef41Sopenharmony_ci uprv_memcpy(outBytes, inBytes, size); 3631cb0ef41Sopenharmony_ci } 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci // Swap the int32_t indexes[]. 3661cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes, indexesLength * 4, outBytes, &errorCode); 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci // The following is a modified version of CollationDataReader::read(). 3691cb0ef41Sopenharmony_ci // Here we use indexes[] not inIndexes[] because 3701cb0ef41Sopenharmony_ci // the inIndexes[] may not be in this machine's endianness. 3711cb0ef41Sopenharmony_ci int32_t index; // one of the indexes[] slots 3721cb0ef41Sopenharmony_ci int32_t offset; // byte offset for the index part 3731cb0ef41Sopenharmony_ci // int32_t length; // number of bytes in the index part 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ci index = IX_REORDER_CODES_OFFSET; 3761cb0ef41Sopenharmony_ci offset = indexes[index]; 3771cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 3781cb0ef41Sopenharmony_ci if(length > 0) { 3791cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes + offset, length, outBytes + offset, &errorCode); 3801cb0ef41Sopenharmony_ci } 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci // Skip the IX_REORDER_TABLE_OFFSET byte array. 3831cb0ef41Sopenharmony_ci 3841cb0ef41Sopenharmony_ci index = IX_TRIE_OFFSET; 3851cb0ef41Sopenharmony_ci offset = indexes[index]; 3861cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 3871cb0ef41Sopenharmony_ci if(length > 0) { 3881cb0ef41Sopenharmony_ci utrie2_swap(ds, inBytes + offset, length, outBytes + offset, &errorCode); 3891cb0ef41Sopenharmony_ci } 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci index = IX_RESERVED8_OFFSET; 3921cb0ef41Sopenharmony_ci offset = indexes[index]; 3931cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 3941cb0ef41Sopenharmony_ci if(length > 0) { 3951cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED8_OFFSET\n", length); 3961cb0ef41Sopenharmony_ci errorCode = U_UNSUPPORTED_ERROR; 3971cb0ef41Sopenharmony_ci return 0; 3981cb0ef41Sopenharmony_ci } 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci index = IX_CES_OFFSET; 4011cb0ef41Sopenharmony_ci offset = indexes[index]; 4021cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 4031cb0ef41Sopenharmony_ci if(length > 0) { 4041cb0ef41Sopenharmony_ci ds->swapArray64(ds, inBytes + offset, length, outBytes + offset, &errorCode); 4051cb0ef41Sopenharmony_ci } 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci index = IX_RESERVED10_OFFSET; 4081cb0ef41Sopenharmony_ci offset = indexes[index]; 4091cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 4101cb0ef41Sopenharmony_ci if(length > 0) { 4111cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED10_OFFSET\n", length); 4121cb0ef41Sopenharmony_ci errorCode = U_UNSUPPORTED_ERROR; 4131cb0ef41Sopenharmony_ci return 0; 4141cb0ef41Sopenharmony_ci } 4151cb0ef41Sopenharmony_ci 4161cb0ef41Sopenharmony_ci index = IX_CE32S_OFFSET; 4171cb0ef41Sopenharmony_ci offset = indexes[index]; 4181cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 4191cb0ef41Sopenharmony_ci if(length > 0) { 4201cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes + offset, length, outBytes + offset, &errorCode); 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci index = IX_ROOT_ELEMENTS_OFFSET; 4241cb0ef41Sopenharmony_ci offset = indexes[index]; 4251cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 4261cb0ef41Sopenharmony_ci if(length > 0) { 4271cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes + offset, length, outBytes + offset, &errorCode); 4281cb0ef41Sopenharmony_ci } 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci index = IX_CONTEXTS_OFFSET; 4311cb0ef41Sopenharmony_ci offset = indexes[index]; 4321cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 4331cb0ef41Sopenharmony_ci if(length > 0) { 4341cb0ef41Sopenharmony_ci ds->swapArray16(ds, inBytes + offset, length, outBytes + offset, &errorCode); 4351cb0ef41Sopenharmony_ci } 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci index = IX_UNSAFE_BWD_OFFSET; 4381cb0ef41Sopenharmony_ci offset = indexes[index]; 4391cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 4401cb0ef41Sopenharmony_ci if(length > 0) { 4411cb0ef41Sopenharmony_ci ds->swapArray16(ds, inBytes + offset, length, outBytes + offset, &errorCode); 4421cb0ef41Sopenharmony_ci } 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci index = IX_FAST_LATIN_TABLE_OFFSET; 4451cb0ef41Sopenharmony_ci offset = indexes[index]; 4461cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 4471cb0ef41Sopenharmony_ci if(length > 0) { 4481cb0ef41Sopenharmony_ci ds->swapArray16(ds, inBytes + offset, length, outBytes + offset, &errorCode); 4491cb0ef41Sopenharmony_ci } 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci index = IX_SCRIPTS_OFFSET; 4521cb0ef41Sopenharmony_ci offset = indexes[index]; 4531cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 4541cb0ef41Sopenharmony_ci if(length > 0) { 4551cb0ef41Sopenharmony_ci ds->swapArray16(ds, inBytes + offset, length, outBytes + offset, &errorCode); 4561cb0ef41Sopenharmony_ci } 4571cb0ef41Sopenharmony_ci 4581cb0ef41Sopenharmony_ci // Skip the IX_COMPRESSIBLE_BYTES_OFFSET byte array. 4591cb0ef41Sopenharmony_ci 4601cb0ef41Sopenharmony_ci index = IX_RESERVED18_OFFSET; 4611cb0ef41Sopenharmony_ci offset = indexes[index]; 4621cb0ef41Sopenharmony_ci length = indexes[index + 1] - offset; 4631cb0ef41Sopenharmony_ci if(length > 0) { 4641cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED18_OFFSET\n", length); 4651cb0ef41Sopenharmony_ci errorCode = U_UNSUPPORTED_ERROR; 4661cb0ef41Sopenharmony_ci return 0; 4671cb0ef41Sopenharmony_ci } 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci return size; 4701cb0ef41Sopenharmony_ci} 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci} // namespace 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci/* swap ICU collation data like ucadata.icu */ 4751cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2 4761cb0ef41Sopenharmony_ciucol_swap(const UDataSwapper *ds, 4771cb0ef41Sopenharmony_ci const void *inData, int32_t length, void *outData, 4781cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) { 4791cb0ef41Sopenharmony_ci if(U_FAILURE(*pErrorCode)) { return 0; } 4801cb0ef41Sopenharmony_ci 4811cb0ef41Sopenharmony_ci /* udata_swapDataHeader checks the arguments */ 4821cb0ef41Sopenharmony_ci int32_t headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 4831cb0ef41Sopenharmony_ci if(U_FAILURE(*pErrorCode)) { 4841cb0ef41Sopenharmony_ci // Try to swap the old format version which did not have a standard data header. 4851cb0ef41Sopenharmony_ci *pErrorCode=U_ZERO_ERROR; 4861cb0ef41Sopenharmony_ci return swapFormatVersion3(ds, inData, length, outData, pErrorCode); 4871cb0ef41Sopenharmony_ci } 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci /* check data format and format version */ 4901cb0ef41Sopenharmony_ci const UDataInfo &info=*(const UDataInfo *)((const char *)inData+4); 4911cb0ef41Sopenharmony_ci if(!( 4921cb0ef41Sopenharmony_ci info.dataFormat[0]==0x55 && // dataFormat="UCol" 4931cb0ef41Sopenharmony_ci info.dataFormat[1]==0x43 && 4941cb0ef41Sopenharmony_ci info.dataFormat[2]==0x6f && 4951cb0ef41Sopenharmony_ci info.dataFormat[3]==0x6c && 4961cb0ef41Sopenharmony_ci (3<=info.formatVersion[0] && info.formatVersion[0]<=5) 4971cb0ef41Sopenharmony_ci )) { 4981cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swap(): data format %02x.%02x.%02x.%02x " 4991cb0ef41Sopenharmony_ci "(format version %02x.%02x) is not recognized as collation data\n", 5001cb0ef41Sopenharmony_ci info.dataFormat[0], info.dataFormat[1], 5011cb0ef41Sopenharmony_ci info.dataFormat[2], info.dataFormat[3], 5021cb0ef41Sopenharmony_ci info.formatVersion[0], info.formatVersion[1]); 5031cb0ef41Sopenharmony_ci *pErrorCode=U_UNSUPPORTED_ERROR; 5041cb0ef41Sopenharmony_ci return 0; 5051cb0ef41Sopenharmony_ci } 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_ci inData=(const char *)inData+headerSize; 5081cb0ef41Sopenharmony_ci if(length>=0) { length-=headerSize; } 5091cb0ef41Sopenharmony_ci outData=(outData == nullptr) ? nullptr : (char *)outData+headerSize; 5101cb0ef41Sopenharmony_ci int32_t collationSize; 5111cb0ef41Sopenharmony_ci if(info.formatVersion[0]>=4) { 5121cb0ef41Sopenharmony_ci collationSize=swapFormatVersion4(ds, inData, length, outData, *pErrorCode); 5131cb0ef41Sopenharmony_ci } else { 5141cb0ef41Sopenharmony_ci collationSize=swapFormatVersion3(ds, inData, length, outData, pErrorCode); 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci if(U_SUCCESS(*pErrorCode)) { 5171cb0ef41Sopenharmony_ci return headerSize+collationSize; 5181cb0ef41Sopenharmony_ci } else { 5191cb0ef41Sopenharmony_ci return 0; 5201cb0ef41Sopenharmony_ci } 5211cb0ef41Sopenharmony_ci} 5221cb0ef41Sopenharmony_ci 5231cb0ef41Sopenharmony_ci/* swap inverse UCA collation data (invuca.icu) */ 5241cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2 5251cb0ef41Sopenharmony_ciucol_swapInverseUCA(const UDataSwapper *ds, 5261cb0ef41Sopenharmony_ci const void *inData, int32_t length, void *outData, 5271cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) { 5281cb0ef41Sopenharmony_ci const UDataInfo *pInfo; 5291cb0ef41Sopenharmony_ci int32_t headerSize; 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci const uint8_t *inBytes; 5321cb0ef41Sopenharmony_ci uint8_t *outBytes; 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci const InverseUCATableHeader *inHeader; 5351cb0ef41Sopenharmony_ci InverseUCATableHeader *outHeader; 5361cb0ef41Sopenharmony_ci InverseUCATableHeader header={ 0,0,0,0,0,{0,0,0,0},{0,0,0,0,0,0,0,0} }; 5371cb0ef41Sopenharmony_ci 5381cb0ef41Sopenharmony_ci /* udata_swapDataHeader checks the arguments */ 5391cb0ef41Sopenharmony_ci headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 5401cb0ef41Sopenharmony_ci if(pErrorCode==nullptr || U_FAILURE(*pErrorCode)) { 5411cb0ef41Sopenharmony_ci return 0; 5421cb0ef41Sopenharmony_ci } 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_ci /* check data format and format version */ 5451cb0ef41Sopenharmony_ci pInfo=(const UDataInfo *)((const char *)inData+4); 5461cb0ef41Sopenharmony_ci if(!( 5471cb0ef41Sopenharmony_ci pInfo->dataFormat[0]==0x49 && /* dataFormat="InvC" */ 5481cb0ef41Sopenharmony_ci pInfo->dataFormat[1]==0x6e && 5491cb0ef41Sopenharmony_ci pInfo->dataFormat[2]==0x76 && 5501cb0ef41Sopenharmony_ci pInfo->dataFormat[3]==0x43 && 5511cb0ef41Sopenharmony_ci pInfo->formatVersion[0]==2 && 5521cb0ef41Sopenharmony_ci pInfo->formatVersion[1]>=1 5531cb0ef41Sopenharmony_ci )) { 5541cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swapInverseUCA(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not an inverse UCA collation file\n", 5551cb0ef41Sopenharmony_ci pInfo->dataFormat[0], pInfo->dataFormat[1], 5561cb0ef41Sopenharmony_ci pInfo->dataFormat[2], pInfo->dataFormat[3], 5571cb0ef41Sopenharmony_ci pInfo->formatVersion[0], pInfo->formatVersion[1]); 5581cb0ef41Sopenharmony_ci *pErrorCode=U_UNSUPPORTED_ERROR; 5591cb0ef41Sopenharmony_ci return 0; 5601cb0ef41Sopenharmony_ci } 5611cb0ef41Sopenharmony_ci 5621cb0ef41Sopenharmony_ci inBytes=(const uint8_t *)inData+headerSize; 5631cb0ef41Sopenharmony_ci outBytes=(uint8_t *)outData+headerSize; 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci inHeader=(const InverseUCATableHeader *)inBytes; 5661cb0ef41Sopenharmony_ci outHeader=(InverseUCATableHeader *)outBytes; 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci /* 5691cb0ef41Sopenharmony_ci * The inverse UCA collation binary must contain at least the InverseUCATableHeader, 5701cb0ef41Sopenharmony_ci * starting with its size field. 5711cb0ef41Sopenharmony_ci * sizeof(UCATableHeader)==8*4 in ICU 2.8 5721cb0ef41Sopenharmony_ci * check the length against the header size before reading the size field 5731cb0ef41Sopenharmony_ci */ 5741cb0ef41Sopenharmony_ci if(length<0) { 5751cb0ef41Sopenharmony_ci header.byteSize=udata_readInt32(ds, inHeader->byteSize); 5761cb0ef41Sopenharmony_ci } else if( 5771cb0ef41Sopenharmony_ci ((length-headerSize)<(8*4) || 5781cb0ef41Sopenharmony_ci (uint32_t)(length-headerSize)<(header.byteSize=udata_readInt32(ds, inHeader->byteSize))) 5791cb0ef41Sopenharmony_ci ) { 5801cb0ef41Sopenharmony_ci udata_printError(ds, "ucol_swapInverseUCA(): too few bytes (%d after header) for inverse UCA collation data\n", 5811cb0ef41Sopenharmony_ci length); 5821cb0ef41Sopenharmony_ci *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 5831cb0ef41Sopenharmony_ci return 0; 5841cb0ef41Sopenharmony_ci } 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci if(length>=0) { 5871cb0ef41Sopenharmony_ci /* copy everything, takes care of data that needs no swapping */ 5881cb0ef41Sopenharmony_ci if(inBytes!=outBytes) { 5891cb0ef41Sopenharmony_ci uprv_memcpy(outBytes, inBytes, header.byteSize); 5901cb0ef41Sopenharmony_ci } 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci /* swap the necessary pieces in the order of their occurrence in the data */ 5931cb0ef41Sopenharmony_ci 5941cb0ef41Sopenharmony_ci /* read more of the InverseUCATableHeader (the byteSize field was read above) */ 5951cb0ef41Sopenharmony_ci header.tableSize= ds->readUInt32(inHeader->tableSize); 5961cb0ef41Sopenharmony_ci header.contsSize= ds->readUInt32(inHeader->contsSize); 5971cb0ef41Sopenharmony_ci header.table= ds->readUInt32(inHeader->table); 5981cb0ef41Sopenharmony_ci header.conts= ds->readUInt32(inHeader->conts); 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_ci /* swap the 32-bit integers in the header */ 6011cb0ef41Sopenharmony_ci ds->swapArray32(ds, inHeader, 5*4, outHeader, pErrorCode); 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_ci /* swap the inverse table; tableSize counts uint32_t[3] rows */ 6041cb0ef41Sopenharmony_ci ds->swapArray32(ds, inBytes+header.table, header.tableSize*3*4, 6051cb0ef41Sopenharmony_ci outBytes+header.table, pErrorCode); 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ci /* swap the continuation table; contsSize counts UChars */ 6081cb0ef41Sopenharmony_ci ds->swapArray16(ds, inBytes+header.conts, header.contsSize*U_SIZEOF_UCHAR, 6091cb0ef41Sopenharmony_ci outBytes+header.conts, pErrorCode); 6101cb0ef41Sopenharmony_ci } 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_ci return headerSize+header.byteSize; 6131cb0ef41Sopenharmony_ci} 6141cb0ef41Sopenharmony_ci 6151cb0ef41Sopenharmony_ci#endif /* #if !UCONFIG_NO_COLLATION */ 616