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